



























@@ -1388,32 +1388,25 @@ describe("runCodexAppServerAttempt", () => {
13881388await harness.completeTurn({ threadId: "thread-1", turnId: "turn-1" });
13891389await run;
139013901391-expect(beforePromptBuild).toHaveBeenCalledWith(
1392-{
1393-prompt: "hello",
1394-messages: [expect.objectContaining({ role: "assistant" })],
1395-},
1396-expect.objectContaining({
1397-runId: "run-1",
1398-sessionId: "session-1",
1399-}),
1400-);
1401-expect(harness.requests).toEqual(
1402-expect.arrayContaining([
1403-{
1404-method: "thread/start",
1405-params: expect.objectContaining({
1406-developerInstructions: expect.stringContaining("pre system\n\ncustom codex system"),
1407-}),
1408-},
1409-{
1410-method: "turn/start",
1411-params: expect.objectContaining({
1412-input: [{ type: "text", text: "queued context\n\nhello", text_elements: [] }],
1413-}),
1414-},
1415-]),
1416-);
1391+expect(beforePromptBuild).toHaveBeenCalledOnce();
1392+const [hookInput, hookContext] = beforePromptBuild.mock.calls[0] as unknown as [
1393+{ messages?: Array<{ role?: string }>; prompt?: string },
1394+{ runId?: string; sessionId?: string },
1395+];
1396+expect(hookInput.prompt).toBe("hello");
1397+expect(hookInput.messages?.[0]?.role).toBe("assistant");
1398+expect(hookContext.runId).toBe("run-1");
1399+expect(hookContext.sessionId).toBe("session-1");
1400+const threadStart = harness.requests.find((request) => request.method === "thread/start");
1401+const threadStartParams = threadStart?.params as { developerInstructions?: string } | undefined;
1402+expect(threadStartParams?.developerInstructions).toContain("pre system\n\ncustom codex system");
1403+const turnStart = harness.requests.find((request) => request.method === "turn/start");
1404+const turnStartParams = turnStart?.params as
1405+| { input?: Array<{ text?: string; text_elements?: unknown[]; type?: string }> }
1406+| undefined;
1407+expect(turnStartParams?.input).toEqual([
1408+{ type: "text", text: "queued context\n\nhello", text_elements: [] },
1409+]);
14171410});
1418141114191412it("projects mirrored history when starting Codex without a native thread binding", async () => {
@@ -1501,27 +1494,30 @@ describe("runCodexAppServerAttempt", () => {
15011494expect(llmInput).toHaveBeenCalled();
15021495await new Promise<void>((resolve) => setImmediate(resolve));
150314961504-expect(llmInput.mock.calls).toEqual(
1505-expect.arrayContaining([
1506-[
1507-expect.objectContaining({
1508-runId: "run-1",
1509-sessionId: "session-1",
1510-provider: "codex",
1511-model: "gpt-5.4-codex",
1512-prompt: "hello",
1513-imagesCount: 0,
1514-historyMessages: [expect.objectContaining({ role: "assistant" })],
1515-systemPrompt: expect.stringContaining(CODEX_GPT5_BEHAVIOR_CONTRACT),
1516-}),
1517-expect.objectContaining({
1518-runId: "run-1",
1519-sessionId: "session-1",
1520-sessionKey: "agent:main:session-1",
1521-}),
1522-],
1523-]),
1524-);
1497+const [llmInputPayload, llmInputContext] = llmInput.mock.calls[0] as unknown as [
1498+{
1499+historyMessages?: Array<{ role?: string }>;
1500+imagesCount?: number;
1501+model?: string;
1502+prompt?: string;
1503+provider?: string;
1504+runId?: string;
1505+sessionId?: string;
1506+systemPrompt?: string;
1507+},
1508+{ runId?: string; sessionId?: string; sessionKey?: string },
1509+];
1510+expect(llmInputPayload.runId).toBe("run-1");
1511+expect(llmInputPayload.sessionId).toBe("session-1");
1512+expect(llmInputPayload.provider).toBe("codex");
1513+expect(llmInputPayload.model).toBe("gpt-5.4-codex");
1514+expect(llmInputPayload.prompt).toBe("hello");
1515+expect(llmInputPayload.imagesCount).toBe(0);
1516+expect(llmInputPayload.historyMessages?.[0]?.role).toBe("assistant");
1517+expect(llmInputPayload.systemPrompt).toContain(CODEX_GPT5_BEHAVIOR_CONTRACT);
1518+expect(llmInputContext.runId).toBe("run-1");
1519+expect(llmInputContext.sessionId).toBe("session-1");
1520+expect(llmInputContext.sessionKey).toBe("agent:main:session-1");
1525152115261522await harness.notify({
15271523method: "item/agentMessage/delta",
@@ -1538,30 +1534,26 @@ describe("runCodexAppServerAttempt", () => {
15381534expect(result.assistantTexts).toEqual(["hello back"]);
15391535expect(llmOutput).toHaveBeenCalledTimes(1);
15401536expect(agentEnd).toHaveBeenCalledTimes(1);
1541-const agentEvents = onRunAgentEvent.mock.calls.map(([event]) => event);
1542-expect(agentEvents).toEqual(
1543-expect.arrayContaining([
1544-{
1545-stream: "lifecycle",
1546-data: expect.objectContaining({
1547-phase: "start",
1548-startedAt: expect.any(Number),
1549-}),
1550-},
1551-{
1552-stream: "assistant",
1553-data: { text: "hello back" },
1554-},
1555-{
1556-stream: "lifecycle",
1557-data: expect.objectContaining({
1558-phase: "end",
1559-startedAt: expect.any(Number),
1560-endedAt: expect.any(Number),
1561-}),
1562-},
1563-]),
1537+const agentEvents = onRunAgentEvent.mock.calls.map(([event]) => event) as Array<{
1538+data: {
1539+endedAt?: number;
1540+phase?: string;
1541+startedAt?: number;
1542+text?: string;
1543+};
1544+stream: string;
1545+}>;
1546+const lifecycleStart = agentEvents.find(
1547+(event) => event.stream === "lifecycle" && event.data.phase === "start",
1548+);
1549+expect(typeof lifecycleStart?.data.startedAt).toBe("number");
1550+const assistantEvent = agentEvents.find((event) => event.stream === "assistant");
1551+expect(assistantEvent?.data).toEqual({ text: "hello back" });
1552+const lifecycleEnd = agentEvents.find(
1553+(event) => event.stream === "lifecycle" && event.data.phase === "end",
15641554);
1555+expect(typeof lifecycleEnd?.data.startedAt).toBe("number");
1556+expect(typeof lifecycleEnd?.data.endedAt).toBe("number");
15651557const startIndex = agentEvents.findIndex(
15661558(event) => event.stream === "lifecycle" && event.data.phase === "start",
15671559);
@@ -1572,54 +1564,48 @@ describe("runCodexAppServerAttempt", () => {
15721564expect(startIndex).toBeGreaterThanOrEqual(0);
15731565expect(assistantIndex).toBeGreaterThan(startIndex);
15741566expect(endIndex).toBeGreaterThan(assistantIndex);
1575-expect(globalAgentEvents).toEqual(
1576-expect.arrayContaining([
1577-expect.objectContaining({
1578-runId: "run-1",
1579-sessionKey: "agent:main:session-1",
1580-stream: "assistant",
1581-data: { text: "hello back" },
1582-}),
1583-expect.objectContaining({
1584-runId: "run-1",
1585-sessionKey: "agent:main:session-1",
1586-stream: "lifecycle",
1587-data: expect.objectContaining({ phase: "end" }),
1588-}),
1589-]),
1567+const globalAssistantEvent = globalAgentEvents.find((event) => event.stream === "assistant");
1568+expect(globalAssistantEvent?.runId).toBe("run-1");
1569+expect(globalAssistantEvent?.sessionKey).toBe("agent:main:session-1");
1570+expect(globalAssistantEvent?.data).toEqual({ text: "hello back" });
1571+const globalEndEvent = globalAgentEvents.find(
1572+(event) => event.stream === "lifecycle" && event.data.phase === "end",
15901573);
1574+expect(globalEndEvent?.runId).toBe("run-1");
1575+expect(globalEndEvent?.sessionKey).toBe("agent:main:session-1");
159115761592-expect(llmOutput).toHaveBeenCalledWith(
1593-expect.objectContaining({
1594-runId: "run-1",
1595-sessionId: "session-1",
1596-provider: "codex",
1597-model: "gpt-5.4-codex",
1598-resolvedRef: "codex/gpt-5.4-codex",
1599-harnessId: "codex",
1600-assistantTexts: ["hello back"],
1601-lastAssistant: expect.objectContaining({
1602-role: "assistant",
1603-}),
1604-}),
1605-expect.objectContaining({
1606-runId: "run-1",
1607-sessionId: "session-1",
1608-}),
1609-);
1610-expect(agentEnd).toHaveBeenCalledWith(
1611-expect.objectContaining({
1612-success: true,
1613-messages: expect.arrayContaining([
1614-expect.objectContaining({ role: "user" }),
1615-expect.objectContaining({ role: "assistant" }),
1616-]),
1617-}),
1618-expect.objectContaining({
1619-runId: "run-1",
1620-sessionId: "session-1",
1621-}),
1622-);
1577+const [llmOutputPayload, llmOutputContext] = llmOutput.mock.calls[0] as unknown as [
1578+{
1579+assistantTexts?: string[];
1580+harnessId?: string;
1581+lastAssistant?: { role?: string };
1582+model?: string;
1583+provider?: string;
1584+resolvedRef?: string;
1585+runId?: string;
1586+sessionId?: string;
1587+},
1588+{ runId?: string; sessionId?: string },
1589+];
1590+expect(llmOutputPayload.runId).toBe("run-1");
1591+expect(llmOutputPayload.sessionId).toBe("session-1");
1592+expect(llmOutputPayload.provider).toBe("codex");
1593+expect(llmOutputPayload.model).toBe("gpt-5.4-codex");
1594+expect(llmOutputPayload.resolvedRef).toBe("codex/gpt-5.4-codex");
1595+expect(llmOutputPayload.harnessId).toBe("codex");
1596+expect(llmOutputPayload.assistantTexts).toEqual(["hello back"]);
1597+expect(llmOutputPayload.lastAssistant?.role).toBe("assistant");
1598+expect(llmOutputContext.runId).toBe("run-1");
1599+expect(llmOutputContext.sessionId).toBe("session-1");
1600+const [agentEndPayload, agentEndContext] = agentEnd.mock.calls[0] as unknown as [
1601+{ messages?: Array<{ role?: string }>; success?: boolean },
1602+{ runId?: string; sessionId?: string },
1603+];
1604+expect(agentEndPayload.success).toBe(true);
1605+expect(agentEndPayload.messages?.some((message) => message.role === "user")).toBe(true);
1606+expect(agentEndPayload.messages?.some((message) => message.role === "assistant")).toBe(true);
1607+expect(agentEndContext.runId).toBe("run-1");
1608+expect(agentEndContext.sessionId).toBe("session-1");
16231609});
1624161016251611it("forwards Codex app-server verbose tool summaries and completed output", async () => {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。