Skip to content

Commit 0d6de5e

Browse files
author
snowzlm
committed
fix: skip Responses item id replay without store
1 parent 930bc96 commit 0d6de5e

4 files changed

Lines changed: 144 additions & 4 deletions

File tree

src/agents/embedded-agent-runner-extraparams.test.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2919,6 +2919,33 @@ describe("applyExtraParamsToAgent", () => {
29192919
expect(capturedOptions?.replayResponsesItemIds).toBe(true);
29202920
});
29212921

2922+
it("disables Responses replay item ids when custom Responses routes strip store", () => {
2923+
let capturedOptions:
2924+
| (SimpleStreamOptions & {
2925+
replayResponsesItemIds?: boolean;
2926+
})
2927+
| undefined;
2928+
const baseStreamFn: StreamFn = (_model, _context, options) => {
2929+
capturedOptions = options;
2930+
return {} as ReturnType<StreamFn>;
2931+
};
2932+
const streamFn = createOpenAIResponsesContextManagementWrapper(baseStreamFn, undefined);
2933+
2934+
void streamFn(
2935+
{
2936+
api: "openai-responses",
2937+
provider: "codex-ai02",
2938+
id: "gpt-5.5",
2939+
baseUrl: "https://custom.example.com/v1",
2940+
compat: { supportsStore: false },
2941+
} as unknown as Model<"openai-responses">,
2942+
{ messages: [] },
2943+
{},
2944+
);
2945+
2946+
expect(capturedOptions?.replayResponsesItemIds).toBe(false);
2947+
});
2948+
29222949
it("forces store=true for azure-openai provider with openai-responses API (#42800)", () => {
29232950
const payload = runResponsesPayloadMutationCase({
29242951
applyProvider: "azure-openai",

src/agents/openai-transport-stream.test.ts

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2895,6 +2895,116 @@ describe("openai transport stream", () => {
28952895
expect(functionCall?.id).toBeUndefined();
28962896
});
28972897

2898+
it("omits Responses replay item ids when custom Responses routes strip store support", () => {
2899+
const params = buildOpenAIResponsesParams(
2900+
{
2901+
id: "gpt-5.5",
2902+
name: "GPT-5.5",
2903+
api: "openai-responses",
2904+
provider: "codex-ai02",
2905+
baseUrl: "https://custom.example.com/v1",
2906+
compat: { supportsStore: false },
2907+
reasoning: true,
2908+
input: ["text"],
2909+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
2910+
contextWindow: 1_000_000,
2911+
maxTokens: 128_000,
2912+
} satisfies Model<"openai-responses">,
2913+
{
2914+
systemPrompt: "system",
2915+
messages: [
2916+
{
2917+
role: "assistant",
2918+
api: "openai-responses",
2919+
provider: "codex-ai02",
2920+
model: "gpt-5.5",
2921+
usage: {
2922+
input: 0,
2923+
output: 0,
2924+
cacheRead: 0,
2925+
cacheWrite: 0,
2926+
totalTokens: 0,
2927+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
2928+
},
2929+
stopReason: "toolUse",
2930+
timestamp: 1,
2931+
content: [
2932+
{
2933+
type: "thinking",
2934+
thinking: "Need a tool.",
2935+
thinkingSignature: JSON.stringify({
2936+
type: "reasoning",
2937+
id: "rs_prior",
2938+
encrypted_content: "ciphertext",
2939+
}),
2940+
},
2941+
{
2942+
type: "text",
2943+
text: "Checking the price.",
2944+
textSignature: JSON.stringify({
2945+
v: 1,
2946+
id: "msg_prior",
2947+
phase: "commentary",
2948+
}),
2949+
},
2950+
{
2951+
type: "toolCall",
2952+
id: "call_abc|fc_prior",
2953+
name: "price_lookup",
2954+
arguments: { symbol: "SOL" },
2955+
},
2956+
],
2957+
},
2958+
{
2959+
role: "toolResult",
2960+
toolCallId: "call_abc|fc_prior",
2961+
toolName: "price_lookup",
2962+
content: [{ type: "text", text: "$83.95" }],
2963+
isError: false,
2964+
timestamp: 2,
2965+
},
2966+
],
2967+
tools: [],
2968+
} as never,
2969+
{ sessionId: "session-123" },
2970+
) as {
2971+
store?: boolean;
2972+
input?: Array<{
2973+
type?: string;
2974+
role?: string;
2975+
id?: string;
2976+
call_id?: string;
2977+
phase?: string;
2978+
encrypted_content?: string;
2979+
summary?: unknown;
2980+
}>;
2981+
};
2982+
2983+
expect(params).not.toHaveProperty("store");
2984+
const reasoningItem = params.input?.find((item) => item.type === "reasoning");
2985+
expectRecordFields(reasoningItem, {
2986+
type: "reasoning",
2987+
summary: [],
2988+
});
2989+
expect(reasoningItem?.id).toBeUndefined();
2990+
expect(reasoningItem).not.toHaveProperty("encrypted_content");
2991+
const assistantMessage = params.input?.find(
2992+
(item) => item.type === "message" && item.role === "assistant",
2993+
);
2994+
expectRecordFields(assistantMessage, {
2995+
type: "message",
2996+
role: "assistant",
2997+
phase: "commentary",
2998+
});
2999+
expect(assistantMessage?.id).toBeUndefined();
3000+
const functionCall = params.input?.find((item) => item.type === "function_call");
3001+
expectRecordFields(functionCall, {
3002+
type: "function_call",
3003+
call_id: "call_abc",
3004+
});
3005+
expect(functionCall?.id).toBeUndefined();
3006+
});
3007+
28983008
it("preserves Responses replay item ids when a store-enabled wrapper requests replay", () => {
28993009
const params = buildOpenAIResponsesParams(
29003010
{

src/agents/openai-transport-stream.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2095,7 +2095,8 @@ export function buildOpenAIResponsesParams(
20952095
const payloadPolicy = resolveOpenAIResponsesPayloadPolicy(model, {
20962096
storeMode: "disable",
20972097
});
2098-
const policyAllowsReplayIds = payloadPolicy.explicitStore !== false;
2098+
const policyAllowsReplayIds =
2099+
payloadPolicy.explicitStore !== false && !payloadPolicy.shouldStripStore;
20992100
const replayResponsesItemIds =
21002101
!isNativeCodexResponses && (options?.replayResponsesItemIds ?? policyAllowsReplayIds);
21012102
const messages = convertResponsesMessages(

src/llm/providers/stream-wrappers/openai.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -397,9 +397,11 @@ export function createOpenAIResponsesContextManagementWrapper(
397397

398398
const originalOnPayload = options?.onPayload;
399399
const replayResponsesItemIds =
400-
policy.explicitStore === undefined
401-
? (options as OpenAIResponsesReplayOptions | undefined)?.replayResponsesItemIds
402-
: policy.explicitStore;
400+
policy.explicitStore === true
401+
? true
402+
: policy.explicitStore === false || policy.shouldStripStore
403+
? false
404+
: (options as OpenAIResponsesReplayOptions | undefined)?.replayResponsesItemIds;
403405
const nextOptions: OpenAIResponsesReplayOptions = {
404406
...options,
405407
...(replayResponsesItemIds === undefined ? {} : { replayResponsesItemIds }),

0 commit comments

Comments
 (0)