fix(consultation): ensure final response after tool completion

This commit is contained in:
Jesse_Chen
2026-08-14 17:02:02 +08:00
parent afc8af5b8e
commit ae4a6e4720
2 changed files with 47 additions and 1 deletions
+21
View File
@@ -32,6 +32,14 @@ async function* readChunks(stream: ChunkStream): AsyncIterable<Chunk> {
}
type Status = "ready" | "degraded" | "blocked";
export const ENSURE_FINAL_RESPONSE_FALLBACK =
"本次计算已完成,但暂时没有生成可展示的回答。请换一个角度提问,我会基于已完成的计算继续说明。";
export function ensureFinalResponseText(output: string, contractIsReady: boolean) {
if (!contractIsReady || /\S/.test(output)) return null;
return ENSURE_FINAL_RESPONSE_FALLBACK;
}
type EventOptions = {
runId: string;
requestId: string;
@@ -202,6 +210,19 @@ export function streamAgentResponse(options: StreamAgentResponseOptions) {
await consumeAttempt(controller, await options.retry());
}
if (!contractReady(options)) throw new Error("runtime_contract_incomplete");
const ensuredFinalResponse = ensureFinalResponseText(fullOutput, contractReady(options));
if (ensuredFinalResponse) {
if (options.state.steps.length < 32) {
options.state.steps.push({ sequence: options.state.steps.length + 1, kind: "validation", name: "ensure-final-response", status: "completed" });
}
if (!firstOutput) {
firstOutput = true;
await options.onFirstOutput?.();
}
send(controller, { type: "answer.delta", text: ensuredFinalResponse });
fullOutput = ensuredFinalResponse;
emitted = true;
}
if (!/\S/.test(fullOutput)) {
if (/\S/.test(first.held) || /\S/.test(first.attemptOutput)) throw new Error("runtime_contract_incomplete");
throw new Error("empty_answer");