mirror of
https://github.com/agentclientprotocol/claude-agent-acp.git
synced 2026-10-27 12:40:32 +00:00
Don't get out of sync when background task creates new init/result (#386)
Relates to #336. This does NOT ensure that the results are immediately sent to the client. See https://github.com/zed-industries/claude-agent-acp/issues/336#issuecomment-4011939471. I guess some tests for this would be useful.
This commit is contained in:
@@ -497,17 +497,23 @@ export class ClaudeAcpAgent implements Agent {
|
||||
|
||||
const userMessage = promptToClaude(params);
|
||||
|
||||
const promptUuid = randomUUID();
|
||||
userMessage.uuid = promptUuid;
|
||||
|
||||
let promptReplayed = false;
|
||||
|
||||
if (session.promptRunning) {
|
||||
const uuid = randomUUID();
|
||||
userMessage.uuid = uuid;
|
||||
session.input.push(userMessage);
|
||||
const order = session.nextPendingOrder++;
|
||||
const cancelled = await new Promise<boolean>((resolve) => {
|
||||
session.pendingMessages.set(uuid, { resolve, order });
|
||||
session.pendingMessages.set(promptUuid, { resolve, order });
|
||||
});
|
||||
if (cancelled) {
|
||||
return { stopReason: "cancelled" };
|
||||
}
|
||||
// The replay resolved the promise, mark in this loop too,
|
||||
// so we don't treat the next result as a background task's result.
|
||||
promptReplayed = true;
|
||||
} else {
|
||||
session.input.push(userMessage);
|
||||
}
|
||||
@@ -582,10 +588,6 @@ export class ClaudeAcpAgent implements Agent {
|
||||
}
|
||||
break;
|
||||
case "result": {
|
||||
if (session.cancelled) {
|
||||
return { stopReason: "cancelled" };
|
||||
}
|
||||
|
||||
// Accumulate usage from this result
|
||||
session.accumulatedUsage.inputTokens += message.usage.input_tokens;
|
||||
session.accumulatedUsage.outputTokens += message.usage.output_tokens;
|
||||
@@ -613,6 +615,18 @@ export class ClaudeAcpAgent implements Agent {
|
||||
});
|
||||
}
|
||||
|
||||
if (!promptReplayed) {
|
||||
// This result is from a background task that finished after
|
||||
// the previous prompt loop ended. Consume it and continue
|
||||
// waiting for our own prompt's result.
|
||||
this.logger.log(`Session ${params.sessionId}: consuming background task result`);
|
||||
break;
|
||||
}
|
||||
|
||||
if (session.cancelled) {
|
||||
return { stopReason: "cancelled" };
|
||||
}
|
||||
|
||||
// Build the usage response
|
||||
const usage: PromptResponse["usage"] = {
|
||||
inputTokens: session.accumulatedUsage.inputTokens,
|
||||
@@ -688,8 +702,14 @@ export class ClaudeAcpAgent implements Agent {
|
||||
break;
|
||||
}
|
||||
|
||||
// Check for queued prompt replay
|
||||
// Check for prompt replay
|
||||
if (message.type === "user" && "uuid" in message && message.uuid) {
|
||||
if (message.uuid === promptUuid) {
|
||||
// Our own prompt was replayed back — we're now processing
|
||||
// our prompt's response (not a background task's).
|
||||
promptReplayed = true;
|
||||
break;
|
||||
}
|
||||
const pending = session.pendingMessages.get(message.uuid as string);
|
||||
if (pending) {
|
||||
pending.resolve(false);
|
||||
|
||||
Reference in New Issue
Block a user