Files
magpie/docs
yetone acdaa28aa1 codex: a conversation that searched the web declares cached search to the ChatGPT backend, so its compaction and turns aren't refused "response protection is unavailable" (#1270, #1099)
The ChatGPT backend answers HTTP 200 and only `event: error` "response
protection is unavailable" to any request whose input replays one of its
own web_search_call items while the request doesn't declare the web_search
tool. Probed on a real ChatGPT Pro account (gpt-6.1-sol, 2026-10-09) with
a real searched turn: refused with tools [], with function tools only and
with a compaction_trigger; answered once {"type":"web_search",
"external_web_access":false} is declared. A Responses Lite request refuses
a top-level web_search (400) but takes it in an additional_tools item. So
xjdata's case (Codex compacting a custom provider's conversation itself, a
plain /responses with tools [] that magpie's codexCompact never sees) failed
every time once the session had searched, and congee949's thread
descriptions too.

What changed:
- provider.DeclareSearch / declareSearch: when the input holds a
  web_search_call and nothing declares search, add cached-only web_search to
  the tools, or for Lite (header, reasoning.context all_turns, or an
  additional_tools item present) to the additional_tools item (prepended
  when there is none). With no tools offered, tool_choice becomes "none" so
  the model can't search; a forced choice is kept. Otherwise the body is
  unchanged (bytes untouched when no web_search_call is in it).
- codexBody (every ChatGPT account route: serveAgent, codexCompact, warmup,
  magpie's codex/* models) calls it; codexUpstreamOn calls it for Codex's
  own sign-in relayed to the backend's /responses.
- Not changed: siwc, API-key passthrough to api.openai.com, the legacy
  /responses/compact endpoint (no evidence they are refused so; not probed).
- docs/subsystems/gateway-routing.md names the cause and the fix.

Tests: internal/gateway/search_history_test.go replays the backend's real
items from that probe against a fake that refuses as the backend did.
TestSearchedConversationCompactsOnAnAccount, ...FunctionTools and
...OnCodexSignIn fail on the old code with "event: error"; ...CompactionTrigger
fails with "asked 2 times, not once". TestUnsearchedConversationUnchanged
and provider TestDeclareSearch cover what's left alone.

Run: gofmt -l (clean); go vet, GOOS=linux go vet -tags nogui, GOOS=windows
go vet -tags nogui on internal/provider and internal/gateway; HOME=<temp>
go test -tags nogui ./internal/provider ./internal/gateway (ok). Real
account, sandbox magpie on 127.0.0.1:3491 under a scratch HOME, replaying
the real searched history: old binary -> /v1/responses codex/gpt-6.1-sol
text compaction with tools [] and /backend-api/codex/responses (standard
and Lite compaction_trigger) all "response protection is unavailable";
new binary -> all response.completed, Lite with a compaction item.
Codex CLI 0.161.0 end to end was not done: on a custom provider it
offered no web_search tool, so no search could get into its history.
2026-10-09 22:40:53 +08:00
..