mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-06 13:32:54 +00:00
fix(codex): stream final answer partials (#88730)
This commit is contained in:
committed by
GitHub
parent
beb499b4d1
commit
3bac0bcbfb
@@ -316,6 +316,29 @@ describe("CodexAppServerEventProjector", () => {
|
||||
expect(result.replayMetadata.replaySafe).toBe(true);
|
||||
});
|
||||
|
||||
it("streams final-answer assistant deltas into partial replies", async () => {
|
||||
const { onPartialReply, projector } = await createProjectorWithAssistantHooks();
|
||||
|
||||
await projector.handleNotification(
|
||||
forCurrentTurn("item/started", {
|
||||
item: {
|
||||
type: "agentMessage",
|
||||
id: "msg-final",
|
||||
phase: "final_answer",
|
||||
text: "",
|
||||
},
|
||||
}),
|
||||
);
|
||||
await projector.handleNotification(agentMessageDelta("hel", "msg-final"));
|
||||
await projector.handleNotification(agentMessageDelta("lo", "msg-final"));
|
||||
|
||||
expect(onPartialReply).toHaveBeenCalledTimes(2);
|
||||
expect(onPartialReply.mock.calls.map((call) => call[0])).toEqual([
|
||||
{ text: "hel", delta: "hel" },
|
||||
{ text: "hello", delta: "lo" },
|
||||
]);
|
||||
});
|
||||
|
||||
it("suppresses mirrored user prompt when the inbound message was already persisted", async () => {
|
||||
const params = await createParams();
|
||||
const projector = await createProjector({
|
||||
|
||||
@@ -447,6 +447,11 @@ export class CodexAppServerEventProjector {
|
||||
if (!delta) {
|
||||
return;
|
||||
}
|
||||
this.rememberAssistantPhase(readItem(params.item));
|
||||
const phase = readString(params, "phase");
|
||||
if (phase) {
|
||||
this.assistantPhaseByItem.set(itemId, phase);
|
||||
}
|
||||
if (!this.assistantStarted) {
|
||||
this.assistantStarted = true;
|
||||
await this.params.onAssistantMessageStart?.();
|
||||
@@ -456,10 +461,13 @@ export class CodexAppServerEventProjector {
|
||||
this.assistantTextByItem.set(itemId, text);
|
||||
if (this.isCommentaryAssistantItem(itemId)) {
|
||||
this.emitCommentaryProgress({ itemId, text });
|
||||
} else if (this.shouldStreamAssistantPartial(itemId)) {
|
||||
await this.params.onPartialReply?.({ text, delta });
|
||||
}
|
||||
// Codex app-server can emit multiple agentMessage items per turn, including
|
||||
// intermediate coordination/progress prose. Keep those deltas internal until
|
||||
// turn completion chooses the last assistant item as the user-visible reply.
|
||||
// their phase identifies terminal answer text or turn completion chooses the
|
||||
// last assistant item as the user-visible reply.
|
||||
}
|
||||
|
||||
private async handleReasoningDelta(
|
||||
@@ -970,6 +978,10 @@ export class CodexAppServerEventProjector {
|
||||
return this.assistantPhaseByItem.get(itemId) === "commentary";
|
||||
}
|
||||
|
||||
private shouldStreamAssistantPartial(itemId: string): boolean {
|
||||
return this.assistantPhaseByItem.get(itemId) === "final_answer";
|
||||
}
|
||||
|
||||
private emitCommentaryProgress(params: { itemId: string; text: string }): void {
|
||||
const progressText = params.text.replace(/\s+/g, " ").trim();
|
||||
if (
|
||||
|
||||
Reference in New Issue
Block a user