fix(OpenAI Responses/provider): skip Responses item id replay when store support is stripped#89729
fix(OpenAI Responses/provider): skip Responses item id replay when store support is stripped#89729snowzlm wants to merge 4 commits into
Conversation
|
Codex review: needs maintainer review before merge. Reviewed June 3, 2026, 11:28 AM ET / 15:28 UTC. Summary PR surface: Source +3, Tests +137. Total +140 across 4 files. Reproducibility: yes. Source inspection shows current main can resolve shouldStripStore: true while still defaulting replay ids on because the replay gate only checks explicitStore !== false; the PR body also supplies before/after terminal output and a local backend smoke, though I did not run tests in this read-only review. Review metrics: none identified. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Next step before merge
Security Review detailsBest possible solution: Land this focused fix after normal maintainer review and required checks; keep the linked follow-up issue open until the merge closes it. Do we have a high-confidence way to reproduce the issue? Yes. Source inspection shows current main can resolve shouldStripStore: true while still defaulting replay ids on because the replay gate only checks explicitStore !== false; the PR body also supplies before/after terminal output and a local backend smoke, though I did not run tests in this read-only review. Is this the best way to solve the issue? Yes. The best fix is to use the existing payload policy at the two replay handoff points; provider-specific branching or stripping ids inside conversion would be a less direct owner boundary. AGENTS.md: found and applied where relevant. Codex review notes: model gpt-5.5, reasoning high; reviewed against d358294f897c. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source +3, Tests +137. Total +140 across 4 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
|
|
@clawsweeper Re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
|
@clawsweeper Re-review |
|
🦞👀 Command router queued. I will update this comment with the next step. Re-review progress:
|
Summary
What problem does this PR solve?
store=false) or store support is stripped because a custom OpenAI Responses-compatible provider declarescompat.supportsStore=false.Follow-up issue:
Why the previous main fix was not enough
03dec8bb3a00209780d3140ec3f10ad0eb069030is included in currentmain, but currentmainstill allows replay for this custom-provider path:In that path, the payload policy has:
explicitStore === undefinedshouldStripStore === trueCurrent
mainstill uses:Because
undefined !== falseistrue, stale Responses item ids can still be replayed even though store support has been stripped.This PR adds the missing
shouldStripStoregate and ensures wrapper-created options disablereplayResponsesItemIdswhen the effective payload is storeless.Real behavior proof
Behavior or issue addressed: Custom OpenAI Responses-compatible providers that strip Responses store support must not replay prior store-backed Responses item ids. Before this fix, current
mainstill replays stalereasoning,message, andfunction_callitem ids in that storeless path. After this fix, those ids are omitted while the toolcall_idremains available for stateless tool-result linking.Real environment tested: Real local OpenClaw checkout on Linux, updated to latest upstream
mainand this PR branch. Latest upstreammainwased4c4afc0f6e6ce455bafcd3a2d4857fd1ebc778; updated PR branch wasce91ed58658c11c875055ee252c7e6f755cc7cba. The provider in the repro is a generic custom OpenAI Responses-compatible provider only:provider: "custom-openai-responses",baseUrl: "https://custom.example.com/v1",compat: { supportsStore: false, supportsPromptCacheKey: false }.Exact steps or command run after this patch: Ran a Node/tsx source-level payload capture in the real checkout. The repro creates prior assistant
reasoning,message, andfunction_callentries with old Responses idsrs_prior,msg_prior, andfc_prior, then callsbuildOpenAIResponsesParamsfor the generic custom OpenAI Responses-compatible provider withcompat.supportsStore=false. The same command was run against latest upstreammainand against this updated PR branch.Observed result after fix: Latest upstream
mainincludes prior item ids in the outgoing storeless payload (hasAnyPriorReplayId=true,safeForStorelessReplay=false). This PR branch omits those prior item ids (hasAnyPriorReplayId=false,safeForStorelessReplay=true) while preservingcall_id: "call_abc".Evidence after fix: Terminal output from the real checkout source-level reproduction:
Focused tests and CI evidence after fix: GitHub Actions was run first on this PR head (
ce91ed58658c11c875055ee252c7e6f755cc7cba) via workflow dispatch: https://github.com/snowzlm/openclaw/actions/runs/26872539403. The relevant shards completed successfully:checks-node-agentic-agents-core-runtimeandchecks-node-agentic-agents-embedded. The overall CI run is red only becausebuild-artifacts / Check Control UI i18nfailed, which is unrelated to this OpenAI Responses replay/store policy change.Focused local confirmation also passes in a constrained environment using the repo scoped Vitest configs plus
OPENCLAW_VITEST_INCLUDE_FILE, so each run only loads the target file:Commands used:
Local Responses-compatible proxy backend smoke after fix: Added a redacted local backend-acceptance smoke in the real PR checkout. The smoke starts a local
POST /v1/responsesHTTP server that behaves like a storeless Responses-compatible backend: it rejects follow-up payloads that replay prior Responses item ids (rs_prior,msg_prior,fc_prior) and accepts payloads that omit those ids while preserving the stateless toolcall_id.The smoke uses the same generic custom provider shape as the PR proof (
provider: "custom-openai-responses",baseUrl: "https://custom.example.com/v1",compat.supportsStore=false) and does not use or disclose any real custom provider endpoint.Observed redacted backend result:
{ "smoke": "local Responses-compatible proxy backend acceptance", "prHead": "ce91ed58658c11c875055ee252c7e6f755cc7cba", "provider": "custom-openai-responses", "configuredBaseUrl": "https://custom.example.com/v1", "localEndpoint": "http://127.0.0.1:<redacted>/v1/responses", "negativeControl": { "status": 400, "accepted": false, "inspection": { "itemCount": 5, "replayedPriorIds": ["rs_prior", "msg_prior", "fc_prior"], "hasAnyPriorReplayId": true, "callIds": ["call_abc", "call_abc"], "hasStatelessToolCallId": true, "storeField": null } }, "fixedBranch": { "status": 200, "accepted": true, "responseStatus": "completed", "inspection": { "itemCount": 5, "replayedPriorIds": [], "hasAnyPriorReplayId": false, "callIds": ["call_abc", "call_abc"], "hasStatelessToolCallId": true, "storeField": null } }, "pass": true }This directly exercises the remaining backend-acceptance gap: the local Responses-compatible backend rejects stale replay ids, then accepts the fixed follow-up turn from the PR branch because prior Responses item ids are absent and the stateless
call_idis preserved.What was not tested: No real custom provider endpoint is used or disclosed in this PR body or evidence. The repro and focused tests stay on the generic custom OpenAI Responses-compatible provider path (
provider: "custom-openai-responses",baseUrl: "https://custom.example.com/v1").Tests
buildOpenAIResponsesParamsbehavior when custom Responses routes strip store support.replayResponsesItemIdswhen custom Responses routes strip store support.checks-node-agentic-agents-core-runtimeandchecks-node-agentic-agents-embeddedpassed. The only overall CI failure was unrelatedbuild-artifacts / Check Control UI i18n.OPENCLAW_VITEST_INCLUDE_FILE.400), while the PR branch follow-up payload was accepted (200 completed) with no prior Responses item ids and preserved statelesscall_id.mainis unsafe and this branch is safe for the generic custom OpenAI Responses-compatible provider case.