diff --git a/src/agents/embedded-agent-runner-extraparams.test.ts b/src/agents/embedded-agent-runner-extraparams.test.ts index 2f4aab68034..838fa8e3dee 100644 --- a/src/agents/embedded-agent-runner-extraparams.test.ts +++ b/src/agents/embedded-agent-runner-extraparams.test.ts @@ -3100,6 +3100,59 @@ describe("applyExtraParamsToAgent", () => { expect(capturedOptions?.replayResponsesItemIds).toBe(true); }); + it("keeps Responses replay item ids enabled for Azure OpenAI store-enabled requests", () => { + let capturedOptions: + | (SimpleStreamOptions & { + replayResponsesItemIds?: boolean; + }) + | undefined; + const baseStreamFn: StreamFn = (_model, _context, options) => { + capturedOptions = options; + return {} as ReturnType; + }; + const streamFn = createOpenAIResponsesContextManagementWrapper(baseStreamFn, undefined); + + void streamFn( + { + api: "openai-responses", + provider: "azure-openai", + id: "gpt-5-mini", + baseUrl: "https://example.openai.azure.com/openai/v1", + } as unknown as Model<"openai-responses">, + { messages: [] }, + {}, + ); + + expect(capturedOptions?.replayResponsesItemIds).toBe(true); + }); + + it("does not disable replay defaults for store-capable third-party Responses routes", () => { + let capturedOptions: + | (SimpleStreamOptions & { + replayResponsesItemIds?: boolean; + }) + | undefined; + const baseStreamFn: StreamFn = (_model, _context, options) => { + capturedOptions = options; + return {} as ReturnType; + }; + const streamFn = createOpenAIResponsesContextManagementWrapper(baseStreamFn, undefined); + + void streamFn( + { + api: "openai-responses", + provider: "custom-openai-responses", + id: "store-capable-model", + baseUrl: "https://custom.example.invalid/v1", + compat: { supportsStore: true }, + } as unknown as Model<"openai-responses">, + { messages: [] }, + { replayResponsesItemIds: true } as never, + ); + + expect(capturedOptions?.replayResponsesItemIds).toBe(true); + }); + it("disables Responses replay item ids when custom Responses routes strip store", () => { let capturedOptions: | (SimpleStreamOptions & { diff --git a/src/agents/openai-transport-stream.test.ts b/src/agents/openai-transport-stream.test.ts index 2a50b714272..969e736d608 100644 --- a/src/agents/openai-transport-stream.test.ts +++ b/src/agents/openai-transport-stream.test.ts @@ -3839,6 +3839,104 @@ describe("openai transport stream", () => { }); }); + it("preserves Responses replay item ids for store-capable third-party opt-in routes", () => { + const params = buildOpenAIResponsesParams( + { + id: "store-capable-model", + name: "Store-capable model", + api: "openai-responses", + provider: "custom-openai-responses", + baseUrl: "https://custom.example.com/v1", + compat: { supportsStore: true } as never, + reasoning: true, + input: ["text"], + cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, + contextWindow: 200000, + maxTokens: 8192, + } satisfies Model<"openai-responses">, + { + systemPrompt: "system", + messages: [ + { + role: "assistant", + api: "openai-responses", + provider: "custom-openai-responses", + model: "store-capable-model", + usage: { + input: 0, + output: 0, + cacheRead: 0, + cacheWrite: 0, + totalTokens: 0, + cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 }, + }, + stopReason: "toolUse", + timestamp: 1, + content: [ + { + type: "thinking", + thinking: "Need a tool.", + thinkingSignature: JSON.stringify({ + type: "reasoning", + id: "rs_prior", + summary: [], + }), + }, + { + type: "text", + text: "Checking the price.", + textSignature: JSON.stringify({ + v: 1, + id: "msg_prior", + phase: "commentary", + }), + }, + { + type: "toolCall", + id: "call_abc|fc_prior", + name: "price_lookup", + arguments: { symbol: "SOL" }, + }, + ], + }, + ], + tools: [], + } as never, + { replayResponsesItemIds: true, sessionId: "session-123" }, + ) as { + input?: Array<{ + type?: string; + role?: string; + id?: string; + call_id?: string; + phase?: string; + summary?: unknown; + }>; + }; + + const reasoningItem = params.input?.find((item) => item.type === "reasoning"); + expectRecordFields(reasoningItem, { + type: "reasoning", + id: "rs_prior", + summary: [], + }); + const assistantMessage = params.input?.find( + (item) => item.type === "message" && item.role === "assistant", + ); + expectRecordFields(assistantMessage, { + type: "message", + role: "assistant", + id: "msg_prior", + phase: "commentary", + }); + const functionCall = params.input?.find((item) => item.type === "function_call"); + expectRecordFields(functionCall, { + type: "function_call", + id: "fc_prior", + call_id: "call_abc", + }); + }); + it("omits prior Responses replay item ids when store is disabled for custom Codex-compatible responses", () => { const model = { id: "gpt-5.4",