

























@@ -1253,6 +1253,174 @@ describe("CodexAppServerEventProjector", () => {
12531253expect(toolResultContentItem.content).toBe("ok");
12541254});
125512551256+it("synthesizes native tool progress from turn completion snapshots", async () => {
1257+const onAgentEvent = vi.fn();
1258+const onToolResult = vi.fn();
1259+const projector = await createProjector({
1260+ ...(await createParams()),
1261+verboseLevel: "on",
1262+ onAgentEvent,
1263+ onToolResult,
1264+});
1265+1266+await projector.handleNotification(
1267+turnCompleted([
1268+{
1269+type: "commandExecution",
1270+id: "cmd-snapshot",
1271+command: "pnpm test extensions/codex",
1272+cwd: "/workspace",
1273+processId: null,
1274+source: "agent",
1275+status: "completed",
1276+commandActions: [],
1277+aggregatedOutput: "ok",
1278+exitCode: 0,
1279+durationMs: 42,
1280+},
1281+]),
1282+);
1283+1284+const itemStart = findAgentEvent(onAgentEvent, {
1285+stream: "item",
1286+phase: "start",
1287+itemId: "cmd-snapshot",
1288+}).data;
1289+expect(itemStart.kind).toBe("command");
1290+expect(itemStart.name).toBe("bash");
1291+expect(itemStart.suppressChannelProgress).toBe(true);
1292+const toolStart = findAgentEvent(onAgentEvent, {
1293+stream: "tool",
1294+phase: "start",
1295+itemId: "cmd-snapshot",
1296+name: "bash",
1297+}).data;
1298+expect(toolStart.args).toEqual({ command: "pnpm test extensions/codex", cwd: "/workspace" });
1299+const toolResult = findAgentEvent(onAgentEvent, {
1300+stream: "tool",
1301+phase: "result",
1302+itemId: "cmd-snapshot",
1303+name: "bash",
1304+}).data;
1305+expect(toolResult.status).toBe("completed");
1306+expect(toolResult.isError).toBe(false);
1307+expect(onToolResult).toHaveBeenCalledWith({
1308+text: "🛠️ `run tests (workspace)`",
1309+});
1310+});
1311+1312+it("does not duplicate native tool starts when the snapshot completes a started item", async () => {
1313+const onAgentEvent = vi.fn();
1314+const projector = await createProjector({ ...(await createParams()), onAgentEvent });
1315+const commandItem = {
1316+type: "commandExecution",
1317+id: "cmd-started",
1318+command: "pnpm test extensions/codex",
1319+cwd: "/workspace",
1320+processId: null,
1321+source: "agent",
1322+status: "completed",
1323+commandActions: [],
1324+aggregatedOutput: "ok",
1325+exitCode: 0,
1326+durationMs: 42,
1327+};
1328+1329+await projector.handleNotification(
1330+forCurrentTurn("item/started", {
1331+item: { ...commandItem, status: "inProgress", aggregatedOutput: null, exitCode: null },
1332+}),
1333+);
1334+await projector.handleNotification(turnCompleted([commandItem]));
1335+1336+const toolEvents = onAgentEvent.mock.calls
1337+.map((call) => requireRecord(call[0], "agent event"))
1338+.filter((event) => event.stream === "tool")
1339+.map((event) => requireRecord(event.data, "agent event data"));
1340+expect(
1341+toolEvents.filter((event) => event.phase === "start" && event.itemId === "cmd-started"),
1342+).toHaveLength(1);
1343+expect(
1344+toolEvents.filter((event) => event.phase === "result" && event.itemId === "cmd-started"),
1345+).toHaveLength(1);
1346+});
1347+1348+it("does not synthesize completed progress for running turn completion snapshots", async () => {
1349+const onAgentEvent = vi.fn();
1350+const projector = await createProjector({ ...(await createParams()), onAgentEvent });
1351+1352+await projector.handleNotification(
1353+turnCompleted([
1354+{
1355+type: "commandExecution",
1356+id: "cmd-running-snapshot",
1357+command: "pnpm test extensions/codex",
1358+cwd: "/workspace",
1359+processId: null,
1360+source: "agent",
1361+status: "inProgress",
1362+commandActions: [],
1363+aggregatedOutput: null,
1364+exitCode: null,
1365+durationMs: null,
1366+},
1367+]),
1368+);
1369+1370+const toolEvents = onAgentEvent.mock.calls
1371+.map((call) => requireRecord(call[0], "agent event"))
1372+.filter((event) => event.stream === "tool")
1373+.map((event) => requireRecord(event.data, "agent event data"));
1374+expect(toolEvents).toEqual([]);
1375+});
1376+1377+it("does not synthesize progress for stale prior-turn snapshot items", async () => {
1378+const onAgentEvent = vi.fn();
1379+const projector = await createProjector({ ...(await createParams()), onAgentEvent });
1380+1381+await projector.handleNotification(
1382+turnCompleted([
1383+{
1384+type: "commandExecution",
1385+id: "cmd-prior-turn",
1386+turnId: "turn-old",
1387+command: "pnpm test extensions/codex",
1388+cwd: "/workspace",
1389+processId: null,
1390+source: "agent",
1391+status: "completed",
1392+commandActions: [],
1393+aggregatedOutput: "ok",
1394+exitCode: 0,
1395+durationMs: 42,
1396+},
1397+{
1398+type: "commandExecution",
1399+id: "cmd-current-turn",
1400+turnId: TURN_ID,
1401+command: "pnpm test extensions/codex",
1402+cwd: "/workspace",
1403+processId: null,
1404+source: "agent",
1405+status: "completed",
1406+commandActions: [],
1407+aggregatedOutput: "ok",
1408+exitCode: 0,
1409+durationMs: 42,
1410+},
1411+]),
1412+);
1413+1414+const toolEvents = onAgentEvent.mock.calls
1415+.map((call) => requireRecord(call[0], "agent event"))
1416+.filter((event) => event.stream === "tool")
1417+.map((event) => requireRecord(event.data, "agent event data"));
1418+expect(toolEvents.map((event) => event.itemId)).toEqual([
1419+"cmd-current-turn",
1420+"cmd-current-turn",
1421+]);
1422+});
1423+12561424it("orders declined native tool diagnostics after their start event", async () => {
12571425const projector = await createProjector();
12581426const diagnosticEvents: DiagnosticEventPayload[] = [];
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。