@oh-my-pi/pi-ai 17.4.2 → 18.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/CHANGELOG.md +41 -3350
  2. package/dist/types/auth-broker/wire-schemas.d.ts +68 -4
  3. package/dist/types/error/flags.d.ts +1 -0
  4. package/dist/types/index.d.ts +1 -0
  5. package/dist/types/providers/amazon-bedrock.d.ts +12 -0
  6. package/dist/types/providers/connect-error-detail.d.ts +14 -0
  7. package/dist/types/providers/cowork-fetch.d.ts +12 -1
  8. package/dist/types/providers/cursor.d.ts +14 -9
  9. package/dist/types/providers/openai-shared.d.ts +16 -8
  10. package/dist/types/providers/vision-guard.d.ts +17 -0
  11. package/dist/types/types.d.ts +10 -0
  12. package/dist/types/utils/event-stream.d.ts +12 -1
  13. package/dist/types/utils/glyph-codec.d.ts +22 -0
  14. package/dist/types/utils/proxy.d.ts +19 -0
  15. package/package.json +5 -5
  16. package/src/auth-broker/client.ts +37 -18
  17. package/src/auth-broker/discover.ts +10 -9
  18. package/src/auth-broker/server.ts +10 -5
  19. package/src/auth-broker/snapshot-cache.ts +28 -0
  20. package/src/auth-broker/wire-schemas.ts +402 -40
  21. package/src/auth-gateway/server.ts +2 -2
  22. package/src/error/auth-classify.ts +2 -1
  23. package/src/error/flags.ts +5 -3
  24. package/src/error/rate-limit.ts +1 -1
  25. package/src/index.ts +1 -0
  26. package/src/providers/amazon-bedrock.ts +55 -9
  27. package/src/providers/anthropic.ts +2 -0
  28. package/src/providers/connect-error-detail.ts +83 -0
  29. package/src/providers/cowork-fetch.ts +80 -29
  30. package/src/providers/cursor.ts +208 -48
  31. package/src/providers/devin.ts +70 -1
  32. package/src/providers/openai-codex-responses.ts +106 -51
  33. package/src/providers/openai-completions.ts +3 -3
  34. package/src/providers/openai-shared.ts +40 -9
  35. package/src/providers/pi-native-server.ts +3 -0
  36. package/src/providers/vision-guard.ts +37 -2
  37. package/src/stream.ts +44 -4
  38. package/src/types.ts +10 -0
  39. package/src/usage/cursor.ts +37 -30
  40. package/src/utils/event-stream.ts +24 -2
  41. package/src/utils/glyph-codec.ts +458 -0
  42. package/src/utils/glyph-notice.md +3 -0
  43. package/src/utils/proxy.ts +124 -8
  44. package/src/utils/thinking-loop.ts +33 -15
  45. package/dist/types/auth-broker/wire-schema-resource.d.ts +0 -53
  46. package/src/auth-broker/wire-schema-resource.ts +0 -487
