refactor(server): replace stream() with subscribe() + startTurn() across all providers
Replace three competing event paths (foreground stream, live event pump, JSONL history poller) with a single push-based subscribe() + startTurn() contract. This fixes duplicate user messages and stuck running state caused by timing-based routing between concurrent event sources. Key changes: - AgentSession interface: remove stream(), add subscribe() and startTurn() - All providers (Claude, Codex, OpenCode): single subscribers Set with notifySubscribers() for push-based event delivery and turnId stamping - Agent manager: identity-based turn ownership via activeForegroundTurnId replacing pendingRun async generator - Delete: dual queues, routeSdkMessageFromPump, startLiveHistoryPolling, snapHistoryOffsetToEnd, liveEventBacklog, Pushable - Fix Codex provider not clearing activeForegroundTurnId on turn completion - Add real-provider integration tests for event stream invariants
This commit is contained in:
@@ -199,10 +199,7 @@ function startAgentRun(
|
||||
logger: Logger,
|
||||
options?: { replaceRunning?: boolean },
|
||||
): void {
|
||||
const snapshot = agentManager.getAgent(agentId);
|
||||
const shouldReplace =
|
||||
options?.replaceRunning &&
|
||||
Boolean(snapshot && (snapshot.lifecycle === "running" || snapshot.pendingRun));
|
||||
const shouldReplace = Boolean(options?.replaceRunning && agentManager.hasInFlightRun(agentId));
|
||||
const iterator = shouldReplace
|
||||
? agentManager.replaceAgentRun(agentId, prompt)
|
||||
: agentManager.streamAgent(agentId, prompt);
|
||||
@@ -696,7 +693,7 @@ export async function createAgentMcpServer(options: AgentMcpServerOptions): Prom
|
||||
throw new Error(`Agent ${agentId} not found`);
|
||||
}
|
||||
|
||||
if (snapshot.lifecycle === "running" || snapshot.pendingRun) {
|
||||
if (agentManager.hasInFlightRun(agentId)) {
|
||||
waitTracker.cancel(agentId, "Agent run interrupted by new prompt");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user