

























@@ -2788,22 +2788,24 @@ describe("CodexAppServerEventProjector", () => {
27882788terminalPresentation = observation.terminalPresentation;
27892789},
27902790});
2791+const item = {
2792+type: "commandExecution",
2793+id: "command-clear-presentation",
2794+command: "git status --short",
2795+cwd: "/workspace",
2796+processId: null,
2797+source: "agent",
2798+status: "completed",
2799+commandActions: [{ type: "unknown", command: "git status --short" }],
2800+aggregatedOutput: "",
2801+exitCode: 0,
2802+durationMs: 1,
2803+};
279128042805+await projector.handleNotification(forCurrentTurn("item/started", { item }));
27922806await projector.handleNotification(
27932807forCurrentTurn("item/completed", {
2794-item: {
2795-type: "commandExecution",
2796-id: "command-clear-presentation",
2797-command: "git status --short",
2798-cwd: "/workspace",
2799-processId: null,
2800-source: "agent",
2801-status: "completed",
2802-commandActions: [{ type: "unknown", command: "git status --short" }],
2803-aggregatedOutput: "",
2804-exitCode: 0,
2805-durationMs: 1,
2806-},
2808+ item,
28072809}),
28082810);
28092811@@ -2826,9 +2828,90 @@ describe("CodexAppServerEventProjector", () => {
28262828id: "image-view-clear-presentation",
28272829path: "/workspace/reference.png",
28282830},
2831+{
2832+type: "dynamicToolCall",
2833+id: "stale-dynamic-tool",
2834+turnId: "turn-old",
2835+tool: "web_fetch",
2836+status: "completed",
2837+},
2838+]),
2839+);
2840+2841+expect(terminalPresentation).toBeUndefined();
2842+});
2843+2844+it("keeps a later dynamic presentation over an earlier snapshot-only native tool", async () => {
2845+let terminalPresentation: string | undefined = "later dynamic result";
2846+let latestOrdinal = 1;
2847+let nextOrdinal = 0;
2848+const projector = await createProjector({
2849+ ...(await createParams()),
2850+allocateToolOutcomeOrdinal: () => nextOrdinal++,
2851+onToolOutcome: (observation) => {
2852+const ordinal = observation.toolCallOrdinal ?? latestOrdinal + 1;
2853+if (ordinal >= latestOrdinal) {
2854+latestOrdinal = ordinal;
2855+terminalPresentation = observation.terminalPresentation;
2856+}
2857+},
2858+});
2859+const nativeItem = {
2860+type: "imageView",
2861+id: "image-view-before-dynamic",
2862+path: "/workspace/reference.png",
2863+};
2864+2865+await projector.handleNotification(
2866+forCurrentTurn("item/completed", {
2867+item: nativeItem,
2868+}),
2869+);
2870+2871+await projector.handleNotification(
2872+turnCompleted([
2873+nativeItem,
2874+{
2875+type: "dynamicToolCall",
2876+id: "dynamic-after-image-view",
2877+turnId: TURN_ID,
2878+tool: "web_fetch",
2879+status: "completed",
2880+},
2881+{
2882+type: "imageView",
2883+id: "stale-image-view",
2884+turnId: "turn-old",
2885+path: "/workspace/stale.png",
2886+},
28292887]),
28302888);
283128892890+expect(terminalPresentation).toBe("later dynamic result");
2891+});
2892+2893+it("clears a prior presentation for a completion-only native item without a turn snapshot", async () => {
2894+let terminalPresentation: string | undefined = "stale dynamic result";
2895+let nextOrdinal = 1;
2896+const projector = await createProjector({
2897+ ...(await createParams()),
2898+allocateToolOutcomeOrdinal: () => nextOrdinal++,
2899+onToolOutcome: (observation) => {
2900+terminalPresentation = observation.terminalPresentation;
2901+},
2902+});
2903+2904+await projector.handleNotification(
2905+forCurrentTurn("item/completed", {
2906+item: {
2907+type: "imageView",
2908+id: "completion-only-image-view",
2909+path: "/workspace/reference.png",
2910+},
2911+}),
2912+);
2913+await projector.handleNotification(turnCompleted([]));
2914+28322915expect(terminalPresentation).toBeUndefined();
28332916});
28342917此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。