Preserve optional function arguments with explicit non-strict schemas.
Send stable session and thread identities, retain routing state through
one user turn and dispose it on completion or cancellation.
Compress Codex OAuth request bodies with zstd when supported, retaining
readable request audit data and a local compatibility opt-out without
replaying submitted requests.
Validation: 352 focused offline API/provider tests passed. The real query
loop regression covers tool continuation, next-turn reset and cleanup.
Selected repository verification passed with mocked transports.
Normalize a terminal API version at Anthropic request boundaries while
preserving gateway prefixes and saved provider settings. Cover SDK messages,
token counting, proxy streams, connectivity, titles, files, and recovery CLI.
Fixes#1279
Adapt structured policy-error handling and Astra model metadata from sub2api's recent compatibility updates. Preserve rejection codes through HTTP and SSE, stop retry and non-streaming replay, and add Astra's effective context to the official runtime.
Reference: https://github.com/Wei-Shaw/sub2api/pull/6636 and https://github.com/Wei-Shaw/sub2api/pull/6572. Implementation uses the existing TypeScript runtime and local regression harnesses.
Add grok-4.6 to the bundled fallback catalog with specs from the live
/v1/models endpoint (500k context, high default effort, xhigh..low
effort levels) and make it the default main model for the Grok Official
provider.
Load the authenticated Codex model catalog with a bundled fallback and carry model-native reasoning effort through the OpenAI OAuth transport. Keep desktop effort choices aligned with each model's advertised capabilities.
Constraint: Ultra remains a composite Codex delegation mode and is not exposed as a wire-level effort.
Confidence: high
Scope-risk: moderate
Tested: bun run check:server; bun run check:desktop; bun run check:persistence-upgrade; focused OAuth, WebSocket, and browser smoke checks
Not-tested: bun run verify
Refs: #896, #953
Make provider network proxy mode explicit so desktop sidecar system proxy env does not affect provider connectivity tests or OpenAI-compatible proxy requests unless System proxy is selected.
Tested: bun test src/server/__tests__/network-settings.test.ts src/server/__tests__/providers.test.ts src/server/__tests__/proxy-network-settings.test.ts
Tested: cd desktop && bun run test -- src/stores/settingsStore.test.ts src/__tests__/generalSettings.test.tsx --run
Tested: bun run check:server
Tested: cd desktop && bun run lint
Tested: cd desktop && bun run build
Confidence: high
Scope-risk: moderate
Add a provider-level disableExperimentalBetas setting that writes CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1 into managed provider runtime env, keeps stale parent env isolated, and exposes the toggle in desktop provider settings.
Tested: bun test src/server/__tests__/provider-runtime-env.test.ts --test-name-pattern "experimental betas|stale proxy"
Tested: bun test src/server/__tests__/providers.test.ts --test-name-pattern "experimental betas|POST /api/providers should create a provider|PUT /api/providers/:id should update a provider"
Tested: bun test src/server/__tests__/conversation-service.test.ts --test-name-pattern "experimental beta kill switch"
Tested: cd desktop && bun run test -- --run src/__tests__/generalSettings.test.tsx -t "experimental beta headers|Tool Search"
Tested: cd desktop && bun run test -- --run src/lib/__tests__/providerSettingsJson.test.ts
Tested: bun run check:server
Tested: cd desktop && bun run build
Not-tested: bun run verify
Confidence: high
Scope-risk: moderate
Provider connectivity tests now pass the actual upstream URL and loopback no-proxy rules into proxy fetch option resolution, including IPv6 loopback. This closes the local test/connectivity gap in the #896 proxy compatibility work without closing GitHub issues before release.
Tested: bun test src/utils/proxy.test.ts src/server/__tests__/providers.test.ts src/server/__tests__/network-settings.test.ts src/services/api/client.test.ts
Tested: bun run check:server
Not-tested: Windows dev-sidecar real-machine retest and release build confirmation for #896.
Confidence: medium
Scope-risk: narrow
Add per-model 1M capability flags for custom providers and persist them through provider settings.
When a model is marked as 1M-capable, runtime env uses the local [1m] marker and the desktop form auto-fills a 1000000-token context window when needed.
Tested: bun test src/server/__tests__/providers.test.ts -t "custom providers can mark main and role models as 1M-capable"
Tested: cd desktop && bun run test -- generalSettings.test.tsx -t "normalizes blank model mappings|saves 1M model declarations"
Tested: bun run check:desktop
Tested: bun run check:server
Not-tested: bun run verify / coverage gates were not run for this scoped local handoff.
Confidence: high
Scope-risk: moderate
Add a provider-level Tool Search capability that defaults on for native Anthropic Messages providers and writes ENABLE_TOOL_SEARCH through the managed provider env path. Keep OpenAI proxy formats opted out because the proxy transforms do not support Anthropic tool_reference history yet.
Preserve upgrade safety by normalizing missing or stringly typed stored values instead of dropping saved providers.
Tested: bun test src/server/__tests__/provider-runtime-env.test.ts src/server/__tests__/providers.test.ts
Tested: cd desktop && bun run test -- src/__tests__/generalSettings.test.tsx --run
Tested: cd desktop && bun run lint
Tested: bun run check:server
Confidence: high
Scope-risk: moderate
Persist runtime provider metadata for desktop sessions so context estimates stay tied to the provider that launched the session. Infer a unique saved provider window for older sessions without runtime metadata, and keep Xiaomi MiMo custom providers on thinking-only capability mapping instead of max-effort passthrough.
Tested: bun test src/server/__tests__/conversations.test.ts -t "unique saved provider context window|pass the active provider id|provider model context windows"
Tested: bun test src/server/__tests__/providers.test.ts -t "Xiaomi MiMo custom providers|custom providers declare|model context windows"
Tested: bun test src/server/__tests__/sessions.test.ts src/server/__tests__/searchService.sessions.test.ts src/server/__tests__/ws-memory-events.test.ts
Tested: cd desktop && bun run test -- src/stores/chatStore.test.ts src/stores/providerStore.test.ts src/components/controls/ModelSelector.test.tsx
Not-tested: full bun run verify was not run for this local issue handoff.
Confidence: high
Scope-risk: moderate
Render provider settings through dnd-kit sortable rows, include official providers in the same order model, and persist providerOrder across server and desktop state.
Tested:
- bun test src/server/__tests__/providers.test.ts src/server/__tests__/persistence-upgrade.test.ts
- cd desktop && bun run test -- --run src/stores/providerStore.test.ts src/__tests__/generalSettings.test.tsx -t "providerStore reorderProviders|Settings > Providers tab"
- cd desktop && bun run lint
- cd desktop && bun run build
- bun run check:persistence-upgrade
Not-tested:
- bun run check:server (broad suite hit environment failures during this run: MCP stdio zshrc timeout, adapter dependency gap at the time, and e2e cascade)
Confidence: high
Scope-risk: moderate
Strip the rotating billing attribution line before converting system
prompts to OpenAI Chat/Responses requests, forward a stable
prompt_cache_key derived from the client session, request stream usage
explicitly on Chat streams, and map cached_tokens back to Anthropic
cache_read_input_tokens with exclusive input accounting.
Tested:
- cd desktop && bun run test -- --run src/pages/TraceList.test.tsx
- bun test src/server/__tests__/trace-capture.test.ts
- bun run check:desktop
- bun run check:server
Scope-risk: broad
Ensure custom OpenAI-compatible provider tests explicitly request non-stream responses for both direct connectivity checks and the proxy pipeline. This avoids default SSE responses being parsed as empty JSON by provider validation.
Tested: bun test src/server/__tests__/providers.test.ts --test-name-pattern "requests non-stream OpenAI Chat responses during provider tests"
Tested: bun test src/server/__tests__/providers.test.ts
Tested: bun test src/server/__tests__/proxy-transform.test.ts
Tested: bun run check:server
Confidence: high
Scope-risk: narrow
Provider connectivity checks and proxy validation are API boundaries, but they kept the user-facing context suffix in the model id while the chat runtime already strips it. Normalize these paths so MiMo-style models with [1m] test the same model that sessions send.
Constraint: [1m]/[2m] are client-side context markers and upstream APIs may reject them
Rejected: Strip suffixes when saving provider config | would change the user-visible model selection instead of only the API boundary
Confidence: high
Scope-risk: narrow
Directive: Keep all provider API boundaries aligned with normalizeModelStringForAPI before sending requests upstream
Tested: bun test src/server/__tests__/providers.test.ts --test-name-pattern "normalizes context-window suffixes"
Tested: bun test src/server/__tests__/providers.test.ts
Tested: bun run check:server
Tested: git diff --check
Not-tested: Live MiMo API call; no provider credential was used
Related: #620
DeepSeek's OpenAI-compatible chat schema accepts text content rather than OpenAI vision content parts, so forwarding Anthropic image blocks as image_url makes the upstream reject the request before the model can answer. Keep normal OpenAI Chat vision behavior as the default, but switch known DeepSeek-compatible chat proxy requests to a text-only conversion that preserves prompt text and replaces image payloads with a small omission marker.
Constraint: DeepSeek official Chat Completions docs list user message content as string text, while its Anthropic compatibility table marks image blocks as not supported.
Rejected: Expand unsupported-image error string matching only | it still surfaces the first turn as an API error and depends on provider wording.
Confidence: high
Scope-risk: narrow
Tested: bun test src/server/__tests__/proxy-transform.test.ts
Tested: bun test src/server/__tests__/providers.test.ts --test-name-pattern "handleProxyRequest|omits image_url"
Tested: bun test src/services/api/errors.test.ts tests/mediaRecoveryAndEstimation.test.ts
Tested: bun run check:server
ChatGPT Official runs through Codex OAuth, so context accounting should follow
the Codex model catalog and its effective context window instead of public API
limits. This keeps GPT-5.5 at the same usable window shown by Codex while
preserving GPT-5.4's larger Codex window.
Constraint: Codex OAuth model metadata applies effective_context_window_percent to raw catalog windows
Rejected: Use public API GPT-5.5 1.05M context | Codex app and OAuth runtime clamp this model to the smaller effective window
Confidence: high
Scope-risk: narrow
Directive: Keep ChatGPT Official context values aligned to Codex model catalog behavior, not generic OpenAI API docs
Tested: bun test src/services/openaiAuth/models.test.ts src/services/compact/autoCompact.test.ts src/server/__tests__/providers.test.ts
Tested: bun run check:server
Tested: git diff --check
Not-tested: Manual desktop screenshot after rebuilding the app
The worktree implementation adds one General settings surface for AI request timeout and proxy configuration. This merge keeps main's newer attribution-signing and ChatGPT Official provider paths while preserving the unified network override across CLI sessions, provider checks, and OpenAI-compatible proxy forwarding.
Constraint: Main had newer attribution and official-provider changes touching the same server integration points
Rejected: Prefer the worktree proxy body verbatim | it would drop main's signed CCH attribution wrapper
Rejected: Keep provider preset timeouts above General | it would violate the single timeout control requirement
Confidence: high
Scope-risk: moderate
Directive: General network settings must remain the final AI request timeout and proxy override for every provider protocol
Tested: bun test src/server/__tests__/conversation-service.test.ts src/server/__tests__/network-settings.test.ts src/server/__tests__/providers.test.ts src/server/__tests__/proxy-network-settings.test.ts
Tested: cd desktop && bun run test -- --run src/stores/settingsStore.test.ts src/__tests__/generalSettings.test.tsx
Not-tested: Full bun run verify after resolving main merge conflicts
Local main added desktop branch-from-chat, attribution headers, sidecar packaging changes, and provider model normalization. The merge keeps those mainline changes while preserving ChatGPT Official provider metadata, OpenAI OAuth runtime env, provider-load guards, and model catalog behavior.
Constraint: Current worktree was detached; created feat/chatgpt-official-oauth-provider before merging to preserve the OAuth commit line.
Rejected: Rebase the OAuth line over main | the branch already contains many reviewed commits and a merge makes the integration point explicit.
Confidence: high
Scope-risk: moderate
Tested: bun test src/server/__tests__/providers.test.ts src/server/__tests__/settings.test.ts src/server/__tests__/conversation-service.test.ts src/server/__tests__/proxy-transform.test.ts src/utils/__tests__/providerManagedEnvCompat.test.ts src/services/api/client.test.ts src/services/openaiAuth/fetch.test.ts src/server/__tests__/haha-openai-oauth-service.test.ts src/server/__tests__/haha-openai-oauth-api.test.ts
Tested: cd desktop && bun run test -- src/__tests__/generalSettings.test.tsx src/components/settings/ChatGPTOfficialLogin.test.tsx src/stores/providerStore.test.ts src/components/controls/ModelSelector.test.tsx --testNamePattern "ChatGPT|OpenAI OAuth|Providers tab|ChatGPTOfficialLogin|ModelSelector|providerStore"
Tested: git diff --cached --check
Provider-managed environments should preserve Claude attribution only when the selected model is actually Claude-prefixed. Non-Claude provider models now disable the attribution header so third-party providers do not inherit Claude-specific prompt metadata.
Constraint: Claude model detection is intentionally model-name based to match the requested provider policy.
Rejected: Remove attribution headers globally | official Claude-prefixed models should keep existing behavior.
Confidence: high
Scope-risk: moderate
Directive: Do not broaden this policy without live provider request-shape verification.
Tested: Targeted server, provider, settings, cron, and managed-env tests in prior verification pass.
Not-tested: Full verify gate after this commit.
Settings General now owns AI request timeout and proxy policy so Anthropic-native and OpenAI-compatible provider paths share one user-visible control. The desktop UI persists the network settings, the server proxy and provider checks read them directly, and CLI sessions receive the same timeout/proxy environment.
Constraint: Provider request behavior must be consistent across Anthropic, OpenAI Chat, and OpenAI Responses formats
Rejected: Keep preset API_TIMEOUT_MS precedence | it would make the General timeout control unreliable for some providers
Confidence: high
Scope-risk: moderate
Directive: Do not add protocol-specific AI request timeout controls without preserving General as the final override
Tested: bun test src/server/__tests__/conversation-service.test.ts src/server/__tests__/network-settings.test.ts src/server/__tests__/providers.test.ts src/server/__tests__/proxy-network-settings.test.ts
Tested: cd desktop && bun run test -- --run src/stores/settingsStore.test.ts src/__tests__/generalSettings.test.tsx
Tested: bun run check:desktop
Tested: bun run check:server
Not-tested: socks5 manual proxy support; manual proxy validation currently accepts HTTP/HTTPS URLs only
Provider presets and custom entries can leave haiku, sonnet, or opus blank when the main model is the intended fallback. Normalize those mappings at both the Settings UI and ProviderService boundaries so persisted provider config and generated runtime env stay consistent.
Constraint: Users may configure only a main model for custom providers.
Rejected: Keep blank secondary model slots | runtime env would still receive empty ANTHROPIC_DEFAULT_* values.
Confidence: high
Scope-risk: narrow
Directive: Keep UI and ProviderService normalization aligned for provider model mapping changes.
Tested: Not run per maintainer request.
Not-tested: Local test suite skipped by request.
Activating the built-in ChatGPT provider now writes a dedicated OpenAI OAuth runtime environment instead of clearing provider state. The runtime points the CLI at the desktop-managed OpenAI token file, avoids Anthropic auth/base-url variables, reports auth from the OpenAI token file, and prevents Claude OAuth injection when ChatGPT Official is active.
Constraint: Default provider sessions read cc-haha managed settings, while session-scoped provider selections inject env directly from the desktop host.
Rejected: Treat ChatGPT Official as a generic OpenAI proxy provider | proxy routing would require API-key shaped auth and would leak it into the wrong runtime path.
Confidence: high
Scope-risk: moderate
Tested: bun test src/server/__tests__/providers.test.ts
Tested: bun test src/server/__tests__/conversation-service.test.ts
Tested: bun test src/services/openaiAuth/storage.test.ts src/server/__tests__/haha-openai-oauth-service.test.ts src/server/__tests__/haha-openai-oauth-api.test.ts
Tested: git diff --check
Switching from a saved provider to the built-in ChatGPT provider must remove previously managed Anthropic env without writing any OpenAI runtime env yet. This keeps Task 1 metadata-only while preventing stale provider settings from surviving the switch.
Constraint: Task 1 still must not write ChatGPT OAuth runtime env
Rejected: Return without touching settings.json | stale ANTHROPIC_* env survives from the previous provider
Confidence: high
Scope-risk: narrow
Tested: bun test src/server/__tests__/providers.test.ts --test-name-pattern "ChatGPT Official"
Tested: bun test src/server/__tests__/providers.test.ts
Tested: git diff --check
Task 1 should only persist the built-in provider selection. The generic managed env and proxy paths remain reserved for saved Anthropic-compatible providers until the dedicated OpenAI OAuth runtime is wired in a later task.
Constraint: Task 1 must not write managed provider env for openai-official
Rejected: Reuse buildManagedEnv for openai-official | writes placeholder Anthropic env before Task 3 runtime exists
Rejected: Return generic proxy config for openai-official | lets empty-key proxy resolution masquerade as a working runtime
Confidence: high
Scope-risk: narrow
Directive: Do not route openai-official through managed settings or generic proxy lookup until the dedicated OAuth runtime is implemented
Tested: bun test src/server/__tests__/providers.test.ts --test-name-pattern "ChatGPT Official"
Tested: bun test src/server/__tests__/providers.test.ts
Tested: bun run check:server
ChatGPT OAuth needs a stable built-in provider identity and a runtime kind that survives provider index normalization. This keeps normal saved providers unchanged while letting the desktop treat openai-official as an active provider without storing secrets in providers.json.
Constraint: providers.json migration must preserve activeId=openai-official even when providers[] is empty
Constraint: ChatGPT Official metadata must stay token-free in the provider index
Rejected: Treat ChatGPT Official as a normal openai_responses provider row | it would require persisting a fake saved provider and would still lose activeId during migration
Confidence: high
Scope-risk: narrow
Directive: Do not teach later OpenAI OAuth work to depend on providers[] containing the built-in provider
Tested: bun test src/server/__tests__/providers.test.ts --test-name-pattern "ChatGPT Official provider metadata"
Tested: bun test src/server/__tests__/providers.test.ts
Tested: cd desktop && bun run lint
Tested: git diff --check