package/CHANGELOG.md CHANGED
@@ -2,6 +2,46 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [18.0.1] - 2026-08-23
6
+
7
+ ### Changed
8
+
9
+ - Broker-backed startup no longer blocks on a broker round trip when the encrypted snapshot cache is fresh: the credential store starts from the cached snapshot and the background snapshot stream revalidates immediately (stale-while-revalidate). First launches and expired caches still fail fast with the actionable broker error.
10
+
11
+ ### Fixed
12
+
13
+ - Captured bounded Devin Connect trailer details and request-shape evidence for diagnosing intermittent `invalid_argument` stream rejections ([#4218](https://github.com/can1357/oh-my-pi/issues/4218)).
14
+ - Fixed abandoned `auth-broker-snapshot.enc.*.tmp` files accumulating in the cache directory when a process exited mid-write; stale temp files are now swept on each cache write.
15
+ - Fixed Cursor GPT effort models failing with `not_found` on accounts that require the discovered effort-specific model id ([#9287](https://github.com/can1357/oh-my-pi/issues/9287)).
16
+ - Fixed thinking-loop detection going silent after the first streamed tool call, so Grok/xAI reasoning loops that continue after a tool call starts still abort and retry instead of spinning until you press Esc.
17
+ - Fixed Codex continuations, retries, and compaction replacing or dropping the turn-scoped sticky-routing token ([#9277](https://github.com/can1357/oh-my-pi/issues/9277)).
18
+ - Fixed Codex Responses append chains falling back to full-context replay when replay-sanitized assistant items differ only by output-only IDs or lifecycle status.
19
+ - Fixed Cursor usage reporting “no usage data” for plans without a numeric legacy request cap.
20
+ - Fixed DeepSeek models rejecting requests with HTTP 400 `unknown variant \`image_url\`, expected \`text\`` when screenshots or image-producing tool results are present in conversation history or when `model.input` claims vision capability; `convertMessages` in `openai-completions` now strips `image_url` content parts and injects non-vision image placeholders for all DeepSeek endpoints.
21
+ - Fixed `PI_PROXY` covering only provider streams: OAuth token refresh and login, usage probes, and model discovery went out through the bare global `fetch` and ignored it, so a region-blocked token endpoint answered `403 Request not allowed` (Anthropic `/v1/oauth/token`) and disabled the credential while the proxied stream itself worked. `installGlobalProxyFetch()` now routes the process-wide `fetch` through `PI_PROXY`; a per-request proxy such as `PI_PROXY_<PROVIDER>` still wins, and loopback / private-range / `NO_PROXY` targets stay direct.
22
+ - Fixed Anthropic inference ignoring every proxy setting. `coworkFetch` runs on `node:https`, whose Bun shim discards both `agent.createConnection` and `options.createConnection`: the CONNECT tunnel to `PI_PROXY` was built, TLS-negotiated, then abandoned, and the request dialed `api.anthropic.com` on the default route (measured at the proxy: 581 bytes of handshake, zero request bytes). On a region-blocked egress that returned `403 {"type":"forbidden","message":"Request not allowed"}` with the proxy apparently configured. Proxied requests now go through Bun's own `fetch`, which honors `init.proxy`, trading the Cowork TLS/header profile for a proxy that actually carries the traffic; the dead tunnel plumbing is gone from the transport. `node:http2` (Cursor) does honor `createConnection` and is unaffected.
23
+ - Fixed `cowork-fetch` capturing `globalThis.fetch` at module load, so a proxy wrapper installed later in startup was ignored on its fallback path.
24
+ - Cursor Connect end-stream failures now surface bounded server trailer details instead of opaque generic errors ([#9137](https://github.com/can1357/oh-my-pi/pull/9137) by [@Mustaqeem66](https://github.com/Mustaqeem66))
25
+ - Fixed Cursor sessions aborting on the next turn or during compaction after MCP tools returned numeric-looking string arguments ([#9394](https://github.com/can1357/oh-my-pi/issues/9394)).
26
+ - Fixed glyph tokenization crashing with `entries is not a function` when `Context.systemPrompt` arrived as a bare string (e.g. from legacy earendil-works extensions); it is now normalized to an array before iterating, matching every provider path ([#9384](https://github.com/can1357/oh-my-pi/issues/9384)).
27
+
28
+ ### Added
29
+
30
+ - Added Amazon Bedrock Converse guardrail configuration with provider-scoped identifier, version, and trace settings.
31
+
32
+ ### Changed
33
+ ## [18.0.0] - 2026-08-22
34
+
35
+ ### Added
36
+
37
+ - Added reversible private-use glyph tokenization for Claude-compatible provider requests, including prompt notices, streamed response decoding, and safe handling of unresolved model-authored glyph tokens.
38
+
39
+ ## [17.4.3] - 2026-08-21
40
+
41
+ ### Fixed
42
+
43
+ - Fixed completed Anthropic turns remaining busy when the provider sent `message_stop` but kept the SSE connection open, which stranded tool execution and queued steering until timeout.
44
+
5
45
  ## [17.4.2] - 2026-08-21
6
46
 
7
47
  ### Added
@@ -1897,3353 +1937,4 @@
1897
1937
 
1898
1938
  - Removed the dead `iterateUntilAbort` helper (superseded by `iterateWithIdleTimeout`); it leaked the upstream iterator when the consumer abandoned mid-yield and had no production call sites.
1899
1939
 
1900
- ## [15.10.10] - 2026-06-09
1901
-
1902
- ### Added
1903
-
1904
- - Exported `wrapFetchForCch` so non-streaming OAuth callers (e.g. the web-search provider) can patch the Claude Code billing-header `cch` attestation into their request bodies instead of shipping the `cch=00000` placeholder.
1905
-
1906
- ### Fixed
1907
-
1908
- - Fixed an unbounded, zero-backoff Codex WebSocket reconnect loop on `websocket_connection_limit_reached`: the no-content reconnect path never consulted the retry budget and never waited, hammering the endpoint forever when the limit is account-scoped. Reconnects are now budgeted and delayed like every other WS retry path, falling back to a single SSE replay when exhausted.
1909
- - Fixed the Codex whitespace-loop breaker not observing degenerate frames that arrive after their item closed (or before it opened) — those frames count as stream progress, so the idle watchdogs never fired and the turn hung forever, which is exactly the failure mode the breaker exists for. Whitespace-loop recovery now also refuses to replay the turn once a `toolcall_end` was delivered, surfacing the error instead of re-emitting the same tool calls.
1910
- - Fixed the two remaining Codex retry paths (WS mid-stream reconnect and the empty-content SSE fallback) leaking blockless native output items (e.g. `web_search_call`) from the failed attempt into the replayed turn's `providerPayload` and append baseline.
1911
- - Fixed Codex WebSocket failure handling closing whatever connection currently occupies the session slot — including a concurrent caller's in-flight CONNECTING handshake, whose rejection (`websocket closed before open`) is classified fatal and disabled WebSockets for the whole session. Failure cleanup now skips CONNECTING sockets and the pool re-joins replacement handshakes (bounded).
1912
- - Fixed the Codex request transformer not repairing orphan `custom_tool_call_output` items (only `function_call_output` was folded into an assistant note) — a compaction splice that dropped an `apply_patch` call while keeping its result produced a hard 400 on the default GPT-5 Codex toolset.
1913
- - Fixed `processResponsesStream` finalizing reasoning items via a bare `itemId` content scan instead of the routed entry: with id-less reasoning items (local hosts), every `output_item.done` matched the FIRST thinking block — the second item's text clobbered it and the second block was never finalized or signed.
1914
- - Fixed `processResponsesStream` dropping tool calls and message text whose `output_item.added` event was lost (lossy proxies): `toolcall_end` was emitted with a dangling contentIndex while the call never entered `message.content`, so the agent loop silently never executed it. The done handler now synthesizes the missing block; still-open tool-call blocks are also final-parsed at `response.completed` so the `toolUse` override cannot hand the agent stale `{}` arguments.
1915
- - Fixed `response.incomplete` with `incomplete_details.reason: "content_filter"` being reported as a token-cap truncation (`stopReason: "length"`) — the agent loop's length recovery then asked the model to "shorten" a filtered prompt. Content-filtered turns now surface as errors; usage is also populated from `response.failed` events, and an unknown terminal status degrades to `"stop"` with a logged anomaly instead of throwing away a fully-streamed response.
1916
- - Fixed Copilot `premiumRequests` accounting being dropped from failed/cancelled responses: `populateResponsesUsageFromResponse` replaced `usage` wholesale and the error path threw before the success-path re-apply. The populate now preserves the field.
1917
- - Fixed `deduplicateToolCallIds` suffixing the whole composite Responses id (`callId|itemId`) — `normalizeResponsesToolCallId` extracts the first segment as the wire `call_id` at encode time, so both copies collapsed back onto one `call_id` and the request carried duplicate call/output pairs. The suffix and length budget now apply per segment.
1918
- - Gated native history payload replay on api + model id in both Responses providers: after a mid-session model switch, reasoning items carrying encrypted content minted by the previous model were replayed verbatim under the new model. Replay now falls back to block re-encode (which already strips foreign signatures), matching `transformMessages`' same-model trust rule.
1919
- - Fixed Azure OpenAI Responses requests omitting `store: false` while requesting `reasoning.encrypted_content` (stateless-only per OpenAI), replaying custom tool calls paired with mismatched `function_call_output` items (customCallIds was never threaded through), letting the SDK's internal retries (maxRetries 5) silently re-POST inside the explicit first-event deadline, and sending a `prompt_cache_key` when the caller opted out via `cacheRetention: "none"`.
1920
- - Fixed strict-pairing Responses backends (Azure, Copilot) silently discarding tool results whose call is absent from history — the result is now folded into an assistant note (same shape as orphan-output repair) so the model keeps the information.
1921
- - Fixed the OpenAI Responses first-event watchdog staying armed across the `onResponse` notification callback (a slow callback aborted an already-connected stream), Copilot transient-model retries re-attempting on an already-aborted signal (instant dead retry surfacing the scheduler's AbortError), Codex `reasoningSummary: null` being coerced to `"auto"` (the documented omit-summary contract was unreachable), nested Codex error codes (`response.error.code`) being invisible to the connection-limit/previous-response recovery matchers, and the session id leaking unredacted into `PI_CODEX_DEBUG` logs via the `x-client-request-id` header.
1922
- - Fixed `processResponsesStream` (shared by `openai-responses` and `azure-openai-responses`) ignoring the terminal `response.incomplete` event: a max-output-tokens-truncated response ended with `stopReason: "stop"`, zero usage, and no cost instead of `"length"` with the reported token counts. `response.incomplete` is now handled alongside `response.completed` and counts as stream progress for the idle watchdogs.
1923
- - Fixed custom tool-call content blocks keeping the transient `partialJson` accumulation buffer (and a potentially stale `arguments.input`) after `response.output_item.done` in the shared Responses stream processor — the function_call branch already cleaned these up.
1924
- - Fixed two OpenAI Codex stream-retry paths (whitespace-loop recovery and retryable provider errors) leaking native output items from the abandoned attempt into the replayed turn's `providerPayload` — stale reasoning items completed before the failure were re-sent as history input on subsequent requests alongside the retry's own items.
1925
- - Fixed the Codex WebSocket queue wiping already-received frames when a transport error arrived: a `response.completed` queued just before an eager server close was discarded, turning a finished response into a spurious `websocket closed` failure and a full request replay. Errors now append behind pending data frames.
1926
- - Fixed concurrent `getOrCreateCodexWebSocketConnection` callers (prewarm racing the first request) tearing down each other's in-flight handshake — closing a CONNECTING socket rejected the other caller with a fatal `websocket closed before open`, disabling WebSockets for the entire session. Callers now join the pending handshake.
1927
- - Stopped the Codex connection-limit recovery from replaying a turn over SSE after a `toolcall_end` had already been delivered to the consumer (`canSafelyReplayWebsocketOverSse` guard was bypassed, re-emitting the same tool calls); the error now surfaces instead.
1928
- - Extended the Codex whitespace-only argument-delta circuit breaker to `custom_tool_call_input.delta` frames, which counted as stream progress and could keep a degenerate response alive forever with no cap on buffer growth.
1929
- - Fixed Codex stream failures during transport open reporting a synthetic request dump (empty URL/body) instead of the real request, and a `response.created` event resetting the recorded time-to-first-token.
1930
- - Fixed the Codex WebSocket connect watchdog timer leaking (pinning the event loop for up to 10s) when the request signal aborted before or during the handshake.
1931
- - Fixed OpenRouter-hosted Anthropic adaptive reasoning models (Claude Fable/Mythos 5 and Opus 4.6+) so the catalog exposes `xhigh`; Fable/Mythos and Opus 4.7+ requests now map user `high`/`xhigh` onto OpenRouter's Anthropic `xhigh`/`max` effort scale.
1932
- - Fixed an unknown Anthropic `stop_reason` failing the whole turn after the response had fully streamed. `mapStopReason` threw on unrecognized values, and since the reason arrives on the trailing `message_delta` the error was unretryable — the live `model_context_window_exceeded` stop reason (default on Sonnet 4.5+) hit this path. It now maps to `length`, and any future unknown reason degrades to a logged anomaly plus a normal `stop` instead of an error.
1933
- - Stopped clamping API-key Anthropic requests to Claude Code's 64k output cap. The `CLAUDE_CODE_MAX_OUTPUT_TOKENS` clamp exists to match the OAuth wire fingerprint, but `buildParams` applied it unconditionally, silently halving the output budget of 128k-output models (e.g. Opus 4.8) for API-key callers. OAuth requests keep the clamp.
1934
- - Stopped a successful strict-tools fallback from shipping `errorMessage` on a `stopReason: "stop"` assistant message. After a grammar-too-large 400 triggered the non-strict retry, the original 400 text was kept on the final message even when the retry succeeded — consumers that treat `errorMessage` presence as failure (e.g. balance probes) misclassified the turn, and the stale text suppressed later refusal explanations. The fallback is now logged instead.
1935
- - Fixed model-supplied `User-Agent` headers being silently dropped on non-OAuth Anthropic requests. `enforcedHeaderKeys` filtered the header out of `modelHeaders` in every branch but only the OAuth branch set one back; the Cloudflare-gateway, bearer-gateway, and `X-Api-Key` branches now forward the caller's value verbatim.
1936
- - Stopped sending the `fast-mode-2026-02-01` beta header once a session has learned the endpoint+model rejects fast mode (`fastModeDisabled` provider state), matching the already-dropped `speed` param.
1937
- - Stopped `buildAnthropicHeaders` defaulting API-key requests onto the full Claude Code OAuth beta list (`oauth-2025-04-20`, `claude-code-20250219`, …). The `claudeCodeBetas` default is now OAuth-gated, matching the streaming path — the web-search header builder was the only caller hitting the default, so API-key search requests now carry just their own betas (e.g. `web-search-2025-03-05`). An empty `anthropic-beta` header is omitted entirely instead of being sent as an empty string.
1938
- - Fixed image-bearing `developer` messages being upgraded to mid-conversation `system` turns on Opus 4.8+/Fable/Mythos 5. System content is text-only on the wire, so a developer turn carrying image blocks in an upgrade-eligible position produced a 400; it now stays a `user` message.
1939
- - Fixed a spliced reconnect's second envelope overwriting the completed Anthropic message: `message_delta` was not gated by the terminal-stop flag (content events and duplicate `message_start` were), so the splice's `stop_reason`/usage replaced the finished turn's — a `tool_use` turn could be relabeled `stop`, and the harness then never executed the streamed tool calls. Post-terminal deltas are now logged as envelope anomalies and skipped.
1940
- - Fixed a `ping` arriving before `message_start` consuming the Anthropic first-event watchdog: the stall was then classified as a terminal mid-stream idle timeout instead of a retryable first-event timeout. Pings no longer count as the first item but still refresh the idle deadline once content is flowing.
1941
- - Fixed Anthropic-compatible proxies that omit `usage`/`delta` objects from `message_start`/`message_delta`/`content_block_*` envelopes crashing the turn with an unretryable `TypeError`; the missing payloads now degrade to logged envelope anomalies like every other malformed-frame case.
1942
- - Fixed `applyPromptCaching` placing `cache_control` on `thinking`/`redacted_thinking` blocks — Anthropic rejects that with a 400. A thinking-only assistant turn inside the trailing cache window (e.g. followed by the synthetic `Continue.` pad) no longer receives a breakpoint.
1943
- - Fixed consecutive `assistant` params reaching the wire when an empty user/developer turn between two assistant turns was dropped by the converter (e.g. an empty "nudge" submission after a length-truncated reply); Anthropic 400s on non-alternating assistant turns, and the broken triple replayed on every subsequent request. A `user: "Continue."` separator is now inserted, mirroring the trailing-prefill fallback.
1944
- - Fixed `supportsAdaptiveThinkingDisplay` misparsing bare dated Opus ids: `claude-opus-4-20250514` (Opus 4.0) parsed as minor `20250514` ≥ 4.7, which silently dropped the `interleaved-thinking-2025-05-14` beta for API-key Opus 4.0 requests.
1945
- - Fixed `output_config.effort` shipping without the `effort-2025-11-24` beta on thinking-off requests against adaptive-only Claude models (the effort:"low" pin), and the mid-conversation `system` role shipping without `mid-conversation-system-2026-04-07` on API-key and OAuth-utility requests; both betas are now added whenever the request can carry the corresponding field.
1946
- - Fixed GitHub Copilot anthropic-messages requests going out with no `Content-Type` and no `anthropic-version` header — the copilot branch builds its headers from scratch and Bun's fetch does not default `Content-Type` for string bodies. Both headers are now pinned to match every other branch.
1947
- - Fixed Anthropic client/provider retry multiplication: with the first-event watchdog disabled (`PI_STREAM_FIRST_EVENT_TIMEOUT_MS=0`), the client's internal `maxRetries: 5` reactivated and stacked with the provider loop's 3 retries — up to 24 wire attempts with double backoff. The provider now pins per-request `maxRetries: 0` unconditionally.
1948
- - Fixed `AnthropicMessagesClient` spreading `fetchOptions` after the core request fields, letting a caller-supplied `signal`/`method`/`body` silently disconnect the timeout controller or corrupt the request. Transport extras (TLS) still pass through; core fields now always win.
1949
- - Fixed Foundry mTLS/CA material being cached for the process lifetime when the env vars point at files: the cache key now folds in the file mtime so on-disk certificate rotation takes effect.
1950
- - Fixed the Claude Code fingerprint version drifting across surfaces: the usage endpoint (`claude-cli/2.1.160`) and OAuth bootstrap (`claude-code/2.1.160`) pinned a stale version while `/v1/messages` reported 2.1.165; both now derive from `claudeCodeVersion`.
1951
- - Fixed a system prompt that merely *mentions* `x-anthropic-billing-header:` mid-text suppressing the entire Claude Code system-block injection (billing header, instruction, and cch attestation); the resumed-session guard now anchors with `startsWith`.
1952
- - Fixed lone surrogates in cross-API tool-call arguments reaching Anthropic's strict UTF-8 validation: replayed OpenAI/Google-origin `tool_use.input` string leaves are now deep-sanitized with `toWellFormed()`, while same-API Anthropic arguments stay byte-identical to keep prompt-cache prefixes stable.
1953
- - Bounded the many-image resize fan-out to 4 concurrent decodes (it previously decoded every oversized image at once, two encode pipelines each — multi-GB transient memory at the 20+-image threshold that activates the feature).
1954
- - Fixed `mergeHeaders` merging case-sensitively on the Copilot/client-options path, where a miscased user-configured header (e.g. `authorization` next to the synthesized `Authorization`) survived as two keys that the `Headers` constructor joins comma-separated on the wire.
1955
- - Hardened the Anthropic stream lifecycle: prologue failures (e.g. a malformed Copilot credential in `buildCopilotDynamicHeaders`) and error-finalization failures now surface as an `error` event instead of an unhandled rejection that left `stream.result()` hanging forever; the spurious "cch billing placeholder not patched" warning no longer fires when the placeholder only appears in user content.
1956
-
1957
- ## [15.10.9] - 2026-06-09
1958
-
1959
- ### Added
1960
-
1961
- - Added `antigravityRankingStrategy` and registered it as the default `CredentialRankingStrategy` for `google-antigravity`, so multi-account selection consumes the per-counter Antigravity usage reports (sorted ascending by `remainingFraction` in `fetchAntigravityUsage`) before falling back to round-robin — preventing the exhausted-counter credential from being chosen first when an unblocked sibling has headroom ([#2187](https://github.com/can1357/oh-my-pi/issues/2187)).
1962
- - Added Claude Fable 5 to the first-party Anthropic catalog, seeded directly via `ANTHROPIC_CURATED_FALLBACK_MODELS` rather than waiting on models.dev (1M context / 128k output, adaptive thinking, $10/$50 per MTok). The model parser recognizes the `fable` kind so effort tiers (low→max), adaptive thinking, and Opus-4.7-style sampling restrictions apply; token limits and pricing are pinned in `applyAnthropicCatalogPolicy`.
1963
-
1964
- ### Fixed
1965
-
1966
- - Fixed `google-antigravity` not rotating to another stored OAuth account when Cloud Code Assist returns `429 You have exhausted your capacity on this model. Your quota will reset after …`. `parseRateLimitReason` matched the literal `capacity` before the `quota will reset` suffix and downgraded the failure to `MODEL_CAPACITY_EXHAUSTED` (45–75 s backoff), and `isUsageLimitError` returned false for the same message — so `markUsageLimitReached` was never invoked and the agent kept hammering the exhausted credential while the retry layer bailed on the multi-hour `retry-after`. Both paths now treat the Antigravity phrasing as `QUOTA_EXHAUSTED` / usage-limit, blocking the current credential until reset and letting the session pick an unblocked sibling ([#2187](https://github.com/can1357/oh-my-pi/issues/2187)).
1967
- - Fixed OpenRouter Anthropic chat-completions requests placing `cache_control` on empty assistant tool-call content. The cache marker now skips empty text and attaches to the most recent non-empty text part, avoiding HTTP 400 payloads with `{type:"text", text:"", cache_control:...}`.
1968
- - Fixed Fable-only Anthropic request shaping to cover Claude Mythos 5, and added Mythos 5 to the first-party Anthropic catalog seed. Adaptive display, sampling suppression, mid-conversation system messages, forced-tool-choice downgrade, and Bedrock adaptive metadata now handle both model families.
1969
- - Fixed adaptive-only Claude models (Opus 4.6+, Sonnet 4.6+, Fable/Mythos 5) returning HTTP 400 `"thinking.type.disabled" is not supported for this model` whenever thinking was turned off (utility calls and forced-tool turns route through the disable path). These models accept only `thinking.type: "adaptive"`; the request builder now omits the thinking field and pins the lowest adaptive effort instead of emitting `type: "disabled"`.
1970
- - Widened the OpenAI-completions first-event watchdog floor from 120s to 300s for DeepSeek V4 reasoning models hosted on the official DeepSeek API. The reasoner emits no SSE bytes until its private chain-of-thought finishes, which routinely takes longer than the generic 100s first-event budget under load — every chat then aborted with `OpenAI completions stream timed out while waiting for the first event` and silently retried. Mirrors the existing GLM coding-plan widening ([#2177](https://github.com/can1357/oh-my-pi/issues/2177)).
1971
-
1972
- ## [15.10.8] - 2026-06-09
1973
-
1974
- ### Added
1975
-
1976
- - Added optional `fetch` transport override (`fetch?: FetchImpl`) to Google, Ollama, and OpenAI-compatible model-manager options so dynamic model discovery and metadata lookups can use a caller-supplied HTTP client instead of only global `fetch`
1977
- - Added optional `fetch` on OAuth controller and API-key validation/login flows so token exchange, refresh, and device/PKCE login requests can be routed through a custom `fetch` implementation
1978
- - Added optional `fetch` support to usage polling context, allowing usage providers to execute usage checks using an injected HTTP client
1979
- - Added `AssistantMessage.upstreamProvider`, capturing the upstream provider an aggregator routed the request to (OpenRouter reports it via a top-level `provider` field on every chunk, e.g. `"Anthropic"`). Surfaced from the OpenAI-completions stream alongside `responseId`.
1980
-
1981
- ### Fixed
1982
-
1983
- - Fixed a degenerate OpenAI Codex stream (the model emits whitespace-only `function_call_arguments.delta` frames forever — commonly seen right after a `todo` tool call) terminating the turn with an error instead of recovering. The whitespace-loop circuit-breaker now (a) stops aborting the shared per-request `AbortController` — `requestSignal` is an `AbortSignal.any` over it, so aborting latched it and made every reopen on the reused `requestSetup` impossible — and (b) drops the half-built junk tool call and replays the request from scratch, bounded by `CODEX_WHITESPACE_LOOP_RETRY_LIMIT` (2). Sampling nondeterminism usually clears the loop on a fresh attempt; once the budget is exhausted the error is surfaced as before, but without the junk tool call polluting the message.
1984
- - Capped requested output tokens at 64k (`OPENAI_MAX_OUTPUT_TOKENS`, mirroring Anthropic's `CLAUDE_CODE_MAX_OUTPUT_TOKENS`) on OpenAI-family wires with a known upstream output cap — the `openai-completions` request builder (non-OpenRouter) and the shared responses sampling helper (`openai-responses`, `azure-openai-responses`). A model's catalog `maxTokens` often tracks its context window rather than the upstream's per-request output cap, so requesting the full ceiling 400'd (e.g. `z-ai/glm-4.7` asking for 131072 output exceeded the upstream's 131072-token *total* context). Output is now `min(requested, model.maxTokens, 64000)`.
1985
- - Stopped sending `max_tokens`/`max_completion_tokens` on OpenRouter (`openrouter.ai`) completions requests. OpenRouter filters out any upstream whose advertised output cap is below the requested `max_tokens`, so a value derived from the catalog (which reflects the highest-cap provider) silently excluded lower-cap upstreams — `provider.order: ["cerebras"]` for `z-ai/glm-4.7` fell through to DeepInfra because Cerebras's ~40k output cap is below the request, while `only: ["cerebras"]` (no fallback target) bypassed the filter and worked. Omitting the field lets each upstream self-cap and keeps provider routing (`only`/`order`) honored. Kimi via OpenRouter stays exempt — it derives TPM rate limits from `max_tokens`.
1986
-
1987
- ## [15.10.7] - 2026-06-08
1988
-
1989
- ### Fixed
1990
-
1991
- - Fixed first-party Anthropic requests returning HTTP 400 "Invalid `signature` in `thinking` block" after interrupting the model during its visible output. `transformMessages` stripped the signature from every `thinking` block of an `aborted`/`error` turn, including blocks that had already finished streaming — Anthropic delivers a block's signature at `content_block_stop` before the next block starts, so a thinking block followed by `text`/`tool_use` is fully signed. The valid signature was then replayed empty (`signature: ""`), which signature-enforcing Anthropic rejects, including when the provider is routed through an LLM gateway baseUrl. Only the single mid-stream block at the abort point is now treated as untrustworthy; completed thinking blocks keep their replayable signatures ([#2144](https://github.com/can1357/oh-my-pi/issues/2144)).
1992
- - Pinned a regression test against issue [#2123](https://github.com/can1357/oh-my-pi/issues/2123): OAuth requests to adaptive-thinking Claude Opus models (4.6+) ship a `context_management.edits[clear_thinking_20251015]` block paired with the `thinking` field, but the eager-todo prelude (and other paths that force `tool_choice` to `tool`/`any` on the first user turn) route through `disableThinkingIfToolChoiceForced`, which would strip `params.thinking` while leaving the orphan `context_management` behind. The Anthropic API then rejected the request with `400 ... clear_thinking_20251015 strategy requires thinking to be enabled or adaptive`. The fix that lands in [15.10.5] now drops both fields together; the new test locks the contract so the strategy can never outlive its enabling `thinking` payload again.
1993
- - Fixed Antigravity usage counters so exhausted Google/Gemini quota renders as `0% free` while separate Anthropic/OpenAI-backed Antigravity model counters remain visible independently, without replaying stale pre-fix cached usage reports.
1994
-
1995
- ## [15.10.6] - 2026-06-08
1996
-
1997
- ### Added
1998
-
1999
- - Added AIML API as an OpenAI-compatible provider preset with `AIMLAPI_API_KEY` discovery ([#2105](https://github.com/can1357/oh-my-pi/issues/2105)).
2000
-
2001
- ## [15.10.5] - 2026-06-08
2002
-
2003
- ### Breaking Changes
2004
-
2005
- - Renamed the OAuth subpath export `@oh-my-pi/pi-ai/utils/oauth` → `@oh-my-pi/pi-ai/oauth` (and `@oh-my-pi/pi-ai/utils/oauth/*` → `@oh-my-pi/pi-ai/oauth/*`, e.g. `oauth/types`, `oauth/callback-server`, `oauth/openai-codex`) after relocating the OAuth implementation out of `utils/oauth/` into `registry/oauth/`. The high-level OAuth API (`getOAuthProviders`, `refreshOAuthToken`, `getOAuthApiKey`, `registerOAuthProvider`, `unregisterOAuthProviders`, `getOAuthProvider`) and the `OAuth*` types stay exported from the package root, unchanged.
2006
-
2007
- ### Changed
2008
-
2009
- - Changed Anthropic retry handling to avoid retrying 4xx responses other than 408 and 429
2010
- - Optimized the Anthropic `cch` attestation patch to locate the billing-header placeholder with native `Buffer.indexOf` (memmem) instead of a hand-rolled byte loop. The marker sits ~99% through the body (`messages` serializes before `system`), so the old scan walked almost the entire payload; output bytes are unchanged but the patch is ~7.5x faster (563µs -> 75µs on a 1MB body).
2011
- - Refactored provider configuration to a single-source registry (`registry/`, renamed from `provider-registry/` with its `providers/` subdir flattened up). The `KnownProvider`/`OAuthProvider` type unions, `PROVIDER_DESCRIPTORS`, `DEFAULT_MODEL_PER_PROVIDER`, the `serviceProviderMap` env-key fallbacks, the `/login` provider list (`builtInOAuthProviders`), and the `refreshOAuthToken`/`AuthStorage.login` dispatch are all derived from it. Provider defs live directly under `registry/`; thin provider-specific login flows are inlined into the def file, while heavier provider-local OAuth flows and the shared OAuth flow infra (`callback-server`, `pkce`, `google-oauth-shared`, `types`, runtime `index`) now live together under `registry/oauth/` (previously split across `provider-registry/providers/oauth/` and `utils/oauth/`). The non-OAuth API-key paste/validation helpers (`api-key-login`, `api-key-validation`) sit beside the defs in `registry/`. Adding a provider that reuses an existing wire API is now one new provider def plus one registry entry in the common case. Exposes `PROVIDER_REGISTRY`, `getProviderDefinition`, `ProviderDefinition`, and `PASTE_CODE_LOGIN_PROVIDERS`.
2012
-
2013
- ### Fixed
2014
-
2015
- - Disabled OpenAI Codex Responses stream obfuscation by sending `stream_options.include_obfuscation=false`, reducing raw WebSocket/SSE debug noise and bandwidth.
2016
- - Interrupted OpenAI Codex Responses streams that emit long runs of whitespace-only tool-call argument deltas, preventing degenerate WebSocket/SSE responses from filling the raw stream buffer indefinitely.
2017
- - Preserved streaming responses when Anthropic emits unrecognized content_block envelopes by ignoring unknown blocks and continuing to emit known content
2018
- - Applied cache control to the most recent tool result block when building Anthropic OAuth payloads without a preceding text block, enabling ephemeral caching for tool-result-only messages
2019
- - Kept Anthropic sampling parameters (temperature, top_p, top_k) when thinking is explicitly disabled
2020
- - Fixed raw Anthropic SSE handling by parsing event frames with strict JSON parsing and matching event-type validation, surfacing malformed frames as stream errors instead of repairing them
2021
- - Fixed Anthropic stream envelope handling to reject duplicate `content_block_start` indexes and block deltas/stops for unopened blocks, preventing malformed envelope states from producing partial output
2022
- - Fixed Anthropic image conversion to normalize `image/jpg` to `image/jpeg` and emit a placeholder for unsupported image MIME types
2023
- - Fixed Anthropic thinking request preparation by clamping `max_tokens` to provider/model limits and adjusting thinking budgets to a valid value
2024
- - Fixed Anthropic request shaping around forced tool choice, unsigned thinking replay, prompt-cache marker placement, non-Anthropic bearer gateways, Foundry TLS loading, and strict tool-schema normalization so malformed or incompatible request payloads are rejected locally or shaped consistently before streaming
2025
- - Fixed the Anthropic stream parser shipping a truncated tool call as a completed turn. When a transport drop cut the SSE stream mid-`tool_use` and a transparent reconnect spliced a fresh message envelope onto the same stream, the duplicate `message_start` was deduped but the orphaned tool block — which never received its `content_block_stop` — survived in the assistant message with its seed `{}` (or partially-parsed) arguments. The terminal stop signal from the reconnect then let it flow through as a normal tool call, so e.g. a `read` dispatched with `{}` failed downstream validation (`path: expected string, received undefined`). The parser now treats any tool block left open at stream end as a truncated envelope and routes it through the existing retry/error path instead of emitting bogus arguments.
2026
- - Fixed the Zhipu Coding Plan login prompt advertising a misleading `sk-...` placeholder. Zhipu API keys are formatted `<id>.<secret>` (no `sk-` prefix), so the placeholder now matches the actual format instead of suggesting the wrong shape. ([#2106](https://github.com/can1357/oh-my-pi/issues/2106))
2027
- - Fixed Moonshot `kimi-k2.6` (and any future `kimi-k2.x`) discovered via `MOONSHOT_API_KEY` stalling on first turn with no output. The `moonshotModelManagerOptions` discovery mapper only marked ids containing `"thinking"` as `reasoning: true`, so dynamic `kimi-k2.6` entries fell through with `reasoning: false`; the openai-completions z.ai branch was then skipped and the request reached Moonshot with no `thinking` parameter at all. Moonshot K2.6 requires an explicit `thinking: {type}` field (the same native-API wire shape #1838 introduced `thinking.keep` for), so the server held the stream silently. The mapper now stamps `reasoning: true`, vision input, and default `thinking` metadata on every `kimi-k2.x` id, restoring the explicit `thinking: {type: "disabled"|"enabled"}` wire body the Moonshot endpoint expects. ([#2113](https://github.com/can1357/oh-my-pi/issues/2113))
2028
-
2029
- ## [15.10.4] - 2026-06-08
2030
-
2031
- ### Added
2032
-
2033
- - Added `anthropic-client-platform` (`desktop_app`) and `anthropic-client-version` (`1.11187.4`) headers to the Anthropic request fingerprint for OAuth sessions
2034
-
2035
- ### Changed
2036
-
2037
- - Changed non-built-in tool names sent to Anthropic from `proxy_` prefixing to `_` prefixing (for example `bash` to `_bash`) while built-in tool names remain unchanged
2038
- - Updated the Anthropic OAuth stealth fingerprint to track Claude Code 2.1.165: `claudeCodeVersion` bumped to `2.1.165` (flows into both the `cc_version` billing header and the `claude-cli/<version>` user-agent), `claudeCodeSystemInstruction` changed to `"You are a Claude agent, built on Anthropic's Claude Agent SDK."`, and the billing-header `cc_entrypoint` changed from `cli` to `local-agent`.
2039
- - Clamped the Anthropic request `max_tokens` to `Math.min(CLAUDE_CODE_MAX_OUTPUT_TOKENS, options.maxTokens || model.maxTokens)` (64k) so OAuth requests match Claude Code's requested output cap instead of sending the model's full ceiling (e.g. 128k for Opus 4.8).
2040
-
2041
- ## [15.10.3] - 2026-06-08
2042
-
2043
- ### Removed
2044
-
2045
- - Removed the synthetic `<turn-aborted>` developer guidance note that `transformMessages` injected after an aborted/errored assistant turn (and its `turn-aborted-guidance.md` prompt). The per-call synthetic `"aborted"` tool results already tell the model the turn's tools were terminated, so the extra "verify current state before retrying" note was redundant — and it biased the model toward second-guessing a deliberate user interrupt when the turn was resumed.
2046
- - Removed the legacy Anthropic first-user-message skip for `<system-reminder>` blocks now that synthetic reminders no longer travel as user messages.
2047
-
2048
- ## [15.10.2] - 2026-06-08
2049
-
2050
- ### Added
2051
-
2052
- - Added support for `impersonated_service_account` Application Default Credentials (ADC) in Vertex AI to enable chained impersonation without failing via 401 `invalid_client`.
2053
- - Added `AuthStorage.getCredentialOrigin(provider)` (returning a structured `CredentialOrigin` / `CredentialOriginKind`) and `getEnvApiKeyName(provider)`, so callers can render where a provider's auth comes from — runtime override, config, stored OAuth/api-key, env var (with the backing variable name), or fallback resolver — without parsing the prose of `describeCredentialSource`.
2054
-
2055
- ### Changed
2056
-
2057
- - Changed `onSseEvent` recording for OpenAI Responses, Azure OpenAI Responses, OpenAI Completions, and Anthropic stream providers to emit reconstructed SSE events from decoded SDK stream items instead of wrapping raw fetch responses
2058
- - Changed OpenAI Completions SSE diagnostics to include `event: "chat.completion.chunk"` in `onSseEvent` records for chunked responses
2059
- - Changed the default Anthropic model in `DEFAULT_MODEL_PER_PROVIDER` from `claude-sonnet-4-6` to `claude-opus-4-6`, so sessions that fall back to the provider default (no configured `default` role, no `--model`, no restored session) now start on Claude Opus 4.6.
2060
-
2061
- ### Fixed
2062
-
2063
- - Fixed duplicate upstream `tool_call_id` values collapsing distinct tool calls during message transformation, preserving one call/result pairing per emitted tool call before provider replay and keeping generated duplicate IDs distinct after OpenAI/Mistral wire-length caps. ([#2055](https://github.com/can1357/oh-my-pi/issues/2055))
2064
- - Fixed the Anthropic provider retrying persistent account usage/quota limits (e.g. `429 "This request would exceed your account's rate limit"`, `usage_limit_reached`) as if they were transient. Because the error text contains "rate limit", `isProviderRetryableError` matched it and the stream retry loop looped through its 2s/4s/8s backoff (then the `streamSimple` a/b/c policy re-minted the credential and ran the whole thing again) before surfacing the failure — even though the server's `retry-after` parked the account for minutes-to-hours. These errors are now recognized via `isUsageLimitError` and surfaced immediately to the credential-rotation layer, so e.g. `omp dry-balance --bench` reports a rate-limited account as failed at once instead of appearing to hang.
2065
- - Fixed MiniMax-compatible OpenAI-completions hosts losing tool-call argument content when `function.arguments` is streamed as an object across more than one delta. The accumulator added in #1776 wrote `block.partialArgs = rawArgs` per chunk, so every chunk but the last was overwritten — for an `edit` call this surfaced as a tail-slice of the patch text being applied (e.g. a single-line `replace 91..91:` body extending the deletion across the surrounding rows). Chunks are now shallow-merged; for shared string keys, `startsWith` distinguishes cumulative restatements (take the latest) from per-chunk-delta fragments (concatenate). Per-chunk `toolcall_delta` emission for the object branch is suppressed (the previous code emitted `JSON.stringify(rawArgs)` per chunk, which fed downstream concat consumers — `packages/agent/src/proxy.ts`, `openai-chat-server`, `openai-responses-server`, `anthropic-messages-server` — an invalid sequence like `{"input":"a"}{"input":"b"}`); the merged object is flushed instead as a single concat-safe delta in `finishToolCallBlock` before `toolcall_end`, so accumulators reconstruct the args correctly. The single-chunk shape covered by the existing #1776 regression test stays correct end-to-end. ([#2080](https://github.com/can1357/oh-my-pi/issues/2080))
2066
- - Fixed the OpenAI Responses compatibility server misrouting late `toolcall_delta` events for earlier parallel tool calls after a later `toolcall_start`. The encoder now keeps OpenFunctionCall state by content index, allocates output indexes at item start, and closes each tool item by its own `toolcall_end`, preserving deferred MiniMax object-argument flushes for the matching call. ([#2080](https://github.com/can1357/oh-my-pi/issues/2080))
2067
-
2068
- ## [15.10.1] - 2026-06-07
2069
-
2070
- ### Breaking Changes
2071
-
2072
- - Removed the `onAuthError` option from stream request options and shifted auth retry handling to resolver-based `apiKey` behavior, requiring callers using custom auth-retry hooks to migrate
2073
-
2074
- ### Added
2075
-
2076
- - Added `ApiKeyResolver` and `ApiKey` auth helpers, including `isApiKeyResolver`, `isAuthRetryableError`, `resolveApiKeyOnce`, and `withAuth`, and exported them from the package root
2077
- - Added support for a function-valued `apiKey` in `SimpleStreamOptions` so a single stream request can refresh or rotate credentials during retry
2078
- - Added `forceRefresh` credential option to `AuthStorage.getApiKey` and `rotateSessionCredential` support for session-level credential rotation after auth failures
2079
- - Added `AuthStorage.resolver(provider, options)` method that builds an `ApiKeyResolver` implementing the a/b/c auth-retry policy directly on the storage instance
2080
-
2081
- ### Changed
2082
-
2083
- - Changed gateway and stream auth flows to share the a/b/c retry policy, refreshing the same session credential first and then switching to a sibling credential on repeated auth failures
2084
-
2085
- ### Fixed
2086
-
2087
- - Fixed streaming auth retries to handle `401` and usage-limit errors before replay-unsafe content is emitted, including failures surfaced only via `errorStatus`
2088
- - Fixed tool argument validation to coerce singleton non-string values into arrays when the schema expects an array, preventing Anthropic-compatible models that emit `todo.ops` as an object from getting stuck in repeated validation-error loops. ([#2026](https://github.com/can1357/oh-my-pi/issues/2026))
2089
- - Fixed streaming retries to buffer and suppress partial `start` events from failed auth attempts so only clean retried events are delivered
2090
- - Fixed the HTTP 400 raw-request dumper (`appendRawHttpRequestDumpFor400`) littering the real `~/.omp/logs/http-400-requests` directory during tests. Provider suites exercise the 400 error path with mocked `fetch` responses, which the dumper could not distinguish from genuine failures; it now skips persistence under the Bun test runner (`isBunTestRuntime()`).
2091
- - Fixed Anthropic Opus requests unnecessarily forcing `tool_choice.disable_parallel_tool_use`, allowing Claude Opus to use the provider's default parallel tool-calling behavior again.
2092
- - Fixed parallel `function_call` items losing arguments against llama.cpp's OpenAI Responses endpoint (`/v1/responses`), where every call but the last finalized with `{}` and the agent rejected them with `path: Invalid input: expected string, received undefined`. llama.cpp's `to_json_oaicompat_resp` emits `output_item.added` with only `item.call_id` (no `item.id`, no `output_index`) while the matching `function_call_arguments.delta` carries `item_id: "fc_<call_id>"`. `processResponsesStream` now registers function-call and custom-tool-call items under `item.call_id` as a secondary lookup key (alongside `item.id`/`output_index`) so identifier-deviant hosts route deltas and done events to the right block. ([#2015](https://github.com/can1357/oh-my-pi/issues/2015))
2093
- - Fixed `PI_REQ_DEBUG` response recording truncating the captured body when a streamed response was cancelled mid-flight. The response tee in `wrapResponse` could call `FileRequestDebugResponseLog.close()` from both the `cancel` callback and the resumed `pull` (which observes `done` once the source reader is cancelled); the second caller saw the handle already nulled and returned before the first caller's pending write flushed, so the `.res.log` lost the already-buffered chunk. `close()` now memoizes its flush-and-close promise so every caller awaits the same completion.
2094
-
2095
- ## [15.10.0] - 2026-06-06
2096
-
2097
- ### Added
2098
-
2099
- - Added a dependency-free `@oh-my-pi/pi-ai/effort` module exporting the `Effort` enum and `THINKING_EFFORTS`, split out of `model-thinking` so hot-path consumers can import the thinking levels without pulling in `model-thinking` and its provider-compat dependency graph. The package barrel still re-exports both names, so existing imports are unaffected.
2100
-
2101
- ### Fixed
2102
-
2103
- - Fixed Antigravity usage provider emitting one bar per model instead of deduplicating by tier — a single account's 15+ model entries now collapse to one bar per tier, matching the shared-quota reality of the upstream API.
2104
- - Fixed Antigravity usage reports missing `email` and `accountId` in metadata, so the `/usage` display and the deduplicator can associate reports with their credentials.
2105
- - Fixed usage-report dedup ignoring `projectId` for Google Cloud providers, preventing duplicate credential entries from being recognized as the same account.
2106
- - Fixed Cloud Code Assist (Antigravity / Gemini CLI) rejecting the `github` tool with HTTP 400 when the `pr` parameter schema contained `anyOf: [string, array]`. The CCA mixed-type combiner collapse picked the first non-null type (`string`) but indiscriminately copied type-specific keys from variant branches — `items` from the array variant leaked onto the string-typed result, producing `{type: "string", items: {...}}` which Google's API rejects as invalid. The collapse now filters merged variant fields against the winning type's allowed key set. ([#2002](https://github.com/can1357/oh-my-pi/pull/2002))
2107
- - Fixed OpenAI Responses-family providers (Codex, OpenAI Responses, Azure Responses) rejecting requests with `400 No tool output found for function call …` after the user branched/navigated the session tree to a node that ends on a tool call (the tool-result child is dropped from the reconstructed history) or after a turn was aborted/crashed between the call streaming and its result persisting. The converters now synthesize a placeholder `function_call_output`/`custom_tool_call_output` immediately after any unpaired `function_call`/`custom_tool_call`, symmetric to the existing orphan-output repair, so the model still sees the call and can recover instead of the whole request 400ing.
2108
- - Fixed Anthropic-compatible reasoning endpoints losing prior-turn reasoning on continuation requests when they emit unsigned `thinking` blocks. `convertAnthropicMessages` treated unknown endpoints as signature-enforcing and demoted unsigned reasoning to `type: "text"`, which destabilized tool-call argument serialization on the next turn — the upstream symptom behind the `args?.ops?.map is not a function` crash reported against the `todo` tool. Official `api.anthropic.com` keeps the conservative text fallback; non-official `anthropic-messages` reasoning models now replay unsigned reasoning as native `type: "thinking"` ([#2005](https://github.com/can1357/oh-my-pi/issues/2005)).
2109
-
2110
- ## [15.9.67] - 2026-06-06
2111
-
2112
- ### Fixed
2113
-
2114
- - Fixed llama.cpp/OpenAI Responses parallel tool calls losing arguments when `function_call_arguments.done` events omit `output_index` and `item_id`, by routing those identifierless final-argument events through the open function calls in item order. ([#1970](https://github.com/can1357/oh-my-pi/issues/1970))
2115
- - Fixed local Ollama (`openai-responses`) turns failing with HTTP 400 `invalid reasoning value: "minimal"` when a discovered model ran with `minimal` (or `xhigh`) thinking. Ollama's OpenAI-compatible `reasoning.effort` only accepts `high|medium|low|max|none`, so discovered reasoning-capable Ollama models now carry a `compat.reasoningEffortMap` remapping `minimal → low` and `xhigh → max`; non-reasoning models are left untouched.
2116
-
2117
- ## [15.9.2] - 2026-06-05
2118
-
2119
- ### Added
2120
-
2121
- - Added an AES-256-GCM auth-broker snapshot cache module and `RemoteAuthCredentialStoreOptions.onSnapshot` so broker clients can persist broker-sourced full snapshots without blocking startup on every run.
2122
- - Added `Model.omitMaxOutputTokens` so providers (notably Ollama proxies fronting cloud catalogs) can suppress `max_output_tokens` (Responses) and `max_tokens`/`max_completion_tokens` (Completions) on the wire while still using the catalog `maxTokens` for local budgeting. Without it, `applyCommonResponsesSamplingParams` unconditionally sent the catalog cap and HTTP-400'd against upstream APIs whose true output limit was unknown to OMP. ([#1881](https://github.com/can1357/oh-my-pi/issues/1881))
2123
-
2124
- ### Changed
2125
-
2126
- - Changed usage-ranked OAuth credential selection to pick deterministic session-sticky weighted buckets instead of always choosing the top-ranked account, capping the best account at 2x the baseline session likelihood while keeping equal-priority accounts evenly balanced.
2127
-
2128
- ### Fixed
2129
-
2130
- - Fixed parallel `function_call` items on the OpenAI Responses API losing arguments on every call except the last when the upstream server interleaves their stream events (observed against llama.cpp and other local Responses-compat hosts). `processResponsesStream` no longer routes `function_call_arguments.{delta,done}`, `output_item.done`, content_part/text/refusal/reasoning events through a singleton `currentItem`/`currentBlock` reference; it now tracks every open item in registries keyed by `output_index` and `item_id` so each event is folded into the matching block and the emitted `toolcall_end` carries the correct `contentIndex`. ([#1880](https://github.com/can1357/oh-my-pi/issues/1880))
2131
-
2132
- ## [15.9.1] - 2026-06-04
2133
-
2134
- ### Added
2135
-
2136
- - Added regional Xiaomi Token Plan login/provider entries (`xiaomi-token-plan-sgp`, `xiaomi-token-plan-ams`, `xiaomi-token-plan-cn`) so `omp login` can store token-plan keys against the selected region. ([#1846](https://github.com/can1357/oh-my-pi/issues/1846))
2137
-
2138
- ### Fixed
2139
-
2140
- - Removed the `context-1m-2025-08-07` (1M long-context) beta from the Anthropic agent request headers, the OAuth model-discovery header, and the Claude usage-API header. Sending it caused subscription/OAuth requests without long-context credits to fail with `429 Usage credits are required for long context requests`, breaking Sonnet. The remaining betas are unchanged.
2141
- - Fixed Kimi K2.x `maxTokens` on Fireworks and Fire Pass (`fireworks/kimi-k2.5`, `fireworks/kimi-k2.6`, `firepass/kimi-k2.6-turbo`) being inherited from Fireworks `/v1/models` discovery (`max_completion_tokens: 65536`) rather than the published Kimi-on-Fireworks output budget, which let callers (and the openai-completions default-injection safety net) ship a budget the router cannot honor and made runaway reasoning traces more likely. The Fireworks resolver now clamps every Kimi K2.x id (public catalog ids and the canonical `accounts/fireworks/{models,routers}/kimi-k2…` wire form) to 32,768 output tokens, and the generator applies the same cap as a post-processing safety net so the `firepass` static fallback and the bundled `fireworks` entries stay in sync across regens. ([#1849](https://github.com/can1357/oh-my-pi/issues/1849))
2142
- - Fixed Xiaomi Token Plan MiMo OpenAI-compatible tool-call continuations omitting required `reasoning_content` replay. ([#1846](https://github.com/can1357/oh-my-pi/issues/1846))
2143
- - Fixed Anthropic prompt caching for OpenAI-compatible Claude proxies by honoring `compat.cacheControlFormat: "anthropic"` outside OpenRouter. ([#1845](https://github.com/can1357/oh-my-pi/issues/1845))
2144
- - Fixed Moonshot Kimi K2.6 silently pausing for many seconds between tool calls because the server discarded the `reasoning_content` that omp was already sending with every assistant tool-call replay. The K2.6 `thinking` parameter takes an extra `keep` field whose default (`null`) ignores historical reasoning, so K2.6 had to re-derive its full chain-of-thought from the user prompt on every iteration of the agent loop. The Moonshot direct (`api.moonshot.ai`) and Kimi Code (`api.kimi.com`) wire bodies now send `thinking: { type: "enabled", keep: "all" }` for `kimi-k2.6` requests with reasoning enabled, matching Moonshot's documented best practice for multi-step tool-calling agents. The flag is gated on the K2.6 id and the two native hosts because earlier Moonshot models (K2.5 and below) 400 on the unknown field and every Kimi gateway (OpenRouter, OpenCode, Kilo, Fireworks, …) speaks its own thinking shape. ([#1838](https://github.com/can1357/oh-my-pi/issues/1838))
2145
- - Fixed Alibaba DashScope (Bailian) compatible-mode endpoint `400 InternalError.Algo.InvalidParameter: The provided messages input is invalid. The error info is [Unexpected item type in content.]` when a screenshot or other image-producing tool result was folded into a known text-only Qwen turn (e.g. `qwen3.7-max`, `qwen-max`, `qwen3-coder-*`) hosted at `dashscope.aliyuncs.com/compatible-mode/v1`. `convertMessages` in `openai-completions` no longer forwards `image_url` content parts for those text-only id families even when a misconfigured custom provider claims `input: ["text", "image"]`; multimodal compatible-mode ids such as `qwen3.7-plus` and `qwen-vl-max` still rely on the catalog `input` field. The tool-result branch and the user-content branch both fall back to the standard `[image omitted: model does not support vision]` placeholder for text-only ids so the model still sees the attachment intent. ([#1859](https://github.com/can1357/oh-my-pi/issues/1859))
2146
-
2147
- ## [15.9.0] - 2026-06-04
2148
-
2149
- ### Fixed
2150
-
2151
- - Fixed MiniMax-compatible OpenAI-completions hosts (e.g. `minimax-code-cn/MiniMax-M3`) losing tool-call arguments when the stream delivers `function.arguments` as a complete object instead of the OpenAI JSON-string contract. The streaming buffer previously concatenated the object into a string, coercing it to `[object Object]` and leaving `bash`/`edit` calls with empty or malformed inputs; the tool-call block now holds the object payload directly. ([#1776](https://github.com/can1357/oh-my-pi/issues/1776))
2152
- - Fixed Cloud Code Assist (Gemini / Antigravity) rejecting tool schemas with `Invalid JSON payload received. Unknown name "propertyNames"` (HTTP 400) when a tool exposed a property literally named `properties` (e.g. the Resend MCP `create_contact` tool). The schema normalizer's `insideProperties` flag was re-asserted when descending into such a property's value schema, so Google-unsupported keywords (`propertyNames`, `additionalProperties`, …) nested inside it were never stripped. The flag is now only set when entering a real `properties` map from a schema node, not from within another `properties` map.
2153
- - Fixed local/self-hosted providers leaking machine-specific endpoints into the bundled `models.json`. A `generate-models` run on a machine with a LiteLLM proxy baked 1202 `litellm` models pinned to `http://localhost:4000/v1` into the committed catalog. `litellm` (and `lm-studio`) now join `ollama`/`vllm` in the generator's discovery-only exclusion set, so local providers are never fetched during generation nor written to `models.json` — they are discovered dynamically at runtime instead. LiteLLM model discovery now enriches metadata against models.dev (the same reference source the other gateway providers use) rather than a bundled reference map. Added a regression test pinning the invariant (no local provider blocks, no loopback/private-network `baseUrl`s in the bundled catalog).
2154
-
2155
- ## [15.8.2] - 2026-06-03
2156
-
2157
- ### Fixed
2158
-
2159
- - Fixed `opencode-zen/minimax-m3-free` (and forward-compat `opencode-zen/minimax-m3`) and `opencode-go/minimax-m3` being routed to `anthropic-messages` despite the OpenCode Zen/Go gateways only serving these ids at `/v1/chat/completions`, which surfaced raw MiniMax/tool-call markup (`<invoke name="bash">`, `<tool_call>`, `<description>`, `<cwd>`, `<|minimax|>`) in the UI. Resolver overrides now pin these ids to `openai-completions` and the bundled `models.json` entries are flipped to match. ([#1617](https://github.com/can1357/oh-my-pi/issues/1617))
2160
- - Fixed MiniMax Coding Plan China login opening the international `platform.minimax.io` subscription page instead of the China `platform.minimaxi.com` page.
2161
-
2162
- ## [15.8.0] - 2026-06-02
2163
-
2164
- ### Added
2165
-
2166
- - Added `AnthropicMessagesClient` and related Anthropic wire types/errors via `anthropic-client` export so callers can build a standalone Anthropic Messages client without depending on `@anthropic-ai/sdk`
2167
- - Added `parseClaudeRateLimitHeaders` and `AuthStorage.ingestUsageHeaders` so Anthropic rate-limit response headers can warm the per-credential usage cache with throttling while preserving per-tier data from the last full usage report.
2168
-
2169
- ### Changed
2170
-
2171
- - Changed Anthropic request handling to use the package-local `AnthropicMessagesClient` implementation instead of `@anthropic-ai/sdk` as the default transport
2172
- - Updated the `AnthropicOptions.client` surface to accept any `AnthropicMessagesClientLike` implementation with `messages.create`, enabling custom compatible clients
2173
- - Changed generated OAuth metadata `user_id` to use a deterministic `device_id` derived from the install ID instead of a random value
2174
- - `claudeCodeVersion` bumped to `2.1.148` to match current Claude Code release.
2175
- - `X-Stainless-Package-Version` updated to `0.94.0` (matches the bundled `@anthropic-ai/sdk` version); `X-Stainless-Runtime-Version` pinned to `v24.3.0` (Bun version bundled with CC 2.1.148); `X-Stainless-Os` header key corrected to `X-Stainless-OS`.
2176
- - `createClaudeBillingHeader` now emits a deterministic billing header (`cc_version=<claudeCodeVersion>.<suffix>; cc_entrypoint=cli; cch=00000;`), where `<suffix>` is the first 3 hex chars of `SHA-256(salt + msg[4] + msg[7] + msg[20] + version)` instead of random bytes. The fingerprint seed is taken from the first **user** message (skipping synthetic/developer injections), mirroring Claude Code's `computeFingerprintFromMessages`.
2177
- - `cch` attestation implemented: `cch=00000` is a placeholder that, for OAuth requests, `wrapFetchForCch` rewrites on the wire to `XXHash64(body, 0x4D659218E32A3268) & 0xFFFFF` formatted as 5 lowercase hex chars, computed in-place via `Bun.hash.xxHash64`. The rewrite is anchored to the `system[0]` billing-header prefix so user content is never mutated, and is installed only when a billing-header prefix is present (OAuth turns).
2178
- - `anthropic-beta` header set for OAuth model discovery and Claude usage-API requests expanded to add `context-1m-2025-08-07`, `redact-thinking-2026-02-12`, `mid-conversation-system-2026-04-07`, `advanced-tool-use-2025-11-20`, `effort-2025-11-24`, and `extended-cache-ttl-2025-04-11`. The usage-API `user-agent` is bumped to `claude-cli/2.1.158 (external, cli)`.
2179
- - Reasoning models now append `effort-2025-11-24` to the per-request `Anthropic-Beta` header (matches Claude Code).
2180
- - `buildAnthropicSystemBlocks` (CC-instruction mode) now emits the same 3-block layout as Claude Code: billing header (never cached), system instruction (cached), all user content merged into one block with `\n\n` (cached). Previously emitted one block per item with cache only on the last, which fingerprinted the caller by block count.
2181
- - `applyPromptCaching` now matches Claude Code's breakpoint layout: 2 system (instruction + merged content) + 2 message, with no tool breakpoint. The tool breakpoint was redundant — tools follow system in the token sequence, so when system changes the tool cache prefix also changes. The instruction block (system[1]) is stable across every request and now gets its own guaranteed-hit breakpoint.
2182
- - `applyPromptCaching` now caches the last two messages regardless of role instead of the last two *user* messages. The penultimate assistant message (tool calls + response from the previous turn) is larger and more recently created than the penultimate user message, making it the higher-value cache target.
2183
- - OAuth scope set expanded: added `user:sessions:claude_code`, `user:mcp_servers`, `user:file_upload`. `AUTHORIZE_URL` stays at `claude.ai/oauth/authorize` and `TOKEN_URL` stays at `api.anthropic.com/v1/oauth/token` — the `platform.claude.com` equivalents are CC's console-credential flow and do not grant `user:inference`, which OMP requires for direct OAuth-token inference.
2184
- - Token refresh POST now sends `anthropic-beta: oauth-2025-04-20` and `User-Agent: anthropic-sdk-typescript/0.94.0 userOAuthProvider` (CC sends these on refresh but not on the initial code exchange).
2185
-
2186
- ### Fixed
2187
-
2188
- - Fixed tool argument validation to wrap a plain string in a singleton array when the schema requires an array, allowing tool-level path/list normalization to recover from bare string arguments.
2189
- - Restored `eager_input_streaming` and strict flags on OAuth Anthropic tool definitions when model compatibility allows eager streaming.
2190
- - Fixed OAuth stream calls with injected custom clients missing a `beta` client by falling back to `client.messages.create` instead of requiring `client.beta.messages.create`
2191
- - Fixed direct use of internal API client typing so retry/timeouts and malformed-error classification remain compatible while not requiring the external SDK
2192
- - Fixed Cursor provider requests failing with `Cannot send empty user message to Cursor API` after tool-result history by selecting the latest user/developer turn instead of assuming the final context message is the active user turn.
2193
- - Fixed Anthropic web search dropping `ANTHROPIC_CUSTOM_HEADERS` when `CLAUDE_CODE_USE_FOUNDRY` was unset, causing 401s from corporate API gateways. `resolveAnthropicCustomHeadersForBaseUrl` now forwards the parsed headers whenever the base URL is non-Anthropic (or Foundry is enabled), and `buildAnthropicSearchHeaders` threads them through `buildAnthropicHeaders` so the search and streaming paths behave identically ([#1693](https://github.com/can1357/oh-my-pi/issues/1693)).
2194
- - Fixed OpenCode Go Anthropic-format models such as `qwen3.7-max` sending Anthropic `X-Api-Key` auth alongside the OpenCode bearer token, avoiding spurious Alibaba `401 Invalid API-key provided` errors. ([#1661](https://github.com/can1357/oh-my-pi/issues/1661))
2195
- - Fixed OAuth token exchange and refresh flows to fetch Claude CLI bootstrap identity when token responses omit account information, so `accountId` and `email` are now recovered when available
2196
- - Fixed Anthropic thinking traces being lost on direct OAuth requests. OAuth requests no longer send `redact-thinking-2026-02-12` unless thinking is explicitly hidden, Opus 4.7+ adaptive thinking opts into `display: "summarized"`, and the top user-facing thinking tier now sends Anthropic's `output_config.effort = "max"` rather than the next-lower `"xhigh"` tier.
2197
-
2198
- ### Removed
2199
-
2200
- - Removed the `@anthropic-ai/sdk` runtime dependency. The Anthropic provider now uses the package-local `AnthropicMessagesClient` and hand-maintained wire types in `providers/anthropic-wire.ts`; the SDK was only ever used for URL assembly, auth-header injection, bounded retries, the pre-response timeout, and HTTP-error-to-status mapping, all of which are reproduced with identical observable behavior.
2201
-
2202
- ## [15.7.5] - 2026-06-01
2203
-
2204
- ### Added
2205
-
2206
- - Added Anthropic task budget support, forwarding `taskBudget` as `output_config.task_budget` with the required `task-budgets-2026-03-13` beta header and accepting Anthropic gateway requests that send `output_config.task_budget`.
2207
-
2208
- ### Fixed
2209
-
2210
- - Fixed OpenAI-family first-event timeouts so `PI_OPENAI_STREAM_IDLE_TIMEOUT_MS` cannot be undercut by a lower generic `PI_STREAM_FIRST_EVENT_TIMEOUT_MS` while local OpenAI-compatible servers are still processing large prompts. `PI_OPENAI_STREAM_FIRST_EVENT_TIMEOUT_MS` is now available for an explicit OpenAI-specific first-event override. ([#1603](https://github.com/can1357/oh-my-pi/issues/1603))
2211
-
2212
- ## [15.7.4] - 2026-05-31
2213
-
2214
- ### Fixed
2215
-
2216
- - Fixed Anthropic stream idle-timeout retries after the provider stream has already begun.
2217
- - Fixed Xiaomi MiMo `/login` rejecting token-plan (`tp-`) keys with `401 Invalid API Key`. The validation request was still sending the legacy Anthropic `x-api-key` header against the OpenAI-compatible `/v1/chat/completions` endpoint; switched to `Authorization: Bearer`, matching the runtime path. ([#1580](https://github.com/can1357/oh-my-pi/issues/1580))
2218
- - Fixed OpenAI-compatible tool-call replay to send empty assistant content instead of `null`, avoiding strict custom backends that crash with `str`/`NoneType` concatenation after subagent tool results. ([#1585](https://github.com/can1357/oh-my-pi/issues/1585))
2219
-
2220
- ## [15.7.3] - 2026-05-31
2221
-
2222
- ### Changed
2223
-
2224
- - Throttled per-delta streaming JSON re-parsing of OpenAI Responses/Codex tool-call arguments (bounding mid-stream parse cost from O(N²) to O(N)). Finalization via `response.output_item.done` now writes the authoritative full arguments back to the persisted assistant-message block, so tool calls finalized without a trailing `response.function_call_arguments.done` no longer retain stale/empty (`{}`) arguments. ([#1507](https://github.com/can1357/oh-my-pi/pull/1507))
2225
-
2226
- ## [15.6.0] - 2026-05-30
2227
-
2228
- ### Fixed
2229
-
2230
- - Fixed Anthropic adaptive-thinking replay preserving signed thinking blocks on the latest abandoned tool-use assistant message, avoiding `thinking blocks in the latest assistant message cannot be modified` 400s. ([#1531](https://github.com/can1357/oh-my-pi/issues/1531))
2231
-
2232
- ## [15.5.15] - 2026-05-30
2233
-
2234
- ### Added
2235
-
2236
- - Added `PI_REQ_DEBUG=1` request/response recording for provider transports. Each request writes `rr-session-N.json`; each received response writes `rr-session-N.res.log` with response headers followed by raw body bytes.
2237
-
2238
- ### Fixed
2239
-
2240
- - Fixed OpenCode-Go dynamic model refresh downgrading `qwen3.7-max` from Anthropic Messages to OpenAI-compatible transport, which caused `401 Model qwen3.7-max is not supported for format oa-compat` after `/v1/models` cache refreshes.
2241
-
2242
- ## [15.5.12] - 2026-05-29
2243
-
2244
- ### Removed
2245
-
2246
- - Removed ANTML stream markup healing for `antml:function_calls` and `antml:thinking` envelopes, so Anthropic-compatible providers no longer parse those tags into `toolCall`/`thinking` events
2247
-
2248
- ### Fixed
2249
-
2250
- - Fixed GLM-5.x coding-plan OpenAI-compatible streams to use a longer default watchdog window, avoiding spurious `OpenAI completions stream stalled while waiting for the next event` errors during slow `glm-5.1` thinking/output phases. ([#1494](https://github.com/can1357/oh-my-pi/issues/1494))
2251
- - Fixed `zhipu-coding-plan` model discovery and credential validation to use the dedicated GLM Coding Plan endpoint (`https://open.bigmodel.cn/api/coding/paas/v4`) instead of the general BigModel endpoint, preventing requests from consuming ordinary account balance. ([#1494](https://github.com/can1357/oh-my-pi/issues/1494))
2252
- - Fixed DeepSeek tool calls failing on NanoGPT (e.g. `nanogpt/deepseek/deepseek-v4-pro` with reasoning enabled) by routing tool-bearing DeepSeek requests through NanoGPT's `:tools` model route and adding `nanogpt` to the DSML leak allowlist so streamed `<|DSML|tool_calls>...</|DSML|tool_calls>` envelopes are healed into structured tool calls instead of being passed through as visible text. ([#1488](https://github.com/can1357/oh-my-pi/issues/1488))
2253
- - Fixed DeepSeek tool calls failing on NanoGPT (e.g. `nanogpt/deepseek/deepseek-v4-pro` with reasoning enabled) by adding `nanogpt` to the DSML leak allowlist so streamed `<|DSML|tool_calls>...</|DSML|tool_calls>` envelopes are healed into structured tool calls instead of being passed through as visible text. The `:tools` model suffix is no longer appended on NanoGPT; that route triggered NanoGPT's server-side tool-call parser and 502'd with `code: "malformed_tool_call"` on complex tool schemas (`todo_write`) — the default route forwards `delta.content` (including DSML envelopes) which is healed client-side. ([#1488](https://github.com/can1357/oh-my-pi/issues/1488))
2254
- - Fixed OpenAI-compatible streamed parallel tool calls losing indexed argument deltas by tracking active tool-call blocks by the provider's `tool_calls[].index`; this keeps parallel NanoGPT `read` calls from merging or dropping their `path` arguments. ([#1488](https://github.com/can1357/oh-my-pi/issues/1488))
2255
-
2256
- ## [15.5.11] - 2026-05-29
2257
-
2258
- ### Added
2259
-
2260
- - Added mid-conversation `system` message support for Anthropic Messages by upgrading eligible `developer` turns to `role: "system"` on first-party Claude API with Claude Opus 4.8+ and newer
2261
- - Added `supportsMidConversationSystem` to Anthropic compatibility settings so consumers can opt in to or disable mid-conversation `system` role handling per model
2262
- - Added `anthropic.claude-opus-4-8` model metadata in the model registry for Bedrock Converse streaming with effort-based thinking support through `xhigh`
2263
-
2264
- ### Changed
2265
-
2266
- - Changed Anthropic adaptive-thinking effort mapping for Opus 4.7+ on the Messages API to use the model's full five-tier scale: user-facing efforts now shift up one notch (`minimal→low`, `low→medium`, `medium→high`, `high→xhigh`, `xhigh→max`) so the top tier reaches the genuine `max` level and `high` lands on Anthropic's recommended `xhigh` coding/agentic default. Older adaptive models (Opus 4.6) and Bedrock Converse keep the four-tier legacy mapping where `xhigh` aliases to `max`.
2267
-
2268
- ### Fixed
2269
-
2270
- - Fixed OpenCode Zen `400 thinking is enabled but reasoning_content is missing in assistant tool call message` for every model behind `opencode-go`/`opencode-zen` (Kimi K2.x, DeepSeek V4 Pro/Flash, GLM-5.x, Qwen3.x, MiMo, MiniMax) by reactivating `requiresReasoningContentForToolCalls` and pinning the wire field to `reasoning_content` for any opencode request in thinking mode. The static compat default still omits the field for thinking-disabled turns to preserve the `Extra inputs are not permitted` guard from #1071; forced-tool turns also stay off because the existing `disableReasoningOnForcedToolChoice` guard strips thinking from the wire body. ([#1484](https://github.com/can1357/oh-my-pi/issues/1484))
2271
-
2272
- ## [15.5.8] - 2026-05-28
2273
-
2274
- ### Added
2275
-
2276
- - Added `CheckCredentialsOptions.completionProbe` (and `completionTimeoutMs`) so `AuthStorage.checkCredentials` can additionally exercise each credential against the provider's chat-completion endpoint after refresh-on-expiry. Result lands on `CredentialHealthResult.completion` ({ok, reason?, modelId?, latencyMs?}) without disturbing the usage `ok` field. Public types: `CompletionProbe`, `CompletionProbeInput`, `CompletionProbeCredential`, `CredentialCompletionResult`. The probe is invoked even when no `UsageProvider` is registered for the row, and is skipped when OAuth refresh fails (the stale bytes would only mask the upstream failure).
2277
- - Added Wafer Pass and Wafer Serverless providers (`wafer-pass`, `wafer-serverless`). OpenAI-compatible (`https://pass.wafer.ai/v1`), bearer auth, `wfr_…` keys. `/login wafer-pass` and `/login wafer-serverless` paste-and-validate the key against `/v1/models`. `WAFER_PASS_API_KEY` and `WAFER_SERVERLESS_API_KEY` environment variables wired into `getEnvApiKey`. Bundled catalog seeds `wafer-pass/{GLM-5.1, Qwen3.5-397B-A17B}` and `wafer-serverless/{GLM-5.1, Kimi-K2.6, Qwen3.5-397B-A17B, Qwen3.6-35B-A3B, qwen3.7-max, deepseek-v4-flash, deepseek-v4-pro}`; dynamic discovery via `/v1/models` overlays additional models at runtime. Pass-tier discovery filters `wafer.tier === "pass_included"`. Pass-SKU costs are seeded at `0` (flat-rate subscription, no per-token charge — matches `kimi-code`/`firepass`/`alibaba-coding-plan`). Serverless costs are the wafer.ai retail rate, derived from the `*_cents_per_million` envelope via `value × 125 / 10000` (e.g. GLM-5.1 `120` → $1.50/M, Kimi-K2.6 `88` → $1.10/M). Reasoning entries get a thinking compat picked from the `wafer.provider` envelope: `zai`/`moonshotai` → zai-style `thinking: { type }`, `qwen` → top-level `enable_thinking`, `deepseek` and unknown upstreams stay unset so `detectOpenAICompat` can pick `reasoning_effort` from the id pattern at request time.
2278
-
2279
- ### Changed
2280
-
2281
- - Changed auth-gateway credential resolution to use per-conversation `promptCacheKey`/`sessionId` when calling `AuthStorage.getApiKey`, so repeated turns can keep the same credential until it becomes unavailable
2282
- - Changed auth-gateway and pi-native request handling to align `sessionId` with prompt/context identity before credential lookup
2283
- - Changed Anthropic prompt preparation to downscale image blocks over 2000px when a request includes 20+ images, reducing oversized payloads automatically
2284
- - Changed OpenAI chat request parsing to accept `name` on `tool` messages and fall back to the matching assistant `tool_calls` name, so parsed tool results now carry a proper tool name when the wire omits it
2285
- - Changed `checkCredentials` to skip running `completionProbe` when OAuth refresh fails, so stale bearer tokens are never probed and the refresh failure remains the returned `reason`
2286
- - Changed completion reporting to return `completion: { ok: null, reason: ... }` when a credential has no usable bearer bytes instead of attempting the probe
2287
- - Refactored `AuthStorage.checkCredentials` so OAuth refresh-on-expiry runs up-front and the refreshed credential is shared between the usage probe and the new completion probe; rows without a registered `UsageProvider` no longer short-circuit before the completion probe runs.
2288
-
2289
- ### Fixed
2290
-
2291
- - Fixed DeepSeek DSML tool-call envelope leaks on Ollama Cloud and OpenAI-compatible streams by healing leaked envelopes into structured tool calls without displaying raw DSML markers. ([#1462](https://github.com/can1357/oh-my-pi/issues/1462))
2292
- - Fixed auth-gateway to classify usage-limit messages such as `usage_limit_reached`, `resource_exhausted`, and Codex-style `Try again in ~X min` text as 429 `rate_limit_error` responses
2293
- - Fixed auth-gateway usage-limit handling to honor parsed retry hints and switch to a sibling credential via `markUsageLimitReached` instead of invalidating the rate-limited credential
2294
- - Fixed `streamSimple` to retry on usage-limit errors (including message-only error events) before any content is emitted, so `onAuthError` can rotate credentials automatically
2295
- - Fixed auth-gateway error classification to extract embedded status codes and use word-boundary matching, so `GenerateContentRequest` and similar messages are no longer misreported as rate-limit errors
2296
- - Fixed `checkCredentials` to handle `completionProbe` exceptions by recording the failure in `CredentialHealthResult.completion.reason` while still returning the usage probe result
2297
- - Fixed Google Vertex's bundled model list to use the authoritative models.dev catalog, including MaaS entries such as `deepseek-ai/deepseek-v3.2-maas` and removing retired Gemini 1.5 fallbacks. ([#1456](https://github.com/can1357/oh-my-pi/issues/1456))
2298
-
2299
- ## [15.5.7] - 2026-05-27
2300
-
2301
- ### Added
2302
-
2303
- - `SimpleStreamOptions.openrouterVariant` (`"nitro"`, `"floor"`, `"online"`, `"exacto"`, …) — when set, appends `:<variant>` to OpenRouter model IDs at request time, leaving ids that already carry an explicit `:suffix` untouched. Plumbed through `openai-completions` and the pi-native gateway forwarder.
2304
- - xAI Grok OAuth (SuperGrok Subscription) provider in `/login`. Loopback PKCE flow on `127.0.0.1:56121`; the token unlocks Grok-4.x chat. Ported from NousResearch/hermes-agent (MIT).
2305
- - OpenRouter provider in `/login`. API-key paste flow validated against `https://openrouter.ai/api/v1/auth/key` (the `/models` endpoint is public and cannot validate auth). The pasted key is stored under the existing `openrouter` provider id used by `OPENROUTER_API_KEY`.
2306
- - `XAI_OAUTH_TOKEN` environment variable accepted as a headless fallback for the xAI Grok OAuth provider.
2307
-
2308
- ### Changed
2309
-
2310
- - `OpenAIResponsesOptions` gains four optional, provider-agnostic fields that adapter wrappers can use to compose provider-specific behavior on top of the generic transport: `includeEncryptedReasoning` (gates `include: ["reasoning.encrypted_content"]`; default `true`, preserves current behavior), `filterReasoningHistory` (strips replayed `type: "reasoning"` items from conversation history; default `false`), `headers` (merged onto the client's default headers), and `extraBody` (merged into the request payload).
2311
- - The existing `XAI_API_KEY` path is unchanged — it continues to use the OpenAI-completions transport.
2312
-
2313
- ### Fixed
2314
-
2315
- - Fixed OpenRouter DeepSeek V4 tool-call follow-up requests replaying normalized `reasoning` as-is instead of DeepSeek's required `reasoning_content`, which caused HTTP 400 errors in thinking mode. ([#1445](https://github.com/can1357/oh-my-pi/issues/1445))
2316
-
2317
- ## [15.5.6] - 2026-05-27
2318
-
2319
- ### Added
2320
-
2321
- - Added `PI_CODEX_WEBSOCKET_MAX_IDLE_REUSE_MS` to control how long an idle Codex WebSocket stays eligible for reuse, with `0` disabling the check
2322
-
2323
- ### Fixed
2324
-
2325
- - Fixed reused Codex WebSocket connections that had gone silent without activity to be dropped and replaced with a fresh handshake after the idle-reuse threshold, preventing stalled next requests
2326
- - Fixed stale response frames left in the websocket queue from a completed turn so subsequent requests no longer process terminal frames from the previous response
2327
- - Fixed websocket dead-socket detection to fail a stale connection when no inbound traffic or pong is observed after a ping timeout, improving recovery on runtimes that do not emit pong events
2328
-
2329
- ## [15.5.5] - 2026-05-27
2330
-
2331
- ### Added
2332
-
2333
- - Added `PI_CODEX_WEBSOCKET_PING_INTERVAL_MS` to configure the interval for Codex WebSocket protocol ping heartbeats
2334
- - Added `PI_CODEX_WEBSOCKET_PONG_TIMEOUT_MS` to configure the Codex WebSocket pong timeout used to detect unresponsive connections
2335
- - Added `PI_CODEX_WEBSOCKET_MESSAGE_QUEUE_CAPACITY` to configure the maximum buffered Codex WebSocket inbound queue size before transport fallback
2336
-
2337
- ### Changed
2338
-
2339
- - Improved Codex WebSocket timeout diagnostics to include last event type and time since last progress event
2340
- - Enhanced Codex WebSocket error classification to recognize ping, pong, send, and queue-overflow failures as retryable
2341
-
2342
- ### Fixed
2343
-
2344
- - Fixed Codex WebSocket send failures by wrapping socket.send() in try-catch and surfacing errors as retryable transport errors
2345
- - Fixed Codex WebSocket inbound queue overflow by adding capacity bounds and triggering fallback to SSE when exceeded
2346
- - Fixed Codex WebSocket pong timeout detection by tracking pong events and failing the connection when no pong is received within the configured timeout
2347
- - Fixed Anthropic streaming to suppress hallucinated meta-prompt thinking blocks (the recent "I don't see any current rewritten thinking..." regression). When the marker phrase `rewritten thinking` appears in a streamed thinking summary the block is collapsed to a plain `Thinking...` placeholder and its signature is dropped so subsequent turns can't re-anchor on the garbled chain.
2348
- - Fixed Codex WebSocket silent stalls by adding protocol pings, inbound queue bounding, clearer idle-timeout diagnostics, and SDK retry clamping for first-event timeouts.
2349
-
2350
- ## [15.5.0] - 2026-05-26
2351
-
2352
- ### Added
2353
-
2354
- - Added `zhipu-coding-plan` provider for Zhipu (智谱) BigModel's domestic coding-plan SKU at `https://open.bigmodel.cn/api/coding/paas/v4`, with dynamic model discovery (`ZHIPU_API_KEY`), zai-format thinking, `reasoning_content` field, and OAuth login flow ([#1340](https://github.com/can1357/oh-my-pi/issues/1340)).
2355
-
2356
- ### Removed
2357
-
2358
- - Removed the `pi-ai` CLI binary (`packages/ai/src/cli.ts`) and its `bin` entry. Use the in-process equivalent in the omp coding-agent CLI: `omp auth-broker login [provider]`, `omp auth-broker logout [provider]`, and `omp auth-broker list`. The library API (`AuthStorage.login()`, `getOAuthProviders()`, etc.) is unchanged.
2359
-
2360
- ### Fixed
2361
-
2362
- - Fixed delayed `toolResult` emissions so real tool results are emitted in the correct assistant `toolCall` window after handoff/compaction, preventing out-of-order or orphaned tool results
2363
- - Fixed delayed `toolResult` handling for aborted calls so a late real result is emitted instead of a synthetic `aborted` result for the same `toolCallId`
2364
- - Fixed usage polling to disable credentials when OAuth refresh fails definitively (for example `invalid_grant`) and clear cached last-good usage data so stale reports no longer remain visible
2365
-
2366
- ## [15.4.3] - 2026-05-26
2367
-
2368
- ### Fixed
2369
-
2370
- - Fixed Google Vertex model discovery to use the project-scoped OpenAI-compatible model list so Vertex Model Garden models such as GLM and Claude are available through ADC auth ([#1412](https://github.com/can1357/oh-my-pi/issues/1412)).
2371
-
2372
- ## [15.4.2] - 2026-05-26
2373
-
2374
- ### Fixed
2375
-
2376
- - Fixed OpenCode Zen `big-pickle` follow-up requests replaying assistant tool-call turns without DeepSeek-required `reasoning_content`, which caused HTTP 400 errors in thinking mode.
2377
-
2378
- ## [15.4.1] - 2026-05-26
2379
-
2380
- ### Added
2381
-
2382
- - Added `isOpenAICompletionsProgressChunk` export to identify real progress chunks vs. keepalives in OpenAI completions streams
2383
- - Added per-provider stream watchdog overrides via `getStreamIdleTimeoutMs(fallbackMs)` and `getStreamFirstEventTimeoutMs(idleTimeoutMs, fallbackMs)` to allow providers like Google Gemini CLI to extend first-event timeouts without affecting global defaults
2384
- - Added `promptCacheKey` to `StreamOptions` and passed it through stream option mapping so callers can specify an explicit prompt-cache key separate from `sessionId`
2385
- - Added `promptCacheKey` support to the native server option whitelist so `promptCacheKey` is accepted by `pi-native-server` streams
2386
- - Restored the per-provider stream watchdog (`iterateWithIdleTimeout`) on top of the abortable iterator. The lazy stream forwarder in `register-builtins` now wraps every provider's event stream with the first-event + steady-state idle watchdog (`PI_STREAM_FIRST_EVENT_TIMEOUT_MS`, `PI_STREAM_IDLE_TIMEOUT_MS`; aliases honored), and Anthropic / OpenAI Completions / OpenAI Responses / Azure OpenAI Responses / Codex SSE re-emit their per-provider progress predicates so empty keepalive frames cannot keep a stalled stream alive. Reverts the partial regression from #1392 that left Codex WebSocket subagent runs hanging silently for hours when the broker dropped frames between deltas. The Codex WebSocket transport additionally now resets `lastProgressAt` only on progress events (not keepalives), giving the 300s WS-internal idle ceiling the same liveness semantics as the SSE path.
2387
-
2388
- ### Changed
2389
-
2390
- - Enabled OpenAI Codex WebSocket streams to apply `streamIdleTimeoutMs` and `streamFirstEventTimeoutMs` from `StreamOptions` per request instead of fixed internal defaults
2391
- - Changed stream idle watchdog implementation from `iterateUntilAbort` to `iterateWithIdleTimeout`, which now enforces maximum idle gaps between streamed events and distinguishes between first-event and steady-state timeouts
2392
- - Changed Anthropic, OpenAI Responses, OpenAI Completions, Azure OpenAI Responses, and OpenAI Codex Responses providers to use the new idle-timeout iterator with per-provider progress predicates so empty keepalive frames cannot keep a stalled stream alive
2393
- - Changed Codex WebSocket transport to reset `lastProgressAt` only on progress events (not keepalives), giving the 300s WS-internal idle ceiling the same liveness semantics as the SSE path
2394
- - Changed Google Gemini CLI stream forwarding defaults to use a 5-minute first-event floor via per-provider lazy-stream limits to avoid premature first-event timeouts on slow startup
2395
- - Changed OpenAI Responses and OpenAI Codex request handling to keep `sessionId` for provider routing and conversation headers while `promptCacheKey` controls the `prompt_cache_key` payload independently
2396
- - Changed `StreamOptions.streamIdleTimeoutMs` documentation to clarify it is now wired into every built-in provider and the lazy stream forwarder, and that `streamFirstEventTimeoutMs` is honored at both the SDK-request layer and the iterator-watchdog layer
2397
- - Changed OpenAI Responses and OpenAI Codex request handling so `sessionId` continues to drive provider routing and state while `promptCacheKey` controls the `prompt_cache_key` payload
2398
- - Changed Google Gemini CLI stream forwarding defaults to use a 5-minute first-event floor to avoid premature first-event timeouts on slow startup
2399
- - Changed auth-gateway request mapping to preserve incoming `prompt_cache_key` as both `promptCacheKey` and `sessionId` when routing OpenAI-compatible sessions
2400
- - Un-deprecated `StreamOptions.streamIdleTimeoutMs`; the option is wired into every built-in provider and the lazy stream forwarder again. `streamFirstEventTimeoutMs` is now honored at both the SDK-request layer (via `createSdkStreamRequestOptions`) and the iterator-watchdog layer, in cooperation.
2401
-
2402
- ### Removed
2403
-
2404
- - Removed `installH2Fetch` and the `fetch` patch that forced HTTP/2 on HTTPS requests; callers now use the default Bun `fetch` transport
2405
-
2406
- ### Fixed
2407
-
2408
- - Fixed first-item timeout handling so `iterateWithIdleTimeout` no longer keeps first-event timers active after the source throws or the consumer stops before semantic progress
2409
- - Fixed silent multi-hour hangs on Codex WebSocket subagent runs when the broker dropped frames between deltas by restoring per-provider stream watchdogs with progress-event filtering
2410
- - Fixed z.ai/GLM-via-OpenRouter subagent stalls where no-op keepalive chunks reset the idle watchdog indefinitely by filtering non-progress items before resetting the deadline
2411
-
2412
- ## [15.4.0] - 2026-05-26
2413
-
2414
- ### Breaking Changes
2415
-
2416
- - Removed `findAnthropicAuth` from `anthropic-auth` and replaced store-driven auth discovery with `buildAnthropicAuthConfig`, requiring callers to provide an already-resolved API key before building Anthropic auth config
2417
-
2418
- ### Added
2419
-
2420
- - Added `PI_CODEX_WEBSOCKET_FIRST_EVENT_TIMEOUT_MS` and `PI_CODEX_WEBSOCKET_IDLE_TIMEOUT_MS` options to tune Codex WebSocket timeout behavior before fallback
2421
- - Added `AuthStorage.getOAuthAccess` to return a refreshed OAuth access token with identity metadata (`accountId`, `email`, `projectId`, `enterpriseUrl`) for callers that need bearer-token headers together
2422
- - Added Codex WebSocket forwarding to the `onSseEvent` observer so the raw provider-stream debug viewer captures the inbound JSON frames and the outbound request frame from the WS transport using the same synthesized SSE-wire shape (`event:` + `data:` lines, prefixed with a `: ws ← <type>` (inbound) or `: ws → <type>` (outbound) comment).
2423
-
2424
- ### Changed
2425
-
2426
- - Changed OAuth selection in `AuthStorage` to treat credentials as stale when they are within 60 seconds of expiry and rotate them preemptively
2427
- - Changed Google Gemini CLI, Google Gemini usage, Antigravity usage, and Kimi usage flows to stop refreshing OAuth tokens directly and rely on `AuthStorage` for token rotation
2428
-
2429
- ### Deprecated
2430
-
2431
- - Deprecated `streamIdleTimeoutMs` in `StreamOptions` as a compatibility-only field that is no longer used by providers
2432
-
2433
- ### Removed
2434
-
2435
- - Removed provider-local OAuth refresh helpers from Google Gemini CLI and Google/Kimi/Antigravity usage probes, preventing direct refresh calls from those usage paths
2436
-
2437
- ### Fixed
2438
-
2439
- - Dropped truncated, thinking-only assistant turns with only `thinking`/`redacted_thinking` blocks and no `text` or `tool` content during message transformation, preventing Anthropic requests from sending consecutive assistant messages after a `max_tokens`/`error`/`aborted` interruption
2440
- - Fixed Amazon Bedrock bearer-token authentication to honor `AWS_BEARER_TOKEN_BEDROCK` before resolving AWS profiles or running `credential_process`, matching Bedrock API-key precedence. ([#1399](https://github.com/can1357/oh-my-pi/issues/1399))
2441
- - Updated `isRetryableError` to treat Bun HTTP/2 transport errors (`HTTP2StreamReset`, `HTTP2RefusedStream`) as retryable so transient stream-reset failures can be retried
2442
- - Fixed Codex WebSocket streaming to recover from stalled sessions by falling back to SSE when the first event or subsequent progress is delayed beyond the configured websocket timeout
2443
- - Fixed expired OAuth handling so provider-level paths no longer attempt direct token refresh calls for expired credentials and instead rely on `AuthStorage` for rotation
2444
- - Fixed provider streams aborting slow-but-valid first tokens or silent inter-event gaps with OMP-owned first-event/idle watchdog errors. Built-in lazy streams, OpenAI/Anthropic/Azure/Codex SSE, and Codex WebSocket streams now wait for provider output, provider/socket errors, caller aborts, or explicit request-layer timeouts instead of treating provider silence as failure ([#1392](https://github.com/can1357/oh-my-pi/issues/1392)).
2445
- - Fixed Claude Opus 4.7 on Amazon Bedrock streaming no reasoning output (and appearing to hang on long reasoning runs) because Anthropic silently switched the adaptive-thinking display default to `"omitted"`. The Bedrock provider now sends `thinking.display = "summarized"` by default on Opus 4.7+ adaptive models and on budget-based Claude models, mirroring the existing direct-Anthropic behavior. `BedrockOptions.thinkingDisplay` (`"summarized" | "omitted"`) is exposed for callers that want to opt out, and `hideThinkingSummary` now wires through to the Bedrock case ([#1373](https://github.com/can1357/oh-my-pi/issues/1373)).
2446
- - Fixed Cursor Composer resume/tool-continuation turns failing with `Cannot send empty user message to Cursor API`. Empty current user turns now use Cursor's `resumeAction` instead of constructing an invalid `userMessageAction` ([#1376](https://github.com/can1357/oh-my-pi/issues/1376)).
2447
- - Fixed `pi-ai login moonshot` failing with `invalid temperature: only 1 is allowed for this model` (HTTP 400) because the API-key validator probed `kimi-k2.5` with `temperature: 0`. Moonshot login now validates against `GET /v1/models`, matching the DeepSeek/Fireworks/NanoGPT/ZenMux pattern and authenticating the key without invoking model-specific parameter restrictions.
2448
-
2449
- ## [15.3.2] - 2026-05-25
2450
-
2451
- ### Added
2452
-
2453
- - Added `GET /v1/snapshot/stream` for live auth-broker snapshot updates via SSE with `snapshot`, `entry`, and `removed` event frames
2454
- - Added `AuthBrokerClient.openSnapshotStream()` for consuming SSE snapshot streams from `/v1/snapshot/stream`
2455
- - Added `streamSnapshots` option to `RemoteAuthCredentialStore` (default `true`) to enable or disable SSE-based snapshot synchronization
2456
- - Added `streamKeepaliveMs` to `startAuthBroker()` to tune heartbeat frequency for the SSE stream
2457
- - Added `AuthStorage.checkCredentials({ signal?, timeoutMs?, baseUrlResolver? })` that returns a per-credential `CredentialHealthResult` with tri-state `ok` (`true` / `false` / `null`-unverifiable), the credential's identity (provider, type, email/accountId, broker-refresh flag), and the upstream error string when the probe fails. Iterates sequentially over `listAuthCredentials()`, exercises OAuth refresh on expiry, then calls the per-provider `UsageProvider.fetchUsage` without swallowing errors — so callers can identify which row in a multi-account broker is producing 401s instead of getting a silently-deduplicated `fetchUsageReports` list.
2458
- - Added `GET /v1/credentials/check` to `startAuthGateway()` that forwards to `AuthStorage.checkCredentials` and returns `{ generatedAt, credentials }`. Gated by the same bearer as the rest of the gateway.
2459
-
2460
- ### Changed
2461
-
2462
- - Changed `RemoteAuthCredentialStore` to prefer SSE snapshot streaming and automatically fall back to long-polling when a broker returns 404 for `/v1/snapshot/stream`
2463
- - Changed snapshot write-refresh flow so `RemoteAuthCredentialStore` skips immediate `/v1/snapshot` refreshes when SSE streaming is active
2464
- - Changed broker SSE stream behavior to keep connections open with periodic keepalives and an increased server idle timeout
2465
-
2466
- ## [15.3.0] - 2026-05-25
2467
-
2468
- ### Added
2469
-
2470
- - Added DeepSeek to the built-in API-key login provider catalog so `omp login deepseek` stores a reusable `DEEPSEEK_API_KEY` credential for the bundled DeepSeek models.
2471
-
2472
- ## [15.2.4] - 2026-05-22
2473
-
2474
- ### Fixed
2475
-
2476
- - Fixed ChatGPT Plus/Pro (Codex) OAuth login returning `Token exchange failed: 403` on Windows. When port 1455 was in use, the callback server silently fell back to a random port; OpenAI's authorization endpoint accepts any localhost redirect URI (loose validation), so the browser callback succeeds and shows "Authentication Successful", but the token endpoint rejects the non-registered port with 403. The `OpenAICodexOAuthFlow` now enforces a fixed `redirectUri` option so a busy port immediately surfaces as "port unavailable" instead of producing a confusing 403 ([#1277](https://github.com/can1357/oh-my-pi/issues/1277)).
2477
- - Improved `exchangeCodeForToken` error diagnostics: the 403 response body (`error` / `error_description` fields) is now included in the thrown message, matching the existing `refreshOpenAICodexToken` behaviour.
2478
-
2479
- ### Added
2480
-
2481
- - Added `ChatGPT Plus/Pro (Codex, headless/device)` (`openai-codex-device`) as an alternative login method for the Codex provider. Uses OpenAI's device-code flow (`/api/accounts/deviceauth/usercode` → poll `/api/accounts/deviceauth/token`), which avoids a local callback server and port 1455 entirely. Credentials are stored under the existing `openai-codex` provider key so all models and tooling continue to work without reconfiguration ([#1277](https://github.com/can1357/oh-my-pi/issues/1277)).
2482
-
2483
- ## [15.2.2] - 2026-05-22
2484
-
2485
- ### Fixed
2486
-
2487
- - Fixed `gemini-3.1-pro-high` and `gemini-3.1-pro-low` on the `google-antigravity` provider always returning HTTP 400 from Cloud Code Assist. The `ANTIGRAVITY_SYSTEM_INSTRUCTION` identity header was not injected for these models because the internal check matched the string `"gemini-3-pro-high"` (hyphen) instead of the versioned `"gemini-3.1-pro-..."` form. The guard now matches all `gemini-3` model variants ([#1274](https://github.com/can1357/oh-my-pi/issues/1274)).
2488
-
2489
- ## [15.2.0] - 2026-05-21
2490
-
2491
- ### Fixed
2492
-
2493
- - Fixed `/login` (and `/logout`, plus any `AuthStorage.set` / `remove` call) against a remote auth-broker throwing `RemoteAuthCredentialStore is read-only on the client. Use 'omp auth-broker login <provider>' to mutate credentials.` Added three optional async write hooks to `AuthCredentialStore` (`upsertAuthCredentialRemote`, `replaceAuthCredentialsRemote`, `deleteAuthCredentialsRemote`); `RemoteAuthCredentialStore` implements them via the broker's `POST /v1/credential` and `POST /v1/credential/:id/disable` endpoints and applies the broker's authoritative post-write entries to the local snapshot. `AuthStorage` routes through the hooks when present, so OAuth and API-key logins (and logouts) initiated from a broker-backed client now persist server-side and surface immediately without waiting for the long-poll snapshot tick.
2494
-
2495
- ## [15.1.9] - 2026-05-21
2496
-
2497
- ### Fixed
2498
-
2499
- - Fixed Ollama named tool forcing to send only the requested tool when the caller passes a named `toolChoice`, preserving `tool_choice: "required"` while preventing local models from selecting a different tool. ([#1236](https://github.com/can1357/oh-my-pi/issues/1236))
2500
- - Fixed `/btw` (and IRC background replies) returning a `BedrockException` 400 (`The toolConfig field must be defined when using toolUse and toolResult content blocks.`) on LiteLLM → Bedrock once the session has tool-call history. Two source fixes in `buildParams`: (1) `if (context.tools)` → `if (context.tools?.length)` so an explicit `context.tools = []` (the /btw opt-out) never routes through `convertTools` and never emits an empty `"tools"` array; (2) `else if (hasToolHistory(...))` → `else if (context.tools === undefined && hasToolHistory(...))` so the Anthropic-proxy sentinel that injects `tools: []` for tool-history turns is suppressed when the caller explicitly opted out, preventing it from re-introducing the empty array. As defence-in-depth, `tool_choice: "none"` is also dropped when the resolved tools list is missing or empty. ([#1227](https://github.com/can1357/oh-my-pi/issues/1227))
2501
-
2502
- ## [15.1.8] - 2026-05-20
2503
-
2504
- ### Added
2505
-
2506
- - Added Fireworks Fire Pass as a separate `firepass` provider with API-key login flow, bundled `kimi-k2.6-turbo` model entry (Kimi K2.6 Turbo), and wire-id translation from the friendly catalog id to the `accounts/fireworks/routers/kimi-k2p6-turbo` router endpoint. Fire Pass keys (`fpk_…`) authorize only the dedicated router and reject `/v1/models`, so login validation pings chat completions against the router id directly. Extended the openai-completions Kimi-family safety net so the firepass entry inherits the per-Fireworks-docs "always send `max_tokens`" default ([Kimi K2 guide](https://docs.fireworks.ai/models/kimi-k2)); the router's accepted `reasoning_effort` set includes `xhigh`, so it is forwarded verbatim rather than remapped. See https://docs.fireworks.ai/firepass.
2507
-
2508
- ### Fixed
2509
-
2510
- - Fixed DeepSeek V4 direct API requests with tools to keep documented thinking mode instead of dropping reasoning: lower OMP efforts now map to DeepSeek's supported `high`, `tool_choice` is omitted, `thinking: { type: "enabled" }` and `max_tokens` are sent, and partial user `reasoningEffortMap` overrides merge with DeepSeek defaults. ([#1207](https://github.com/can1357/oh-my-pi/issues/1207))
2511
- - Fixed model cache schema v2 databases so offline refreshes preserve cached provider discoveries after upgrading to schema v3 and subsequent online refreshes can overwrite the cache. ([#1219](https://github.com/can1357/oh-my-pi/issues/1219))
2512
- - Fixed Perplexity OAuth credentials being treated as expired one hour after login. `getJwtExpiry` was fabricating `expires = now + 1h` whenever the JWT had no `exp` claim (the common case — Perplexity sessions are server-side). Once the hour elapsed, `getOAuthApiKey` would mark the cred expired and the search provider's loader would silently skip it, surfacing as "logged out". Logins with no `exp` now persist a far-future sentinel; `getOAuthApiKey` also normalizes any stale `expires` written by older builds.
2513
-
2514
- ## [15.1.7] - 2026-05-19
2515
-
2516
- ### Added
2517
-
2518
- - Added Anthropic realization of `serviceTier: "priority"`. The anthropic-messages provider now sets `speed: "fast"` on the request and appends the `fast-mode-2026-02-01` beta to `Anthropic-Beta` whenever the caller passes `serviceTier: "priority"`. When the server rejects an unsupported model with `invalid_request_error`, the provider transparently retries the same turn without the fast-mode signal (mirroring the strict-tools fallback pattern), persists the disable via a new `providerSessionState.fastModeDisabled` flag so subsequent requests in the session skip the field, and surfaces the action via the new `AssistantMessage.disabledFeatures` array (id `"priority"`) so callers can sync user-facing toggles. A new `clearAnthropicFastModeFallback(providerSessionState)` helper lets callers re-arm priority after the auto-fallback fired.
2519
- - Added scoped `ServiceTier` values: `"openai-only"` (priority on `openai`/`openai-codex`, ignored elsewhere) and `"claude-only"` (priority on direct `anthropic`, ignored on Bedrock/Vertex Claude and elsewhere). A new `resolveServiceTier(serviceTier, provider)` helper computes the effective tier for the provider; existing OpenAI/Anthropic provider code routes through it, so `service_tier` and Anthropic fast-mode emission both respect scope. `getPriorityPremiumRequests` now counts Anthropic+priority as one premium request (previously zero) and continues to ignore providers that drop the field on the wire.
2520
-
2521
- ### Fixed
2522
-
2523
- - Fixed Anthropic fast mode (`serviceTier: "priority"`) looping on 429 `rate_limit_error: "Extra usage is required for fast mode."` for accounts without the extra-usage entitlement. `isAnthropicFastModeUnsupportedError` now matches the 429 phrasing in addition to the 400 `invalid_request_error` "does not support the `speed` parameter" case, so the provider drops `speed: "fast"` on the in-turn retry, sets `providerSessionState.fastModeDisabled` for the remainder of the session, and surfaces `disabledFeatures: ["priority"]` to the caller instead of retrying with the same payload until `PROVIDER_MAX_RETRIES` is exhausted.
2524
-
2525
- ## [15.1.6] - 2026-05-19
2526
-
2527
- ### Fixed
2528
-
2529
- - Fixed `{}` (empty JSON Schema, the wire representation of `z.unknown()`) being passed verbatim to grammar-constrained samplers (llama.cpp, etc.) in `additionalProperties`, `items`, and other schema-valued positions across **every provider** (OpenAI, Anthropic, Google, Ollama, Bedrock, Cursor). Grammar builders treat `{}` as "generate an empty object" rather than "any JSON value", causing open-typed fields (e.g. `extra.title` from `z.record(z.string(), z.unknown())`) to always emit `{}` instead of the intended string/number/etc. `toolWireSchema` now applies a new `normalizeEmptySchemas` pass (exported) to both the Zod and TypeBox/raw-JSON-Schema branches, converting `{}` → `true` (semantically identical per JSON Schema draft 2020-12 §4.3.1) in all schema-valued positions. Strict-mode opt-out is preserved across all providers: OpenAI's `hasUnrepresentableStrictObjectMap` hits the `=== true` branch instead of the `isJsonObject({})` branch (same result); Anthropic's `normalizeAnthropicStrictSchemaNode` opts out via `additionalProperties !== false` (still true for `true`); Google's `normalizeSchemaForGoogle` strips `additionalProperties` regardless (pre-existing). ([#1179](https://github.com/can1357/oh-my-pi/issues/1179))
2530
- - Fixed `pi-ai login <provider>` crashing with `Unknown provider` for providers that only the `auth-storage` `login()` switch knew about (perplexity, alibaba-coding-plan, gitlab-duo, huggingface, opencode-zen/go, lm-studio, ollama, cerebras, fireworks, qianfan, synthetic, venice, litellm, moonshot, together, cloudflare/vercel ai gateways, vllm, qwen-portal, nvidia, xiaomi, and any custom OAuth provider). The CLI now delegates to `SqliteAuthCredentialStore.login()` instead of duplicating a smaller switch, so the auth-broker `omp auth-broker login <provider>` flow works for every registered OAuth provider.
2531
-
2532
- ## [15.1.4] - 2026-05-19
2533
-
2534
- ### Changed
2535
-
2536
- - Updated auth-gateway format and pi-native request handling to invalidate the failed API key and retry the provider request with a replacement key when authentication fails
2537
-
2538
- ### Fixed
2539
-
2540
- - Fixed OpenAI Responses and Codex tool schema normalization to emit `properties: {}` for no-argument object schemas without rewriting literal payloads. ([#1147](https://github.com/can1357/oh-my-pi/issues/1147))
2541
- - Fixed Anthropic 400 (`unexpected tool_use_id found in tool_result blocks ... Each tool_result block must have a corresponding tool_use block in the previous message`) when handoff/compaction folds an assistant `tool_use` into the handoff summary string but leaves the matching user-side `tool_result` message in the history. `transformMessages` now indexes every `tool_use` id surviving the first pass and drops orphan `tool_result` messages whose originator was compacted away, preserving the text payload as a user-level `<stale-tool-result>` note so the model still sees what the tool returned. The note is emitted with `role: "user"` rather than `role: "developer"` so providers that elevate developer-role messages (Ollama: `developer` → `system`; OpenAI chat-completions reasoning models: `developer` → `developer`) cannot lift stale tool output to an instruction-priority tier above the surrounding user/developer messages.
2542
- - Fixed streaming authentication retry to trigger when a provider emits a 401 `error` event after a `start` event but before any replay-unsafe content is emitted
2543
- - Added `credential_process` support to the Bedrock provider's AWS credential resolver so profiles delegating to external brokers (`aws-vault`, `granted`, in-house tools) resolve instead of falling through to `Unable to resolve AWS credentials`. Parses the AWS SDK `Version: 1` JSON envelope, honors `Expiration` in the per-profile cache, propagates `AbortSignal` to the spawned helper, routes Windows `.cmd`/`.bat` helpers through `cmd.exe /c`, and ships a POSIX-shell-style tokenizer that preserves backslashes inside double quotes so Windows paths survive ([#1142](https://github.com/can1357/oh-my-pi/issues/1142))
2544
-
2545
- ## [15.1.3] - 2026-05-17
2546
-
2547
- ### Breaking Changes
2548
-
2549
- - Changed `AuthBrokerClient.fetchSnapshot()` to return status-based results (`200` or `304`) instead of always returning a raw snapshot body, so callers now need to branch on `status`
2550
- - Renamed public schema utilities in `@oh-my-pi/pi-ai/utils/schema` by replacing `sanitizeSchemaForGoogle`, `sanitizeSchemaForCCA`, `prepareSchemaForCCA`, and `sanitizeSchemaForMCP` with `normalizeSchemaForGoogle`, `normalizeSchemaForCCA`, and `normalizeSchemaForMCP`
2551
- - Added MCP schema normalization via `normalizeSchemaForMCP` for compatibility checks
2552
- - Removed the `StringEnum` helper from `@oh-my-pi/pi-ai/utils/schema`. Use `z.enum([...])` directly; Zod's emitted JSON Schema is already wire-compatible with Google and other providers.
2553
- - Renamed the concrete SQLite credential store class from `AuthCredentialStore` to `SqliteAuthCredentialStore`. `AuthCredentialStore` is now the persistence interface implemented by both the SQLite store and the new `RemoteAuthCredentialStore`. Update `new AuthCredentialStore(db)` / `AuthCredentialStore.open(...)` call-sites to `SqliteAuthCredentialStore`; type-position uses (`store: AuthCredentialStore`) continue to work unchanged.
2554
-
2555
- ### Added
2556
-
2557
- - Added `onAuthError` to `StreamOptions` and wired `streamSimple()` to retry once with a replacement API key when the first provider response is a 401 before any assistant events are emitted
2558
- - Added generation-aware snapshot metadata (`generation`, `serverNowMs`, `refresher`, and `rotatesInMs`) to auth-broker snapshot responses to support client-side credential-rotation planning
2559
- - Added `transport: "pi-native"` on `Model` and the matching `streamPiNative` client. When `model.transport === "pi-native"`, `streamSimple` short-circuits the per-provider dispatch and POSTs the canonical `Context` to the auth-gateway's `POST /v1/pi/stream` endpoint. The response is SSE-framed `AssistantMessageEvent`s parsed by `readSseJson` and pushed verbatim into the local `AssistantMessageEventStream` — no wire-format translation, no partial-stripping reconstruction. Used by containerized omp installs (robomp slots, swarm extension, etc.) to route every LLM call through a credential-holding sidecar; the slot itself never sees the real provider tokens. Server-controlled fields (`apiKey`, `signal`, `fetch`, lifecycle callbacks, the provider-session map) are stripped from the wire body — `apiKey` rides in the `Authorization` header as the gateway bearer.
2560
- - Added `POST /v1/pi/stream` to the auth-gateway. Same auth + abort + model-resolution + codex-compat + prefix-cache plumbing as the foreign-wire routes; only the wire-format translation is skipped. Request body is `{ modelId, context, options?, stream? }` where `context` is the canonical pi-ai `Context` and `options` is `SimpleStreamOptions` with non-serializable fields stripped. Response is SSE-framed `AssistantMessageEvent` (terminated by `data: [DONE]`) when streaming, or `{ message: AssistantMessage }` JSON when `stream: false`.
2561
- - Added Vertex AI authentication via Google Application Default Credentials from `GOOGLE_APPLICATION_CREDENTIALS`, `~/.config/gcloud/application_default_credentials.json`, or metadata server tokens, with token caching and refresh skew control via `GOOGLE_VERTEX_REFRESH_SKEW_MS`
2562
- - Added support for Anthropic image message parts with `type: "url"` and `type: "file"` sources
2563
- - Added `stopSequences` and `frequencyPenalty` to shared stream options and wired them through to OpenAI request translation
2564
- - Added optional request cancellation support to auth-broker interactions by propagating `AbortSignal` into health, snapshot, usage, and refresh calls
2565
- - Added `AuthStorage.setConfigApiKey` / `removeConfigApiKey` / `clearConfigApiKeys` for config-sourced per-provider bearers (e.g. `models.yml` `providers.<name>.apiKey`). The new tier sits between runtime `--api-key` and stored credentials in `getApiKey`/`peekApiKey` resolution, so a bearer pinned in config now beats the broker's OAuth access token. Also suppresses OAuth `account_uuid` attribution when active, since outbound auth is the explicit config bearer, not OAuth. `describeCredentialSource` reports `"config override (models.yml)"` for visibility.
2566
- - Added per-model `additional_rate_limits` parsing to `openaiCodexUsageProvider`. The Codex `wham/usage` endpoint surfaces a separate `GPT-5.3-Codex-Spark` rate limit (`metered_feature: codex_bengalfox`) on Pro accounts; these now emit dedicated `openai-codex:spark:{primary,secondary}` `UsageLimit` entries with `scope.tier = "spark"`, mirroring how Anthropic exposes `anthropic:7d:sonnet` separately from the umbrella `anthropic:7d` bucket. The osx-widgets client already keyed spark detection off `limit.id.includes("spark")`; this populates that contract end-to-end.
2567
- - Added `GET /v1/usage` to the auth-broker API to expose aggregated usage reports from `AuthStorage.fetchUsageReports`
2568
- - Added auth-broker usage polling response handling that returns normalized usage reports plus generation timestamp for clients (5-min per-credential cache via `AuthStorage`)
2569
- - Added the auth-broker subsystem (`@oh-my-pi/pi-ai/auth-broker`) for sharing OAuth credentials across machines without leaking refresh tokens.
2570
- - `startAuthBroker(...)` boots a `Bun.serve` HTTP server exposing `GET /v1/healthz`, `GET /v1/snapshot`, `POST /v1/credential` (upsert), `POST /v1/credential/:id/refresh`, and `POST /v1/credential/:id/disable`.
2571
- - `AuthBrokerClient` is the matching HTTP client used by remote clients.
2572
- - `RemoteAuthCredentialStore` is a client-side `AuthCredentialStore` that mirrors a broker snapshot in memory; mutating methods (`replace*`, `upsert*`, `delete*ForProvider`) throw because writes are server-side only.
2573
- - `AuthBrokerRefresher` is the background refresh loop that pre-refreshes credentials within `refreshSkewMs` and disables on definitive failure (`invalid_grant` / non-network 401-403).
2574
- - Added `AuthStorage.exportSnapshot()`, `AuthStorage.upsertCredential(provider, credential)`, `AuthStorage.forceRefreshCredentialById(id)`, and `AuthStorage.disableCredentialById(id, cause)` public methods consumed by the auth-broker server.
2575
- - Added `AuthStorageOptions.refreshOAuthCredential` override so a remote-store client can route every OAuth refresh through the broker instead of the local OAuth endpoint.
2576
- - Added `REMOTE_REFRESH_SENTINEL` (`"__remote__"`) — the wire placeholder substituted for OAuth refresh tokens in broker snapshots; clients never see the real refresh token.
2577
- - Exposed the OAuth provider catalog (`getOAuthProviders`, `OAuthProvider`, `OAuthProviderInfo`) and `refreshOAuthToken` through the package barrel so the coding-agent CLI can target them without reaching into `utils/oauth`.
2578
- - Added the auth-gateway subsystem (`@oh-my-pi/pi-ai/auth-gateway`) — a forward-proxy that sits between unauthenticated clients (the macOS usage widget, llm-git, robomp containers, …) and the broker. Clients send standard provider-format requests; the gateway parses them into omp's canonical `Context`, dispatches through pi-ai's `streamSimple()`, and translates the canonical event stream back to the matching wire format. `Authorization` is injected server-side so access tokens never leave the gateway host. Wire surface:
2579
- - `GET /healthz` — unauth liveness.
2580
- - `GET /v1/usage` — aggregated provider usage; 5-min per-credential cache via `AuthStorage.fetchUsageReports`.
2581
- - `GET /v1/models` — model catalog (scoped to providers with credentials).
2582
- - `POST /v1/chat/completions` — OpenAI chat-completions in/out.
2583
- - `POST /v1/messages` — Anthropic messages in/out (text + thinking + tool_use blocks, SSE event taxonomy preserved).
2584
- - `POST /v1/responses` — OpenAI Responses in/out (reasoning items + function_call output items, SSE pass-through).
2585
- - Added exports from `@oh-my-pi/pi-ai/auth-gateway`: `startAuthGateway`, `AuthGatewayServerOptions`, `AuthGatewayBootOptions`, `AuthGatewayServerHandle`, `ModelResolver`, `DEFAULT_AUTH_GATEWAY_BIND`. Per-format `parseRequest` / `encodeResponse` / `encodeStream` triples are reachable via the `./providers/*` subpath as `openai-chat-server`, `anthropic-messages-server`, and `openai-responses-server`.
2586
- - Added `listProvidersWithEnvKey()` to enumerate every provider with an env-var fallback (used by the new migrate command in coding-agent).
2587
-
2588
- ### Changed
2589
-
2590
- - Changed `GET /v1/snapshot` to support generation-based polling with `If-None-Match` and `wait` for long-poll updates and to return `304` when no snapshot changes are available
2591
- - Changed Bedrock credential resolution for streaming calls to prefer environment keys, AWS profile/SSO credentials, and IMDSv2 fallback when available
2592
- - Changed auth-gateway parsing for OpenAI chat-completions and Responses to ignore unsupported SDK-only fields instead of rejecting requests
2593
- - Changed auth-gateway protocol handling to include CORS headers on responses and support browser-origin requests
2594
- - Changed prompt-cache handling to resolve cache keys from request metadata and headers and preserve them through protocol translation
2595
- - Changed Anthropic messages parsing to forward request `metadata` through to downstream execution
2596
- - Changed usage report caching to use a 5-minute per-credential TTL with jittered refresh timing to reduce usage endpoint rate-limit collisions
2597
- - Changed usage polling failure handling so transient errors continue serving the last known report instead of returning null and dropping the credential from usage aggregates after cache expiry
2598
- - Changed `sanitizeSchemaForGoogle` to normalize snake_case schema keys (such as `any_of` and `additional_properties`) to camelCase and auto-generate `propertyOrdering` for multi-property objects
2599
- - Changed strict-mode sanitization to resolve `$ref` nodes with sibling keys by inlining and merging referenced local definitions
2600
- - Changed strict-mode sanitization to flatten single-entry `allOf` nodes and remove the `allOf` wrapper
2601
- - Changed Anthropic tool schema normalization to preserve supported metadata keywords such as `$ref`, `$defs`, `$schema`, `enum`, `const`, `default`, `title`, and `nullable` instead of stripping them
2602
- - Changed string schema processing to retain only supported `format` values (`date-time`, `time`, `date`, `duration`, `email`, `hostname`, `uri`, `ipv4`, `ipv6`, `uuid`) and demote unsupported `format` values to `description` hints
2603
-
2604
- ### Fixed
2605
-
2606
- - Fixed OAuth credential refresh flow so concurrent manual and background refreshes now share one in-flight attempt per credential, and `RemoteAuthCredentialStore` now re-synchronizes before using near-expiring OAuth credentials
2607
- - Fixed stale-credential handling after auth failures by waiting for updated broker snapshots and refreshing suspect credentials through broker endpoints before continuing
2608
- - Fixed Google Generative AI startup behavior to throw a clear API-key-required error when no key is configured
2609
- - Fixed AWS Bedrock image message serialization to preserve base64 `source.bytes` payloads instead of decoding and rebuilding them
2610
- - Fixed Google provider error handling to extract the API-reported `error.message` from JSON response bodies when available
2611
- - Fixed `RemoteAuthCredentialStore.getUsageReport` to return the matching credential-specific usage report and coalesce parallel callers into one broker `/v1/usage` fetch
2612
- - Fixed auth-broker credential upload validation to reject the remote refresh-token sentinel and prevent storing a non-refresh value
2613
- - Fixed OpenAI Responses streaming output to emit `reasoning_summary_text` events and parse/send `summary_text` reasoning payloads
2614
- - Fixed Anthropic stop-sequence handling by trimming requests to the API limit of four entries before forwarding
2615
- - Fixed prompt caching behavior across protocol translations so cached-token usage is preserved when Anthropic and OpenAI requests are routed through each other
2616
- - Fixed Claude usage fetching to retry transient `429` and `5xx` responses with exponential backoff, respecting `Retry-After` before returning failure
2617
- - Fixed auth-gateway request translation to preserve OpenAI Responses string/system message content, reasoning replay payloads, completed item text in stream item-done events, Anthropic tool-result ordering, and OpenAI Chat/Responses cached-token usage totals
2618
- - Fixed auth-gateway failure handling so unsupported request controls, upstream terminal errors, non-streaming aborts, and already-aborted client requests fail explicitly instead of being accepted, ignored, or encoded as successful HTTP 200 responses
2619
- - Fixed Gemini CLI / Antigravity tool schema normalization to run the full Cloud Code Assist pipeline, matching shared Google schema handling for union/object merging and nullable extraction
2620
- - Fixed stripped validation hints to be preserved as description spill text (`{key: value}` blocks) when `normalizeSchemaForGoogle` and `normalizeSchemaForCCA` drop unsupported schema keywords
2621
- - Fixed `sanitizeSchemaForGoogle` to collapse nullability forms (`type:'null'` and null-bearing `anyOf` variants) into `nullable` while preserving remaining variants
2622
- - Fixed `sanitizeSchemaForGoogle` to inline local `$defs` references instead of dropping `$ref`/`$defs` structure during Google schema sanitization
2623
- - Fixed `normalizeAnthropicToolSchema` to handle self-referential schemas without infinite recursion
2624
- - Fixed object schema normalization so explicit open-map declarations (`additionalProperties: true` and schema-valued `additionalProperties`) are preserved instead of being converted to closed objects
2625
- - Fixed unsupported schema constraints on arrays and strings (`maxItems`, `uniqueItems`, `pattern`, `minLength`, `maxLength`, and `minItems` when greater than 1) by demoting them into `description` rather than dropping them
2626
-
2627
- ### Security
2628
-
2629
- - Hardened auth-gateway bearer-token checks with constant-time comparison to avoid timing-side-channel leaks
2630
-
2631
- ## [15.1.2] - 2026-05-15
2632
-
2633
- ### Breaking Changes
2634
-
2635
- - Rejected draft-07 tuple and dependency keywords (`items` arrays, `dependencies`, `additionalItems`) in JSON Schema validation
2636
-
2637
- ### Added
2638
-
2639
- - Added `responseHeaders`, `responseStatus`, and `responseRequestId` fields to `MockResponse` so mock providers can provide synthetic `ProviderResponseMetadata`
2640
- - Added `onResponse` metadata emission for mocks that sends lowercased headers and a default status of 200 before streaming when response headers are configured
2641
- - Added recursive strict-mode sanitization for array `prefixItems` entries so tuple schemas now enforce object constraints per item
2642
-
2643
- ### Changed
2644
-
2645
- - Normalized legacy draft-07 JSON Schema constructs used in tool parameters (`items` arrays, `additionalItems`, `definitions`, `dependencies`) to draft 2020-12 before OpenAI/Google/CCA sanitization, wire conversion, and argument validation
2646
- - Reworked OpenAI response schema adaptation to rewrite `oneOf` into `anyOf` while preserving existing `anyOf` branches
2647
- - Changed tuple array validation to validate per-index schemas from `prefixItems` and apply `items` only to remaining elements
2648
-
2649
- ### Fixed
2650
-
2651
- - Fixed validation of plain JSON Schema tool arguments that omitted a `$schema` URI so draft-07-shaped schemas now pass validation instead of being rejected
2652
- - Fixed tuple-array validation for legacy JSON Schema tool schemas to enforce `additionalItems: false` and per-position constraints after automatic draft upgrade
2653
- - Fixed Anthropic tool schema normalization to recurse into `prefixItems` so unsupported constraints inside tuple items are stripped in the generated input schema
2654
- - Fixed Anthropic tool-schema normalization stripping the body of explicit open `additionalProperties` (e.g. Zod's `z.record(z.string(), z.unknown())` compiling to `additionalProperties: {}`) by unconditionally overwriting it with `false`, which closed record-style fields and prevented models from supplying any key. The coding-agent's `resolve` tool exposes plan-approval titles via such a field, so Kimi K2 (and any other Anthropic-shaped provider) could not pass `extra: { title }`, blocking plan mode entirely ([#1104](https://github.com/can1357/oh-my-pi/issues/1104))
2655
- - Fixed Anthropic strict tool planning to leave tools with open `additionalProperties` maps non-strict instead of sending schemas Anthropic rejects.
2656
-
2657
- ## [15.1.0] - 2026-05-15
2658
-
2659
- ### Breaking Changes
2660
-
2661
- - Removed TypeBox root exports (`Type`, `Static`, and `TSchema`) from the package entrypoint, so callers importing those symbols from `@oh-my-pi/pi-ai` must migrate to `zod` or `@oh-my-pi/pi-ai/types`
2662
-
2663
- ### Added
2664
-
2665
- - Added support for defining tool schemas with Zod (`z.object`, `z.string`, etc.) by allowing `Tool.parameters` to be either Zod schemas or legacy JSON Schema objects and converting them to provider wire format automatically
2666
- - Added package-level schema helpers in the `zod/v4` style by exporting `z` and `ZodType` from the root entrypoint
2667
- - Added a `mock` API provider via `createMockModel` to build `Model<"mock">` instances for fully in-memory, deterministic assistant streams in tests
2668
- - Added `streamMock` and `registerMockApi` so mock responses can be consumed through `stream()` and the global custom API registry without an external model backend
2669
- - Added async/sync response scripting with optional context-based handlers, and new `push()`/`reset()` controls to drive multi-turn mock interactions and inspect per-call invocation state
2670
- - Added support in mock responses for simulating tool calls, usage metadata, custom stop reasons, delayed emissions, and terminal error/aborted outcomes
2671
-
2672
- ### Changed
2673
-
2674
- - Changed Azure OpenAI Responses tool schema conversion to sanitize tool parameter schemas and rewrite `oneOf` branches as `anyOf` so tool calls remain compatible with Azure's schema expectations
2675
- - Changed `Static<S>` to extract a schema object’s `static` type when present, improving inferred tool argument types for non-Zod parameter definitions
2676
- - Changed `Static` typing behavior so it now infers argument types from Zod schemas and defaults to `unknown` for non-Zod JSON Schema parameter definitions
2677
- - Restored the default steady-state stream idle timeout to 120s (regressed in 15.0.0). 30s was too aggressive for reasoning models, slow proxies, and tool-call planning gaps, surfacing as repeated `Provider stream stalled while waiting for the next event` errors. Existing `PI_STREAM_IDLE_TIMEOUT_MS` / `PI_OPENAI_STREAM_IDLE_TIMEOUT_MS` overrides are unchanged.
2678
-
2679
- ### Fixed
2680
-
2681
- - Preserved top-level unknown fields in validated tool-call arguments so extra root properties are retained after schema coercion
2682
- - Fixed coercion for Zod `record` fields by parsing JSON-stringified record arguments into objects
2683
- - Validated legacy draft-07 JSON Schema tool parameters directly instead of converting through Zod, improving support for features like `$ref`, `definitions`, `nullable`, and `uniqueItems`
2684
- - Fixed Cloud Code Assist schema preparation to strip unsupported `propertyNames` and fall back to a minimal tool schema when schema meta-validation detects malformed keywords
2685
- - Fixed OpenAI Completions streaming to avoid treating non-output chunks (including role-only preambles) as progress events so idle-timeout watchdog behavior no longer hangs on no-op streamed chunks
2686
- - Fixed Cloud Code Assist schema compatibility checks by replacing strict AJV meta-schema validation with structural JSON Schema validation to avoid rejecting structurally valid tool schemas
2687
- - Fixed lazy built-in provider streams (`anthropic-messages`, `bedrock-converse-stream`, `cursor-agent`, `google-*`, `ollama-chat`, `openai-*`) prematurely aborting slow first-token responses with `Provider stream stalled while waiting for the next event`. The lazy-stream watchdog wrapper was treating the synthetic `start` event (yielded immediately by every provider before the model emits any tokens) as the first real item, which caused the watchdog to drop from `firstItemTimeoutMs` (100s) to `idleTimeoutMs` (30s) before the upstream model had produced anything. The shared `iterateWithIdleTimeout` now keeps `awaitingFirstItem` true until a real progress item arrives, and the lazy-stream wrapper marks `start` as a non-progress keepalive ([#1073](https://github.com/can1357/oh-my-pi/pull/1073) regression).
2688
- - Heal leaked Kimi K2 chat-template tool-call tokens (`<|tool_calls_section_begin|>` … `<|tool_call_argument_begin|>` … `<|tool_calls_section_end|>`) that some hosts (native `kimi-code` API, OpenRouter, Fireworks, etc.) emit into `delta.content` instead of structured `tool_calls`. The OpenAI-completions stream consumer now strips the markers from visible text, reconstructs the embedded calls as proper `toolCall` content blocks (stream-aware, token-boundary-safe), and promotes `finish_reason: stop` to `toolUse` when calls were healed.
2689
- - Fixed OpenAI-completions Kimi K2 healed-call promotion clobbering non-stop terminal finish reasons (`error`, `length`, `aborted`); promotion now only fires when the prior stop reason is the natural-completion `stop`
2690
- - Fixed OpenAI-completions duplicate Kimi tool calls when a single chunk delivers both leaked markers and a structured `delta.tool_calls`; the healer now strips visible markers but discards its synthesized calls so structured payloads remain the single source of truth
2691
- - Fixed Kimi tool-call healer synthesizing a bogus empty call when assistant text mentions a literal `<|tool_call_end|>` (or `<|tool_call_begin|>` / `<|tool_call_argument_begin|>`) outside an active `<|tool_calls_section_begin|>…<|tool_calls_section_end|>` section; the tokens now survive as text
2692
- - Fixed OpenAI-completions ignoring per-request `StreamOptions.streamFirstEventTimeoutMs` when configuring the underlying OpenAI SDK HTTP timeout, causing slow-before-headers providers to be aborted at the env default before the wrapping watchdog armed
2693
- - Fixed JSON Schema validator silently accepting values that violate `propertyNames`, `patternProperties`, `dependentRequired`, `dependencies`, `if`/`then`/`else`, `contains`, and `prefixItems`; the in-tree validator now enforces these keywords instead of falling through. `unevaluatedProperties`/`unevaluatedItems` remain permissive but log a one-time warning so tool authors are not surprised.
2694
- - Fixed recursive `$ref` schemas being treated as universally valid: the validator previously short-circuited on the second occurrence of any ref it had already seen, so nested values violating the referenced sub-schema passed. Cycle detection now keys on (ref, value-identity) pairs with a depth cap for primitive values, so genuine sub-tree violations are still caught.
2695
- - Fixed JSON Schema meta-validator accepting malformed `if`/`then`/`else` and `dependencies` keywords; each conditional sub-schema is now structurally validated and draft-07 `dependencies` accepts either a schema or a string array of dependent keys.
2696
- - Fixed Zod-emitted wire schemas dropping null-valued unknown root fields before `preserveUnknownRootFields` could snapshot them, so callers like `task.simple` no longer lose a `schema: null` argument and downstream rejection paths fire as intended.
2697
- - Fixed mock provider partial `Usage` to recompute `totalTokens` (and `cost.total` when cost components are supplied) when omitted, instead of reporting 0
2698
- - Fixed mock provider auto-generated tool-call IDs to use a per-instance counter (now reset by `reset()`), so test order no longer affects IDs across `createMockModel()` instances
2699
-
2700
- ## [15.0.2] - 2026-05-15
2701
-
2702
- ### Fixed
2703
-
2704
- - Fixed `StreamOptions.fetch` typing to accept fetch-compatible override functions that do not expose `preconnect`, allowing custom fetch implementations to be used without type errors across runtimes
2705
- - Fixed Moonshot Kimi K2.6 forced tool calls to send `thinking: { type: "disabled" }`, avoiding `tool_choice 'specified' is incompatible with thinking enabled` 400s while preserving the requested named tool ([#1077](https://github.com/can1357/oh-my-pi/issues/1077)).
2706
-
2707
- ## [15.0.1] - 2026-05-14
2708
-
2709
- ### Breaking Changes
2710
-
2711
- - Increased the minimum Bun runtime version to `>=1.3.14` for the `@aws-?` package
2712
-
2713
- ### Added
2714
-
2715
- - Added `installH2Fetch` to patch `globalThis.fetch` so HTTPS requests attempt HTTP/2 over ALPN with automatic HTTP/1.1 fallback when HTTP/2 is unsupported
2716
- - Added priority service-tier traffic to the `premiumRequests` accounting on OpenAI and OpenAI Codex providers. Sending `serviceTier: "priority"` now increments `usage.premiumRequests` by 1 per request, matching the existing GitHub Copilot premium-request budget semantics so downstream consumers (e.g. the `omp stats` "Premium Reqs" card and `/usage`) reflect priority traffic alongside Copilot premium calls.
2717
-
2718
- ## [15.0.0] - 2026-05-13
2719
-
2720
- ### Added
2721
-
2722
- - Added `AuthStorage.onCredentialDisabled(listener)` — a multi-subscriber `on/off` API for `credential_disabled` events. Returns an unsubscribe function; calling it more than once is a no-op. Multiple subscribers all receive every disable event, with synchronous and async exceptions isolated per-listener so a misbehaving subscriber cannot starve the rest of the chain. Buffer-and-replay semantics are preserved: events emitted while no listener is subscribed are buffered (FIFO, capped at 32) and replayed once to the listener that triggers the empty→non-empty transition. After every subscriber unsubscribes, subsequent disable events buffer again until the next subscribe.
2723
-
2724
- ### Fixed
2725
-
2726
- - Fixed OAuth credentials being silently disabled when two omp processes (or any two `AuthStorage` instances sharing a `agent.db`) race on token refresh. Anthropic rotates refresh tokens on every use, so the loser's `invalid_grant` response previously soft-deleted the row that the winner just rotated, forcing the user to `/login` again. `#tryOAuthCredential` now re-reads the row from disk before declaring a definitive failure: if the persisted `refresh` differs from the snapshot it tried, the peer-rotated credential is reloaded and the request retries against the fresh token instead of disabling the live row.
2727
- - Closed a remaining race window in OAuth refresh-failure handling: between re-reading the credential row to check for peer rotation and the subsequent soft-delete, another process could still complete a refresh and rotate the row, leaving us to disable the freshly-rotated credential by `id`. The disable now runs as a single CAS update conditioned on the row's `data` still matching the snapshot we tried to refresh, and on `disabled_cause IS NULL`. If the CAS reports 0 rows changed (peer rotation, or row already disabled by a concurrent failure on the same snapshot), we reload from disk and retry instead of mutating the wrong row or emitting a spurious `credential_disabled` event.
2728
-
2729
- ## [14.9.3] - 2026-05-10
2730
-
2731
- ### Fixed
2732
-
2733
- - Anthropic provider now retries generic transient connect failures (`unable to connect`, `fetch failed`, `connection error`, etc.) by falling back to the shared `isRetryableError` allowlist after the provider-specific patterns. Previously these errors bypassed the hand-curated regex in `isProviderRetryableError` and aborted the stream on the first attempt, while the OpenAI SDK and Codex `fetchWithRetry` paths already handled them.
2734
-
2735
- ## [14.9.0] - 2026-05-10
2736
-
2737
- ### Fixed
2738
-
2739
- - Fixed silent forwarding of image content (for example Python plot output rendered in the terminal) to models without vision support, which produced opaque 404 errors from upstream. Image blocks are now stripped and replaced with a `[image omitted: model does not support vision]` placeholder for non-vision models, including tool-result payloads ([#967](https://github.com/can1357/oh-my-pi/issues/967), [#968](https://github.com/can1357/oh-my-pi/issues/968)).
2740
- - Added `AuthStorage` `onCredentialDisabled` callback (sync or async) so embedders can react when a credential is automatically disabled (e.g. OAuth refresh fails with `invalid_grant`) — useful for surfacing a banner or auto-launching a re-login flow instead of letting the credential silently disappear. Sync throws and async rejections are both caught and logged so a misbehaving subscriber cannot break the disable path.
2741
- - Added Anthropic OAuth `account.uuid` and `account.email_address` extraction from the `/v1/oauth/token` exchange and refresh responses; both `AnthropicOAuthFlow.exchangeToken()` and `refreshAnthropicToken()` now populate `OAuthCredentials.{accountId, email}` so downstream consumers can attribute requests to the authenticated account without a separate `/api/oauth/profile` round-trip.
2742
- - Added `onSseEvent` stream diagnostics so HTTP SSE providers can expose raw SSE frames without changing parsed model output.
2743
- - Added `streamIdleTimeoutMs` option (and `PI_STREAM_IDLE_TIMEOUT_MS` env override; `PI_OPENAI_STREAM_IDLE_TIMEOUT_MS` remains a backward-compatible alias) for a steady-state inter-event watchdog. Set to `0` to disable.
2744
- - Added a semantic-progress predicate to OpenAI Responses and Codex SSE/WebSocket transports so `response.in_progress`-style keepalives no longer reset the idle deadline on stalled tool calls.
2745
-
2746
- ### Changed
2747
-
2748
- - Anthropic streams now enforce a steady-state idle timeout (defaults to 120s, same control as `PI_STREAM_IDLE_TIMEOUT_MS`) in addition to the first-event watchdog. Long-running responses that go fully silent between events will now surface as `Anthropic stream stalled while waiting for the next event` instead of hanging.
2749
- - Fixed `resolveAnthropicMetadataUserId()` to accept JSON-format `user_id` values that match real Claude Code's payload shape (`{ device_id, account_uuid, session_id, ... }` from `services/api/claude.ts:getAPIMetadata`). Previously only the synthetic `user_<hex>_account_<uuid>_session_<uuid>` cloaking format was accepted on OAuth, which caused stable session-keyed metadata supplied by callers to be discarded and replaced with fresh random entropy on every request — defeating session-count attribution on the Claude OAuth path.
2750
-
2751
- ## [14.8.0] - 2026-05-09
2752
-
2753
- ### Fixed
2754
-
2755
- - Fixed Gemini 3 Pro thinking metadata so `medium` effort is rejected with the expected error instead of being silently accepted: `ThinkingConfig` now carries an optional explicit `levels` list that survives `expandEffortRange`, letting non-contiguous supported sets (e.g. `[low, high]`) round-trip through enrichment.
2756
- - Fixed Kimi Code OAuth expiry handling to refresh access tokens 5 minutes before server expiry, avoiding daily 401s from using tokens right up to the cutoff.
2757
-
2758
- ## [14.7.6] - 2026-05-07
2759
-
2760
- ### Added
2761
-
2762
- - Added `hideThinkingSummary` option to `SimpleStreamOptions`. When true, `streamSimple` requests that the underlying provider omit reasoning/thinking summaries: Anthropic receives `thinking.display = "omitted"` (where supported), and OpenAI Responses / Azure / Codex providers leave `reasoning.summary` unset so the server skips emitting the human-readable summary stream entirely.
2763
-
2764
- ### Changed
2765
-
2766
- - Changed OpenAI Responses, Azure OpenAI Responses, and OpenAI Codex providers to omit `reasoning.summary` from requests when `reasoningSummary` is explicitly `null` (previously fell back to `"auto"`).
2767
-
2768
- ## [14.7.5] - 2026-05-07
2769
-
2770
- ### Added
2771
-
2772
- - Added `OpenAICompat.supportsMultipleSystemMessages` so chat-completions hosts can opt out of separate leading system blocks. Auto-detected as `true` for OpenAI, Azure, OpenRouter, Cerebras, Together, Fireworks, Groq, DeepSeek, Mistral, xAI, Z.ai, GitHub Copilot, and Zenmux; `false` for MiniMax, Alibaba Dashscope, and Qwen Portal whose chat templates reject follow-up system messages. Unknown OpenAI-compatible hosts (custom vLLM/local) default to `false`; users can opt back in via `compat.supportsMultipleSystemMessages: true`.
2773
-
2774
- ### Fixed
2775
-
2776
- - Fixed strict-template OpenAI-compatible hosts (e.g. Qwen 3.5+ via vLLM, MiniMax) rejecting follow-up `system`/`developer` messages by coalescing ordered system prompts into a single block joined by `\n\n` when `compat.supportsMultipleSystemMessages` is false. Canonical hosts continue to receive separate blocks so KV-cache reuse stays effective when only the trailing prompt changes ([#958](https://github.com/can1357/oh-my-pi/issues/958)).
2777
-
2778
- ## [14.7.2] - 2026-05-06
2779
-
2780
- ### Fixed
2781
-
2782
- - Fixed VLLM model discovery to use `max_model_len` as the context window when the endpoint reports it.
2783
- - Fixed custom Ollama Cloud/local-proxy model aliases (for example `deepseek-v4-pro:cloud`) to inherit bundled cache-pricing metadata when the upstream model is known ([#937](https://github.com/can1357/oh-my-pi/issues/937)).
2784
- - Fixed local Ollama model discovery to apply `/api/show` thinking and vision capabilities in addition to native context windows ([#928](https://github.com/can1357/oh-my-pi/issues/928)).
2785
-
2786
- ## [14.7.0] - 2026-05-04
2787
-
2788
- ### Breaking Changes
2789
-
2790
- - Changed `Context.systemPrompt` from a string to `string[]`, so callers must now pass an array of prompts instead of a single string
2791
- - Changed behavior will throw at runtime for non-array system prompts because request builders now normalize system prompts as an array
2792
-
2793
- ### Added
2794
-
2795
- - Added support for multiple system prompts by changing `Context.systemPrompt` to an ordered string array and preserving provider-appropriate instruction precedence
2796
-
2797
- ### Changed
2798
-
2799
- - Changed request builders for Anthropic, OpenAI, Bedrock, Azure, Cursor, Google, and Ollama to propagate every non-empty system prompt entry without demoting durable instructions into ordinary conversation turns
2800
-
2801
- ### Fixed
2802
-
2803
- - Filtered out empty normalized system prompts so blank entries are no longer sent to providers
2804
- - Removed blank system prompt strings from provider payloads to avoid unnecessary empty instruction messages
2805
-
2806
- ## [14.6.6] - 2026-05-04
2807
-
2808
- ### Added
2809
-
2810
- - Added always-on OpenRouter response caching (1h TTL) by sending `X-OpenRouter-Cache: true` and `X-OpenRouter-Cache-TTL: 3600` on every OpenRouter request — identical requests replay from OpenRouter's edge cache for free. https://openrouter.ai/docs/features/response-caching
2811
-
2812
- ## [14.6.4] - 2026-05-03
2813
-
2814
- ### Fixed
2815
-
2816
- - Fixed OpenAI Codex websocket continuations to retry with full context when `previous_response_id` expires server-side instead of surfacing `previous_response_not_found`.
2817
-
2818
- ## [14.6.2] - 2026-05-03
2819
-
2820
- ### Added
2821
-
2822
- - Added `EventStream.fail(err)` method to terminate the async iterator with an error, enabling consumers to catch stream-level failures via `for await` without hanging
2823
-
2824
- ### Fixed
2825
-
2826
- - Fixed OpenAI Responses tool schema conversion to rewrite non-strict `oneOf` unions to `anyOf` before sending tools to the Responses API ([#920](https://github.com/can1357/oh-my-pi/issues/920))
2827
-
2828
- ## [14.6.0] - 2026-05-02
2829
-
2830
- ### Added
2831
-
2832
- - Added `disableReasoning` to stream and OpenAI completion options to force reasoning off for models that support it, sending `reasoning: { enabled: false }` for OpenRouter-compatible requests
2833
- - Added `thinkingDisplay` option to Anthropic options to control whether adaptive and explicit reasoning is returned as `summarized` or `omitted`
2834
- - Added Anthropic model compatibility flags `supportsEagerToolInputStreaming` and `supportsLongCacheRetention` for API-capability-specific request behavior
2835
-
2836
- ### Changed
2837
-
2838
- - Changed Anthropic request payloads to send `thinking: { type: "disabled" }` when `thinkingEnabled` is explicitly `false` on reasoning-enabled models
2839
- - Changed Anthropic cache retention handling so `cacheRetention: "long"` now uses `ttl: "1h"` only for canonical Anthropic endpoints with long-cache support
2840
- - Changed Anthropic tool schema generation to include `eager_input_streaming` only on models that advertise support
2841
- - Changed Anthropic OAuth login flow to include browser fallback guidance and richer error context when token exchange or refresh fails
2842
-
2843
- ### Fixed
2844
-
2845
- - Fixed Anthropic non-thinking requests to include the caller-provided `temperature` value in request payloads
2846
- - Fixed Anthropic `claude-opus-4-7` non-thinking payloads to omit sampling fields (`temperature`, `top_p`, and `top_k`)
2847
- - Fixed OpenAI Codex base URL normalization so configured base URLs with or without `/codex` or `/codex/responses` now resolve to `/codex/responses`
2848
- - Fixed OpenAI Codex websocket handling to parse JSON from non-string message payloads including `ArrayBuffer`, typed arrays, and `Blob` values
2849
- - Fixed OpenAI Codex websocket handshakes to replace stale `openai-beta` values with the websocket beta and avoid sending request-body headers over websocket transport
2850
- - Fixed abort tracking so caller-initiated cancellations are treated as user aborts even after local watchdog timeouts, preventing unintended automatic retries
2851
- - Fixed Anthropic stream handling to parse raw SSE envelopes directly, ignore unrelated events, and repair malformed JSON in SSE payloads
2852
- - Fixed Anthropic streaming to emit an explicit error when the SSE stream ends without a `message_stop` event
2853
- - Fixed OpenAI Codex websocket continuations to send true `previous_response_id` deltas for `store: false` transcripts, expose request stats, and default text verbosity to `low` unless explicitly overridden.
2854
- - Fixed OpenAI Codex websocket append reuse after `response.completed` terminal events.
2855
-
2856
- ## [14.5.14] - 2026-05-01
2857
-
2858
- ### Added
2859
-
2860
- - Added package-level `google-gemini-headers` exports (`getGeminiCliHeaders`, `getGeminiCliUserAgent`, `getAntigravityHeaders`, `extractRetryDelay`, and `ANTIGRAVITY_SYSTEM_INSTRUCTION`) for header and retry handling reuse without importing full Google providers
2861
-
2862
- ### Changed
2863
-
2864
- - Changed package exports and streaming/provider wiring to load heavy Google/Kimi/GitLab/synthetic provider modules lazily through `register-builtins`, reducing startup import overhead from optional provider SDKs
2865
-
2866
- ### Fixed
2867
-
2868
- - Fixed DeepSeek V4 tool-call follow-up 400 errors from three root causes:
2869
- - Mapped `reasoning_effort` "xhigh" to "max" for DeepSeek-family models on any provider (NVIDIA, OpenCode-Go, etc.), not just `deepseek`
2870
- - Recovered `reasoning_content` from thinking blocks with valid signatures that were filtered by the non-empty-text check
2871
- - Added empty-string fallback when `reasoning_content` is genuinely absent (e.g. proxy-stripped) but the provider requires the field
2872
-
2873
- ## [14.5.13] - 2026-05-01
2874
-
2875
- ### Breaking Changes
2876
-
2877
- - Removed `utils/oauth` re-exports from the package entrypoint, so OAuth helper imports from the root module must be updated
2878
-
2879
- ## [14.5.10] - 2026-04-30
2880
-
2881
- ### Added
2882
-
2883
- - Added provider response metadata callbacks for Anthropic and OpenAI streaming requests.
2884
-
2885
- ## [14.5.9] - 2026-04-30
2886
-
2887
- ### Added
2888
-
2889
- - Added `usage.reasoningTokens` to OpenAI and Google usage output when providers report reasoning/thinking tokens
2890
- - Added `usage.cttl.ephemeral5m` and `usage.cttl.ephemeral1h` to report Anthropic cache-write TTL token buckets
2891
- - Added `usage.server.webSearch` and `usage.server.webFetch` to report Anthropic server tool-call request counts
2892
-
2893
- ### Fixed
2894
-
2895
- - Fixed OpenAI usage attribution to avoid double-counting `reasoning_tokens` in output totals
2896
- - Fixed Anthropic streaming usage handling so a previously populated cache TTL breakdown is preserved when later events omit `cache_creation`
2897
-
2898
- ## [14.5.4] - 2026-04-28
2899
-
2900
- ### Changed
2901
-
2902
- - Changed OpenAI custom Lark grammar payloads to strip comments and blank lines before sending provider requests.
2903
-
2904
- ### Fixed
2905
-
2906
- - Fixed OpenAI Codex GPT model pricing by inheriting matching OpenAI catalog rates for zero-priced discovered Codex entries.
2907
-
2908
- ## [14.5.3] - 2026-04-27
2909
-
2910
- ### Added
2911
-
2912
- - Added `fireworks` as a supported provider with API key login flow and credential storage
2913
- - Added Fireworks model catalog support with `fireworks`-scoped openai-completions models `glm-5`, `glm-5.1`, `kimi-k2.5`, `kimi-k2.6`, and `minimax-m2.7`
2914
- - Added built-in discovery wiring so providers with base URL `api.fireworks.ai` are recognized as OpenAI-compatible and can use streaming token control
2915
-
2916
- ### Changed
2917
-
2918
- - Updated the built-in model catalog to use corrected `contextWindow` and `maxTokens` values for many existing models instead of placeholder limits
2919
- - Updated several model cost entries, including cache-read pricing, to corrected values
2920
-
2921
- ### Fixed
2922
-
2923
- - Fixed Fireworks request formatting by translating between public model IDs and API wire IDs when sending OpenAI-completions requests
2924
- - Fixed OpenAI-compatible model parameter handling for Fireworks by allowing `max_tokens` to be sent during requests
2925
-
2926
- ## [14.5.1] - 2026-04-26
2927
-
2928
- ### Fixed
2929
-
2930
- - Fixed NVIDIA NIM DeepSeek-V4 models leaking chat-template tool-call markers (e.g. `<|DSML|tool_calls|>`) into visible response text by stripping the special tokens from streamed `delta.content` ([#798](https://github.com/can1357/oh-my-pi/issues/798))
2931
-
2932
- ## [14.4.0] - 2026-04-26
2933
-
2934
- ### Added
2935
-
2936
- - Added an `examples` option to `StringEnum` to include example values in the generated schema
2937
-
2938
- ### Changed
2939
-
2940
- - Changed Anthropic tool schema generation to strip unsupported schema fields (including `patternProperties`), add `additionalProperties: false` for object types, and apply Anthropic strict-mode limits when marking tools as strict
2941
- - Changed Anthropic strict tool planning to cap strict `tools` at twenty entries and convert excess optional/union parameters to nullable schemas to stay within provider constraints
2942
-
2943
- ### Fixed
2944
-
2945
- - Fixed Anthropic tool schema compilation failures by keeping the `write` tool out of the strict-tool allowlist when the full coding-agent tool set is active
2946
- - Fixed Anthropic 400 `tools.*.custom: For 'object' type, property 'minItems' is not supported` by stripping `minItems` from object-shaped JSON schema nodes (array nodes still keep supported `minItems` values)
2947
- - Fixed Anthropic tool schemas that used tuple-style arrays by stripping unsupported `maxItems` and only preserving provider-supported `minItems` values
2948
- - Fixed Anthropic and OpenRouter Anthropic tool calls that previously failed with `compiled grammar is too large` by retrying automatically without strict tool schemas and reusing non-strict mode for subsequent requests in the same provider session
2949
- - Fixed parsing of JSON tool arguments containing raw control characters inside string values (such as embedded newlines) by escaping them before JSON parsing
2950
- - Fixed `validateToolArguments` to accept stringified objects and arrays that include literal control characters inside string fields
2951
- - Fixed OpenAI Codex Spark OAuth selection to fall back to non-Pro accounts when no ChatGPT Pro account is connected, so users without a Pro account can still attempt Spark requests in case the server permits access.
2952
-
2953
- ## [14.3.0] - 2026-04-25
2954
-
2955
- ### Added
2956
-
2957
- - Added support for Claude Opus 4.7 (`claude-opus-4-7`) model ([#726](https://github.com/can1357/oh-my-pi/issues/726))
2958
- - Suppresses sampling parameters (temperature/top_p/top_k) that Opus 4.7 rejects
2959
- - Enables `display: "summarized"` for adaptive thinking to restore visible thinking content
2960
-
2961
- ### Fixed
2962
-
2963
- - Fixed Cursor provider losing conversation history on follow-up turns (model responding "this appears to be the start of our session") by populating `ConversationStateStructure.rootPromptMessagesJson` with JSON blob IDs for the system prompt plus prior user/assistant/tool-result messages. Cursor's server builds the model prompt from `rootPromptMessagesJson`, not from the protobuf `turns[]` tree, so sending only the system prompt there caused prior turns to be dropped
2964
- - Fixed Cursor provider multi-turn conversations failing with `Connect error internal: Blob not found` on the second message by storing `ConversationStateStructure.turns`, `AgentConversationTurnStructure.user_message`, and `AgentConversationTurnStructure.steps` as content-addressed blob IDs in the KV store (matching the existing handling for `rootPromptMessagesJson`) rather than sending the raw serialized bytes inline ([#678](https://github.com/can1357/oh-my-pi/issues/678))
2965
-
2966
- ## [14.2.1] - 2026-04-24
2967
-
2968
- ### Fixed
2969
-
2970
- - Fixed OpenAI Codex Spark OAuth selection to require a verified ChatGPT Pro account instead of falling back to Plus or unknown-plan accounts.
2971
-
2972
- ## [14.2.0] - 2026-04-23
2973
-
2974
- ### Added
2975
-
2976
- - Added `gpt-5.5` to the built-in model catalog for both OpenAI Responses (`openai`) and local `litellm` (`openai-completions`) providers
2977
- - Added `gpt-image-2` to the `litellm` built-in model catalog
2978
- - Added `isCopilotTransientModelError()` and `callWithCopilotModelRetry()` helpers in `utils/retry` that detect GitHub Copilot's intermittent `HTTP 400 model_not_supported` responses for preview models (`gpt-5.3-codex`, `gpt-5.4`, `gpt-5.4-mini`, ...) and retry the request up to three times with backoff. OpenAI Responses, OpenAI Completions, and Anthropic provider paths now participate in this retry when the model is served through Copilot.
2979
- - Added OpenAI Responses custom-tool grammar support for Codex-style `apply_patch` calls, including freeform streaming, history replay, and forced tool-choice mapping to the custom wire name.
2980
-
2981
- ### Changed
2982
-
2983
- - Updated built-in model metadata with revised `contextWindow`, `maxTokens`, and pricing values for existing entries
2984
- - Changed generated model policies to assign `applyPatchToolType: "freeform"` for first-party GPT-5 OpenAI Responses and Codex models, so regenerated `models.json` preserves the `apply_patch` custom-tool metadata.
2985
- - Renamed `rewriteCopilotAuthError` to `rewriteCopilotError` and extended it to rewrite `HTTP 400 model_not_supported` after retries are exhausted with guidance about Copilot's OAuth-client-specific rollout gap (see opencode#13313).
2986
-
2987
- ### Fixed
2988
-
2989
- - Fixed Amazon Bedrock proxy handling to honor lowercase `http_proxy`, `https_proxy`, and `all_proxy` environment variables when using HTTP/1 fallback
2990
- - Fixed Amazon Bedrock streaming behind corporate HTTP proxies by using a proxy-aware HTTP/1 transport when `HTTPS_PROXY`, `HTTP_PROXY`, or `ALL_PROXY` is configured, including AWS SSO credential calls.
2991
- - Fixed Amazon Bedrock requests to retry once with HTTP/1 when the AWS SDK's default HTTP/2 transport fails before streaming begins.
2992
- - Fixed OpenAI Responses streaming to display thinking tokens from local providers (llama.cpp, etc.) that send raw `reasoning_text.delta` events and empty `summary` arrays in `output_item.done`. Previously, thinking content was silently dropped during streaming while non-streaming mode worked correctly.
2993
- - Synced the bundled OpenCode Go catalog with the current docs so `kimi-k2.6`, `mimo-v2.5`, and `mimo-v2.5-pro` appear in offline/default model lists.
2994
-
2995
- ## [14.1.3] - 2026-04-17
2996
-
2997
- ### Fixed
2998
-
2999
- - Preserved user-provided `session_id` and `x-client-request-id` headers in OpenAI Responses requests instead of overriding them with automatic session-derived values
3000
- - Stopped sending `session_id` and `x-client-request-id` headers for OpenAI Responses requests when `cacheRetention` is set to `none`
3001
- - Fixed direct OpenAI Responses requests to send `session_id` and `x-client-request-id` from the same session-derived value as `prompt_cache_key`, improving prompt cache affinity for append-only sessions
3002
-
3003
- ## [14.1.1] - 2026-04-14
3004
-
3005
- ### Added
3006
-
3007
- - Added `toolStrictMode` compatibility option (`"all_strict"` or `"none"`) to OpenAI-compatible model config to force tool schemas to be sent uniformly strict, uniformly non-strict, or keep mixed per-tool behavior
3008
-
3009
- ### Changed
3010
-
3011
- - Changed Cerebras OpenAI-compatible providers to default `toolStrictMode` to `"all_strict"` unless explicitly overridden
3012
-
3013
- ### Fixed
3014
-
3015
- - Fixed OpenAI Completions handling for providers that reject mixed `strict` flags by automatically retrying with non-strict tool schemas when an initial all-strict tool request fails with strict-format 400/422 errors
3016
- - Fixed OpenAI-completions error reporting by including captured JSON error body details such as type, param, and code when a request fails without a body in the thrown SDK error
3017
- - Fixed shell execution failure responses to preserve all result fields when sanitizing, preventing truncated metadata in stream results
3018
- - Fixed context overflow detection to recognize `model_context_window_exceeded` from z.ai / GLM providers, preventing infinite retry loops when context window is exceeded ([#638](https://github.com/can1357/oh-my-pi/issues/638))
3019
- - Fixed strict tool schema enforcement to preserve `additionalProperties: false` and required keys for reused nested object schemas, preventing invalid `todo_write` function schemas in Codex/OpenAI requests
3020
-
3021
- ## [14.1.0] - 2026-04-11
3022
-
3023
- ### Added
3024
-
3025
- - Added `accountId` to usage report metadata
3026
-
3027
- ### Changed
3028
-
3029
- - Changed usage parsing to emit a usage report with available fields when parsing fails, rather than returning null
3030
-
3031
- ### Fixed
3032
-
3033
- - Fixed `planType` resolution to fall back to the raw payload `plan_type` when parsed value is absent
3034
- - Fixed usage metadata `raw` fallback to preserve the original payload when parsed raw output is missing
3035
-
3036
- ## [14.0.5] - 2026-04-11
3037
-
3038
- ### Changed
3039
-
3040
- - Replaced GitHub Copilot authentication from VSCode extension impersonation to the opencode OAuth flow, eliminating TOS concerns. Existing users will need to re-authenticate once with `/login github-copilot`.
3041
- - Simplified Copilot token handling: GitHub OAuth token is used directly for all API requests (no JWT exchange or refresh cycle).
3042
- - Changed GitHub Copilot API base URL from `api.individual.githubcopilot.com` to `api.githubcopilot.com`.
3043
- - Updated default OpenAI stream idle timeout to 120,000 milliseconds to keep stream generation alive longer
3044
-
3045
- ### Fixed
3046
-
3047
- - Fixed duplicate synthetic tool results being generated when a real tool result appears later in message history
3048
- - Fixed GitHub Copilot `/models` discovery to unwrap structured OAuth credentials before sending the bearer token, preserving dynamic catalog refresh for OAuth-backed callers.
3049
-
3050
- ### Removed
3051
-
3052
- - Removed Copilot JWT proxy-ep base URL resolution (no longer needed with opencode auth).
3053
-
3054
- ## [14.0.3] - 2026-04-09
3055
-
3056
- ### Fixed
3057
-
3058
- - Fixed Ollama discovery cache normalization so cached models upgrade to the OpenAI Responses transport after the provider change
3059
-
3060
- ## [14.0.0] - 2026-04-08
3061
-
3062
- ### Breaking Changes
3063
-
3064
- - Removed `coerceNullStrings` function and its automatic null-string coercion behavior from JSON parsing
3065
-
3066
- ### Added
3067
-
3068
- - Added support for OpenRouter provider with strict mode detection
3069
- - Added automatic cleaning of literal escape sequences (`\n`, `\t`, `\r`) in JSON parsing to handle LLM encoding confusion
3070
- - Added support for healing JSON with trailing junk after balanced containers (e.g., `]\n</invoke>`)
3071
- - Added `CODEX_STARTUP_EVENT_CHANNEL` constant and `CodexStartupEvent` type for monitoring Codex provider initialization status
3072
- - Added automatic healing of malformed JSON with single-character bracket errors at the end of strings, improving LLM tool argument parsing robustness
3073
-
3074
- ## [13.19.0] - 2026-04-05
3075
-
3076
- ### Fixed
3077
-
3078
- - Fixed GitHub Copilot model context window detection by correcting fallback priority for maxContextWindowTokens and maxPromptTokens
3079
- - Fixed Gemini 2.5 Pro context window detection in GitHub Copilot model limits test
3080
- - Fixed Claude Opus 4.6 context window detection in GitHub Copilot model limits test
3081
- - Fixed Anthropic streaming to suppress transient SDK console errors for malformed SSE keep-alive frames so the TUI only shows surfaced provider errors
3082
- - Added environment-based credential fallback for the OpenAI Codex provider.
3083
-
3084
- ## [13.17.6] - 2026-04-01
3085
-
3086
- ### Fixed
3087
-
3088
- - Fixed Anthropic first-event timeouts to exclude stream connection setup from the watchdog, preserve timeout-specific retry classification after local aborts, and reset retry state cleanly between attempts
3089
-
3090
- ## [13.17.5] - 2026-04-01
3091
-
3092
- ### Changed
3093
-
3094
- - Increased default first-event timeout from 15s to 45s to better accommodate longer request setup times
3095
- - Modified first-event watchdog to inherit idle timeout when it exceeds the default, ensuring consistent timeout behavior across different configurations
3096
-
3097
- ### Fixed
3098
-
3099
- - Fixed first-event watchdog initialization timing so it no longer starts before the actual stream request is created, preventing premature timeouts during request setup
3100
- - Fixed first-event watchdog timing so OpenAI-family providers no longer count slow request setup against the first streamed event timeout, and raised the default first-event timeout to avoid false aborts after long tool turns
3101
-
3102
- ## [13.17.2] - 2026-04-01
3103
-
3104
- ### Fixed
3105
-
3106
- - Fixed OpenAI-family first-event timeouts to preserve provider-specific timeout errors for retry classification instead of flattening them to generic aborts ([#591](https://github.com/can1357/oh-my-pi/issues/591))
3107
-
3108
- ## [13.17.1] - 2026-04-01
3109
-
3110
- ### Added
3111
-
3112
- - Added `thinkingSignature` field to thinking content blocks to preserve the original reasoning field name (e.g., `reasoning_text`, `reasoning_content`) for accurate follow-up requests
3113
- - Added first-event timeout detection for streaming responses to abort stuck requests before user-visible content arrives
3114
- - Added `PI_STREAM_FIRST_EVENT_TIMEOUT_MS` environment variable to configure first-event timeout (defaults to 15 seconds or idle timeout, whichever is lower)
3115
- - Added Vercel AI Gateway to `/login` providers for interactive API key setup
3116
-
3117
- ### Changed
3118
-
3119
- - Changed thinking block handling to track and distinguish between different reasoning field types, enabling proper field name preservation across multiple turns
3120
-
3121
- ### Fixed
3122
-
3123
- - Fixed Anthropic stream timeout errors to be properly retried by recognizing first-event timeout messages
3124
- - Fixed stream stall detection to distinguish between first-event timeouts and idle timeouts, enabling faster recovery for stuck connections
3125
- - Fixed `omp commit` failing with HTTP 400 errors when using reasoning-enabled models on OpenAI-compatible endpoints that don't support the `developer` role (e.g., GitHub Copilot, custom proxies). Now falls back to `system` role when `developer` is unsupported.
3126
-
3127
- ## [13.17.0] - 2026-03-30
3128
-
3129
- ### Changed
3130
-
3131
- - Bumped zai provider default model from glm-4.6 to glm-5.1
3132
-
3133
- ## [13.16.5] - 2026-03-29
3134
-
3135
- ### Added
3136
-
3137
- - Added Gemma 3 27B model support for Google Generative AI
3138
-
3139
- ### Changed
3140
-
3141
- - Updated Kwaipilot KAT-Coder-Pro V2 model display name and pricing information
3142
- - Updated Kwaipilot KAT-Coder-Pro V2 context window from 222,222 to 256,000 tokens and max tokens from 8,888 to 80,000
3143
-
3144
- ### Fixed
3145
-
3146
- - Fixed normalizeAnthropicBaseUrl returning empty string instead of undefined when baseUrl is empty
3147
-
3148
- ## [13.16.4] - 2026-03-28
3149
-
3150
- ### Added
3151
-
3152
- - Added support for Groq Compound and Compound Mini models with extended context window (131K tokens) and configurable thinking levels
3153
- - Added support for OpenAI GPT-OSS-Safeguard-20B model with reasoning capabilities across multiple providers
3154
- - Added support for Kwaipilot KAT-Coder-Pro V2 model across Kilo, NanoGPT, and OpenRouter providers
3155
- - Added support for GLM-5.1 model with extended context window (200K tokens) and max output of 131K tokens
3156
- - Added support for Qwen3.5-27B-Musica-v1 model
3157
- - Added support for zai-org/glm-5.1 model with reasoning capabilities
3158
- - Added support for Sapiens AI Agnes-1.5-Lite model with multimodal input (text and image) and reasoning
3159
- - Added support for Venice openai-gpt-54-mini model
3160
-
3161
- ### Changed
3162
-
3163
- - Updated Qwen QwQ 32B max tokens from 16,384 to 40,960 across multiple providers
3164
- - Updated OpenAI GPT-OSS-Safeguard-20B model name to 'Safety GPT OSS 20B' and enabled reasoning capabilities
3165
- - Updated OpenAI GPT-OSS-Safeguard-20B context window from 222,222 to 131,072 tokens and max tokens from 8,888 to 65,536
3166
- - Updated OpenRouter Qwen QwQ 32B pricing: input from 0.2 to 0.19, output from 1.17 to 1.15, cache read from 0.1 to 0.095
3167
- - Updated OpenRouter Claude 3.5 Sonnet pricing: input from 0.45 to 0.42, cache read from 0.225 to 0.21
3168
-
3169
- ## [13.16.3] - 2026-03-28
3170
-
3171
- ### Changed
3172
-
3173
- - Modified OAuth credential saving to preserve unrelated identities instead of replacing all credentials for a provider
3174
- - Updated credential identity resolution to use provider context for more accurate email deduplication
3175
-
3176
- ### Fixed
3177
-
3178
- - Fixed OAuth credential updates to replace matching credentials in-place rather than creating disabled rows, preventing unbounded accumulation of soft-deleted credentials
3179
-
3180
- ## [13.15.0] - 2026-03-23
3181
-
3182
- ### Added
3183
-
3184
- - Added `isUsageLimitError()` to `rate-limit-utils` as a single source of truth for detecting usage/quota limit errors across all providers
3185
-
3186
- ### Fixed
3187
-
3188
- - Fixed lazy stream forwarding to properly handle final results from source streams with `result()` methods
3189
- - Fixed lazy stream error handling to convert iterator failures into terminal error results instead of silently failing
3190
- - Fixed `parseRateLimitReason` to recognize "usage limit" in error messages and correctly classify them as `QUOTA_EXHAUSTED`
3191
- - Fixed Codex `fetchWithRetry` retrying 429 responses for `usage_limit_reached` errors for up to 5 minutes instead of returning immediately for credential switching
3192
- - Removed `usage.?limit` from `TRANSIENT_MESSAGE_PATTERN` in retry utils since usage limits are not transient and require credential rotation
3193
- - Fixed `parseRateLimitReason` not recognizing "usage limit" in Codex error messages, causing incorrect fallback to `UNKNOWN` classification instead of `QUOTA_EXHAUSTED`
3194
-
3195
- ## [13.14.2] - 2026-03-21
3196
-
3197
- ### Changed
3198
-
3199
- - Updated thinking configuration format from `levels` array to `minLevel` and `maxLevel` properties for improved clarity
3200
- - Corrected context window from 400000 to 272000 tokens for GPT-5.4 mini and nano variants on Codex transport
3201
- - Normalized GPT-5.4 variant priority handling to use parsed variant instead of special-casing raw model IDs
3202
- - Added support for `mini` variant in OpenAI model parsing regex
3203
-
3204
- ### Fixed
3205
-
3206
- - Fixed inconsistent thinking level configuration across multiple model definitions
3207
-
3208
- ## [13.14.0] - 2026-03-20
3209
-
3210
- ### Fixed
3211
-
3212
- - Fixed resumed OpenAI Responses sessions to avoid replaying stale same-provider native history on the first follow-up after process restart ([#488](https://github.com/can1357/oh-my-pi/issues/488))
3213
-
3214
- ### Added
3215
-
3216
- - Added bundled GPT-5.4 mini model metadata for OpenAI, OpenAI Codex, and GitHub Copilot, including low-to-xhigh thinking support and GitHub Copilot premium multiplier metadata
3217
- - Added bundled GPT-5.4 nano model metadata for OpenAI and OpenAI Codex, including low-to-xhigh thinking support
3218
-
3219
- ## [13.13.2] - 2026-03-18
3220
-
3221
- ### Changed
3222
-
3223
- - Modified tool result handling for aborted assistant messages to preserve existing tool results when already recorded, instead of always replacing them with synthetic 'aborted' results
3224
-
3225
- ## [13.13.0] - 2026-03-18
3226
-
3227
- ### Changed
3228
-
3229
- - Changed tool argument validation to always normalize optional null values before type coercion, ensuring consistent handling of LLM-generated 'null' strings
3230
-
3231
- ### Fixed
3232
-
3233
- - Fixed tool argument validation to properly handle string 'null' values from LLMs on optional fields by stripping them during normalization
3234
- - Improved type safety of `validateToolCall` and `validateToolArguments` functions by returning properly typed `ToolCall["arguments"]` instead of `any`
3235
-
3236
- ## [13.12.9] - 2026-03-17
3237
-
3238
- ### Changed
3239
-
3240
- - Extracted OpenAI compatibility detection and resolution logic into dedicated `openai-completions-compat` module for improved maintainability and reusability
3241
-
3242
- ### Fixed
3243
-
3244
- - Fixed `openai-responses` manual history replay to strip replay-only item IDs and preserve normalized tool `call_id` values for GitHub Copilot follow-up turns ([#457](https://github.com/can1357/oh-my-pi/issues/457))
3245
-
3246
- ## [13.12.0] - 2026-03-14
3247
-
3248
- ### Added
3249
-
3250
- - Added support for `qwen-chat-template` thinking format to enable reasoning via `chat_template_kwargs.enable_thinking`
3251
- - Added `reasoningEffortMap` option to `OpenAICompat` for mapping pi-ai reasoning levels to provider-specific `reasoning_effort` values
3252
- - Added `extraBody` to `OpenAICompat` to support provider-specific request body routing fields in OpenAI-completions requests
3253
- - Added support for reading token usage from choice-level `usage` field as fallback when root-level usage is unavailable
3254
- - Added new models: DeepSeek-V3.2 (Bedrock), Llama 3.1 405B Instruct, Magistral Small 1.2, Ministral 3 3B, Mistral Large 3, Pixtral Large (25.02), NVIDIA Nemotron Nano 3 30B, and Qwen3-5-9b
3255
- - Added `close()` method to `AuthStorage` for properly closing the underlying credential store
3256
- - Added `initiatorOverride` option in OpenAI and Anthropic providers to customize message attribution
3257
-
3258
- ### Changed
3259
-
3260
- - Changed assistant message content serialization to always use plain string format instead of text block arrays to prevent recursive nesting in OpenAI-compatible backends
3261
- - Changed Bedrock Opus 4.6 context window from 1M to 1M and added max tokens limit of 128K
3262
- - Changed OpenCode Zen/Go Sonnet 4.0/4.5 context window from 1M to 200K
3263
- - Changed GitHub Copilot context windows from 200K to 128K for both gpt-4o and gpt-4o-mini
3264
- - Changed Claude 3.5 Sonnet (Anthropic API) pricing: input from $0.5 to $0.25, output from $3 to $1.5, cache read from $0.05 to $0.025, cache write from $0 to $1
3265
- - Changed Devstral 2 model name from '135B' to '123B'
3266
- - Changed ByteDance Seed 2.0-Lite to support reasoning with effort-based thinking mode and image inputs
3267
- - Changed Qwen3-32b (Groq) reasoning effort mapping to normalize all levels to 'default'
3268
- - Changed finish_reason 'end' to map to 'stop' for improved compatibility with additional providers
3269
- - Changed Anthropic reference model merging to prioritize bundled metadata for known models while using models.dev for newly discovered IDs
3270
-
3271
- ### Fixed
3272
-
3273
- - Fixed reasoning_effort parameter handling to use provider-specific mappings instead of raw effort values
3274
- - Fixed assistant content serialization for GitHub Copilot and other OpenAI-compatible backends that mirror array payloads
3275
- - Fixed token usage calculation to properly extract cached tokens from both root and nested `prompt_tokens_details` fields
3276
- - Fixed stop reason mapping to handle string values and unknown finish reasons gracefully
3277
- - Fixed resource cleanup in `AuthCredentialStore.close()` to properly finalize all prepared statements before closing the database
3278
-
3279
- ## [13.11.1] - 2026-03-13
3280
-
3281
- ### Fixed
3282
-
3283
- - Added `llama.cpp` as local provider
3284
- - Fixed auth schema V0-to-V1 migration crash when the V0 table lacks a `disabled` column
3285
-
3286
- ## [13.11.0] - 2026-03-12
3287
-
3288
- ### Added
3289
-
3290
- - Added support for Parallel AI provider with API key authentication
3291
- - Added `PARALLEL_API_KEY` environment variable support for Parallel provider configuration
3292
- - Added automatic websocket reconnection handling for connection limit errors, with fallback to SSE replay when content has already been emitted
3293
-
3294
- ### Changed
3295
-
3296
- - Enhanced `CodexProviderStreamError` to include an optional error code field for better error categorization and handling
3297
-
3298
- ### Fixed
3299
-
3300
- - Improved retry logic to handle HTTP/2 stream errors and internal_error responses from Anthropic API
3301
-
3302
- ## [13.9.16] - 2026-03-10
3303
-
3304
- ### Added
3305
-
3306
- - Support for `onPayload` callback to replace provider request payloads before sending, enabling request interception and modification
3307
- - Support for structured text signature metadata with phase information (commentary/final_answer) in OpenAI and Azure OpenAI Responses providers
3308
- - Support for OpenAI Codex Spark model selection with plan-based account prioritization
3309
- - Added `modelId` option to `getApiKey()` to enable model-specific credential ranking
3310
-
3311
- ### Changed
3312
-
3313
- - Enhanced `onPayload` callback signature to accept model parameter and support async payload replacement
3314
- - Improved error messages for `response.failed` events to include detailed error codes, messages, and incomplete reasons
3315
- - Refactored OpenAI Codex response streaming to improve code organization and maintainability with extracted helper functions and type definitions
3316
- - Enhanced websocket fallback logic to safely replay buffered output over SSE when websocket connections fail mid-stream
3317
- - Improved error recovery for websocket streams by distinguishing between fatal connection errors and retryable stream errors
3318
- - Updated credential ranking strategy to prioritize Pro plan accounts when requesting OpenAI Codex Spark models
3319
-
3320
- ### Fixed
3321
-
3322
- - Fixed websocket stream recovery to properly reset output state and clear buffered items when falling back to SSE after partial output
3323
- - Fixed handling of malformed JSON messages in websocket streams to trigger immediate fallback to SSE without retry attempts
3324
-
3325
- ## [13.9.13] - 2026-03-10
3326
-
3327
- ### Added
3328
-
3329
- - Added `isSpecialServiceTier` utility function to validate OpenAI service tier values
3330
-
3331
- ## [13.9.12] - 2026-03-09
3332
-
3333
- ### Added
3334
-
3335
- - Added Tavily web search provider support with API key authentication
3336
-
3337
- ### Fixed
3338
-
3339
- - Fixed OpenAI-family streaming transports to fail with an explicit idle-timeout error instead of hanging indefinitely when the provider stops sending events mid-response
3340
- - Fixed OpenAI Codex OAuth refresh and usage-limit lookups to respect request timeouts instead of waiting indefinitely during account selection or rotation
3341
- - Fixed OpenAI Codex prewarmed websocket requests to fall back quickly when the socket connects but never starts the response stream
3342
-
3343
- ## [13.9.10] - 2026-03-08
3344
-
3345
- ### Added
3346
-
3347
- - Added `identity_key` column to auth credentials storage for improved credential deduplication
3348
- - Added schema versioning system to auth credentials database for safer migrations
3349
- - Added automatic backfilling of identity keys during database schema migrations
3350
-
3351
- ### Changed
3352
-
3353
- - Changed credential deduplication logic to use single identity key instead of multiple identifiers for better performance
3354
- - Changed database schema to store normalized identity keys alongside credentials
3355
- - Changed auth schema migration to support upgrading from legacy database versions with automatic data backfill
3356
-
3357
- ### Fixed
3358
-
3359
- - Fixed API key credential matching to correctly identify when the same key is re-stored, preventing unnecessary row duplication on re-login
3360
- - Fixed credential deduplication to correctly handle OAuth accounts with matching emails but different account IDs
3361
- - Fixed API key replacement to reuse existing stored rows instead of accumulating disabled duplicates
3362
- - Fixed auth storage to preserve newer recorded schema versions when opened by older binaries
3363
-
3364
- ## [13.9.8] - 2026-03-08
3365
-
3366
- ### Fixed
3367
-
3368
- - Fixed WebSocket stream fallback logic to safely replay buffered output over SSE when WebSocket fails after partial content has been streamed
3369
-
3370
- ## [13.9.4] - 2026-03-07
3371
-
3372
- ### Changed
3373
-
3374
- - Simplified API key credential storage to always replace existing credentials on re-login instead of accumulating multiple keys
3375
- - Updated Kagi API key placeholder from `kagi_...` to `KG_...` to match current API key format
3376
- - Updated Kagi login instructions to clarify Search API access is beta-only and provide support contact
3377
- - Disabled usage reporting in streaming responses for Cerebras models due to compatibility issues
3378
-
3379
- ### Fixed
3380
-
3381
- - Fixed Cerebras model compatibility by preventing `stream_options` usage requests in chat completions
3382
-
3383
- ## [13.9.3] - 2026-03-07
3384
-
3385
- ### Breaking Changes
3386
-
3387
- - Changed `reasoning` parameter from `ThinkingLevel | undefined` to `Effort | undefined` in `SimpleStreamOptions`; 'off' is no longer valid (omit the field instead)
3388
- - Removed `supportsXhigh()` function; check `model.thinking?.maxLevel` instead
3389
- - Removed `ThinkingLevel` and `ThinkingEffort` types; use `Effort` enum
3390
- - Removed `getAvailableThinkingLevels()` and `getAvailableThinkingEfforts()` functions
3391
- - Changed `transformRequestBody()` signature to require `Model` parameter as second argument for effort validation
3392
- - Removed `thinking.ts` module export; import from `model-thinking.ts` instead
3393
-
3394
- ### Added
3395
-
3396
- - Added `incremental` flag to `OpenAIResponsesHistoryPayload` to support building conversation history from multiple assistant messages instead of replacing it
3397
- - Added `dt` flag to `OpenAIResponsesHistoryPayload` for transport-level metadata
3398
- - Added `ThinkingConfig` interface to models for canonical thinking transport metadata with min/max effort levels and provider-specific mode
3399
- - Added `thinking` field to `Model` type containing per-model thinking capabilities used to clamp and map user-facing effort levels
3400
- - Added `Effort` enum (minimal, low, medium, high, xhigh) as canonical user-facing thinking levels replacing `ThinkingLevel`
3401
- - Added `enrichModelThinking()` function to automatically populate thinking metadata on models based on their capabilities
3402
- - Added `mapEffortToAnthropicAdaptiveEffort()` function to map user effort levels to Anthropic adaptive thinking effort
3403
- - Added `mapEffortToGoogleThinkingLevel()` function to map user effort levels to Google thinking levels
3404
- - Added `requireSupportedEffort()` function to validate and clamp effort levels per model, throwing errors for unsupported combinations
3405
- - Added `clampThinkingLevelForModel()` function to clamp thinking levels to model-supported range
3406
- - Added `applyGeneratedModelPolicies()` and `linkSparkPromotionTargets()` exports from model-thinking module
3407
- - Added `serviceTier` option to control OpenAI processing priority and cost (auto, default, flex, scale, priority)
3408
- - Added `providerPayload` field to messages and responses for reconstructing transport-native history
3409
- - Added Gemini usage provider for tracking quota and tier information
3410
- - Added `getCodexAccountId()` utility to extract account ID from Codex JWT tokens
3411
- - Added email extraction from OpenAI Codex OAuth tokens for credential deduplication
3412
-
3413
- ### Changed
3414
-
3415
- - Changed credential disabling mechanism from boolean `disabled` flag to `disabled_cause` text field for tracking why credentials were disabled
3416
- - Changed `deleteAuthCredential()` and `deleteAuthCredentialsForProvider()` methods to require a `disabledCause` parameter explaining the reason for disabling
3417
- - Changed Gemini model parsing to strip `-preview` suffix for consistent model identification
3418
- - Changed OpenAI Codex websocket error handling to detect fatal connection errors and immediately fall back to SSE without retrying
3419
- - Changed OpenAI Codex to always use websockets v2 protocol (removed v1 support)
3420
- - Changed `reasoning` parameter type from `ThinkingLevel` to `Effort` in `SimpleStreamOptions`, removing 'off' value (callers should omit the field instead)
3421
- - Changed thinking configuration to use model-specific metadata instead of hardcoded provider logic for effort mapping
3422
- - Changed OpenAI Codex request transformer to accept `Model` parameter for effort validation instead of string model ID
3423
- - Changed Anthropic provider to use model thinking metadata for determining adaptive thinking support instead of model ID pattern matching
3424
- - Changed Google Vertex and Google providers to use shorter variable names for thinking config construction
3425
- - Moved thinking-related utilities from `thinking.ts` to new `model-thinking.ts` module with expanded functionality
3426
- - Moved model policy functions from `provider-models/model-policies.ts` to `model-thinking.ts`
3427
- - Moved `googleGeminiCliUsageProvider` from `providers/google-gemini-cli-usage.ts` to `usage/gemini.ts`
3428
- - Changed default OpenAI model from gpt-5.1-codex to gpt-5.4 across all providers
3429
- - Changed `UsageFetchContext` to remove cache and now() dependencies—usage fetchers now use Date.now() directly
3430
- - Removed `resetInMs` field from usage windows; consumers should calculate from `resetsAt` timestamp
3431
- - Changed OpenAI Codex credential ranking to deduplicate by email when accountId matches
3432
- - Improved OpenAI Codex error handling with retryable error detection
3433
-
3434
- ### Removed
3435
-
3436
- - Removed `thinking.ts` module; use `model-thinking.ts` instead
3437
- - Removed `provider-models/model-policies.ts` module; functionality moved to `model-thinking.ts`
3438
- - Removed `supportsXhigh()` function from models.ts; use model.thinking metadata instead
3439
- - Removed `ThinkingLevel` and `ThinkingEffort` types; use `Effort` enum instead
3440
- - Removed `getAvailableThinkingLevels()` and `getAvailableThinkingEfforts()` functions
3441
- - Removed `model-policies` export from `provider-models/index.ts`
3442
- - Removed hardcoded thinking level clamping logic from OpenAI Codex request transformer; now uses model metadata
3443
- - Removed `UsageCache` and `UsageCacheEntry` interfaces—caching is now handled internally by AuthStorage
3444
- - Removed `google-gemini-cli-usage` export; use new `gemini` usage provider instead
3445
- - Removed `resetInMs` computation from all usage providers
3446
- - Removed cache TTL constants and cache management from usage fetchers (claude, github-copilot, google-antigravity, kimi, openai-codex, zai)
3447
-
3448
- ### Fixed
3449
-
3450
- - Fixed credential purging to respect disabled credentials when deduplicating by email, preventing re-enablement of intentionally disabled credentials
3451
- - Fixed OpenAI Codex websocket error reporting to include detailed error messages from error events
3452
- - Fixed conversation history reconstruction to support incremental updates from multiple assistant messages while maintaining backward compatibility with full-snapshot payloads
3453
- - Fixed OpenAI Codex to reject unsupported effort levels instead of silently clamping them, providing clear error messages about supported efforts
3454
- - Fixed model cache normalization to properly apply thinking enrichment when loading cached models
3455
- - Fixed dynamic model merging to apply thinking enrichment to merged model results
3456
- - Fixed OpenAI Codex streaming to properly include service_tier in SSE payloads
3457
- - Fixed type safety in OpenAI responses by removing unsafe type casts on image content blocks
3458
- - Fixed credential purging to respect disabled credentials when deduplicating by email
3459
-
3460
- ## [13.9.2] - 2026-03-05
3461
-
3462
- ### Added
3463
-
3464
- - Support for redacted thinking blocks in Anthropic messages, enabling secure handling of encrypted reasoning content
3465
- - Preservation of latest Anthropic thinking blocks and redacted thinking content during message transformation, even when switching between Anthropic models
3466
-
3467
- ### Changed
3468
-
3469
- - Assistant message content now includes `RedactedThinkingContent` type alongside existing text, thinking, and tool call blocks
3470
- - Message transformation logic now preserves signed thinking blocks and redacted thinking for the latest assistant message in Anthropic conversations
3471
-
3472
- ### Fixed
3473
-
3474
- - Fixed Unicode normalization to consistently apply `toWellFormed()` to all text content, including thinking blocks, ensuring proper handling of malformed UTF-16 sequences
3475
-
3476
- ## [13.9.1] - 2026-03-05
3477
-
3478
- ### Breaking Changes
3479
-
3480
- - Removed `THINKING_LEVELS`, `ALL_THINKING_LEVELS`, `ALL_THINKING_MODES`, `THINKING_MODE_DESCRIPTIONS`, and `THINKING_MODE_LABELS` exports
3481
- - Renamed `formatThinking()` to `getThinkingMetadata()` with changed return type from string to `ThinkingMetadata` object
3482
- - Renamed `getAvailableThinkingLevel()` to `getAvailableThinkingLevels()` and added default parameter
3483
- - Renamed `getAvailableThinkingEffort()` to `getAvailableThinkingEfforts()` and added default parameter
3484
-
3485
- ### Added
3486
-
3487
- - Added `ThinkingMetadata` type to provide structured access to thinking mode information (value, label, description)
3488
-
3489
- ## [13.9.0] - 2026-03-05
3490
-
3491
- ### Added
3492
-
3493
- - Exported new thinking module with `ThinkingEffort`, `ThinkingLevel`, and `ThinkingMode` types for managing reasoning effort levels
3494
- - Added `getAvailableThinkingEffort()` function to determine supported thinking effort levels based on model capabilities
3495
- - Added `parseThinkingEffort()`, `parseThinkingLevel()`, and `parseThinkingMode()` functions for parsing thinking configuration strings
3496
- - Added `THINKING_LEVELS`, `ALL_THINKING_LEVELS`, and `ALL_THINKING_MODES` constants for iterating over available thinking options
3497
- - Added `THINKING_MODE_DESCRIPTIONS` and `THINKING_MODE_LABELS` for displaying thinking modes in user interfaces
3498
- - Added `formatThinking()` function to format thinking modes as compact display labels
3499
-
3500
- ### Changed
3501
-
3502
- - Refactored thinking level handling to distinguish between `ThinkingEffort` (provider-level, no "off") and `ThinkingLevel` (user-facing, includes "off")
3503
- - Updated `ThinkingBudgets` type to use `ThinkingEffort` instead of `ThinkingLevel` for more precise token budget configuration
3504
- - Improved reasoning option handling to explicitly support "off" value for disabling reasoning across all providers
3505
- - Simplified thinking effort mapping logic by centralizing provider-specific clamping behavior
3506
-
3507
- ## [13.7.8] - 2026-03-04
3508
-
3509
- ### Added
3510
-
3511
- - Added ZenMux provider support with mixed API routing: Anthropic-owned models discovered from `https://zenmux.ai/api/v1/models` now use the Anthropic transport (`https://zenmux.ai/api/anthropic`), while other ZenMux models use the OpenAI-compatible transport.
3512
-
3513
- ## [13.7.7] - 2026-03-04
3514
-
3515
- ### Changed
3516
-
3517
- - Modified response ID normalization to preserve existing item ID prefixes when truncating oversized IDs
3518
- - Updated tool call ID normalization to use `fc_` prefix for generated item IDs instead of `item_` prefix
3519
-
3520
- ### Fixed
3521
-
3522
- - Fixed handling of reasoning item IDs to remain untouched during response normalization while function call IDs are properly normalized
3523
-
3524
- ## [13.7.2] - 2026-03-04
3525
-
3526
- ### Added
3527
-
3528
- - Added support for Kagi API key authentication via `login kagi` command
3529
- - Added Kagi to the list of available OAuth providers
3530
-
3531
- ### Fixed
3532
-
3533
- - MCP tool schemas with `$ref`/`$defs` are now dereferenced before being sent to LLM providers, fixing dangling references that left models without type definitions
3534
- - Ajv schema validation no longer emits `console.warn()` for non-standard format keywords (e.g. `"uint"`) from MCP servers, preventing TUI corruption
3535
- - Tool schema compilation is now cached per schema identity, eliminating redundant recompilation on every tool call
3536
-
3537
- ## [13.6.0] - 2026-03-03
3538
-
3539
- ### Added
3540
-
3541
- - Added Anthropic Foundry gateway mode controlled by `CLAUDE_CODE_USE_FOUNDRY`, with support for `FOUNDRY_BASE_URL`, `ANTHROPIC_FOUNDRY_API_KEY`, `ANTHROPIC_CUSTOM_HEADERS`, and optional mTLS material (`CLAUDE_CODE_CLIENT_CERT`, `CLAUDE_CODE_CLIENT_KEY`, `NODE_EXTRA_CA_CERTS`)
3542
- - Added LM Studio provider support with OpenAI-compatible model discovery and OAuth login.
3543
- - Added support for `LM_STUDIO_API_KEY` and `LM_STUDIO_BASE_URL` environment variables for authentication and custom host configuration.
3544
-
3545
- ### Changed
3546
-
3547
- - Anthropic key resolution now prefers `ANTHROPIC_FOUNDRY_API_KEY` over `ANTHROPIC_OAUTH_TOKEN` and `ANTHROPIC_API_KEY` when Foundry mode is enabled
3548
- - Anthropic auth base-URL fallback now prefers `FOUNDRY_BASE_URL` when `CLAUDE_CODE_USE_FOUNDRY` is enabled
3549
-
3550
- ## [13.5.8] - 2026-03-02
3551
-
3552
- ### Fixed
3553
-
3554
- - Fixed schema compatibility issue where patternProperties in tool parameters caused failures when converting to legacy Antigravity format
3555
-
3556
- ## [13.5.5] - 2026-03-01
3557
-
3558
- ### Changed
3559
-
3560
- - Anthropic Claude system-block cloaking now leaves the agent identity block uncached and applies `cache_control: { type: "ephemeral" }` to injected user system blocks without forcing `ttl: "1h"`
3561
-
3562
- ### Fixed
3563
-
3564
- - Anthropic request payload construction now enforces a maximum of 4 `cache_control` breakpoints (tools/system/messages priority order) before dispatch
3565
- - Anthropic cache-control normalization now removes later `ttl: "1h"` entries when a default/5m block has already appeared earlier in evaluation order
3566
-
3567
- ## [13.5.3] - 2026-03-01
3568
-
3569
- ### Fixed
3570
-
3571
- - Fixed tool argument coercion to handle malformed JSON with trailing wrapper braces by parsing leading JSON containers
3572
-
3573
- ## [13.4.0] - 2026-03-01
3574
-
3575
- ### Breaking Changes
3576
-
3577
- - Removed `TInput` generic parameter from `ToolResultMessage` interface and removed `$normative` property
3578
-
3579
- ### Added
3580
-
3581
- - `hasUnrepresentableStrictObjectMap()` pre-flight check in `tryEnforceStrictSchema`: schemas with `patternProperties` or schema-valued `additionalProperties` now degrade gracefully to non-strict mode instead of throwing during enforcement
3582
- - `generateClaudeCloakingUserId()` generates structured user IDs for Anthropic OAuth metadata (`user_{hex64}_account_{uuid}_session_{uuid}`)
3583
- - `isClaudeCloakingUserId()` validates whether a string matches the cloaking user-ID format
3584
- - `mapStainlessOs()` and `mapStainlessArch()` map `process.platform`/`process.arch` to Stainless header values; X-Stainless-Os and X-Stainless-Arch in `claudeCodeHeaders` are now runtime-computed
3585
- - `buildClaudeCodeTlsFetchOptions()` attaches SNI and default TLS ciphers for direct `api.anthropic.com` connections
3586
- - `createClaudeBillingHeader()` generates the `x-anthropic-billing-header` block (SHA-256 payload fingerprint + random build hash)
3587
- - `buildAnthropicSystemBlocks()` now injects a billing header block and the Claude Agent SDK identity block with `ephemeral` 1h cache-control when `includeClaudeCodeInstruction` is set
3588
- - `resolveAnthropicMetadataUserId()` auto-generates a cloaking user ID for OAuth requests when `metadata.user_id` is absent or invalid
3589
- - `AnthropicOAuthFlow` is now exported for direct use
3590
- - OAuth callback server timeout extended from 2 min to 5 min
3591
- - `parseGeminiCliCredentials()` parses Google Cloud credential JSON with support for legacy (`{token,projectId}`), alias (`project_id`/`refresh`/`expires`), and enriched formats
3592
- - `shouldRefreshGeminiCliCredentials()` and proactive token refresh before requests for both Gemini CLI and Antigravity providers (60s pre-expiry buffer)
3593
- - `normalizeAntigravityTools()` converts `parametersJsonSchema` → `parameters` in function declarations for Antigravity compatibility
3594
- - `ANTIGRAVITY_SYSTEM_INSTRUCTION` is now exported for use by search and other consumers
3595
- - `ANTIGRAVITY_LOAD_CODE_ASSIST_METADATA` constant exported from OAuth module with `ANTIGRAVITY` ideType
3596
- - Antigravity project onboarding: `onboardProjectWithRetries()` provisions a new project via `onboardUser` LRO when `loadCodeAssist` returns no existing project (up to 5 attempts, 2s interval)
3597
- - `getOAuthApiKey` now includes `refreshToken`, `expiresAt`, `email`, and `accountId` in the Gemini/Antigravity JSON credential payload to enable proactive refresh
3598
- - Antigravity model discovery now tries the production daily endpoint first, with sandbox as fallback
3599
- - `ANTIGRAVITY_DISCOVERY_DENYLIST` filters low-quality/internal models from discovery results
3600
-
3601
- ### Changed
3602
-
3603
- - Replaced `sanitizeSurrogates()` utility with native `String.prototype.toWellFormed()` for handling unpaired Unicode surrogates across all providers
3604
- - Extended `ANTHROPIC_OAUTH_BETA` constant in the OpenAI-compat Anthropic route with `interleaved-thinking-2025-05-14`, `context-management-2025-06-27`, and `prompt-caching-scope-2026-01-05` beta flags
3605
- - `claudeCodeVersion` bumped to `2.1.63`; `claudeCodeSystemInstruction` updated to identify as Claude Agent SDK
3606
- - `claudeCodeHeaders`: removed `X-Stainless-Helper-Method`, updated package version to `0.74.0`, runtime version to `v24.3.0`
3607
- - `applyClaudeToolPrefix` / `stripClaudeToolPrefix` now accept an optional prefix override and skip Anthropic built-in tool names (`web_search`, `code_execution`, `text_editor`, `computer`)
3608
- - Accept-Encoding header updated to `gzip, deflate, br, zstd`
3609
- - Non-Anthropic base URLs now receive `Authorization: Bearer` regardless of OAuth status
3610
- - Prompt-caching logic now skips applying breakpoints when any block already carries `cache_control`, instead of stripping then re-applying
3611
- - `fine-grained-tool-streaming-2025-05-14` removed from default beta set
3612
- - Anthropic OAuth token URL changed from `platform.claude.com` to `api.anthropic.com`
3613
- - Anthropic OAuth scopes reduced to `org:create_api_key user:profile user:inference`
3614
- - OAuth code exchange now strips URL fragment from callback code, using the fragment as state override when present
3615
- - Claude usage headers aligned: user-agent updated to `claude-cli/2.1.63 (external, cli)`, anthropic-beta extended with full beta set
3616
- - Antigravity session ID format changed to signed decimal (negative int63 derived from SHA-256 of first user message, or random bounded int63)
3617
- - Antigravity `requestId` now uses `agent-{uuid}` format; non-Antigravity requests no longer include requestId/userAgent/requestType in the payload
3618
- - `ANTIGRAVITY_DAILY_ENDPOINT` corrected to `daily-cloudcode-pa.googleapis.com`; sandbox endpoint kept as fallback only
3619
- - Antigravity discovery: removed `recommended`/`agentModelSorts` filter; now includes all non-internal, non-denylisted models
3620
- - Antigravity discovery no longer sends `project` in the request body
3621
- - Gemini/Antigravity OAuth flows no longer use PKCE (code_challenge removed)
3622
- - Antigravity `loadCodeAssist` metadata ideType changed from `IDE_UNSPECIFIED` to `ANTIGRAVITY`
3623
- - Antigravity `discoverProject` now uses a single canonical production endpoint; falls back to project onboarding instead of a hardcoded default project ID
3624
- - `VALIDATED` tool calling config applied to Antigravity requests with Claude models
3625
- - `maxOutputTokens` removed from Antigravity generation config for non-Claude models
3626
- - System instruction injection for Antigravity scoped to Claude and `gemini-3-pro-high` models only
3627
-
3628
- ### Removed
3629
-
3630
- - Removed `sanitizeSurrogates()` utility function; use native `String.prototype.toWellFormed()` instead
3631
-
3632
- ## [13.3.14] - 2026-02-28
3633
-
3634
- ### Added
3635
-
3636
- - Exported schema utilities from new `./utils/schema` module, consolidating JSON Schema handling across providers
3637
- - Added `CredentialRankingStrategy` interface for providers to implement usage-based credential selection
3638
- - Added `claudeRankingStrategy` for Anthropic OAuth credentials to enable smart multi-account selection based on usage windows
3639
- - Added `codexRankingStrategy` for OpenAI Codex OAuth credentials with priority boost for fresh 5-hour window starts
3640
- - Added `adaptSchemaForStrict()` helper for unified OpenAI strict schema enforcement across providers
3641
- - Added schema equality and merging utilities: `areJsonValuesEqual()`, `mergeCompatibleEnumSchemas()`, `mergePropertySchemas()`
3642
- - Added Cloud Code Assist schema normalization: `copySchemaWithout()`, `stripResidualCombiners()`, `prepareSchemaForCCA()`
3643
- - Added `sanitizeSchemaForGoogle()` and `sanitizeSchemaForCCA()` for provider-specific schema sanitization
3644
- - Added `StringEnum()` helper for creating string enum schemas compatible with Google and other providers
3645
- - Added `enforceStrictSchema()` and `sanitizeSchemaForStrictMode()` for OpenAI strict mode schema validation
3646
- - Added package exports for `./utils/schema` and `./utils/schema/*` subpaths
3647
- - Added `validateSchemaCompatibility()` to statically audit a JSON Schema against provider-specific rules (`openai-strict`, `google`, `cloud-code-assist-claude`) and return structured violations
3648
- - Added `validateStrictSchemaEnforcement()` to verify the strict-fail-open contract: enforced schemas pass strict validation, failed schemas return the original object identity
3649
- - Added `COMBINATOR_KEYS` (`anyOf`, `allOf`, `oneOf`) and `CCA_UNSUPPORTED_SCHEMA_FIELDS` as exported constants in `fields.ts` to eliminate duplication across modules
3650
- - Added `tryEnforceStrictSchema` result cache (`WeakMap`) to avoid redundant sanitize + enforce work for the same schema object
3651
- - Added comprehensive schema normalization test suite (`schema-normalization.test.ts`) covering strict mode, Google, and Cloud Code Assist normalization paths
3652
- - Added schema compatibility validation test suite (`schema-compatibility.test.ts`) covering all three provider targets
3653
-
3654
- ### Changed
3655
-
3656
- - Moved schema utilities from `./utils/typebox-helpers` to new `./utils/schema` module with expanded functionality
3657
- - Refactored OpenAI provider tool conversion to use unified `adaptSchemaForStrict()` helper across codex, completions, and responses
3658
- - Updated `AuthStorage` to support generic credential ranking via `CredentialRankingStrategy` instead of Codex-only logic
3659
- - Moved Google schema sanitization functions from `google-shared.ts` to `./utils/schema` module
3660
- - Changed export path: `./utils/typebox-helpers` → `./utils/schema` in main index
3661
- - `sanitizeSchemaForGoogle()` / `sanitizeSchemaForCCA()` now accept a parameterized `unsupportedFields` set internally, enabling code reuse between the two sanitizers
3662
- - `copySchemaWithout()` rewritten using object-rest destructuring for clarity
3663
-
3664
- ### Fixed
3665
-
3666
- - Fixed cycle detection: `WeakSet` guards added to all recursive schema traversals (`sanitizeSchemaForStrictMode`, `enforceStrictSchema`, `normalizeSchemaForCCA`, `normalizeNullablePropertiesForCloudCodeAssist`, `stripResidualCombiners`, `sanitizeSchemaImpl`, `hasResidualCloudCodeAssistIncompatibilities`) — circular schemas no longer cause infinite loops or stack overflows
3667
- - Fixed `hasResidualCloudCodeAssistIncompatibilities`: cycle detection now returns `false` (not `true`) for already-visited nodes, eliminating false positives that forced the CCA fallback schema on valid recursive inputs
3668
- - Fixed `stripResidualCombiners` to iterate to a fixpoint rather than making a single pass, ensuring chained combiner reductions (where one reduction enables another) are fully resolved
3669
- - Fixed `mergeObjectCombinerVariants` required-field computation: the flattened object now takes the intersection of all variants' `required` arrays (unioned with own-level required properties that exist in the merged schema), preventing required fields from being silently dropped or over-included
3670
- - Fixed `mergeCompatibleEnumSchemas` to use deep structural equality (`areJsonValuesEqual`) instead of `Object.is` when deduplicating object-valued enum members
3671
- - Fixed `sanitizeSchemaForGoogle` const-to-enum deduplication to use deep equality instead of reference equality
3672
- - Fixed `sanitizeSchemaForGoogle` type inference for `anyOf`/`oneOf`-flattened const enums: type is now derived from all variants (must agree), falling back to inference from enum values; mixed null/non-null infers the non-null type and sets `nullable`
3673
- - Fixed `sanitizeSchemaForGoogle` recursion to spread options when descending (previously only `insideProperties`, `normalizeTypeArrayToNullable`, `stripNullableKeyword` were forwarded; new fields `unsupportedFields` and `seen` were silently dropped)
3674
- - Fixed `sanitizeSchemaForGoogle` array-valued `type` filtering to exclude non-string entries before processing
3675
- - Removed incorrect `additionalProperties: false` stripping from `sanitizeSchemaForGoogle` (the field is valid in Google schemas when `false`)
3676
- - Fixed `sanitizeSchemaForStrictMode` to strip the `nullable` keyword and expand it into `anyOf: [schema, {type: "null"}]` in the output, matching what OpenAI strict mode actually expects
3677
- - Fixed `sanitizeSchemaForStrictMode` to infer `type: "array"` when `items` is present but `type` is absent
3678
- - Fixed `sanitizeSchemaForStrictMode` to infer a scalar `type` from uniform `enum` values when `type` is not explicitly set
3679
- - Fixed `sanitizeSchemaForStrictMode` const-to-enum merge to use deep equality, preventing duplicate enum entries when `const` and `enum` both exist with the same value
3680
- - Fixed `enforceStrictSchema` to drop `additionalProperties` unconditionally (previously only object-valued `additionalProperties` was recursed into; non-object values were passed through, violating strict schema requirements)
3681
- - Fixed `enforceStrictSchema` to recurse into `$defs` and `definitions` blocks so referenced sub-schemas are also made strict-compliant
3682
- - Fixed `enforceStrictSchema` to handle tuple-style `items` arrays (previously only single-schema `items` objects were recursed)
3683
- - Fixed `enforceStrictSchema` double-wrapping: optional properties already expressed as `anyOf: [..., {type: "null"}]` are not wrapped again
3684
- - Fixed `enforceStrictSchema` `Array.isArray` type-narrowing for `type` field to filter non-string entries before checking for `"object"`
3685
-
3686
- ## [13.3.8] - 2026-02-28
3687
-
3688
- ### Fixed
3689
-
3690
- - Fixed response body reuse error when handling 429 rate limit responses with retry logic
3691
-
3692
- ## [13.3.7] - 2026-02-27
3693
-
3694
- ### Added
3695
-
3696
- - Added `tryEnforceStrictSchema` function that gracefully downgrades to non-strict mode when schema enforcement fails, enabling better compatibility with malformed or circular schemas
3697
- - Added `sanitizeSchemaForStrictMode` function to normalize JSON schemas by stripping non-structural keywords, converting `const` to `enum`, and expanding type arrays into `anyOf` variants
3698
- - Added Kilo Gateway provider support with OpenAI-compatible model discovery, OAuth `/login kilo`, and `KILO_API_KEY` environment variable support ([#193](https://github.com/can1357/oh-my-pi/issues/193))
3699
-
3700
- ### Changed
3701
-
3702
- - Changed strict mode handling in OpenAI providers to use `tryEnforceStrictSchema` for safer schema enforcement with automatic fallback to non-strict mode
3703
- - Enhanced `enforceStrictSchema` to properly handle schemas with type arrays containing `object` (e.g., `type: ["object", "null"]`)
3704
-
3705
- ### Fixed
3706
-
3707
- - Fixed `enforceStrictSchema` to properly handle malformed object schemas with required keys but missing properties
3708
- - Fixed `enforceStrictSchema` to correctly process nested object schemas within `anyOf`, `allOf`, and `oneOf` combinators
3709
-
3710
- ## [13.3.1] - 2026-02-26
3711
-
3712
- ### Added
3713
-
3714
- - Added `topP`, `topK`, `minP`, `presencePenalty`, and `repetitionPenalty` options to `StreamOptions` for fine-grained control over model sampling behavior
3715
-
3716
- ## [13.3.0] - 2026-02-26
3717
-
3718
- ### Changed
3719
-
3720
- - Allowed OAuth provider logins to supply a manual authorization code handler with a default prompt when none is provided
3721
-
3722
- ## [13.2.0] - 2026-02-23
3723
-
3724
- ### Added
3725
-
3726
- - Added support for GitHub Copilot provider in strict mode for both openai-completions and openai-responses tool schemas
3727
-
3728
- ### Fixed
3729
-
3730
- - Fixed tool descriptions being rejected when undefined by providing empty string fallback across all providers
3731
-
3732
- ## [12.19.1] - 2026-02-22
3733
-
3734
- ### Added
3735
-
3736
- - Exported `isProviderRetryableError` function for detecting rate-limit and transient stream errors
3737
- - Support for retrying malformed JSON stream-envelope parse errors from Anthropic-compatible proxy endpoints
3738
-
3739
- ### Changed
3740
-
3741
- - Expanded retry detection to include JSON parse errors (unterminated strings, unexpected end of input) in addition to rate-limit errors
3742
-
3743
- ## [12.19.0] - 2026-02-22
3744
-
3745
- ### Added
3746
-
3747
- - Added GitLab Duo provider with support for Claude, GPT-5, and other models via GitLab AI Gateway
3748
- - Added OAuth authentication for GitLab Duo with automatic token refresh and direct access caching
3749
- - Added 16 new GitLab Duo models including Claude Opus/Sonnet/Haiku variants and GPT-5 series models
3750
- - Added `isOAuth` option to Anthropic provider to force OAuth bearer auth mode for proxy tokens
3751
- - Added `streamGitLabDuo` function to route requests through GitLab AI Gateway with direct access tokens
3752
- - Added `getGitLabDuoModels` function to retrieve available GitLab Duo model configurations
3753
- - Added `clearGitLabDuoDirectAccessCache` function to manually clear cached direct access tokens
3754
-
3755
- ### Changed
3756
-
3757
- - Enhanced `getModelMapping()` to support both GitLab Duo alias IDs (e.g., `duo-chat-gpt-5-codex`) and canonical model IDs (e.g., `gpt-5-codex`) for improved model resolution flexibility
3758
- - Migrated `AuthCredentialStore` and `AuthStorage` into `@oh-my-pi/pi-ai` as shared credential primitives for downstream packages
3759
- - Moved Anthropic auth helpers (`findAnthropicAuth`, `isOAuthToken`, `buildAnthropicSearchHeaders`, `buildAnthropicUrl`) into shared AI utilities for reuse across providers
3760
- - Replaced `CliAuthStorage` with `AuthCredentialStore` for improved credential management with multiple credentials per provider
3761
- - Updated models.json pricing for Claude 3.5 Sonnet (input: 0.23→0.45, output: 3→2.2, added cache read: 0.225) and Claude 3 Opus (input: 0.3→0.95)
3762
- - Moved `mapAnthropicToolChoice` function from gitlab-duo provider to stream module for broader reusability
3763
- - Enhanced HTTP status code extraction to handle string-formatted status codes in error objects
3764
-
3765
- ### Removed
3766
-
3767
- - Removed `CliAuthStorage` class in favor of new `AuthCredentialStore` with enhanced functionality
3768
-
3769
- ## [12.17.2] - 2026-02-21
3770
-
3771
- ### Added
3772
-
3773
- - Exported `getAntigravityUserAgent()` function for constructing Antigravity User-Agent headers
3774
-
3775
- ### Changed
3776
-
3777
- - Updated default Antigravity version from 1.15.8 to 1.18.3
3778
- - Unified User-Agent header generation across Antigravity API calls to use centralized `getAntigravityUserAgent()` function
3779
-
3780
- ## [12.17.1] - 2026-02-21
3781
-
3782
- ### Added
3783
-
3784
- - Added new export paths for provider models via `./provider-models` and `./provider-models/*`
3785
- - Added new export paths for Cursor and OpenAI Codex providers via `./providers/cursor/gen/*` and `./providers/openai-codex/*`
3786
- - Added new export paths for usage utilities via `./usage/*`
3787
- - Added new export paths for discovery and OAuth utilities via `./utils/discovery` and `./utils/oauth` with subpath exports
3788
-
3789
- ### Changed
3790
-
3791
- - Simplified main export path to use wildcard pattern `./src/*.ts` for broader module access
3792
- - Updated `models.json` export to include TypeScript declaration file at `./src/models.json.d.ts`
3793
- - Reorganized package.json field ordering for improved readability
3794
-
3795
- ## [12.17.0] - 2026-02-21
3796
-
3797
- ### Fixed
3798
-
3799
- - Cursor provider: bind `execHandlers` when passing handler methods to the exec protocol so handlers receive correct `this` context (fixes "undefined is not an object (evaluating 'this.options')" when using exec tools such as web search with Cursor)
3800
-
3801
- ## [12.16.0] - 2026-02-21
3802
-
3803
- ### Added
3804
-
3805
- - Exported `readModelCache` and `writeModelCache` functions for direct SQLite-backed model cache access
3806
- - Added `<turn_aborted>` guidance marker as synthetic user message when assistant messages are aborted or errored, informing the model that tools may have partially executed
3807
- - Added support for Sonnet 4.6 models in adaptive thinking detection
3808
-
3809
- ### Changed
3810
-
3811
- - Updated model cache schema version to support improved global model fallback resolution
3812
- - Improved GitHub Copilot model resolution to prefer provider-specific model definitions over global references when context window is larger, ensuring optimal model capabilities
3813
- - Migrated model cache from per-provider JSON files to unified SQLite database (models.db) for atomic cross-process access
3814
- - Renamed `cachePath` option to `cacheDbPath` in ModelManagerOptions to reflect database-backed storage
3815
- - Improved non-authoritative cache handling with 5-minute retry backoff instead of retrying on every startup
3816
- - Modified handling of aborted/errored assistant messages to preserve tool call structure instead of converting to text summaries, with synthetic 'aborted' tool results injected
3817
- - Updated tool call tracking to use status map (Resolved/Aborted) instead of separate sets for better handling of duplicate and aborted tool results
3818
-
3819
- ## [12.15.0] - 2026-02-20
3820
-
3821
- ### Fixed
3822
-
3823
- - Improved error messages for OAuth token refresh failures by including detailed error information from the provider
3824
- - Separated rate limit and usage limit error handling to provide distinct user-friendly messages for ChatGPT rate limits vs subscription usage limits
3825
-
3826
- ### Changed
3827
-
3828
- - Increased SDK retry attempts to 5 for OpenAI, Azure OpenAI, and Anthropic clients (was SDK default of 2)
3829
- - Changed 429 retry strategy for OpenAI Codex and Google Gemini CLI to use a 5-minute time budget when the server provides a retry delay, instead of a fixed attempt cap
3830
-
3831
- ## [12.14.0] - 2026-02-19
3832
-
3833
- ### Added
3834
-
3835
- - Added `gemini-3.1-pro` model to opencode provider with text and image input support
3836
- - Added `trinity-large-preview-free` model to opencode provider
3837
- - Added `google/gemini-3.1-pro-preview` model to nanogpt provider
3838
- - Added `google/gemini-3.1-pro-preview` model to openrouter provider with text and image input support
3839
- - Added `gemini-3.1-pro` model to cursor provider
3840
- - Added optional `intent` field to `ToolCall` interface for harness-level intent metadata
3841
-
3842
- ### Changed
3843
-
3844
- - Changed `big-pickle` model API from `openai-completions` to `anthropic-messages`
3845
- - Changed `big-pickle` model baseUrl from `https://opencode.ai/zen/v1` to `https://opencode.ai/zen`
3846
- - Changed `minimax-m2.5-free` model API from `openai-completions` to `anthropic-messages`
3847
- - Changed `minimax-m2.5-free` model baseUrl from `https://opencode.ai/zen/v1` to `https://opencode.ai/zen`
3848
-
3849
- ### Fixed
3850
-
3851
- - Fixed tool argument validation to iteratively coerce nested JSON strings across multiple passes, enabling proper handling of deeply nested JSON-serialized objects and arrays
3852
-
3853
- ## [12.13.0] - 2026-02-19
3854
-
3855
- ### Added
3856
-
3857
- - Added NanoGPT provider support with API-key login, dynamic model discovery from `https://nano-gpt.com/api/v1/models`, and text-model filtering for catalog/runtime discovery ([#111](https://github.com/can1357/oh-my-pi/issues/111))
3858
-
3859
- ## [12.12.3] - 2026-02-19
3860
-
3861
- ### Fixed
3862
-
3863
- - Fixed retry logic to recognize 'unable to connect' errors as transient failures
3864
-
3865
- ## [12.11.3] - 2026-02-19
3866
-
3867
- ### Fixed
3868
-
3869
- - Fixed OpenAI Codex streaming to fail truncated responses that end without a terminal completion event, preventing partial outputs from being treated as successful completions.
3870
- - Fixed Codex websocket append fallback by resetting stale turn-state/model-etag session metadata when request shape diverges from appendable history.
3871
-
3872
- ## [12.11.1] - 2026-02-19
3873
-
3874
- ### Added
3875
-
3876
- - Added support for Claude 4.6 Opus and Sonnet models via Cursor API
3877
- - Added support for Composer 1.5 model via Cursor API
3878
- - Added support for GPT-5.1 Codex Mini and GPT-5.1 High models via Cursor API
3879
- - Added support for GPT-5.2 and GPT-5.3 Codex variants (Fast, High, Low, Extra High) via Cursor API
3880
- - Added HTTP/2 transport support for Cursor API requests (required by Cursor API)
3881
-
3882
- ### Changed
3883
-
3884
- - Updated pricing for Claude 3.5 Sonnet model
3885
- - Updated Claude 3.5 Sonnet context window from 262,144 to 131,072 tokens
3886
- - Simplified Cursor model display names by removing '(Cursor)' suffix
3887
- - Changed Cursor API timeout from 15 seconds to 5 seconds
3888
- - Switched Cursor API transport from HTTP/1.1 to HTTP/2
3889
-
3890
- ## [12.11.0] - 2026-02-19
3891
-
3892
- ### Added
3893
-
3894
- - Added `priority` field to Model interface for provider-assigned model prioritization
3895
- - Added `CatalogDiscoveryConfig` interface to standardize catalog discovery configuration across providers
3896
- - Added type guards `isCatalogDescriptor()` and `allowsUnauthenticatedCatalogDiscovery()` for safer descriptor handling
3897
- - Added `DEFAULT_MODEL_PER_PROVIDER` export from descriptors module for centralized default model management
3898
- - Support for 11 new AI providers: Cloudflare AI Gateway, Hugging Face Inference, LiteLLM, Moonshot, NVIDIA, Ollama, Qianfan, Qwen Portal, Together, Venice, vLLM, and Xiaomi MiMo
3899
- - Login flows for new providers with API key validation and OAuth token support
3900
- - Extended `KnownProvider` type to include all newly supported providers
3901
- - API key environment variable mappings for all new providers in service provider map
3902
- - Model discovery and configuration for Cloudflare AI Gateway, Hugging Face, LiteLLM, Moonshot, NVIDIA, Ollama, Qianfan, Qwen Portal, Together, Venice, vLLM, and Xiaomi MiMo
3903
-
3904
- ### Changed
3905
-
3906
- - Refactored OAuth credential retrieval to simplify storage lifecycle management in model generation script
3907
- - Parallelized special model discovery sources (Antigravity, Codex) for improved generation performance
3908
- - Reorganized model JSON structure to place `contextWindow` and `maxTokens` before `compat` field for consistency
3909
- - Added `priority` field to OpenAI Codex models for provider-assigned model prioritization
3910
- - Refactored provider descriptors to use helper functions (`descriptor`, `catalog`, `catalogDescriptor`) for reduced code duplication
3911
- - Refactored models.dev provider descriptors to use helper functions (`simpleModelsDevDescriptor`, `openAiCompletionsDescriptor`, `anthropicMessagesDescriptor`) for improved maintainability
3912
- - Unified provider descriptors into single source of truth in `descriptors.ts` for both runtime model discovery and catalog generation, improving maintainability
3913
- - Refactored model generation script to use declarative `CatalogProviderDescriptor` interface instead of separate descriptor types, reducing code duplication
3914
- - Reorganized models.dev provider descriptors into logical groups (Bedrock, Core, Coding Plans, Specialized) for better code organization
3915
- - Simplified API resolution for OpenCode and GitHub Copilot providers using rule-based matching instead of inline conditionals
3916
- - Refactored model generation script to use declarative provider descriptors instead of inline provider-specific logic, improving maintainability and reducing code duplication
3917
- - Extracted model post-processing policies (cache pricing corrections, context window normalization) into dedicated `model-policies.ts` module for better testability and clarity
3918
- - Removed static bundled models for Ollama and vLLM from `models.json` to rely on dynamic discovery instead, reducing static catalog size
3919
- - Updated `OAuthProvider` type to include new provider identifiers
3920
- - Expanded model registry (models.json) with thousands of new model entries across all new providers
3921
- - Modified environment variable resolution to use `$pickenv` for providers with multiple possible env var names
3922
- - Updated README documentation to list all newly supported providers and their authentication requirements
3923
-
3924
- ## [12.10.1] - 2026-02-18
3925
-
3926
- - Added Synthetic provider
3927
- - Added API-key login helpers for Synthetic and Cerebras providers
3928
-
3929
- ## [12.10.0] - 2026-02-18
3930
-
3931
- ### Breaking Changes
3932
-
3933
- - Renamed public API functions: `getModel()` → `getBundledModel()`, `getModels()` → `getBundledModels()`, `getProviders()` → `getBundledProviders()`
3934
-
3935
- ### Added
3936
-
3937
- - Exported `ModelManager` API for runtime-aware model resolution with dynamic endpoint discovery
3938
- - Exported provider-specific model manager configuration helpers for Google, OpenAI-compatible, Codex, and Cursor providers
3939
- - Exported discovery utilities for fetching models from Antigravity, Codex, Cursor, Gemini, and OpenAI-compatible endpoints
3940
- - Added `createModelManager()` function to manage bundled and dynamically discovered models with configurable refresh strategies
3941
- - Added support for on-disk model caching with TTL-based invalidation
3942
- - Added `resolveProviderModels()` function for runtime model resolution across multiple providers
3943
- - Added EU cross-region inference variants for Claude Haiku 3.5 on Bedrock
3944
- - Added Claude Sonnet 4.6 and Claude Sonnet 4.6 Thinking models to Antigravity provider
3945
- - Added GLM-5 Free model via OpenCode provider
3946
- - Added GLM-4.7-FlashX model via ZAI provider
3947
- - Added MiniMax-M2.5-highspeed model across multiple providers (minimax-code, minimax-code-cn, minimax, minimax-cn)
3948
- - Added Claude Sonnet 4.6 model to OpenRouter provider
3949
- - Added Qwen 3.5 Plus model to Vercel AI Gateway provider
3950
- - Added Claude Sonnet 4.6 model to Vercel AI Gateway provider
3951
-
3952
- ### Changed
3953
-
3954
- - Renamed `getModel()` to `getBundledModel()` to clarify it returns compile-time bundled models only
3955
- - Renamed `getModels()` to `getBundledModels()` for consistency
3956
- - Renamed `getProviders()` to `getBundledProviders()` for consistency
3957
- - Refactored model generation script to use modular discovery functions instead of monolithic provider-specific logic
3958
- - Updated models.json with new model entries and pricing updates across multiple providers
3959
- - Updated pricing for deepseek/deepseek-v3 model on OpenRouter
3960
- - Updated maxTokens from 65536 to 4096 for deepseek/deepseek-v3 on OpenRouter
3961
- - Updated pricing and maxTokens for mistralai/mistral-large-2411 on OpenRouter
3962
- - Updated pricing for qwen/qwen-max on Together AI
3963
- - Updated pricing for qwen/qwen-vl-plus on Together AI
3964
- - Updated pricing for qwen/qwen-plus on Together AI
3965
- - Updated pricing for qwen/qwen-turbo on Together AI
3966
- - Expanded EU cross-region inference variant support to all Claude models on Bedrock (previously limited to Haiku, Sonnet, and Opus 4.5)
3967
-
3968
- ## [12.8.0] - 2026-02-16
3969
-
3970
- ### Added
3971
-
3972
- - Added `contextPromotionTarget` model property to specify preferred fallback model when context promotion is triggered
3973
- - Added automatic context promotion target assignment for Spark models to their base model equivalents
3974
- - Added support for Brave search provider with BRAVE_API_KEY environment variable
3975
-
3976
- ### Changed
3977
-
3978
- - Updated Qwen model context window and max token limits for improved accuracy
3979
-
3980
- ## [12.7.0] - 2026-02-16
3981
-
3982
- ### Added
3983
-
3984
- - Added DeepSeek-V3.2 model support via Amazon Bedrock
3985
- - Added GLM-5 model support via OpenCode
3986
- - Added MiniMax M2.5 model support via OpenCode
3987
-
3988
- ### Changed
3989
-
3990
- - Updated GLM-4.5, GLM-4.5-Air, GLM-4.5-Flash, GLM-4.5V, GLM-4.6, GLM-4.6V, GLM-4.7, GLM-4.7-Flash, and GLM-5 models to use anthropic-messages API instead of openai-completions
3991
- - Updated GLM models base URL from https://api.z.ai/api/coding/paas/v4 to https://api.z.ai/api/anthropic
3992
- - Updated pricing for multiple models including Mistral, Moonshot, and Qwen variants
3993
- - Updated context window and max tokens for several models to reflect accurate specifications
3994
-
3995
- ### Removed
3996
-
3997
- - Removed compat field with supportsDeveloperRole and thinkingFormat properties from GLM models
3998
-
3999
- ## [12.6.0] - 2026-02-16
4000
-
4001
- ### Added
4002
-
4003
- - Added source-scoped custom API and OAuth provider registration helpers for extension-defined providers.
4004
-
4005
- ### Changed
4006
-
4007
- - Expanded `Api` typing to allow extension-defined API identifiers while preserving built-in API exhaustiveness checks.
4008
-
4009
- ### Fixed
4010
-
4011
- - Fixed custom API registration to reject built-in API identifiers and prevent accidental provider overrides.
4012
-
4013
- ## [12.2.0] - 2026-02-13
4014
-
4015
- ### Added
4016
-
4017
- - Added automatic retry logic for WebSocket stream closures before response completion, with configurable retry budget to improve reliability on flaky connections
4018
- - Added `providerSessionState` option to enable provider-scoped mutable state persistence across agent turns
4019
- - Added WebSocket retry logic with configurable retry budget and delay via `PI_CODEX_WEBSOCKET_RETRY_BUDGET` and `PI_CODEX_WEBSOCKET_RETRY_DELAY_MS` environment variables
4020
- - Added WebSocket idle timeout detection via `PI_CODEX_WEBSOCKET_IDLE_TIMEOUT_MS` environment variable to fail stalled connections
4021
- - Added WebSocket v2 beta header support via `PI_CODEX_WEBSOCKET_V2` environment variable for newer OpenAI API versions
4022
- - Added WebSocket handshake header capture to extract and replay session metadata (turn state, models etag, reasoning flags) across SSE fallback requests
4023
- - Added `preferWebsockets` option to enable WebSocket transport for OpenAI Codex responses when supported
4024
- - Added `prewarmOpenAICodexResponses()` function to establish and reuse WebSocket connections across multiple requests
4025
- - Added `getOpenAICodexTransportDetails()` function to inspect transport layer details including WebSocket status and fallback information
4026
- - Added `getProviderDetails()` function to retrieve formatted provider configuration and transport information
4027
- - Added automatic fallback from WebSocket to SSE when connection fails, with transparent retry logic
4028
- - Added session state management to reuse WebSocket connections and enable request appending across turns
4029
- - Added support for x-codex-turn-state header to maintain conversation state across SSE requests
4030
-
4031
- ### Changed
4032
-
4033
- - Changed WebSocket session state storage from global maps to provider-scoped session state for multi-agent isolation
4034
- - Changed WebSocket connection initialization to accept idle timeout configuration and handshake header callbacks
4035
- - Changed WebSocket error handling to use standardized transport error messages with `Codex websocket transport error` prefix
4036
- - Changed WebSocket retry behavior to retry transient failures before activating sticky fallback, improving reliability on flaky connections
4037
- - Changed OpenAI Codex model configuration to prefer WebSocket transport by default with `preferWebsockets: true`
4038
- - Changed header handling to use appropriate OpenAI-Beta header values for WebSocket vs SSE transports
4039
- - Perplexity OAuth token refresh now uses JWT expiry extraction instead of Socket.IO RPC, improving reliability when server is unreachable
4040
- - Removed Socket.IO client implementation for Perplexity token refresh; tokens are now validated using embedded JWT expiry claims
4041
-
4042
- ### Removed
4043
-
4044
- - Removed `refreshPerplexityToken` export; token refresh is now handled internally via JWT expiry detection
4045
-
4046
- ### Fixed
4047
-
4048
- - Fixed WebSocket stream retry logic to properly handle mid-stream connection closures and retry before falling back to SSE transport
4049
- - Fixed `preferWebsockets` option handling to correctly respect explicit `false` values when determining transport preference
4050
- - Fixed WebSocket append state not being reset after aborted requests, preventing stale state from affecting subsequent turns
4051
- - Fixed WebSocket append state not being reset after stream errors, preventing failed append attempts from blocking future requests
4052
- - Fixed Codex model context window metadata to use 272000 input tokens (instead of 400000 total budget) for non-Spark Codex variants
4053
-
4054
- ## [12.0.0] - 2026-02-12
4055
-
4056
- ### Added
4057
-
4058
- - Added GPT-5.3 Codex Spark model with 128K context window and extended reasoning capabilities
4059
- - Added MiniMax M2.5 and M2.5 Lightning models via OpenAI-compatible API (minimax-code provider)
4060
- - Added MiniMax M2.5 and M2.5 Lightning models via OpenAI-compatible API (minimax-code-cn provider for China region)
4061
- - Added MiniMax M2.5 and M2.5 Lightning models via Anthropic API (minimax and minimax-cn providers)
4062
- - Added Llama 3.1 8B model via Cerebras API
4063
- - Added MiniMax M2.5 model via OpenRouter
4064
- - Added MiniMax M2.5 model via Vercel AI Gateway
4065
- - Added MiniMax M2.5 Free model via OpenCode
4066
- - Added Qwen3 VL 32B Instruct multimodal model via OpenRouter
4067
-
4068
- ### Changed
4069
-
4070
- - Updated Z.ai GLM-5 pricing and context window configuration on OpenRouter
4071
- - Updated Qwen3 Max Thinking max tokens from 32768 to 65536 on OpenRouter
4072
- - Updated OpenAI GPT-5 Image Mini pricing on OpenRouter
4073
- - Updated OpenAI GPT-5 Pro pricing and context window on OpenRouter
4074
- - Updated OpenAI o4-mini pricing and context window on OpenRouter
4075
- - Updated Claude Opus 4.5 Thinking model name formatting (removed parentheses)
4076
- - Updated Claude Opus 4.6 Thinking model name formatting (removed parentheses)
4077
- - Updated Claude Sonnet 4.5 Thinking model name formatting (removed parentheses)
4078
- - Updated Gemini 2.5 Flash Thinking model name formatting (removed parentheses)
4079
- - Updated Gemini 3 Pro High and Low model name formatting (removed parentheses)
4080
- - Updated GPT-OSS 120B Medium model name formatting (removed parentheses) and context window to 131072
4081
-
4082
- ### Removed
4083
-
4084
- - Removed GLM-5 model from Z.ai provider
4085
- - Removed Trinity Large Preview Free model from OpenCode provider
4086
- - Removed MiniMax M2.1 Free model from OpenCode provider
4087
- - Removed deprecated Anthropic model entries: `claude-3-5-haiku-latest`, `claude-3-5-haiku-20241022`, `claude-3-7-sonnet-20250219`, `claude-3-7-sonnet-latest`, `claude-3-opus-20240229`, `claude-3-sonnet-20240229` ([#33](https://github.com/can1357/oh-my-pi/issues/33))
4088
-
4089
- ### Fixed
4090
-
4091
- - Added deprecation filter in model generation script to prevent re-adding deprecated Anthropic models ([#33](https://github.com/can1357/oh-my-pi/issues/33))
4092
-
4093
- ## [11.14.1] - 2026-02-12
4094
-
4095
- ### Added
4096
-
4097
- - Added prompt-caching-scope-2026-01-05 beta feature support
4098
-
4099
- ### Changed
4100
-
4101
- - Updated Claude Code version header to 2.1.39
4102
- - Updated runtime version header to v24.13.1 and package version to 0.73.0
4103
- - Increased request timeout from 60s to 600s
4104
- - Reordered Accept-Encoding header values for compression preference
4105
- - Updated OAuth authorization and token endpoints to use platform.claude.com
4106
- - Expanded OAuth scopes to include user:sessions:claude_code and user:mcp_servers
4107
-
4108
- ### Removed
4109
-
4110
- - Removed claude-code-20250219 beta feature from default models
4111
- - Removed fine-grained-tool-streaming-2025-05-14 beta feature
4112
-
4113
- ## [11.13.1] - 2026-02-12
4114
-
4115
- ### Added
4116
-
4117
- - Added Perplexity (Pro/Max) OAuth login support via native macOS app extraction or email OTP authentication
4118
- - Added `loginPerplexity` and `refreshPerplexityToken` functions for Perplexity account integration
4119
- - Added Socket.IO v4 client implementation for authenticated WebSocket communication with Perplexity API
4120
-
4121
- ## [11.12.0] - 2026-02-11
4122
-
4123
- ### Changed
4124
-
4125
- - Increased maximum retry attempts for Codex requests from 2 to 5 to improve reliability on transient failures
4126
-
4127
- ### Fixed
4128
-
4129
- - Fixed tool result content handling in Anthropic provider to provide fallback error message when content is empty
4130
- - Improved retry delay calculation to parse delay values from error response bodies (e.g., 'Please try again in 225ms')
4131
-
4132
- ## [11.11.0] - 2026-02-10
4133
-
4134
- ### Breaking Changes
4135
-
4136
- - Replaced `./models.generated` export with `./models.json` - update imports from `import { MODELS } from './models.generated'` to `import MODELS from './models.json' with { type: 'json' }`
4137
-
4138
- ### Added
4139
-
4140
- - Added TypeScript type declarations for `models.json` to enable proper type inference when importing the JSON file
4141
-
4142
- ### Changed
4143
-
4144
- - Updated available models in google-antigravity provider with new model variants and updated context window/token limits
4145
- - Simplified type signatures for `getModel()` and `getModels()` functions for improved usability
4146
- - Changed models export from TypeScript module to JSON format for improved performance and reduced bundle size
4147
- - Updated `@anthropic-ai/sdk` dependency from ^0.72.1 to ^0.74.0
4148
-
4149
- ## [11.10.0] - 2026-02-10
4150
-
4151
- ### Added
4152
-
4153
- - Added support for Kimi K2, K2 Turbo Preview, and K2.5 models with reasoning capabilities
4154
-
4155
- ### Fixed
4156
-
4157
- - Fixed Claude Opus 4.6 context window to 200K across all providers (was incorrectly set to 1M)
4158
- - Fixed Claude Sonnet 4 context window to 200K across multiple providers (was incorrectly set to 1M)
4159
-
4160
- ## [11.8.0] - 2026-02-10
4161
-
4162
- ### Added
4163
-
4164
- - Added `auto` model alias for OpenRouter with automatic model routing
4165
- - Added `openrouter/aurora-alpha` model with reasoning capabilities
4166
- - Added `qwen/qwen3-max-thinking` model with extended context window support
4167
- - Added support for `parametersJsonSchema` in Google Gemini tool definitions for improved JSON Schema compatibility
4168
-
4169
- ### Changed
4170
-
4171
- - Updated Claude Sonnet 4 and 4.5 context window from 1M to 200K tokens to reflect actual limits
4172
- - Updated Claude Opus 4.6 context window to 200K tokens across providers
4173
- - Changed default `reasoningSummary` for OpenAI Codex from `undefined` to `auto`
4174
- - Updated Qwen model pricing and context window specifications across multiple variants
4175
- - Modified Google Gemini CLI system instruction to use compact format
4176
- - Changed tool parameter handling for Claude models on Google Cloud Code Assist to use legacy `parameters` field for API translation
4177
-
4178
- ### Removed
4179
-
4180
- - Removed `glm-4.7-free` model from OpenCode provider
4181
- - Removed `qwen3-coder` model from OpenCode provider
4182
- - Removed `ai21/jamba-mini-1.7` model from OpenRouter
4183
- - Removed `stepfun-ai/step3` model from OpenRouter
4184
- - Removed duplicate test suite for Google Antigravity Provider with `gemini-3-pro-high`
4185
-
4186
- ### Fixed
4187
-
4188
- - Fixed Amazon Bedrock HTTP/1.1 handler import to use direct import instead of dynamic import
4189
- - Fixed Qwen model context window and pricing inconsistencies across OpenRouter
4190
- - Fixed cache read pricing for multiple Qwen models
4191
- - Fixed OpenAI Codex reasoning effort clamping for `gpt-5.3-codex` model
4192
-
4193
- ## [11.7.1] - 2026-02-07
4194
-
4195
- ### Added
4196
-
4197
- - Added Claude Opus 4.6 Thinking model for Antigravity provider
4198
- - Added Gemini 2.5 Flash, Gemini 2.5 Flash Thinking, and Gemini 2.5 Pro models for Antigravity provider
4199
- - Added Pony Alpha model via OpenRouter
4200
-
4201
- ### Changed
4202
-
4203
- - Updated Antigravity models to use free tier pricing (0 cost) across all models
4204
- - Changed Antigravity model fetching to dynamically load from API when credentials are available, with hardcoded fallback models
4205
- - Updated Claude Opus 4.6 context window from 200,000 to 1,000,000 tokens across Bedrock regions
4206
- - Updated Claude Opus 4.6 cache pricing from 1.5/18.75 to 0.5/6.25 for EU and US regions
4207
- - Updated Antigravity model pricing to free tier (0 cost) for Claude Opus 4.5 Thinking, Claude Sonnet 4.5 Thinking, Gemini 3 Flash, Gemini 3 Pro variants, and GPT-OSS 120B Medium
4208
- - Updated GPT-OSS 120B Medium reasoning capability from false to true
4209
- - Updated Gemini 3 Flash max tokens from 65,535 to 65,536
4210
- - Updated Claude Opus 4.5 Thinking display name formatting to include parentheses
4211
- - Updated various model pricing and context window parameters across OpenRouter and other providers
4212
- - Removed Claude Opus 4.6 20260205 model from Anthropic provider
4213
-
4214
- ### Fixed
4215
-
4216
- - Fixed Claude Opus 4.6 model ID format by removing version suffix (:0) in Bedrock configurations
4217
- - Fixed Llama 3.1 70B Instruct pricing and context window parameters
4218
- - Fixed Mistral model pricing and cache read costs
4219
- - Fixed DeepSeek and other model pricing inconsistencies
4220
- - Fixed Qwen model pricing and token limits
4221
- - Fixed GLM model pricing and context window specifications
4222
-
4223
- ## [11.6.0] - 2026-02-07
4224
-
4225
- ### Added
4226
-
4227
- - Added Bedrock cache retention support with `PI_CACHE_RETENTION` env var and per-request `cacheRetention` option
4228
- - Added adaptive thinking support for Bedrock Opus 4.6+ models
4229
- - Added `AWS_BEDROCK_SKIP_AUTH` env var to support unauthenticated Bedrock proxies
4230
- - Added `AWS_BEDROCK_FORCE_HTTP1` env var to force HTTP/1.1 for custom Bedrock endpoints
4231
- - Re-exported `Static`, `TSchema`, and `Type` from `@sinclair/typebox`
4232
-
4233
- ### Fixed
4234
-
4235
- - Fixed OpenAI Responses storage disabled by default (`store: false`)
4236
- - Fixed reasoning effort clamping for gpt-5.3 Codex models (minimal -> low)
4237
- - Fixed Bedrock `supportsPromptCaching` to also check model cost fields
4238
-
4239
- ## [11.5.1] - 2026-02-07
4240
-
4241
- ### Fixed
4242
-
4243
- - Fixed schema normalization to handle array-valued `type` fields by converting them to a single type with nullable flag for Google provider compatibility
4244
-
4245
- ## [11.3.0] - 2026-02-06
4246
-
4247
- ### Added
4248
-
4249
- - Added `cacheRetention` option to control prompt cache retention preference ('none', 'short', 'long') across providers
4250
- - Added `maxRetryDelayMs` option to cap server-requested retry delays and fail fast when delays exceed the limit
4251
- - Added `effort` option for Anthropic Opus 4.6+ models to control adaptive thinking effort levels ('low', 'medium', 'high', 'max')
4252
- - Added support for Anthropic Opus 4.6+ adaptive thinking mode that lets Claude decide when and how much to think
4253
- - Added `PI_AI_ANTIGRAVITY_VERSION` environment variable to customize Antigravity sandbox endpoint version
4254
- - Exported `convertAnthropicMessages` function for converting message formats to Anthropic API
4255
- - Automatic fallback for Anthropic assistant-prefill requests: appends synthetic user "Continue." message when conversation ends with assistant turn to maintain API compatibility
4256
-
4257
- ### Changed
4258
-
4259
- - Changed `supportsXhigh()` to include GPT-5.1 Codex Max and broaden Anthropic support to all Anthropic Messages API models with budget-based thinking capability
4260
- - Changed Anthropic thinking mode to use adaptive thinking for Opus 4.6+ models instead of budget-based thinking
4261
- - Changed `supportsXhigh()` to support GPT-5.2/5.3 and Anthropic Opus 4.6+ models with adaptive thinking
4262
- - Changed prompt caching to respect `cacheRetention` option and support TTL configuration for Anthropic
4263
- - Changed OpenAI tool definitions to conditionally include `strict` field only when provider supports it
4264
- - Changed Qwen model support to use `enable_thinking` boolean parameter instead of OpenAI-style reasoning_effort
4265
-
4266
- ### Fixed
4267
-
4268
- - Fixed indentation and formatting in `convertAnthropicMessages` function
4269
- - Fixed handling of conversations ending with assistant messages on Anthropic-routed models that reject assistant prefill requests
4270
-
4271
- ## [11.2.3] - 2026-02-05
4272
-
4273
- ### Added
4274
-
4275
- - Added Claude Opus 4.6 model support across multiple providers (Anthropic, Amazon Bedrock, GitHub Copilot, OpenRouter, OpenCode, Vercel AI Gateway)
4276
- - Added GPT-5.3 Codex model support for OpenAI
4277
- - Added `readSseJson` utility import for improved SSE stream handling in Google Gemini CLI provider
4278
-
4279
- ### Changed
4280
-
4281
- - Updated Google Gemini CLI provider to use `readSseJson` utility for cleaner SSE stream parsing
4282
- - Updated pricing for Llama 3.1 405B model on Vercel AI Gateway (cache read rate adjusted)
4283
- - Updated Llama 3.1 405B context window and max tokens on Vercel AI Gateway (256000 for both)
4284
-
4285
- ### Removed
4286
-
4287
- - Removed Kimi K2, Kimi K2 Turbo Preview, and Kimi K2.5 models
4288
- - Removed Deep Cogito Cogito V2 Preview models from OpenRouter
4289
-
4290
- ## [11.0.0] - 2026-02-05
4291
-
4292
- ### Changed
4293
-
4294
- - Replaced direct `process.env` access with `getEnv()` utility from `@oh-my-pi/pi-utils` for consistent environment variable handling across all providers
4295
- - Updated environment variable names from `OMP_*` prefix to `PI_*` prefix for consistency (e.g., `OMP_CODING_AGENT_DIR` → `PI_CODING_AGENT_DIR`)
4296
-
4297
- ### Removed
4298
-
4299
- - Removed automatic environment variable migration from `PI_*` to `OMP_*` prefixes via `migrate-env.ts` module
4300
-
4301
- ## [10.5.0] - 2026-02-04
4302
-
4303
- ### Changed
4304
-
4305
- - Updated @anthropic-ai/sdk to ^0.72.1
4306
- - Updated @aws-sdk/client-bedrock-runtime to ^3.982.0
4307
- - Updated @google/genai to ^1.39.0
4308
- - Updated @smithy/node-http-handler to ^4.4.9
4309
- - Updated openai to ^6.17.0
4310
- - Updated @types/node to ^25.2.0
4311
-
4312
- ### Removed
4313
-
4314
- - Removed proxy-agent dependency
4315
- - Removed undici dependency
4316
-
4317
- ## [9.4.0] - 2026-01-31
4318
-
4319
- ### Added
4320
-
4321
- - Added `getEnv()` function to retrieve environment variables from process.env, cwd/.env, or ~/.env
4322
- - Added support for reading .env files from home directory and current working directory
4323
- - Added support for `exa` and `perplexity` as known providers in `getEnvApiKey()`
4324
-
4325
- ### Changed
4326
-
4327
- - Changed `getEnvApiKey()` to check process.env, cwd/.env, and ~/.env files in order of precedence
4328
- - Refactored provider API key resolution to use a declarative service provider map
4329
-
4330
- ## [9.2.2] - 2026-01-31
4331
-
4332
- ### Added
4333
-
4334
- - Added OpenCode Zen provider with API key authentication for accessing multiple AI models
4335
- - Added 4 new free models via OpenCode: glm-4.7-free, kimi-k2.5-free, minimax-m2.1-free, trinity-large-preview-free
4336
- - Added glm-4.7-flash model via Zai provider
4337
- - Added Kimi Code provider with OpenAI and Anthropic API format support
4338
- - Added prompt cache retention support with PI_CACHE_RETENTION env var
4339
- - Added overflow patterns for Bedrock, MiniMax, Kimi; reclassified 429 as rate limiting
4340
- - Added profile endpoint integration to resolve user emails with 24-hour caching
4341
- - Added automatic token refresh for expired Kimi OAuth credentials
4342
- - Added Kimi Code OAuth handler with device authorization flow
4343
- - Added Kimi Code usage provider with quota caching
4344
- - Added 4 new Kimi Code models (kimi-for-coding, kimi-k2, kimi-k2-turbo-preview, kimi-k2.5)
4345
- - Added Kimi Code provider integration with OAuth and token management
4346
- - Added tool-choice utility for mapping unified ToolChoice to provider-specific formats
4347
- - Added ToolChoice type for controlling tool selection (auto, none, any, required, function)
4348
-
4349
- ### Changed
4350
-
4351
- - Updated Kimi K2.5 cache read pricing from 0.1 to 0.08
4352
- - Updated MiniMax M2 pricing: input 0.6→0.6, output 3→3, cache read 0.1→0.09999999999999999
4353
- - Updated OpenRouter DeepSeek V3.1 pricing and max tokens: input 0.6→0.5, output 3→2.8, maxTokens 262144→4096
4354
- - Updated OpenRouter DeepSeek R1 pricing and max tokens: input 0.06→0.049999999999999996, output 0.24→0.19999999999999998, maxTokens 262144→4096
4355
- - Updated Anthropic Claude 3.5 Sonnet max tokens from 256000 to 65536 on OpenRouter
4356
- - Updated Vercel AI Gateway Claude 3.5 Sonnet cache read pricing from 0.125 to 0.13
4357
- - Updated Vercel AI Gateway Claude 3.5 Sonnet New cache read pricing from 0.125 to 0.13
4358
- - Updated Vercel AI Gateway GPT-5.2 cache read pricing from 0.175 to 0.18 and display name to 'GPT 5.2'
4359
- - Updated Zai GLM-4.6 cache read pricing from 0.024999999999999998 to 0.03
4360
- - Updated Zai Qwen QwQ max tokens from 66000 to 16384
4361
- - Added delta event batching and throttling (50ms, 20 updates/sec max) to AssistantMessageEventStream
4362
- - Updated MiniMax-M2 pricing: input 1.2→0.6, output 1.2→3, cacheRead 0.6→0.1
4363
-
4364
- ### Removed
4365
-
4366
- - Removed OpenRouter google/gemini-2.0-flash-exp:free model
4367
- - Removed Vercel AI Gateway stealth/sonoma-dusk-alpha and stealth/sonoma-sky-alpha models
4368
-
4369
- ### Fixed
4370
-
4371
- - Fixed rate limit issues with Kimi models by always sending max_tokens
4372
- - Added handling for sensitive stop reason from Anthropic API safety filters
4373
- - Added optional chaining for safer JSON schema property access in Anthropic provider
4374
-
4375
- ## [8.6.0] - 2026-01-27
4376
-
4377
- ### Changed
4378
-
4379
- - Replaced JSON5 dependency with Bun.JSON5 parsing
4380
-
4381
- ### Fixed
4382
-
4383
- - Filtered empty user text blocks for OpenAI-compatible completions and normalized Kimi reasoning_content for OpenRouter tool-call messages
4384
-
4385
- ## [8.4.0] - 2026-01-25
4386
-
4387
- ### Added
4388
-
4389
- - Added Azure OpenAI Responses provider with deployment mapping and resource-based base URL support
4390
-
4391
- ### Changed
4392
-
4393
- - Added OpenRouter routing preferences for OpenAI-compatible completions
4394
-
4395
- ### Fixed
4396
-
4397
- - Defaulted Google tool call arguments to empty objects when providers omit args
4398
- - Guarded Responses/Codex streaming deltas against missing content parts and handled arguments.done events
4399
-
4400
- ## [8.2.1] - 2026-01-24
4401
-
4402
- ### Fixed
4403
-
4404
- - Fixed handling of streaming function call arguments in OpenAI responses to properly parse arguments when sent via `response.function_call_arguments.done` events
4405
-
4406
- ## [8.2.0] - 2026-01-24
4407
-
4408
- ### Changed
4409
-
4410
- - Migrated node module imports from named to namespace imports across all packages for consistency with project guidelines
4411
-
4412
- ## [8.0.0] - 2026-01-23
4413
-
4414
- ### Fixed
4415
-
4416
- - Fixed OpenAI Responses API 400 error "function_call without required reasoning item" when switching between models (same provider, different model). The fix omits the `id` field for function_calls from different models to avoid triggering OpenAI's reasoning/function_call pairing validation
4417
- - Fixed 400 errors when reading multiple images via GitHub Copilot's Claude models. Claude requires tool_use -> tool_result adjacency with no user messages interleaved. Images from consecutive tool results are now batched into a single user message
4418
-
4419
- ## [7.0.0] - 2026-01-21
4420
-
4421
- ### Added
4422
-
4423
- - Added usage tracking system with normalized schema for provider quota/limit endpoints
4424
- - Added Claude usage provider for 5-hour and 7-day quota windows
4425
- - Added GitHub Copilot usage provider for chat, completions, and premium requests
4426
- - Added Google Antigravity usage provider for model quota tracking
4427
- - Added Google Gemini CLI usage provider for tier-based quota monitoring
4428
- - Added OpenAI Codex usage provider for primary and secondary rate limit windows
4429
- - Added ZAI usage provider for token and request quota tracking
4430
-
4431
- ### Changed
4432
-
4433
- - Updated Claude usage provider to extract account identifiers from response headers
4434
- - Updated GitHub Copilot usage provider to include account identifiers in usage reports
4435
- - Updated Google Gemini CLI usage provider to handle missing reset time gracefully
4436
-
4437
- ### Fixed
4438
-
4439
- - Fixed GitHub Copilot usage provider to simplify token handling and improve reliability
4440
- - Fixed GitHub Copilot usage provider to properly resolve account identifiers for OAuth credentials
4441
- - Fixed API validation errors when sending empty user messages (resume with `.`) across all providers:
4442
- - Google Cloud Code Assist (google-shared.ts)
4443
- - OpenAI Responses API (openai-responses.ts)
4444
- - OpenAI Codex Responses API (openai-codex-responses.ts)
4445
- - Cursor (cursor.ts)
4446
- - Amazon Bedrock (amazon-bedrock.ts)
4447
- - Clamped OpenAI Codex reasoning effort "minimal" to "low" for gpt-5.2 models to avoid API errors
4448
- - Fixed GitHub Copilot usage fallback to internal quota endpoints when billing usage is unavailable
4449
- - Fixed GitHub Copilot usage metadata to include account identifiers for report dedupe
4450
- - Fixed Anthropic usage metadata extraction to include account identifiers when provided by the usage endpoint
4451
- - Fixed Gemini CLI usage windows to consistently label quota windows for display suppression
4452
-
4453
- ## [6.9.69] - 2026-01-21
4454
-
4455
- ### Added
4456
-
4457
- - Added duration and time-to-first-token (ttft) metrics to all AI provider responses
4458
- - Added performance tracking for streaming responses across all providers
4459
-
4460
- ## [6.9.0] - 2026-01-21
4461
-
4462
- ### Removed
4463
-
4464
- - Removed openai-codex provider exports from main package index
4465
- - Removed openai-codex prompt utilities and moved them inline
4466
- - Removed vitest configuration file
4467
-
4468
- ## [6.8.4] - 2026-01-21
4469
-
4470
- ### Changed
4471
-
4472
- - Updated prompt caching strategy to follow Anthropic's recommended hierarchy
4473
- - Fixed token usage tracking to properly handle cumulative output tokens from message_delta events
4474
- - Improved message validation to filter out empty or invalid content blocks
4475
- - Increased OAuth callback timeout from 120 seconds to 120,000 milliseconds
4476
-
4477
- ## [6.8.3] - 2026-01-21
4478
-
4479
- ### Added
4480
-
4481
- - Added `headers` option to all providers for custom request headers
4482
- - Added `onPayload` hook to observe provider request payloads before sending
4483
- - Added `strictResponsesPairing` option for Azure OpenAI Responses API compatibility
4484
- - Added `originator` option to `loginOpenAICodex` for custom OAuth flow identification
4485
- - Added per-request `headers` and `onPayload` hooks to `StreamOptions`
4486
- - Added `originator` option to `loginOpenAICodex`
4487
-
4488
- ### Fixed
4489
-
4490
- - Fixed tool call ID normalization for OpenAI Responses API cross-provider handoffs
4491
- - Skipped errored or aborted assistant messages during cross-provider transforms
4492
- - Detected AWS ECS/IRSA credentials for Bedrock authentication checks
4493
- - Detected AWS ECS/IRSA credentials for Bedrock authentication checks
4494
- - Normalized Responses API tool call IDs during handoffs and refreshed handoff tests
4495
- - Enforced strict tool call/result pairing for Azure OpenAI Responses API
4496
- - Skipped errored or aborted assistant messages during cross-provider transforms
4497
-
4498
- ### Security
4499
-
4500
- - Enhanced AWS credential detection to support ECS task roles and IRSA web identity tokens
4501
-
4502
- ## [6.8.2] - 2026-01-21
4503
-
4504
- ### Fixed
4505
-
4506
- - Improved error handling for aborted requests in Google Gemini CLI provider
4507
- - Enhanced OAuth callback flow to handle manual input errors gracefully
4508
- - Fixed login cancellation handling in GitHub Copilot OAuth flow
4509
- - Removed fallback manual input from OpenAI Codex OAuth flow
4510
-
4511
- ### Security
4512
-
4513
- - Hardened database file permissions to prevent credential leakage
4514
- - Set secure directory permissions (0o700) for credential storage
4515
-
4516
- ## [6.8.0] - 2026-01-20
4517
-
4518
- ### Added
4519
-
4520
- - Added `logout` command to CLI for OAuth provider logout
4521
- - Added `status` command to show logged-in providers and token expiry
4522
- - Added persistent credential storage using SQLite database
4523
- - Added OAuth callback server with automatic port fallback
4524
- - Added HTML callback page with success/error states
4525
- - Added support for Cursor OAuth provider
4526
-
4527
- ### Changed
4528
-
4529
- - Updated Promise.withResolvers usage for better compatibility
4530
- - Replaced custom sleep implementations with Bun.sleep and abortableSleep
4531
- - Simplified SSE stream parsing using readLines utility
4532
- - Updated test framework from vitest to bun:test
4533
- - Replaced temp directory creation with createTempDirSync utility
4534
- - Changed credential storage from auth.json to ~/.omp/agent/agent.db
4535
- - Changed CLI command examples from npx to bunx
4536
- - Refactored OAuth flows to use common callback server base class
4537
- - Updated OAuth provider interfaces to use controller pattern
4538
-
4539
- ### Fixed
4540
-
4541
- - Fixed OAuth callback handling with improved error states
4542
- - Fixed token refresh for all OAuth providers
4543
-
4544
- ## [6.7.670] - 2026-01-19
4545
-
4546
- ### Changed
4547
-
4548
- - Updated Claude Code compatibility headers and version
4549
- - Improved OAuth token handling with proper state generation
4550
- - Enhanced cache control for tool and user message blocks
4551
- - Simplified tool name prefixing for OAuth traffic
4552
- - Updated PKCE verifier generation for better security
4553
-
4554
- ## [5.7.67] - 2026-01-18
4555
-
4556
- ### Fixed
4557
-
4558
- - Added error handling for unknown OAuth providers
4559
-
4560
- ## [5.6.77] - 2026-01-18
4561
-
4562
- ### Fixed
4563
-
4564
- - Prevented duplicate tool results for errored or aborted messages when results already exist
4565
-
4566
- ## [5.6.7] - 2026-01-18
4567
-
4568
- ### Added
4569
-
4570
- - Added automatic retry logic for OpenAI Codex responses with configurable delay and max retries
4571
- - Added tool call ID sanitization for Amazon Bedrock to ensure valid characters
4572
- - Added tool argument validation that coerces JSON-encoded strings for expected non-string types
4573
-
4574
- ### Changed
4575
-
4576
- - Updated environment variable prefix from PI_ to OMP_ for better consistency
4577
- - Added automatic migration for legacy PI_ environment variables to OMP_ equivalents
4578
- - Adjusted Bedrock Claude thinking budgets to reserve output tokens when maxTokens is too low
4579
-
4580
- ### Fixed
4581
-
4582
- - Fixed orphaned tool call handling to ensure proper tool_use/tool_result pairing for all assistant messages
4583
- - Fixed message transformation to insert synthetic tool results for errored/aborted assistant messages with tool calls
4584
- - Fixed tool prefix handling in Claude provider to use case-insensitive comparison
4585
- - Fixed Gemini 3 model handling to treat unsigned tool calls as context-only with anti-mimicry context
4586
- - Fixed message transformation to filter out empty error messages from conversation history
4587
- - Fixed OpenAI completions provider compatibility detection to use provider metadata
4588
- - Fixed OpenAI completions provider to avoid using developer role for opencode provider
4589
- - Fixed orphaned tool call handling to skip synthetic results for errored assistant messages
4590
-
4591
- ## [5.5.0] - 2026-01-18
4592
-
4593
- ### Changed
4594
-
4595
- - Updated User-Agent header from 'opencode' to 'pi' for OpenAI Codex requests
4596
- - Simplified Codex system prompt instructions
4597
- - Removed bridge text override from Codex system prompt builder
4598
-
4599
- ## [5.3.0] - 2026-01-15
4600
-
4601
- ### Changed
4602
-
4603
- - Replaced detailed Codex system instructions with simplified pi assistant instructions
4604
- - Updated internal documentation references to use pi-internal:// protocol
4605
-
4606
- ## [5.1.0] - 2026-01-14
4607
-
4608
- ### Added
4609
-
4610
- - Added Amazon Bedrock provider with `bedrock-converse-stream` API for Claude models via AWS
4611
- - Added MiniMax provider with OpenAI-compatible API
4612
- - Added EU cross-region inference model variants for Claude models on Bedrock
4613
-
4614
- ### Fixed
4615
-
4616
- - Fixed Gemini CLI provider retries with proper error handling, retry delays from headers, and empty stream retry logic
4617
- - Fixed numbered list items showing "1." for all items when code blocks break list continuity (via `start` property)
4618
-
4619
- ## [5.0.0] - 2026-01-12
4620
-
4621
- ### Added
4622
-
4623
- - Added support for `xhigh` thinking level in `thinkingBudgets` configuration
4624
-
4625
- ### Changed
4626
-
4627
- - Changed Anthropic thinking token budgets: minimal (1024→3072), low (2048→6144), medium (8192→12288), high (16384→24576)
4628
- - Changed Google thinking token budgets: minimal (1024), low (2048→4096), medium (8192), high (16384), xhigh (24575)
4629
- - Changed `supportsXhigh()` to return true for all Anthropic models
4630
-
4631
- ## [4.6.0] - 2026-01-12
4632
-
4633
- ### Fixed
4634
-
4635
- - Fixed incorrect classification of thought signatures in Google Gemini responses—thought signatures are now correctly treated as metadata rather than thinking content indicators
4636
- - Fixed thought signature handling in Google Gemini CLI and Vertex AI streaming to properly preserve signatures across text deltas
4637
- - Fixed Google schema sanitization stripping property names that match schema keywords (e.g., "pattern", "format") from tool definitions
4638
-
4639
- ## [4.4.9] - 2026-01-12
4640
-
4641
- ### Fixed
4642
-
4643
- - Fixed Google provider schema sanitization to strip additional unsupported JSON Schema fields (patternProperties, additionalProperties, min/max constraints, pattern, format)
4644
-
4645
- ## [4.4.8] - 2026-01-12
4646
-
4647
- ### Fixed
4648
-
4649
- - Fixed Google provider schema sanitization to properly collapse `anyOf`/`oneOf` with const values into enum arrays
4650
- - Fixed const-to-enum conversion to infer type from the const value when type is not specified
4651
-
4652
- ## [4.4.6] - 2026-01-11
4653
-
4654
- ### Fixed
4655
-
4656
- - Fixed tool parameter schema sanitization to only apply Google-specific transformations for Gemini models, preserving original schemas for other model types
4657
-
4658
- ## [4.4.5] - 2026-01-11
4659
-
4660
- ### Changed
4661
-
4662
- - Exported `sanitizeSchemaForGoogle` utility function for external use
4663
-
4664
- ### Fixed
4665
-
4666
- - Fixed Google provider schema sanitization to strip additional unsupported JSON Schema fields ($schema, $ref, $defs, format, examples, and others)
4667
- - Fixed Google provider to ignore `additionalProperties: false` which is unsupported by the API
4668
-
4669
- ## [4.4.4] - 2026-01-11
4670
-
4671
- ### Fixed
4672
-
4673
- - Fixed Cursor todo updates to bridge update_todos tool calls to the local todo_write tool
4674
-
4675
- ## [4.3.0] - 2026-01-11
4676
-
4677
- ### Added
4678
-
4679
- - Added debug log filtering and display script for Cursor JSONL logs with follow mode and coalescing support
4680
- - Added protobuf definition extractor script to reconstruct .proto files from bundled JavaScript
4681
- - Added conversation state caching to persist context across multiple Cursor API requests in the same session
4682
- - Added shell streaming support for real-time stdout/stderr output during command execution
4683
- - Added JSON5 parsing for MCP tool arguments with Python-style boolean and None value normalization
4684
- - Added Cursor provider with support for Claude, GPT, and Gemini models via Cursor's agent API
4685
- - Added OAuth authentication flow for Cursor including login, token refresh, and expiry detection
4686
- - Added `cursor-agent` API type with streaming support and tool execution handlers
4687
- - Added Cursor model definitions including Claude 4.5, GPT-5.x, Gemini 3, and Grok variants
4688
- - Added model generation script to automatically fetch and update AI model definitions from models.dev and OpenRouter APIs
4689
-
4690
- ### Changed
4691
-
4692
- - Changed Cursor debug logging to use structured JSONL format with automatic MCP argument decoding
4693
- - Changed MCP tool argument decoding to use protobuf Value schema for improved type handling
4694
- - Changed tool advertisement to filter Cursor native tools (bash, read, write, delete, ls, grep, lsp) instead of only exposing mcp_ prefixed tools
4695
-
4696
- ### Fixed
4697
-
4698
- - Fixed Cursor conversation history serialization so subagents retain task context and can call complete
4699
-
4700
- ## [4.2.1] - 2026-01-11
4701
-
4702
- ### Changed
4703
-
4704
- - Updated `reasoningSummary` option to accept only `"auto"`, `"concise"`, `"detailed"`, or `null` (removed `"off"` and `"on"` values)
4705
- - Changed default `reasoningSummary` from `"auto"` to `"detailed"`
4706
- - OpenAI Codex: switched to bundled system prompt matching opencode, changed originator to "opencode", simplified prompt handling
4707
-
4708
- ### Fixed
4709
-
4710
- - Fixed Cloud Code Assist tool schema conversion to avoid unsupported `const` fields
4711
-
4712
- ## [4.0.0] - 2026-01-10
4713
-
4714
- ### Added
4715
-
4716
- - Added `betas` option in `AnthropicOptions` for passing custom Anthropic beta feature flags
4717
- - OpenCode Zen provider support with 26 models (Claude, GPT, Gemini, Grok, Kimi, GLM, Qwen, etc.). Set `OPENCODE_API_KEY` env var to use.
4718
- - `thinkingBudgets` option in `SimpleStreamOptions` for customizing token budgets per thinking level on token-based providers
4719
- - `sessionId` option in `StreamOptions` for providers that support session-based caching. OpenAI Codex provider uses this to set `prompt_cache_key` and routing headers.
4720
- - `supportsUsageInStreaming` compatibility flag for OpenAI-compatible providers that reject `stream_options: { include_usage: true }`. Defaults to `true`. Set to `false` in model config for providers like gatewayz.ai.
4721
- - `GOOGLE_APPLICATION_CREDENTIALS` env var support for Vertex AI credential detection (standard for CI/production)
4722
- - Exported OpenAI Codex utilities: `CacheMetadata`, `getCodexInstructions`, `getModelFamily`, `ModelFamily`, `buildCodexPiBridge`, `buildCodexSystemPrompt`, `CodexSystemPrompt`
4723
- - Headless OAuth support for all callback-server providers (Google Gemini CLI, Antigravity, OpenAI Codex): paste redirect URL when browser callback is unreachable
4724
- - Cancellable GitHub Copilot device code polling via AbortSignal
4725
- - Improved error messages for OpenRouter providers by including raw metadata from upstream errors
4726
-
4727
- ### Changed
4728
-
4729
- - Changed Anthropic provider to include Claude Code system instruction for all API key types, not just OAuth tokens (except Haiku models)
4730
- - Changed Anthropic OAuth tool naming to use `proxy_` prefix instead of mapping to Claude Code tool names, avoiding potential name collisions
4731
- - Changed Anthropic provider to include Claude Code headers for all requests, not just OAuth tokens
4732
- - Anthropic provider now maps tool names to Claude Code's exact tool names (Read, Write, Edit, Bash, Grep, Glob) instead of using prefixed names
4733
- - OpenAI Completions provider now disables strict mode on tools to allow optional parameters without null unions
4734
-
4735
- ### Fixed
4736
-
4737
- - Fixed Anthropic OAuth code parsing to accept full redirect URLs in addition to raw authorization codes
4738
- - Fixed Anthropic token refresh to preserve existing refresh token when server doesn't return a new one
4739
- - Fixed thinking mode being enabled when tool_choice forces a specific tool, which is unsupported
4740
- - Fixed max_tokens being too low when thinking budget is set, now auto-adjusts to model's maxTokens
4741
- - Google Cloud Code Assist OAuth for paid subscriptions: properly handles long-running operations for project provisioning, supports `GOOGLE_CLOUD_PROJECT` / `GOOGLE_CLOUD_PROJECT_ID` env vars for paid tiers
4742
- - `os.homedir()` calls at module load time; now resolved lazily when needed
4743
- - OpenAI Responses tool strict flag to use a boolean for LM Studio compatibility
4744
- - Gemini CLI abort handling: detect native `AbortError` in retry catch block, cancel SSE reader when abort signal fires
4745
- - Antigravity provider 429 errors by aligning request payload with CLIProxyAPI v6.6.89
4746
- - Thinking block handling for cross-model conversations: thinking blocks are now converted to plain text when switching models
4747
- - OpenAI Codex context window from 400,000 to 272,000 tokens to match Codex CLI defaults
4748
- - Codex SSE error events to surface message, code, and status
4749
- - Context overflow detection for `context_length_exceeded` error codes
4750
- - Codex provider now always includes `reasoning.encrypted_content` even when custom `include` options are passed
4751
- - Codex requests now omit the `reasoning` field entirely when thinking is off
4752
- - Crash when pasting text with trailing whitespace exceeding terminal width
4753
-
4754
- ## [3.37.1] - 2026-01-10
4755
-
4756
- ### Added
4757
-
4758
- - Added automatic type coercion for tool arguments when LLMs return JSON-encoded strings instead of native types (numbers, booleans, arrays, objects)
4759
-
4760
- ### Changed
4761
-
4762
- - Changed tool argument validation to attempt JSON parsing and type coercion before rejecting mismatched types
4763
- - Changed validation error messages to include both original and normalized arguments when coercion was attempted
4764
-
4765
- ## [3.37.0] - 2026-01-10
4766
-
4767
- ### Changed
4768
-
4769
- - Enabled type coercion in JSON schema validation to automatically convert compatible types
4770
-
4771
- ## [3.35.0] - 2026-01-09
4772
-
4773
- ### Added
4774
-
4775
- - Enhanced error messages to include retry-after timing information from API rate limit headers
4776
-
4777
- ## [3.20.0] - 2026-01-06
4778
-
4779
- ### Added
4780
-
4781
- - Added support for kwaipilot/kat-coder-pro model via OpenRouter
4782
- - Added OpenAI Codex responses provider with OAuth login support for ChatGPT Plus/Pro accounts
4783
- - Added Google Vertex AI provider (Gemini via Vertex) with Application Default Credentials support
4784
-
4785
- ### Changed
4786
-
4787
- - Updated model specifications including context windows, max tokens, and pricing for multiple OpenRouter models
4788
-
4789
- ### Removed
4790
-
4791
- - Removed alibaba/tongyi-deepresearch-30b-a3b:free model from OpenRouter
4792
- - Removed nousresearch/hermes-4-405b model from OpenRouter
4793
- - Removed tngtech/tng-r1t-chimera:free model from OpenRouter
4794
-
4795
- ## [3.15.0] - 2026-01-05
4796
-
4797
- ### Changed
4798
-
4799
- - Made `isError` field optional in `ToolResultMessage` interface, defaulting to non-error state
4800
-
4801
- ## [3.5.1337] - 2026-01-03
4802
-
4803
- ### Added
4804
-
4805
- - Added localhost URL detection for OpenAI-compatible provider auto-configuration
4806
-
4807
- ## [1.337.1] - 2026-01-02
4808
-
4809
- ### Changed
4810
-
4811
- - Forked to @oh-my-pi scope with unified versioning across all packages
4812
-
4813
- ### Fixed
4814
-
4815
- - **Gemini CLI rate limit handling**: Added automatic retry with server-provided delay for 429 errors
4816
-
4817
- ## [1.337.0] - 2026-01-02
4818
-
4819
- Initial release under @oh-my-pi scope. See previous releases at [badlogic/pi-mono](https://github.com/badlogic/pi-mono).
4820
-
4821
- ## [0.50.1] - 2026-01-26
4822
-
4823
- ### Fixed
4824
-
4825
- - Fixed OpenCode Zen model generation to exclude deprecated models ([#970](https://github.com/badlogic/pi-mono/pull/970) by [@DanielTatarkin](https://github.com/DanielTatarkin))
4826
-
4827
- ## [0.50.0] - 2026-01-26
4828
-
4829
- ### Added
4830
-
4831
- - Added OpenRouter provider routing support for custom models via `openRouterRouting` compat field ([#859](https://github.com/badlogic/pi-mono/pull/859) by [@v01dpr1mr0s3](https://github.com/v01dpr1mr0s3))
4832
- - Added `azure-openai-responses` provider support for Azure OpenAI Responses API. ([#890](https://github.com/badlogic/pi-mono/pull/890) by [@markusylisiurunen](https://github.com/markusylisiurunen))
4833
- - Added HTTP proxy environment variable support for API requests ([#942](https://github.com/badlogic/pi-mono/pull/942) by [@haoqixu](https://github.com/haoqixu))
4834
- - Added `createAssistantMessageEventStream()` factory function for use in extensions.
4835
- - Added `resetApiProviders()` to clear and re-register built-in API providers.
4836
-
4837
- ### Changed
4838
-
4839
- - Refactored API streaming dispatch to use an API registry with provider-owned `streamSimple` mapping.
4840
- - Moved environment API key resolution to `env-api-keys.ts` and re-exported it from the package entrypoint.
4841
- - Azure OpenAI Responses provider now uses base URL configuration with deployment-aware model mapping and no longer includes service tier handling.
4842
-
4843
- ### Fixed
4844
-
4845
- - Fixed Bun runtime detection for dynamic imports in browser-compatible modules (stream.ts, openai-codex-responses.ts, openai-codex.ts) ([#922](https://github.com/badlogic/pi-mono/pull/922) by [@dannote](https://github.com/dannote))
4846
- - Fixed streaming functions to use `model.api` instead of hardcoded API types
4847
- - Fixed Google providers to default tool call arguments to an empty object when omitted
4848
- - Fixed OpenAI Responses streaming to handle `arguments.done` events on OpenAI-compatible endpoints ([#917](https://github.com/badlogic/pi-mono/pull/917) by [@williballenthin](https://github.com/williballenthin))
4849
- - Fixed OpenAI Codex Responses tool strictness handling after the shared responses refactor
4850
- - Fixed Azure OpenAI Responses streaming to guard deltas before content parts and correct metadata and handoff gating
4851
- - Fixed OpenAI completions tool-result image batching after consecutive tool results ([#902](https://github.com/badlogic/pi-mono/pull/902) by [@terrorobe](https://github.com/terrorobe))
4852
-
4853
- ## [0.49.3] - 2026-01-22
4854
-
4855
- ### Added
4856
-
4857
- - Added `headers` option to `StreamOptions` for custom HTTP headers in API requests. Supported by all providers except Amazon Bedrock (which uses AWS SDK auth). Headers are merged with provider defaults and `model.headers`, with `options.headers` taking precedence.
4858
- - Added `originator` option to `loginOpenAICodex()` for custom OAuth client identification
4859
- - Browser compatibility for pi-ai: replaced top-level Node.js imports with dynamic imports for browser environments ([#873](https://github.com/badlogic/pi-mono/issues/873))
4860
-
4861
- ### Fixed
4862
-
4863
- - Fixed OpenAI Responses API 400 error "function_call without required reasoning item" when switching between models (same provider, different model). The fix omits the `id` field for function_calls from different models to avoid triggering OpenAI's reasoning/function_call pairing validation ([#886](https://github.com/badlogic/pi-mono/issues/886))
4864
-
4865
- ## [0.49.2] - 2026-01-19
4866
-
4867
- ### Added
4868
-
4869
- - Added AWS credential detection for ECS/Kubernetes environments: `AWS_CONTAINER_CREDENTIALS_RELATIVE_URI`, `AWS_CONTAINER_CREDENTIALS_FULL_URI`, `AWS_WEB_IDENTITY_TOKEN_FILE` ([#848](https://github.com/badlogic/pi-mono/issues/848))
4870
-
4871
- ### Fixed
4872
-
4873
- - Fixed OpenAI Responses 400 error "reasoning without following item" by skipping errored/aborted assistant messages entirely in transform-messages.ts ([#838](https://github.com/badlogic/pi-mono/pull/838))
4874
-
4875
- ### Removed
4876
-
4877
- - Removed `strictResponsesPairing` compat option (no longer needed after the transform-messages fix)
4878
-
4879
- ## [0.49.1] - 2026-01-18
4880
-
4881
- ### Added
4882
-
4883
- - Added `OpenAIResponsesCompat` interface with `strictResponsesPairing` option for Azure OpenAI Responses API, which requires strict reasoning/message pairing in history replay ([#768](https://github.com/badlogic/pi-mono/pull/768) by [@nicobako](https://github.com/nicobako))
4884
-
4885
- ### Changed
4886
-
4887
- - Split `OpenAICompat` into `OpenAICompletionsCompat` and `OpenAIResponsesCompat` for type-safe API-specific compat settings
4888
-
4889
- ### Fixed
4890
-
4891
- - Fixed tool call ID normalization for cross-provider handoffs (e.g., Codex to Antigravity Claude) ([#821](https://github.com/badlogic/pi-mono/issues/821))
4892
-
4893
- ## [0.49.0] - 2026-01-17
4894
-
4895
- ### Changed
4896
-
4897
- - OpenAI Codex responses now use the context system prompt directly in the instructions field.
4898
-
4899
- ### Fixed
4900
-
4901
- - Fixed orphaned tool results after errored assistant messages causing Codex API errors. When an assistant message has `stopReason: "error"`, its tool calls are now excluded from pending tool tracking, preventing synthetic tool results from being generated for calls that will be dropped by provider-specific converters. ([#812](https://github.com/badlogic/pi-mono/issues/812))
4902
- - Fixed Bedrock Claude max_tokens handling to always exceed thinking budget tokens, preventing compaction failures. ([#797](https://github.com/badlogic/pi-mono/pull/797) by [@pjtf93](https://github.com/pjtf93))
4903
- - Fixed Claude Code tool name normalization to match the Claude Code tool list case-insensitively and remove invalid mappings.
4904
-
4905
- ## [0.48.0] - 2026-01-16
4906
-
4907
- ### Fixed
4908
-
4909
- - Fixed OpenAI-compatible provider feature detection to use `model.provider` in addition to URL, allowing custom base URLs (e.g., proxies) to work correctly with provider-specific settings ([#774](https://github.com/badlogic/pi-mono/issues/774))
4910
- - Fixed Gemini 3 context loss when switching from providers without thought signatures: unsigned tool calls are now converted to text with anti-mimicry notes instead of being skipped
4911
- - Fixed string numbers in tool arguments not being coerced to numbers during validation ([#786](https://github.com/badlogic/pi-mono/pull/786) by [@dannote](https://github.com/dannote))
4912
- - Fixed Bedrock tool call IDs to use only alphanumeric characters, avoiding API errors from invalid characters ([#781](https://github.com/badlogic/pi-mono/pull/781) by [@pjtf93](https://github.com/pjtf93))
4913
- - Fixed empty error assistant messages (from 429/500 errors) breaking the tool_use to tool_result chain by filtering them in `transformMessages`
4914
-
4915
- ## [0.47.0] - 2026-01-16
4916
-
4917
- ### Fixed
4918
-
4919
- - Fixed OpenCode provider's `/v1` endpoint to use `system` role instead of `developer` role, fixing `400 Incorrect role information` error for models using `openai-completions` API ([#755](https://github.com/badlogic/pi-mono/pull/755) by [@melihmucuk](https://github.com/melihmucuk))
4920
- - Added retry logic to OpenAI Codex provider for transient errors (429, 5xx, connection failures). Uses exponential backoff with up to 3 retries. ([#733](https://github.com/badlogic/pi-mono/issues/733))
4921
-
4922
- ## [0.46.0] - 2026-01-15
4923
-
4924
- ### Added
4925
-
4926
- - Added MiniMax China (`minimax-cn`) provider support ([#725](https://github.com/badlogic/pi-mono/pull/725) by [@tallshort](https://github.com/tallshort))
4927
- - Added `gpt-5.2-codex` models for GitHub Copilot and OpenCode Zen providers ([#734](https://github.com/badlogic/pi-mono/pull/734) by [@aadishv](https://github.com/aadishv))
4928
-
4929
- ### Fixed
4930
-
4931
- - Avoid unsigned Gemini 3 tool calls ([#741](https://github.com/badlogic/pi-mono/pull/741) by [@roshanasingh4](https://github.com/roshanasingh4))
4932
- - Fixed signature support for non-Anthropic models in Amazon Bedrock provider ([#727](https://github.com/badlogic/pi-mono/pull/727) by [@unexge](https://github.com/unexge))
4933
-
4934
- ## [0.45.7] - 2026-01-13
4935
-
4936
- ### Fixed
4937
-
4938
- - Fixed OpenAI Responses timeout option handling ([#706](https://github.com/badlogic/pi-mono/pull/706) by [@markusylisiurunen](https://github.com/markusylisiurunen))
4939
- - Fixed Bedrock tool call conversion to apply message transforms ([#707](https://github.com/badlogic/pi-mono/pull/707) by [@pjtf93](https://github.com/pjtf93))
4940
-
4941
- ## [0.45.6] - 2026-01-13
4942
-
4943
- ### Fixed
4944
-
4945
- - Export `parseStreamingJson` from main package for tsx dev mode compatibility
4946
-
4947
- ## [0.45.4] - 2026-01-13
4948
-
4949
- ### Added
4950
-
4951
- - Added Vercel AI Gateway provider with model discovery and `AI_GATEWAY_API_KEY` env support ([#689](https://github.com/badlogic/pi-mono/pull/689) by [@timolins](https://github.com/timolins))
4952
-
4953
- ### Fixed
4954
-
4955
- - Fixed z.ai thinking/reasoning: z.ai uses `thinking: { type: "enabled" }` instead of OpenAI's `reasoning_effort`. Added `thinkingFormat` compat flag to handle this. ([#688](https://github.com/badlogic/pi-mono/issues/688))
4956
-
4957
- ## [0.45.0] - 2026-01-13
4958
-
4959
- ### Added
4960
-
4961
- - MiniMax provider support with M2 and M2.1 models via Anthropic-compatible API ([#656](https://github.com/badlogic/pi-mono/pull/656) by [@dannote](https://github.com/dannote))
4962
- - Add Amazon Bedrock provider with prompt caching for Claude models (experimental, tested with Anthropic Claude models only) ([#494](https://github.com/badlogic/pi-mono/pull/494) by [@unexge](https://github.com/unexge))
4963
- - Added `serviceTier` option for OpenAI Responses requests ([#672](https://github.com/badlogic/pi-mono/pull/672) by [@markusylisiurunen](https://github.com/markusylisiurunen))
4964
- - **Anthropic caching on OpenRouter**: Interactions with Anthropic models via OpenRouter now set a 5-minute cache point using Anthropic-style `cache_control` breakpoints on the last assistant or user message. ([#584](https://github.com/badlogic/pi-mono/pull/584) by [@nathyong](https://github.com/nathyong))
4965
- - **Google Gemini CLI provider improvements**: Added Antigravity endpoint fallback (tries daily sandbox then prod when `baseUrl` is unset), header-based retry delay parsing (`Retry-After`, `x-ratelimit-reset`, `x-ratelimit-reset-after`), stable `sessionId` derivation from first user message for cache affinity, empty SSE stream retry with backoff, and `anthropic-beta` header for Claude thinking models ([#670](https://github.com/badlogic/pi-mono/pull/670) by [@kim0](https://github.com/kim0))
4966
-
4967
- ## [0.43.0] - 2026-01-11
4968
-
4969
- ### Fixed
4970
-
4971
- - Fixed Google provider thinking detection: `isThinkingPart()` now only checks `thought === true`, not `thoughtSignature`. Per Google docs, `thoughtSignature` is for context replay and can appear on any part type. Also removed `id` field from `functionCall`/`functionResponse` (rejected by Vertex AI and Cloud Code Assist), and added `textSignature` round-trip for multi-turn reasoning context. ([#631](https://github.com/badlogic/pi-mono/pull/631) by [@theBucky](https://github.com/theBucky))
4972
-
4973
- ## [0.42.3] - 2026-01-10
4974
-
4975
- ### Changed
4976
-
4977
- - OpenAI Codex: switched to bundled system prompt matching opencode, changed originator to "pi", simplified prompt handling
4978
-
4979
- ## [0.42.2] - 2026-01-10
4980
-
4981
- ### Added
4982
-
4983
- - Added `GOOGLE_APPLICATION_CREDENTIALS` env var support for Vertex AI credential detection (standard for CI/production).
4984
- - Added `supportsUsageInStreaming` compatibility flag for OpenAI-compatible providers that reject `stream_options: { include_usage: true }`. Defaults to `true`. Set to `false` in model config for providers like gatewayz.ai. ([#596](https://github.com/badlogic/pi-mono/pull/596) by [@XesGaDeus](https://github.com/XesGaDeus))
4985
- - Improved Google model pricing info ([#588](https://github.com/badlogic/pi-mono/pull/588) by [@aadishv](https://github.com/aadishv))
4986
-
4987
- ### Fixed
4988
-
4989
- - Fixed `os.homedir()` calls at module load time; now resolved lazily when needed.
4990
- - Fixed OpenAI Responses tool strict flag to use a boolean for LM Studio compatibility ([#598](https://github.com/badlogic/pi-mono/pull/598) by [@gnattu](https://github.com/gnattu))
4991
- - Fixed Google Cloud Code Assist OAuth for paid subscriptions: properly handles long-running operations for project provisioning, supports `GOOGLE_CLOUD_PROJECT` / `GOOGLE_CLOUD_PROJECT_ID` env vars for paid tiers, and handles VPC-SC affected users ([#582](https://github.com/badlogic/pi-mono/pull/582) by [@cmf](https://github.com/cmf))
4992
-
4993
- ## [0.42.0] - 2026-01-09
4994
-
4995
- ### Added
4996
-
4997
- - Added OpenCode Zen provider support with 26 models (Claude, GPT, Gemini, Grok, Kimi, GLM, Qwen, etc.). Set `OPENCODE_API_KEY` env var to use.
4998
-
4999
- ## [0.39.0] - 2026-01-08
5000
-
5001
- ### Fixed
5002
-
5003
- - Fixed Gemini CLI abort handling: detect native `AbortError` in retry catch block, cancel SSE reader when abort signal fires ([#568](https://github.com/badlogic/pi-mono/pull/568) by [@tmustier](https://github.com/tmustier))
5004
- - Fixed Antigravity provider 429 errors by aligning request payload with CLIProxyAPI v6.6.89: inject Antigravity system instruction with `role: "user"`, set `requestType: "agent"`, and use `antigravity` userAgent. Added bridge prompt to override Antigravity behavior (identity, paths, web dev guidelines) with Pi defaults. ([#571](https://github.com/badlogic/pi-mono/pull/571) by [@ben-vargas](https://github.com/ben-vargas))
5005
- - Fixed thinking block handling for cross-model conversations: thinking blocks are now converted to plain text (no `<thinking>` tags) when switching models. Previously, `<thinking>` tags caused models to mimic the pattern and output literal tags. Also fixed empty thinking blocks causing API errors. ([#561](https://github.com/badlogic/pi-mono/issues/561))
5006
-
5007
- ## [0.38.0] - 2026-01-08
5008
-
5009
- ### Added
5010
-
5011
- - `thinkingBudgets` option in `SimpleStreamOptions` for customizing token budgets per thinking level on token-based providers ([#529](https://github.com/badlogic/pi-mono/pull/529) by [@melihmucuk](https://github.com/melihmucuk))
5012
-
5013
- ### Breaking Changes
5014
-
5015
- - Removed OpenAI Codex model aliases (`gpt-5`, `gpt-5-mini`, `gpt-5-nano`, `codex-mini-latest`, `gpt-5-codex`, `gpt-5.1-codex`, `gpt-5.1-chat-latest`). Use canonical model IDs: `gpt-5.1`, `gpt-5.1-codex-max`, `gpt-5.1-codex-mini`, `gpt-5.2`, `gpt-5.2-codex`. ([#536](https://github.com/badlogic/pi-mono/pull/536) by [@ghoulr](https://github.com/ghoulr))
5016
-
5017
- ### Fixed
5018
-
5019
- - Fixed OpenAI Codex context window from 400,000 to 272,000 tokens to match Codex CLI defaults and prevent 400 errors. ([#536](https://github.com/badlogic/pi-mono/pull/536) by [@ghoulr](https://github.com/ghoulr))
5020
- - Fixed Codex SSE error events to surface message, code, and status. ([#551](https://github.com/badlogic/pi-mono/pull/551) by [@tmustier](https://github.com/tmustier))
5021
- - Fixed context overflow detection for `context_length_exceeded` error codes.
5022
-
5023
- ## [0.37.6] - 2026-01-06
5024
-
5025
- ### Added
5026
-
5027
- - Exported OpenAI Codex utilities: `CacheMetadata`, `getCodexInstructions`, `getModelFamily`, `ModelFamily`, `buildCodexPiBridge`, `buildCodexSystemPrompt`, `CodexSystemPrompt` ([#510](https://github.com/badlogic/pi-mono/pull/510) by [@mitsuhiko](https://github.com/mitsuhiko))
5028
-
5029
- ## [0.37.3] - 2026-01-06
5030
-
5031
- ### Added
5032
-
5033
- - `sessionId` option in `StreamOptions` for providers that support session-based caching. OpenAI Codex provider uses this to set `prompt_cache_key` and routing headers.
5034
-
5035
- ## [0.37.2] - 2026-01-05
5036
-
5037
- ### Fixed
5038
-
5039
- - Codex provider now always includes `reasoning.encrypted_content` even when custom `include` options are passed ([#484](https://github.com/badlogic/pi-mono/pull/484) by [@kim0](https://github.com/kim0))
5040
-
5041
- ## [0.37.0] - 2026-01-05
5042
-
5043
- ### Breaking Changes
5044
-
5045
- - OpenAI Codex models no longer have per-thinking-level variants (e.g., `gpt-5.2-codex-high`). Use the base model ID and set thinking level separately. The Codex provider clamps reasoning effort to what each model supports internally. (initial implementation by [@ben-vargas](https://github.com/ben-vargas) in [#472](https://github.com/badlogic/pi-mono/pull/472))
5046
-
5047
- ### Added
5048
-
5049
- - Headless OAuth support for all callback-server providers (Google Gemini CLI, Antigravity, OpenAI Codex): paste redirect URL when browser callback is unreachable ([#428](https://github.com/badlogic/pi-mono/pull/428) by [@ben-vargas](https://github.com/ben-vargas), [#468](https://github.com/badlogic/pi-mono/pull/468) by [@crcatala](https://github.com/crcatala))
5050
- - Cancellable GitHub Copilot device code polling via AbortSignal
5051
-
5052
- ### Fixed
5053
-
5054
- - Codex requests now omit the `reasoning` field entirely when thinking is off, letting the backend use its default instead of forcing a value. ([#472](https://github.com/badlogic/pi-mono/pull/472))
5055
-
5056
- ## [0.36.0] - 2026-01-05
5057
-
5058
- ### Added
5059
-
5060
- - OpenAI Codex OAuth provider with Responses API streaming support: `openai-codex-responses` streaming provider with SSE parsing, tool-call handling, usage/cost tracking, and PKCE OAuth flow ([#451](https://github.com/badlogic/pi-mono/pull/451) by [@kim0](https://github.com/kim0))
5061
-
5062
- ### Fixed
5063
-
5064
- - Vertex AI dummy value for `getEnvApiKey()`: Returns `"<authenticated>"` when Application Default Credentials are configured (`~/.config/gcloud/application_default_credentials.json` exists) and both `GOOGLE_CLOUD_PROJECT` (or `GCLOUD_PROJECT`) and `GOOGLE_CLOUD_LOCATION` are set. This allows `streamSimple()` to work with Vertex AI without explicit `apiKey` option. The ADC credentials file existence check is cached per-process to avoid repeated filesystem access.
5065
-
5066
- ## [0.32.3] - 2026-01-03
5067
-
5068
- ### Fixed
5069
-
5070
- - Google Vertex AI models no longer appear in available models list without explicit authentication. Previously, `getEnvApiKey()` returned a dummy value for `google-vertex`, causing models to show up even when Google Cloud ADC was not configured.
5071
-
5072
- ## [0.32.0] - 2026-01-03
5073
-
5074
- ### Added
5075
-
5076
- - Vertex AI provider with ADC (Application Default Credentials) support. Authenticate with `gcloud auth application-default login`, set `GOOGLE_CLOUD_PROJECT` and `GOOGLE_CLOUD_LOCATION`, and access Gemini models via Vertex AI. ([#300](https://github.com/badlogic/pi-mono/pull/300) by [@default-anton](https://github.com/default-anton))
5077
-
5078
- ### Fixed
5079
-
5080
- - **Gemini CLI rate limit handling**: Added automatic retry with server-provided delay for 429 errors. Parses delay from error messages like "Your quota will reset after 39s" and waits accordingly. Falls back to exponential backoff for other transient errors. ([#370](https://github.com/badlogic/pi-mono/issues/370))
5081
-
5082
- ## [0.31.0] - 2026-01-02
5083
-
5084
- ### Breaking Changes
5085
-
5086
- - **Agent API moved**: All agent functionality (`agentLoop`, `agentLoopContinue`, `AgentContext`, `AgentEvent`, `AgentTool`, `AgentToolResult`, etc.) has moved to `@oh-my-pi/pi-agent-core`. Import from that package instead of `@oh-my-pi/pi-ai`.
5087
-
5088
- ### Added
5089
-
5090
- - **`GoogleThinkingLevel` type**: Exported type that mirrors Google's `ThinkingLevel` enum values (`"THINKING_LEVEL_UNSPECIFIED" | "MINIMAL" | "LOW" | "MEDIUM" | "HIGH"`). Allows configuring Gemini thinking levels without importing from `@google/genai`.
5091
- - **`ANTHROPIC_OAUTH_TOKEN` env var**: Now checked before `ANTHROPIC_API_KEY` in `getEnvApiKey()`, allowing OAuth tokens to take precedence.
5092
- - **`event-stream.js` export**: `AssistantMessageEventStream` utility now exported from package index.
5093
-
5094
- ### Changed
5095
-
5096
- - **OAuth uses Web Crypto API**: PKCE generation and OAuth flows now use Web Crypto API (`crypto.subtle`) instead of Node.js `crypto` module. This improves browser compatibility while still working in Node.js 20+.
5097
- - **Deterministic model generation**: `generate-models.ts` now sorts providers and models alphabetically for consistent output across runs. ([#332](https://github.com/badlogic/pi-mono/pull/332) by [@mrexodia](https://github.com/mrexodia))
5098
-
5099
- ### Fixed
5100
-
5101
- - **OpenAI completions empty content blocks**: Empty text or thinking blocks in assistant messages are now filtered out before sending to the OpenAI completions API, preventing validation errors. ([#344](https://github.com/badlogic/pi-mono/pull/344) by [@default-anton](https://github.com/default-anton))
5102
- - **zAi provider API mapping**: Fixed zAi models to use `openai-completions` API with correct base URL (`https://api.z.ai/api/coding/paas/v4`) instead of incorrect Anthropic API mapping. ([#344](https://github.com/badlogic/pi-mono/pull/344), [#358](https://github.com/badlogic/pi-mono/pull/358) by [@default-anton](https://github.com/default-anton))
5103
-
5104
- ## [0.28.0] - 2025-12-25
5105
-
5106
- ### Breaking Changes
5107
-
5108
- - **OAuth storage removed** ([#296](https://github.com/badlogic/pi-mono/issues/296)): All storage functions (`loadOAuthCredentials`, `saveOAuthCredentials`, `setOAuthStorage`, etc.) removed. Callers are responsible for storing credentials.
5109
- - **OAuth login functions**: `loginAnthropic`, `loginGitHubCopilot`, `loginGeminiCli`, `loginAntigravity` now return `OAuthCredentials` instead of saving to disk.
5110
- - **refreshOAuthToken**: Now takes `(provider, credentials)` and returns new `OAuthCredentials` instead of saving.
5111
- - **getOAuthApiKey**: Now takes `(provider, credentials)` and returns `{ newCredentials, apiKey }` or null.
5112
- - **OAuthCredentials type**: No longer includes `type: "oauth"` discriminator. Callers add discriminator when storing.
5113
- - **setApiKey, resolveApiKey**: Removed. Callers must manage their own API key storage/resolution.
5114
- - **getApiKey**: Renamed to `getEnvApiKey`. Only checks environment variables for known providers.
5115
-
5116
- ## [0.27.7] - 2025-12-24
5117
-
5118
- ### Fixed
5119
-
5120
- - **Thinking tag leakage**: Fixed Claude mimicking literal `</thinking>` tags in responses. Unsigned thinking blocks (from aborted streams) are now converted to plain text without `<thinking>` tags. The TUI still displays them as thinking blocks. ([#302](https://github.com/badlogic/pi-mono/pull/302) by [@nicobailon](https://github.com/nicobailon))
5121
-
5122
- ## [0.25.1] - 2025-12-21
5123
-
5124
- ### Added
5125
-
5126
- - **xhigh thinking level support**: Added `supportsXhigh()` function to check if a model supports xhigh reasoning level. Also clamps xhigh to high for OpenAI models that don't support it. ([#236](https://github.com/badlogic/pi-mono/pull/236) by [@theBucky](https://github.com/theBucky))
5127
-
5128
- ### Fixed
5129
-
5130
- - **Gemini multimodal tool results**: Fixed images in tool results causing flaky/broken responses with Gemini models. For Gemini 3, images are now nested inside `functionResponse.parts` per the [docs](https://ai.google.dev/gemini-api/docs/function-calling#multimodal). For older models (which don't support multimodal function responses), images are sent in a separate user message.
5131
- - **Queued message steering**: When `getQueuedMessages` is provided, the agent loop now checks for queued user messages after each tool call and skips remaining tool calls in the current assistant message when a queued message arrives (emitting error tool results).
5132
- - **Double API version path in Google provider URL**: Fixed Gemini API calls returning 404 after baseUrl support was added. The SDK was appending its default apiVersion to baseUrl which already included the version path. ([#251](https://github.com/badlogic/pi-mono/pull/251) by [@shellfyred](https://github.com/shellfyred))
5133
- - **Anthropic SDK retries disabled**: Re-enabled SDK-level retries (default 2) for transient HTTP failures. ([#252](https://github.com/badlogic/pi-mono/issues/252))
5134
-
5135
- ## [0.23.5] - 2025-12-19
5136
-
5137
- ### Added
5138
-
5139
- - **Gemini 3 Flash thinking support**: Extended thinking level support for Gemini 3 Flash models (MINIMAL, LOW, MEDIUM, HIGH) to match Pro models' capabilities. ([#212](https://github.com/badlogic/pi-mono/pull/212) by [@markusylisiurunen](https://github.com/markusylisiurunen))
5140
- - **GitHub Copilot thinking models**: Added thinking support for additional Copilot models (o3-mini, o1-mini, o1-preview). ([#234](https://github.com/badlogic/pi-mono/pull/234) by [@aadishv](https://github.com/aadishv))
5141
-
5142
- ### Fixed
5143
-
5144
- - **Gemini tool result format**: Fixed tool result format for Gemini 3 Flash Preview which strictly requires `{ output: value }` for success and `{ error: value }` for errors. Previous format using `{ result, isError }` was rejected by newer Gemini models. Also improved type safety by removing `as any` casts. ([#213](https://github.com/badlogic/pi-mono/issues/213), [#220](https://github.com/badlogic/pi-mono/pull/220))
5145
- - **Google baseUrl configuration**: Google provider now respects `baseUrl` configuration for custom endpoints or API proxies. ([#216](https://github.com/badlogic/pi-mono/issues/216), [#221](https://github.com/badlogic/pi-mono/pull/221) by [@theBucky](https://github.com/theBucky))
5146
- - **GitHub Copilot vision requests**: Added `Copilot-Vision-Request` header when sending images to GitHub Copilot models. ([#222](https://github.com/badlogic/pi-mono/issues/222))
5147
- - **GitHub Copilot X-Initiator header**: Fixed X-Initiator logic to check last message role instead of any message in history. This ensures proper billing when users send follow-up messages. ([#209](https://github.com/badlogic/pi-mono/issues/209))
5148
-
5149
- ## [0.22.3] - 2025-12-16
5150
-
5151
- ### Added
5152
-
5153
- - **Image limits test suite**: Added comprehensive tests for provider-specific image limitations (max images, max size, max dimensions). Discovered actual limits: Anthropic (100 images, 5MB, 8000px), OpenAI (500 images, ≥25MB), Gemini (~2500 images, ≥40MB), Mistral (8 images, ~15MB), OpenRouter (~40 images context-limited, ~15MB). ([#120](https://github.com/badlogic/pi-mono/pull/120))
5154
- - **Tool result streaming**: Added `tool_execution_update` event and optional `onUpdate` callback to `AgentTool.execute()` for streaming tool output during execution. Tools can now emit partial results (e.g., bash stdout) that are forwarded to subscribers. ([#44](https://github.com/badlogic/pi-mono/issues/44))
5155
- - **X-Initiator header for GitHub Copilot**: Added X-Initiator header handling for GitHub Copilot provider to ensure correct call accounting (agent calls are not deducted from quota). Sets initiator based on last message role. ([#200](https://github.com/badlogic/pi-mono/pull/200) by [@kim0](https://github.com/kim0))
5156
-
5157
- ### Changed
5158
-
5159
- - **Normalized tool_execution_end result**: `tool_execution_end` event now always contains `AgentToolResult` (no longer `AgentToolResult | string`). Errors are wrapped in the standard result format.
5160
-
5161
- ### Fixed
5162
-
5163
- - **Reasoning disabled by default**: When `reasoning` option is not specified, thinking is now explicitly disabled for all providers. Previously, some providers like Gemini with "dynamic thinking" would use their default (thinking ON), causing unexpected token usage. This was the original intended behavior. ([#180](https://github.com/badlogic/pi-mono/pull/180) by [@markusylisiurunen](https://github.com/markusylisiurunen))
5164
-
5165
- ## [0.22.2] - 2025-12-15
5166
-
5167
- ### Added
5168
-
5169
- - **Interleaved thinking for Anthropic**: Added `interleavedThinking` option to `AnthropicOptions`. When enabled, Claude 4 models can think between tool calls and reason after receiving tool results. Enabled by default (no extra token cost, just unlocks the capability). Set `interleavedThinking: false` to disable.
5170
-
5171
- ## [0.22.1] - 2025-12-15
5172
-
5173
- _Dedicated to Peter's shoulder ([@steipete](https://twitter.com/steipete))_
5174
-
5175
- ### Added
5176
-
5177
- - **Interleaved thinking for Anthropic**: Enabled interleaved thinking in the Anthropic provider, allowing Claude models to output thinking blocks interspersed with text responses.
5178
-
5179
- ## [0.22.0] - 2025-12-15
5180
-
5181
- ### Added
5182
-
5183
- - **GitHub Copilot provider**: Added `github-copilot` as a known provider with models sourced from models.dev. Includes Claude, GPT, Gemini, Grok, and other models available through GitHub Copilot. ([#191](https://github.com/badlogic/pi-mono/pull/191) by [@cau1k](https://github.com/cau1k))
5184
-
5185
- ### Fixed
5186
-
5187
- - **GitHub Copilot gpt-5 models**: Fixed API selection for gpt-5 models to use `openai-responses` instead of `openai-completions` (gpt-5 models are not accessible via completions endpoint)
5188
- - **GitHub Copilot cross-model context handoff**: Fixed context handoff failing when switching between GitHub Copilot models using different APIs (e.g., gpt-5 to claude-sonnet-4). Tool call IDs from OpenAI Responses API were incompatible with other models. ([#198](https://github.com/badlogic/pi-mono/issues/198))
5189
- - **Gemini 3 Pro thinking levels**: Thinking level configuration now works correctly for Gemini 3 Pro models. Previously all levels mapped to -1 (minimal thinking). Now LOW/MEDIUM/HIGH properly control test-time computation. ([#176](https://github.com/badlogic/pi-mono/pull/176) by [@markusylisiurunen](https://github.com/markusylisiurunen))
5190
-
5191
- ## [0.18.2] - 2025-12-11
5192
-
5193
- ### Changed
5194
-
5195
- - **Anthropic SDK retries disabled**: Set `maxRetries: 0` on Anthropic client to allow application-level retry handling. The SDK's built-in retries were interfering with coding-agent's retry logic. ([#157](https://github.com/badlogic/pi-mono/issues/157))
5196
-
5197
- ## [0.18.1] - 2025-12-10
5198
-
5199
- ### Added
5200
-
5201
- - **Mistral provider**: Added support for Mistral AI models via the OpenAI-compatible API. Includes automatic handling of Mistral-specific requirements (tool call ID format). Set `MISTRAL_API_KEY` environment variable to use.
5202
-
5203
- ### Fixed
5204
-
5205
- - Fixed Mistral 400 errors after aborted assistant messages by skipping empty assistant messages (no content, no tool calls) ([#165](https://github.com/badlogic/pi-mono/issues/165))
5206
- - Removed synthetic assistant bridge message after tool results for Mistral (no longer required as of Dec 2025) ([#165](https://github.com/badlogic/pi-mono/issues/165))
5207
- - Fixed bug where `ANTHROPIC_API_KEY` environment variable was deleted globally after first OAuth token usage, causing subsequent prompts to fail ([#164](https://github.com/badlogic/pi-mono/pull/164))
5208
-
5209
- ## [0.17.0] - 2025-12-09
5210
-
5211
- ### Added
5212
-
5213
- - **`agentLoopContinue` function**: Continue an agent loop from existing context without adding a new user message. Validates that the last message is `user` or `toolResult`. Useful for retry after context overflow or resuming from manually-added tool results.
5214
- - Added `validateToolCall(tools, toolCall)` helper that finds the tool by name and validates arguments.
5215
- - **OpenAI compatibility overrides**: Added `compat` field to `Model` for `openai-completions` API, allowing explicit configuration of provider quirks (`supportsStore`, `supportsDeveloperRole`, `supportsReasoningEffort`, `maxTokensField`). Falls back to URL-based detection if not set. Useful for LiteLLM, custom proxies, and other non-standard endpoints. ([#133](https://github.com/badlogic/pi-mono/issues/133), thanks @fink-andreas for the initial idea and PR)
5216
- - **xhigh reasoning level**: Added `xhigh` to `ReasoningEffort` type for OpenAI codex-max models. For non-OpenAI providers (Anthropic, Google), `xhigh` is automatically mapped to `high`. ([#143](https://github.com/badlogic/pi-mono/issues/143))
5217
-
5218
- ### Breaking Changes
5219
-
5220
- - Removed provider-level tool argument validation. Validation now happens in `agentLoop` via `executeToolCalls`, allowing models to retry on validation errors. For manual tool execution, use `validateToolCall(tools, toolCall)` or `validateToolArguments(tool, toolCall)`.
5221
-
5222
- ### Changed
5223
-
5224
- - **Updated SDK versions**: OpenAI SDK 5.21.0 → 6.10.0, Anthropic SDK 0.61.0 → 0.71.2, Google GenAI SDK 1.30.0 → 1.31.0
5225
-
5226
- ## [0.13.0] - 2025-12-06
5227
-
5228
- ### Breaking Changes
5229
-
5230
- - **Added `totalTokens` field to `Usage` type**: All code that constructs `Usage` objects must now include the `totalTokens` field. This field represents the total tokens processed by the LLM (input + output + cache). For OpenAI and Google, this uses native API values (`total_tokens`, `totalTokenCount`). For Anthropic, it's computed as `input + output + cacheRead + cacheWrite`.
5231
-
5232
- ## [0.12.10] - 2025-12-04
5233
-
5234
- ### Added
5235
-
5236
- - Added `gpt-5.1-codex-max` model support
5237
-
5238
- ### Fixed
5239
-
5240
- - **OpenAI Token Counting**: Fixed `usage.input` to exclude cached tokens for OpenAI providers. Previously, `input` included cached tokens, causing double-counting when calculating total context size via `input + cacheRead`. Now `input` represents non-cached input tokens across all providers, making `input + output + cacheRead + cacheWrite` the correct formula for total context size.
5241
- - **Fixed Claude Opus 4.5 cache pricing** (was 3x too expensive)
5242
- - Corrected cache_read: $1.50 → $0.50 per MTok
5243
- - Corrected cache_write: $18.75 → $6.25 per MTok
5244
- - Added manual override in `scripts/generate-models.ts` until upstream fix is merged
5245
- - Submitted PR to models.dev: https://github.com/sst/models.dev/pull/439
5246
-
5247
- ## [0.9.4] - 2025-11-26
5248
-
5249
- Initial release with multi-provider LLM support.
1940
+ Older entries are archived in [packages/ai/CHANGELOG.md@c821261d1018](https://github.com/can1357/oh-my-pi/blob/c821261d10180d60bd96c1b7334227691c9e14f6/packages/ai/CHANGELOG.md).