fix(gateway+acp): thread stopReason through final event to ACP bridge (#24867)

Complete the stop reason propagation chain so ACP clients can
distinguish end_turn from max_tokens:

- server-chat.ts: emitChatFinal accepts optional stopReason param,
  includes it in the final payload, reads it from lifecycle event data
- translator.ts: read stopReason from the final payload instead of
  hardcoding end_turn

Chain: LLM API → run.ts (meta.stopReason) → agent.ts (lifecycle event)
→ server-chat.ts (final payload) → ACP translator (PromptResponse)
This commit is contained in:
Viz
2026-03-03 00:40:54 -05:00
committed by GitHub
parent b34530a05d
commit 0b3bbfec06
2 changed files with 9 additions and 1 deletions

View File

@@ -423,7 +423,9 @@ export class AcpGatewayAgent implements Agent {
}
if (state === "final") {
this.finishPrompt(pending.sessionId, pending, "end_turn");
const rawStopReason = payload.stopReason as string | undefined;
const stopReason: StopReason = rawStopReason === "max_tokens" ? "max_tokens" : "end_turn";
this.finishPrompt(pending.sessionId, pending, stopReason);
return;
}
if (state === "aborted") {

View File

@@ -346,6 +346,7 @@ export function createAgentEventHandler({
seq: number,
jobState: "done" | "error",
error?: unknown,
stopReason?: string,
) => {
const bufferedText = stripInlineDirectiveTagsForDisplay(
chatRunState.buffers.get(clientRunId) ?? "",
@@ -399,6 +400,7 @@ export function createAgentEventHandler({
sessionKey,
seq,
state: "final" as const,
...(stopReason && { stopReason }),
message:
text && !shouldSuppressSilent
? {
@@ -512,6 +514,8 @@ export function createAgentEventHandler({
if (!isAborted && evt.stream === "assistant" && typeof evt.data?.text === "string") {
emitChatDelta(sessionKey, clientRunId, evt.runId, evt.seq, evt.data.text);
} else if (!isAborted && (lifecyclePhase === "end" || lifecyclePhase === "error")) {
const evtStopReason =
typeof evt.data?.stopReason === "string" ? evt.data.stopReason : undefined;
if (chatLink) {
const finished = chatRunState.registry.shift(evt.runId);
if (!finished) {
@@ -525,6 +529,7 @@ export function createAgentEventHandler({
evt.seq,
lifecyclePhase === "error" ? "error" : "done",
evt.data?.error,
evtStopReason,
);
} else {
emitChatFinal(
@@ -534,6 +539,7 @@ export function createAgentEventHandler({
evt.seq,
lifecyclePhase === "error" ? "error" : "done",
evt.data?.error,
evtStopReason,
);
}
} else if (isAborted && (lifecyclePhase === "end" || lifecyclePhase === "error")) {