@oh-my-pi/pi-ai 15.13.0 → 15.13.2
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.
- package/CHANGELOG.md +325 -55
- package/dist/types/auth-broker/wire-schemas.d.ts +19 -17
- package/dist/types/auth-storage.d.ts +1 -1
- package/dist/types/grammar/anthropic.d.ts +9 -0
- package/dist/types/grammar/catalog.d.ts +3 -0
- package/dist/types/grammar/coercion.d.ts +23 -0
- package/dist/types/grammar/deepseek.d.ts +14 -0
- package/dist/types/grammar/examples.d.ts +2 -0
- package/dist/types/grammar/factory.d.ts +3 -0
- package/dist/types/grammar/glm.d.ts +9 -0
- package/dist/types/grammar/harmony.d.ts +8 -0
- package/dist/types/grammar/hermes.d.ts +9 -0
- package/dist/types/grammar/history.d.ts +3 -0
- package/dist/types/grammar/index.d.ts +8 -0
- package/dist/types/grammar/inventory.d.ts +12 -0
- package/dist/types/grammar/kimi.d.ts +13 -0
- package/dist/types/grammar/owned-stream.d.ts +4 -0
- package/dist/types/grammar/pi.d.ts +9 -0
- package/dist/types/grammar/qwen3.d.ts +9 -0
- package/dist/types/grammar/rendering.d.ts +24 -0
- package/dist/types/grammar/thinking.d.ts +6 -0
- package/dist/types/grammar/types.d.ts +67 -0
- package/dist/types/grammar/xml.d.ts +9 -0
- package/dist/types/provider-details.d.ts +1 -1
- package/dist/types/providers/cursor.d.ts +47 -1
- package/dist/types/types.d.ts +28 -0
- package/dist/types/utils/harmony-leak.d.ts +118 -0
- package/dist/types/utils/schema/index.d.ts +1 -0
- package/dist/types/utils/schema/typescript.d.ts +18 -0
- package/dist/types/utils/stream-markup-healing.d.ts +10 -15
- package/package.json +11 -3
- package/src/auth-broker/wire-schemas.ts +14 -4
- package/src/auth-storage.ts +1 -1
- package/src/grammar/anthropic.md +31 -0
- package/src/grammar/anthropic.ts +521 -0
- package/src/grammar/catalog.ts +27 -0
- package/src/grammar/coercion.ts +136 -0
- package/src/grammar/deepseek.md +23 -0
- package/src/grammar/deepseek.ts +535 -0
- package/src/grammar/examples.ts +33 -0
- package/src/grammar/factory.ts +30 -0
- package/src/grammar/glm.md +32 -0
- package/src/grammar/glm.ts +384 -0
- package/src/grammar/harmony.md +30 -0
- package/src/grammar/harmony.ts +272 -0
- package/src/grammar/hermes.md +24 -0
- package/src/grammar/hermes.ts +171 -0
- package/src/grammar/history.ts +81 -0
- package/src/grammar/index.ts +8 -0
- package/src/grammar/inventory.ts +28 -0
- package/src/grammar/kimi.md +23 -0
- package/src/grammar/kimi.ts +198 -0
- package/src/grammar/owned-stream.ts +337 -0
- package/src/grammar/pi.md +49 -0
- package/src/grammar/pi.ts +585 -0
- package/src/grammar/prompt-template.md +12 -0
- package/src/grammar/qwen3.md +27 -0
- package/src/grammar/qwen3.ts +203 -0
- package/src/grammar/rendering.ts +214 -0
- package/src/grammar/thinking.ts +91 -0
- package/src/grammar/types.ts +55 -0
- package/src/grammar/xml.md +22 -0
- package/src/grammar/xml.ts +33 -0
- package/src/provider-details.ts +1 -1
- package/src/providers/cursor.ts +54 -11
- package/src/providers/openai-codex-responses.ts +170 -90
- package/src/types.ts +32 -0
- package/src/utils/harmony-leak.ts +456 -0
- package/src/utils/schema/index.ts +1 -0
- package/src/utils/schema/typescript.ts +198 -0
- package/src/utils/stream-markup-healing.ts +59 -496
- package/src/utils/validation.ts +98 -22
package/CHANGELOG.md
CHANGED
|
@@ -2,11 +2,48 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [15.13.2] - 2026-06-15
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Added `jsonSchemaToTypeScript` to `@oh-my-pi/pi-ai/utils/schema` to render JSON Schema argument shapes as compact, human-readable TypeScript-style signatures
|
|
10
|
+
- Added the generic `ToolExample` type (`ToolCallExample`/`ToolCompareExample`/`ToolNoteExample`, parameterized over a tool's argument shape) and an `examples` property on the `Tool` interface for defining tool-call examples once as data.
|
|
11
|
+
- Added `renderToolExamples` (via `@oh-my-pi/pi-ai/grammar`) to render a tool's examples into an `<examples>` block in the model's native tool-call syntax, with an optional `_i` intent-field placeholder injected when intent tracing is active.
|
|
12
|
+
- Added per-grammar `renderToolCall` rendering of a single tool-call invocation (the inner element only, without the parallel-call block envelope), distinct from `renderAssistantToolCalls` which renders a complete block of one or more parallel calls.
|
|
13
|
+
- Added a `GrammarRenderOptions.example` flag to `renderToolCall`: when set, the invocation renders as the bare payload — Harmony emits just the JSON arguments, dropping the verbose `<|start|>…<|message|>…<|call|>` envelope — so `renderToolExamples` keeps `<examples>` blocks legible.
|
|
14
|
+
- Added an `abortOnFabrication` parameter to `wrapInbandToolStream` (default `true`): when `false`, a fabricated in-band tool-result continuation is discarded without aborting the provider request instead of cutting the turn short.
|
|
15
|
+
- Added `@oh-my-pi/pi-ai/utils/harmony-leak` export with helpers to detect, audit, and recover GPT-5 Harmony tool-call header leaks
|
|
16
|
+
- Added the `@oh-my-pi/pi-ai/grammar` public entrypoint for grammar factories, prompt/call rendering, in-band scanning, history encoding, and related typed utilities
|
|
17
|
+
- Added a unified in-band tool-call grammar engine with syntax-owned scanners, prompts, history rendering, tool-result rendering, and stream adaptation for GLM, Hermes/Qwen, Kimi, XML/Anthropic, DeepSeek, Harmony, and pi-native formats.
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- Changed Harmony in-band tool-call rendering to omit the `<|constrain|>json` marker before the payload in `commentary` channel calls
|
|
22
|
+
- Changed tool inventory rendering to present each tool’s `Parameters` section as a simplified TypeScript-style signature derived from its wire schema
|
|
23
|
+
- Added raw in-band tool-call block capture to parsed owned tool calls so debugging can inspect the exact model-emitted call syntax.
|
|
24
|
+
- Moved the canonical `ToolCallSyntax` union to `@oh-my-pi/pi-catalog/identity` and re-exported it from `@oh-my-pi/pi-ai/grammar` so the catalog can own the syntax vocabulary without an `@oh-my-pi/pi-ai` runtime import; all existing import paths are unchanged.
|
|
25
|
+
- Made tool-call argument validation more lenient for schema-directed scalar coercions, including object/array stringification and 0/1 boolean coercion.
|
|
26
|
+
- Changed `renderToolInventory` (the verbose system-prompt inventory and `/dump`) to render each tool as a `# Tool: <name>` markdown section instead of a `<tool name="…">…</tool>` wrapper.
|
|
27
|
+
|
|
28
|
+
### Fixed
|
|
29
|
+
|
|
30
|
+
- Fixed Harmony leak handling support by adding `recoverHarmonyToolCall` plus leak-detection workflows for contaminated assistant messages so recoverable tool-call arguments can be safely truncated and retried
|
|
31
|
+
- Fixed false-positive gating in Harmony leak heuristics using signal-based checks so unrelated text containing `to=functions...` is not treated as leaked tool-call markup
|
|
32
|
+
- Routed Kimi, DeepSeek DSML, and plain thinking markup healing through the shared in-band scanners so provider leak repair and owned tool calling parse the same wire formats.
|
|
33
|
+
- Fixed Cursor provider (`cursor-agent` API) streaming dropping large MCP tool-call arguments — most visibly the built-in `task` tool's `tasks` array on multi-subagent dispatches, which failed downstream schema validation with `tasks: Invalid input: expected array, received undefined`. Two upstream behaviors were fighting the stream handler in `packages/ai/src/providers/cursor.ts`: (1) `args_text_delta` carries the *cumulative* args text so far per `agent.proto`, but the handler concatenated each snapshot onto the buffer, garbling the JSON; (2) `tool_call_completed` carries an `McpArgs` map that omits oversized parameters entirely and downgrades unparsable values to their raw string fallback, but the handler unconditionally overwrote the streamed args with that map. The handler now strips the already-buffered prefix from each `args_text_delta` snapshot (falling back to append when the snapshot doesn't extend the buffer) and merges the decoded `McpArgs` map into the streamed args — preserving streamed keys the completion frame omits and the structured value when the completion frame downgrades to a string. ([#2615](https://github.com/can1357/oh-my-pi/issues/2615))
|
|
34
|
+
- Fixed Codex Responses stream mis-routing interleaved `function_call_arguments.delta` events when more than one tool call was open concurrently. The runtime tracked a singleton `currentItem`/`currentBlock`, so every delta — regardless of `item_id` — was appended to whichever item was most recently added, and `output_item.done` for the earlier call then overwrote a sibling's stored arguments (visible as `tasks: Invalid input: expected array, received undefined` on the `task` tool). Open items are now keyed by `item_id` with `output_index` fallback; deltas/done events route to the matching block, late deltas whose item already closed are dropped instead of corrupting a sibling, and `toolcall_*` stream events emit the right `contentIndex` per call ([#2619](https://github.com/can1357/oh-my-pi/issues/2619)).
|
|
35
|
+
|
|
36
|
+
## [15.13.1] - 2026-06-15
|
|
37
|
+
|
|
38
|
+
### Fixed
|
|
39
|
+
|
|
40
|
+
- Fixed the auth-broker (`OMP_AUTH_BROKER_URL`) rejecting OAuth credentials that carry provider-specific extension fields (e.g. an MCP server's `tokenUrl`/`clientId`/`clientSecret`/`resource` embedded for self-contained token refresh): the OAuth credential wire schema was `.strict()`, so `POST /v1/credential` failed with `400 unrecognized_keys` and a broker-backed MCP reauth reported success while the reloaded credential lacked its refresh material and could no longer refresh. The OAuth wire schema now uses `.loose()` to preserve unknown fields — matching the field-preserving local SQLite store — so extra OAuth fields round-trip through broker set->get (envelope and API-key schemas stay strict).
|
|
41
|
+
|
|
5
42
|
## [15.13.0] - 2026-06-14
|
|
6
43
|
|
|
7
44
|
### Fixed
|
|
8
|
-
- Fixed OpenAI Responses/Realtime SSE stream handler crashing with "Error Code undefined: undefined" when parsing error events with nested error details by falling back to the nested error object fields.
|
|
9
45
|
|
|
46
|
+
- Fixed OpenAI Responses/Realtime SSE stream handler crashing with "Error Code undefined: undefined" when parsing error events with nested error details by falling back to the nested error object fields.
|
|
10
47
|
- Fixed OpenAI-compatible providers that reject forced `tool_choice` on thinking-required models by downgrading unsupported forced choices to `auto` while keeping tools available ([#2546](https://github.com/can1357/oh-my-pi/issues/2546)).
|
|
11
48
|
- Fixed GitHub Copilot Anthropic transport (`api.githubcopilot.com/v1/messages`) returning `400 tools.0.custom.eager_input_streaming: Extra inputs are not permitted` on every tool-bearing turn by stopping the emission of the per-tool `eager_input_streaming` flag and the `fine-grained-tool-streaming-2025-05-14` beta header on the Copilot transport — the proxy whitelists neither ([#2558](https://github.com/can1357/oh-my-pi/issues/2558)).
|
|
12
49
|
- Disabled Bun's native ~300s pre-response `fetch` timeout in every streaming provider (OpenAI completions/responses, Azure responses, Anthropic, Codex SSE, Bedrock, Gemini CLI, Ollama). The configurable first-event/idle/SDK watchdogs (`PI_STREAM_FIRST_EVENT_TIMEOUT_MS`, `PI_OPENAI_STREAM_IDLE_TIMEOUT_MS`, `compat.streamIdleTimeoutMs`) were silently capped by Bun's hidden ceiling, so cold large-context streams (e.g. self-hosted vLLM at multi-hundred-K prompts) died at exactly 300s with `TimeoutError: The operation timed out.` Direct callers of `./providers/{amazon-bedrock,google-gemini-cli,ollama,openai-codex-responses}` (which bypass `register-builtins`' iterator-level watchdog) now install a pre-response `AbortSignal.timeout(firstEventTimeoutMs)` alongside the disable, so a stalled upstream still fails within the configured budget instead of hanging forever ([#2422](https://github.com/can1357/oh-my-pi/issues/2422))
|
|
@@ -301,6 +338,63 @@
|
|
|
301
338
|
|
|
302
339
|
- 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.
|
|
303
340
|
|
|
341
|
+
## [15.10.10] - 2026-06-09
|
|
342
|
+
|
|
343
|
+
### Added
|
|
344
|
+
|
|
345
|
+
- 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.
|
|
346
|
+
|
|
347
|
+
### Fixed
|
|
348
|
+
|
|
349
|
+
- 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.
|
|
350
|
+
- 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.
|
|
351
|
+
- 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.
|
|
352
|
+
- 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).
|
|
353
|
+
- 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.
|
|
354
|
+
- 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.
|
|
355
|
+
- 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.
|
|
356
|
+
- 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.
|
|
357
|
+
- 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.
|
|
358
|
+
- 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.
|
|
359
|
+
- 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.
|
|
360
|
+
- 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"`.
|
|
361
|
+
- 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.
|
|
362
|
+
- 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.
|
|
363
|
+
- 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.
|
|
364
|
+
- 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.
|
|
365
|
+
- 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.
|
|
366
|
+
- 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.
|
|
367
|
+
- 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.
|
|
368
|
+
- 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.
|
|
369
|
+
- 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.
|
|
370
|
+
- 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.
|
|
371
|
+
- 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.
|
|
372
|
+
- 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.
|
|
373
|
+
- 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.
|
|
374
|
+
- 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.
|
|
375
|
+
- 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.
|
|
376
|
+
- 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.
|
|
377
|
+
- 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.
|
|
378
|
+
- 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.
|
|
379
|
+
- 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.
|
|
380
|
+
- 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.
|
|
381
|
+
- 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.
|
|
382
|
+
- 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.
|
|
383
|
+
- 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.
|
|
384
|
+
- 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.
|
|
385
|
+
- 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.
|
|
386
|
+
- 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.
|
|
387
|
+
- 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.
|
|
388
|
+
- 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.
|
|
389
|
+
- 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.
|
|
390
|
+
- 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.
|
|
391
|
+
- 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`.
|
|
392
|
+
- 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`.
|
|
393
|
+
- 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.
|
|
394
|
+
- 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).
|
|
395
|
+
- 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.
|
|
396
|
+
- 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.
|
|
397
|
+
|
|
304
398
|
## [15.10.9] - 2026-06-09
|
|
305
399
|
|
|
306
400
|
### Added
|
|
@@ -450,7 +544,6 @@
|
|
|
450
544
|
- 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.
|
|
451
545
|
- Fixed Antigravity usage reports missing `email` and `accountId` in metadata, so the `/usage` display and the deduplicator can associate reports with their credentials.
|
|
452
546
|
- Fixed usage-report dedup ignoring `projectId` for Google Cloud providers, preventing duplicate credential entries from being recognized as the same account.
|
|
453
|
-
|
|
454
547
|
- 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))
|
|
455
548
|
- 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.
|
|
456
549
|
- 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)).
|
|
@@ -649,7 +742,6 @@
|
|
|
649
742
|
### Added
|
|
650
743
|
|
|
651
744
|
- `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.
|
|
652
|
-
|
|
653
745
|
- 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).
|
|
654
746
|
- 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`.
|
|
655
747
|
- `XAI_OAUTH_TOKEN` environment variable accepted as a headless fallback for the xAI Grok OAuth provider.
|
|
@@ -682,14 +774,11 @@
|
|
|
682
774
|
- Added `PI_CODEX_WEBSOCKET_PING_INTERVAL_MS` to configure the interval for Codex WebSocket protocol ping heartbeats
|
|
683
775
|
- Added `PI_CODEX_WEBSOCKET_PONG_TIMEOUT_MS` to configure the Codex WebSocket pong timeout used to detect unresponsive connections
|
|
684
776
|
- Added `PI_CODEX_WEBSOCKET_MESSAGE_QUEUE_CAPACITY` to configure the maximum buffered Codex WebSocket inbound queue size before transport fallback
|
|
685
|
-
- Added `parseStreamingJsonThrottled` to `@oh-my-pi/pi-ai/utils/json-parse` — a per-delta wrapper around `parseStreamingJson` that skips re-parses until the buffer has grown by `minGrowthBytes` (default 256). Wired into the streaming hot path of every provider's tool-call argument accumulator (`anthropic`, `amazon-bedrock`, `openai-completions`, `openai-codex-responses`, `openai-responses-shared`) so per-delta cost is O(N) in total buffer length instead of O(N²). Each provider's `toolcall_end` still runs a final unthrottled parse, so the published `block.arguments` is unchanged.
|
|
686
|
-
- Added named-tool routing support to Google providers: `GoogleSharedStreamOptions.toolChoice` and `GoogleGeminiCliOptions.toolChoice` now accept `{ mode: "ANY"; allowedFunctionNames: [string, ...string[]] }` in addition to the string forms. `mapGoogleToolChoice` converts `ToolChoice` objects of shape `{ type: "tool" | "function", name }` to the wire form. Mirrors the equivalent Anthropic mapper.
|
|
687
777
|
|
|
688
778
|
### Changed
|
|
689
779
|
|
|
690
780
|
- Improved Codex WebSocket timeout diagnostics to include last event type and time since last progress event
|
|
691
781
|
- Enhanced Codex WebSocket error classification to recognize ping, pong, send, and queue-overflow failures as retryable
|
|
692
|
-
- Changed `mapGoogleToolChoice` to be exported from `@oh-my-pi/pi-ai/stream` so callers can build the wire-shape allow-list directly without re-deriving it.
|
|
693
782
|
|
|
694
783
|
### Fixed
|
|
695
784
|
|
|
@@ -698,7 +787,6 @@
|
|
|
698
787
|
- Fixed Codex WebSocket pong timeout detection by tracking pong events and failing the connection when no pong is received within the configured timeout
|
|
699
788
|
- 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.
|
|
700
789
|
- Fixed Codex WebSocket silent stalls by adding protocol pings, inbound queue bounding, clearer idle-timeout diagnostics, and SDK retry clamping for first-event timeouts.
|
|
701
|
-
- Fixed Synthetic model discovery to treat the provider `/models` response as authoritative so deprecated bundled IDs are pruned from the runtime cache, and changed Synthetic login validation to avoid probing a specific model ([#1417](https://github.com/can1357/oh-my-pi/issues/1417)).
|
|
702
790
|
|
|
703
791
|
## [15.5.0] - 2026-05-26
|
|
704
792
|
|
|
@@ -822,10 +910,6 @@
|
|
|
822
910
|
|
|
823
911
|
- 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.
|
|
824
912
|
|
|
825
|
-
### Fixed
|
|
826
|
-
|
|
827
|
-
- Fixed `openai-responses` requests intermittently 400ing with `No tool call found for function call output with call_id …` after an aborted turn or a locally-rejected tool call (e.g. argument-validation failure). `convertConversationMessages` now folds orphan `function_call_output` / `custom_tool_call_output` items — those whose matching `function_call` was wiped by an earlier `dt: false` snapshot splice or never landed in any persisted provider payload — into assistant text notes, preserving the payload while keeping the request grammatically valid ([#1351](https://github.com/can1357/oh-my-pi/issues/1351)).
|
|
828
|
-
|
|
829
913
|
## [15.2.4] - 2026-05-22
|
|
830
914
|
|
|
831
915
|
### Fixed
|
|
@@ -878,7 +962,6 @@
|
|
|
878
962
|
### Fixed
|
|
879
963
|
|
|
880
964
|
- 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.
|
|
881
|
-
- Fixed MiniMax Coding Plan CN streaming `<think>...</think>` reasoning as visible assistant text. The OpenAI-compatible stream parser now enables the existing MiniMax tag parser for both `minimax-code` and `minimax-code-cn`, so CN responses become structured `thinking` blocks instead of raw text. ([#1203](https://github.com/can1357/oh-my-pi/issues/1203))
|
|
882
965
|
|
|
883
966
|
## [15.1.6] - 2026-05-19
|
|
884
967
|
|
|
@@ -895,7 +978,6 @@
|
|
|
895
978
|
|
|
896
979
|
### Fixed
|
|
897
980
|
|
|
898
|
-
- Fixed OpenCode-Go and OpenCode-Zen chat-completions replay to omit stored reasoning fields on Kimi assistant tool-call messages, avoiding provider 400s for rejected `messages[].reasoning` payloads. ([#1157](https://github.com/can1357/oh-my-pi/issues/1157))
|
|
899
981
|
- 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))
|
|
900
982
|
- 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.
|
|
901
983
|
- 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
|
|
@@ -1084,11 +1166,6 @@
|
|
|
1084
1166
|
|
|
1085
1167
|
- 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.
|
|
1086
1168
|
- 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.
|
|
1087
|
-
- Lazy built-in provider streams now enforce the shared idle watchdog and abort stalled provider requests, so session auto-retry can continue after transient network drops instead of remaining stuck. Caller aborts still terminate as aborted.
|
|
1088
|
-
|
|
1089
|
-
### Changed
|
|
1090
|
-
|
|
1091
|
-
- Lowered the default steady-state stream idle timeout from 120s to 30s while preserving the existing environment overrides.
|
|
1092
1169
|
|
|
1093
1170
|
## [14.9.3] - 2026-05-10
|
|
1094
1171
|
|
|
@@ -1101,7 +1178,6 @@
|
|
|
1101
1178
|
### Fixed
|
|
1102
1179
|
|
|
1103
1180
|
- 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)).
|
|
1104
|
-
|
|
1105
1181
|
- 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.
|
|
1106
1182
|
- 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.
|
|
1107
1183
|
- Added `onSseEvent` stream diagnostics so HTTP SSE providers can expose raw SSE frames without changing parsed model output.
|
|
@@ -1119,7 +1195,6 @@
|
|
|
1119
1195
|
|
|
1120
1196
|
- 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.
|
|
1121
1197
|
- 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.
|
|
1122
|
-
- Fixed OpenAI Responses custom tool replay to preserve custom tool call item IDs with the `ctc_` prefix instead of rewriting them as `fc_` function-call IDs ([#977](https://github.com/can1357/oh-my-pi/issues/977)).
|
|
1123
1198
|
|
|
1124
1199
|
## [14.7.6] - 2026-05-07
|
|
1125
1200
|
|
|
@@ -1383,7 +1458,6 @@
|
|
|
1383
1458
|
- Fixed shell execution failure responses to preserve all result fields when sanitizing, preventing truncated metadata in stream results
|
|
1384
1459
|
- 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))
|
|
1385
1460
|
- 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
|
|
1386
|
-
- Fixed GitHub Copilot reasoning regressions by preserving GPT-5.x / Claude 4.x reasoning controls instead of stripping them from requests ([#773](https://github.com/can1357/oh-my-pi/issues/773))
|
|
1387
1461
|
|
|
1388
1462
|
## [14.1.0] - 2026-04-11
|
|
1389
1463
|
|
|
@@ -1446,7 +1520,6 @@
|
|
|
1446
1520
|
- Fixed Gemini 2.5 Pro context window detection in GitHub Copilot model limits test
|
|
1447
1521
|
- Fixed Claude Opus 4.6 context window detection in GitHub Copilot model limits test
|
|
1448
1522
|
- Fixed Anthropic streaming to suppress transient SDK console errors for malformed SSE keep-alive frames so the TUI only shows surfaced provider errors
|
|
1449
|
-
|
|
1450
1523
|
- Added environment-based credential fallback for the OpenAI Codex provider.
|
|
1451
1524
|
|
|
1452
1525
|
## [13.17.6] - 2026-04-01
|
|
@@ -1824,8 +1897,6 @@
|
|
|
1824
1897
|
- Fixed OpenAI Codex streaming to properly include service_tier in SSE payloads
|
|
1825
1898
|
- Fixed type safety in OpenAI responses by removing unsafe type casts on image content blocks
|
|
1826
1899
|
- Fixed credential purging to respect disabled credentials when deduplicating by email
|
|
1827
|
-
- Fixed API-key provider re-login to replace the active stored key instead of appending stale credentials that were still selected first
|
|
1828
|
-
- Fixed Kagi login guidance to use the correct `KG_...` key format and mention Search API beta access requirements
|
|
1829
1900
|
|
|
1830
1901
|
## [13.9.2] - 2026-03-05
|
|
1831
1902
|
|
|
@@ -1850,7 +1921,7 @@
|
|
|
1850
1921
|
- Removed `THINKING_LEVELS`, `ALL_THINKING_LEVELS`, `ALL_THINKING_MODES`, `THINKING_MODE_DESCRIPTIONS`, and `THINKING_MODE_LABELS` exports
|
|
1851
1922
|
- Renamed `formatThinking()` to `getThinkingMetadata()` with changed return type from string to `ThinkingMetadata` object
|
|
1852
1923
|
- Renamed `getAvailableThinkingLevel()` to `getAvailableThinkingLevels()` and added default parameter
|
|
1853
|
-
- Renamed `
|
|
1924
|
+
- Renamed `getAvailableThinkingEffort()` to `getAvailableThinkingEfforts()` and added default parameter
|
|
1854
1925
|
|
|
1855
1926
|
### Added
|
|
1856
1927
|
|
|
@@ -1860,17 +1931,17 @@
|
|
|
1860
1931
|
|
|
1861
1932
|
### Added
|
|
1862
1933
|
|
|
1863
|
-
- Exported new thinking module with `
|
|
1864
|
-
- Added `
|
|
1865
|
-
- Added `
|
|
1934
|
+
- Exported new thinking module with `ThinkingEffort`, `ThinkingLevel`, and `ThinkingMode` types for managing reasoning effort levels
|
|
1935
|
+
- Added `getAvailableThinkingEffort()` function to determine supported thinking effort levels based on model capabilities
|
|
1936
|
+
- Added `parseThinkingEffort()`, `parseThinkingLevel()`, and `parseThinkingMode()` functions for parsing thinking configuration strings
|
|
1866
1937
|
- Added `THINKING_LEVELS`, `ALL_THINKING_LEVELS`, and `ALL_THINKING_MODES` constants for iterating over available thinking options
|
|
1867
1938
|
- Added `THINKING_MODE_DESCRIPTIONS` and `THINKING_MODE_LABELS` for displaying thinking modes in user interfaces
|
|
1868
1939
|
- Added `formatThinking()` function to format thinking modes as compact display labels
|
|
1869
1940
|
|
|
1870
1941
|
### Changed
|
|
1871
1942
|
|
|
1872
|
-
- Refactored thinking level handling to distinguish between `
|
|
1873
|
-
- Updated `ThinkingBudgets` type to use `
|
|
1943
|
+
- Refactored thinking level handling to distinguish between `ThinkingEffort` (provider-level, no "off") and `ThinkingLevel` (user-facing, includes "off")
|
|
1944
|
+
- Updated `ThinkingBudgets` type to use `ThinkingEffort` instead of `ThinkingLevel` for more precise token budget configuration
|
|
1874
1945
|
- Improved reasoning option handling to explicitly support "off" value for disabling reasoning across all providers
|
|
1875
1946
|
- Simplified thinking effort mapping logic by centralizing provider-specific clamping behavior
|
|
1876
1947
|
|
|
@@ -2661,7 +2732,7 @@
|
|
|
2661
2732
|
|
|
2662
2733
|
### Changed
|
|
2663
2734
|
|
|
2664
|
-
- Replaced direct `
|
|
2735
|
+
- Replaced direct `process.env` access with `getEnv()` utility from `@oh-my-pi/pi-utils` for consistent environment variable handling across all providers
|
|
2665
2736
|
- Updated environment variable names from `OMP_*` prefix to `PI_*` prefix for consistency (e.g., `OMP_CODING_AGENT_DIR` → `PI_CODING_AGENT_DIR`)
|
|
2666
2737
|
|
|
2667
2738
|
### Removed
|
|
@@ -2688,13 +2759,13 @@
|
|
|
2688
2759
|
|
|
2689
2760
|
### Added
|
|
2690
2761
|
|
|
2691
|
-
- Added `getEnv()` function to retrieve environment variables from
|
|
2762
|
+
- Added `getEnv()` function to retrieve environment variables from process.env, cwd/.env, or ~/.env
|
|
2692
2763
|
- Added support for reading .env files from home directory and current working directory
|
|
2693
2764
|
- Added support for `exa` and `perplexity` as known providers in `getEnvApiKey()`
|
|
2694
2765
|
|
|
2695
2766
|
### Changed
|
|
2696
2767
|
|
|
2697
|
-
- Changed `getEnvApiKey()` to check
|
|
2768
|
+
- Changed `getEnvApiKey()` to check process.env, cwd/.env, and ~/.env files in order of precedence
|
|
2698
2769
|
- Refactored provider API key resolution to use a declarative service provider map
|
|
2699
2770
|
|
|
2700
2771
|
## [9.2.2] - 2026-01-31
|
|
@@ -2900,7 +2971,7 @@
|
|
|
2900
2971
|
- Replaced custom sleep implementations with Bun.sleep and abortableSleep
|
|
2901
2972
|
- Simplified SSE stream parsing using readLines utility
|
|
2902
2973
|
- Updated test framework from vitest to bun:test
|
|
2903
|
-
- Replaced temp directory creation with
|
|
2974
|
+
- Replaced temp directory creation with createTempDirSync utility
|
|
2904
2975
|
- Changed credential storage from auth.json to ~/.omp/agent/agent.db
|
|
2905
2976
|
- Changed CLI command examples from npx to bunx
|
|
2906
2977
|
- Refactored OAuth flows to use common callback server base class
|
|
@@ -2943,8 +3014,8 @@
|
|
|
2943
3014
|
|
|
2944
3015
|
### Changed
|
|
2945
3016
|
|
|
2946
|
-
- Updated environment variable prefix from
|
|
2947
|
-
- Added automatic migration for legacy
|
|
3017
|
+
- Updated environment variable prefix from PI_ to OMP_ for better consistency
|
|
3018
|
+
- Added automatic migration for legacy PI_ environment variables to OMP_ equivalents
|
|
2948
3019
|
- Adjusted Bedrock Claude thinking budgets to reserve output tokens when maxTokens is too low
|
|
2949
3020
|
|
|
2950
3021
|
### Fixed
|
|
@@ -3061,7 +3132,7 @@
|
|
|
3061
3132
|
|
|
3062
3133
|
- Changed Cursor debug logging to use structured JSONL format with automatic MCP argument decoding
|
|
3063
3134
|
- Changed MCP tool argument decoding to use protobuf Value schema for improved type handling
|
|
3064
|
-
- Changed tool advertisement to filter Cursor native tools (bash, read, write, delete, ls, grep, lsp) instead of only exposing
|
|
3135
|
+
- Changed tool advertisement to filter Cursor native tools (bash, read, write, delete, ls, grep, lsp) instead of only exposing mcp_ prefixed tools
|
|
3065
3136
|
|
|
3066
3137
|
### Fixed
|
|
3067
3138
|
|
|
@@ -3144,6 +3215,222 @@
|
|
|
3144
3215
|
|
|
3145
3216
|
- Enhanced error messages to include retry-after timing information from API rate limit headers
|
|
3146
3217
|
|
|
3218
|
+
## [3.20.0] - 2026-01-06
|
|
3219
|
+
|
|
3220
|
+
### Added
|
|
3221
|
+
|
|
3222
|
+
- Added support for kwaipilot/kat-coder-pro model via OpenRouter
|
|
3223
|
+
- Added OpenAI Codex responses provider with OAuth login support for ChatGPT Plus/Pro accounts
|
|
3224
|
+
- Added Google Vertex AI provider (Gemini via Vertex) with Application Default Credentials support
|
|
3225
|
+
|
|
3226
|
+
### Changed
|
|
3227
|
+
|
|
3228
|
+
- Updated model specifications including context windows, max tokens, and pricing for multiple OpenRouter models
|
|
3229
|
+
|
|
3230
|
+
### Removed
|
|
3231
|
+
|
|
3232
|
+
- Removed alibaba/tongyi-deepresearch-30b-a3b:free model from OpenRouter
|
|
3233
|
+
- Removed nousresearch/hermes-4-405b model from OpenRouter
|
|
3234
|
+
- Removed tngtech/tng-r1t-chimera:free model from OpenRouter
|
|
3235
|
+
|
|
3236
|
+
## [3.15.0] - 2026-01-05
|
|
3237
|
+
|
|
3238
|
+
### Changed
|
|
3239
|
+
|
|
3240
|
+
- Made `isError` field optional in `ToolResultMessage` interface, defaulting to non-error state
|
|
3241
|
+
|
|
3242
|
+
## [3.5.1337] - 2026-01-03
|
|
3243
|
+
|
|
3244
|
+
### Added
|
|
3245
|
+
|
|
3246
|
+
- Added localhost URL detection for OpenAI-compatible provider auto-configuration
|
|
3247
|
+
|
|
3248
|
+
## [1.337.1] - 2026-01-02
|
|
3249
|
+
|
|
3250
|
+
### Changed
|
|
3251
|
+
|
|
3252
|
+
- Forked to @oh-my-pi scope with unified versioning across all packages
|
|
3253
|
+
|
|
3254
|
+
### Fixed
|
|
3255
|
+
|
|
3256
|
+
- **Gemini CLI rate limit handling**: Added automatic retry with server-provided delay for 429 errors
|
|
3257
|
+
|
|
3258
|
+
## [1.337.0] - 2026-01-02
|
|
3259
|
+
|
|
3260
|
+
Initial release under @oh-my-pi scope. See previous releases at [badlogic/pi-mono](https://github.com/badlogic/pi-mono).
|
|
3261
|
+
|
|
3262
|
+
## [0.50.1] - 2026-01-26
|
|
3263
|
+
|
|
3264
|
+
### Fixed
|
|
3265
|
+
|
|
3266
|
+
- Fixed OpenCode Zen model generation to exclude deprecated models ([#970](https://github.com/badlogic/pi-mono/pull/970) by [@DanielTatarkin](https://github.com/DanielTatarkin))
|
|
3267
|
+
|
|
3268
|
+
## [0.50.0] - 2026-01-26
|
|
3269
|
+
|
|
3270
|
+
### Added
|
|
3271
|
+
|
|
3272
|
+
- 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))
|
|
3273
|
+
- 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))
|
|
3274
|
+
- Added HTTP proxy environment variable support for API requests ([#942](https://github.com/badlogic/pi-mono/pull/942) by [@haoqixu](https://github.com/haoqixu))
|
|
3275
|
+
- Added `createAssistantMessageEventStream()` factory function for use in extensions.
|
|
3276
|
+
- Added `resetApiProviders()` to clear and re-register built-in API providers.
|
|
3277
|
+
|
|
3278
|
+
### Changed
|
|
3279
|
+
|
|
3280
|
+
- Refactored API streaming dispatch to use an API registry with provider-owned `streamSimple` mapping.
|
|
3281
|
+
- Moved environment API key resolution to `env-api-keys.ts` and re-exported it from the package entrypoint.
|
|
3282
|
+
- Azure OpenAI Responses provider now uses base URL configuration with deployment-aware model mapping and no longer includes service tier handling.
|
|
3283
|
+
|
|
3284
|
+
### Fixed
|
|
3285
|
+
|
|
3286
|
+
- 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))
|
|
3287
|
+
- Fixed streaming functions to use `model.api` instead of hardcoded API types
|
|
3288
|
+
- Fixed Google providers to default tool call arguments to an empty object when omitted
|
|
3289
|
+
- 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))
|
|
3290
|
+
- Fixed OpenAI Codex Responses tool strictness handling after the shared responses refactor
|
|
3291
|
+
- Fixed Azure OpenAI Responses streaming to guard deltas before content parts and correct metadata and handoff gating
|
|
3292
|
+
- 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))
|
|
3293
|
+
|
|
3294
|
+
## [0.49.3] - 2026-01-22
|
|
3295
|
+
|
|
3296
|
+
### Added
|
|
3297
|
+
|
|
3298
|
+
- 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.
|
|
3299
|
+
- Added `originator` option to `loginOpenAICodex()` for custom OAuth client identification
|
|
3300
|
+
- 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))
|
|
3301
|
+
|
|
3302
|
+
### Fixed
|
|
3303
|
+
|
|
3304
|
+
- 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))
|
|
3305
|
+
|
|
3306
|
+
## [0.49.2] - 2026-01-19
|
|
3307
|
+
|
|
3308
|
+
### Added
|
|
3309
|
+
|
|
3310
|
+
- 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))
|
|
3311
|
+
|
|
3312
|
+
### Fixed
|
|
3313
|
+
|
|
3314
|
+
- 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))
|
|
3315
|
+
|
|
3316
|
+
### Removed
|
|
3317
|
+
|
|
3318
|
+
- Removed `strictResponsesPairing` compat option (no longer needed after the transform-messages fix)
|
|
3319
|
+
|
|
3320
|
+
## [0.49.1] - 2026-01-18
|
|
3321
|
+
|
|
3322
|
+
### Added
|
|
3323
|
+
|
|
3324
|
+
- 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))
|
|
3325
|
+
|
|
3326
|
+
### Changed
|
|
3327
|
+
|
|
3328
|
+
- Split `OpenAICompat` into `OpenAICompletionsCompat` and `OpenAIResponsesCompat` for type-safe API-specific compat settings
|
|
3329
|
+
|
|
3330
|
+
### Fixed
|
|
3331
|
+
|
|
3332
|
+
- Fixed tool call ID normalization for cross-provider handoffs (e.g., Codex to Antigravity Claude) ([#821](https://github.com/badlogic/pi-mono/issues/821))
|
|
3333
|
+
|
|
3334
|
+
## [0.49.0] - 2026-01-17
|
|
3335
|
+
|
|
3336
|
+
### Changed
|
|
3337
|
+
|
|
3338
|
+
- OpenAI Codex responses now use the context system prompt directly in the instructions field.
|
|
3339
|
+
|
|
3340
|
+
### Fixed
|
|
3341
|
+
|
|
3342
|
+
- 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))
|
|
3343
|
+
- 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))
|
|
3344
|
+
- Fixed Claude Code tool name normalization to match the Claude Code tool list case-insensitively and remove invalid mappings.
|
|
3345
|
+
|
|
3346
|
+
## [0.48.0] - 2026-01-16
|
|
3347
|
+
|
|
3348
|
+
### Fixed
|
|
3349
|
+
|
|
3350
|
+
- 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))
|
|
3351
|
+
- 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
|
|
3352
|
+
- 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))
|
|
3353
|
+
- 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))
|
|
3354
|
+
- Fixed empty error assistant messages (from 429/500 errors) breaking the tool_use to tool_result chain by filtering them in `transformMessages`
|
|
3355
|
+
|
|
3356
|
+
## [0.47.0] - 2026-01-16
|
|
3357
|
+
|
|
3358
|
+
### Fixed
|
|
3359
|
+
|
|
3360
|
+
- 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))
|
|
3361
|
+
- 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))
|
|
3362
|
+
|
|
3363
|
+
## [0.46.0] - 2026-01-15
|
|
3364
|
+
|
|
3365
|
+
### Added
|
|
3366
|
+
|
|
3367
|
+
- Added MiniMax China (`minimax-cn`) provider support ([#725](https://github.com/badlogic/pi-mono/pull/725) by [@tallshort](https://github.com/tallshort))
|
|
3368
|
+
- 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))
|
|
3369
|
+
|
|
3370
|
+
### Fixed
|
|
3371
|
+
|
|
3372
|
+
- Avoid unsigned Gemini 3 tool calls ([#741](https://github.com/badlogic/pi-mono/pull/741) by [@roshanasingh4](https://github.com/roshanasingh4))
|
|
3373
|
+
- 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))
|
|
3374
|
+
|
|
3375
|
+
## [0.45.7] - 2026-01-13
|
|
3376
|
+
|
|
3377
|
+
### Fixed
|
|
3378
|
+
|
|
3379
|
+
- Fixed OpenAI Responses timeout option handling ([#706](https://github.com/badlogic/pi-mono/pull/706) by [@markusylisiurunen](https://github.com/markusylisiurunen))
|
|
3380
|
+
- Fixed Bedrock tool call conversion to apply message transforms ([#707](https://github.com/badlogic/pi-mono/pull/707) by [@pjtf93](https://github.com/pjtf93))
|
|
3381
|
+
|
|
3382
|
+
## [0.45.6] - 2026-01-13
|
|
3383
|
+
|
|
3384
|
+
### Fixed
|
|
3385
|
+
|
|
3386
|
+
- Export `parseStreamingJson` from main package for tsx dev mode compatibility
|
|
3387
|
+
|
|
3388
|
+
## [0.45.4] - 2026-01-13
|
|
3389
|
+
|
|
3390
|
+
### Added
|
|
3391
|
+
|
|
3392
|
+
- 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))
|
|
3393
|
+
|
|
3394
|
+
### Fixed
|
|
3395
|
+
|
|
3396
|
+
- 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))
|
|
3397
|
+
|
|
3398
|
+
## [0.45.0] - 2026-01-13
|
|
3399
|
+
|
|
3400
|
+
### Added
|
|
3401
|
+
|
|
3402
|
+
- 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))
|
|
3403
|
+
- 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))
|
|
3404
|
+
- Added `serviceTier` option for OpenAI Responses requests ([#672](https://github.com/badlogic/pi-mono/pull/672) by [@markusylisiurunen](https://github.com/markusylisiurunen))
|
|
3405
|
+
- **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))
|
|
3406
|
+
- **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))
|
|
3407
|
+
|
|
3408
|
+
## [0.43.0] - 2026-01-11
|
|
3409
|
+
|
|
3410
|
+
### Fixed
|
|
3411
|
+
|
|
3412
|
+
- 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))
|
|
3413
|
+
|
|
3414
|
+
## [0.42.3] - 2026-01-10
|
|
3415
|
+
|
|
3416
|
+
### Changed
|
|
3417
|
+
|
|
3418
|
+
- OpenAI Codex: switched to bundled system prompt matching opencode, changed originator to "pi", simplified prompt handling
|
|
3419
|
+
|
|
3420
|
+
## [0.42.2] - 2026-01-10
|
|
3421
|
+
|
|
3422
|
+
### Added
|
|
3423
|
+
|
|
3424
|
+
- Added `GOOGLE_APPLICATION_CREDENTIALS` env var support for Vertex AI credential detection (standard for CI/production).
|
|
3425
|
+
- 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))
|
|
3426
|
+
- Improved Google model pricing info ([#588](https://github.com/badlogic/pi-mono/pull/588) by [@aadishv](https://github.com/aadishv))
|
|
3427
|
+
|
|
3428
|
+
### Fixed
|
|
3429
|
+
|
|
3430
|
+
- Fixed `os.homedir()` calls at module load time; now resolved lazily when needed.
|
|
3431
|
+
- 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))
|
|
3432
|
+
- 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))
|
|
3433
|
+
|
|
3147
3434
|
## [0.42.0] - 2026-01-09
|
|
3148
3435
|
|
|
3149
3436
|
### Added
|
|
@@ -3237,7 +3524,7 @@
|
|
|
3237
3524
|
|
|
3238
3525
|
### Breaking Changes
|
|
3239
3526
|
|
|
3240
|
-
- **Agent API moved**: All agent functionality (`agentLoop`, `agentLoopContinue`, `AgentContext`, `AgentEvent`, `AgentTool`, `AgentToolResult`, etc.) has moved to `@
|
|
3527
|
+
- **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`.
|
|
3241
3528
|
|
|
3242
3529
|
### Added
|
|
3243
3530
|
|
|
@@ -3253,7 +3540,6 @@
|
|
|
3253
3540
|
### Fixed
|
|
3254
3541
|
|
|
3255
3542
|
- **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))
|
|
3256
|
-
- **Thinking token duplication**: Fixed thinking content duplication with chutes.ai provider. The provider was returning thinking content in both `reasoning_content` and `reasoning` fields, causing each chunk to be processed twice. Now only the first non-empty reasoning field is used.
|
|
3257
3543
|
- **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))
|
|
3258
3544
|
|
|
3259
3545
|
## [0.28.0] - 2025-12-25
|
|
@@ -3283,11 +3569,8 @@
|
|
|
3283
3569
|
### Fixed
|
|
3284
3570
|
|
|
3285
3571
|
- **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.
|
|
3286
|
-
|
|
3287
3572
|
- **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).
|
|
3288
|
-
|
|
3289
3573
|
- **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))
|
|
3290
|
-
|
|
3291
3574
|
- **Anthropic SDK retries disabled**: Re-enabled SDK-level retries (default 2) for transient HTTP failures. ([#252](https://github.com/badlogic/pi-mono/issues/252))
|
|
3292
3575
|
|
|
3293
3576
|
## [0.23.5] - 2025-12-19
|
|
@@ -3295,17 +3578,13 @@
|
|
|
3295
3578
|
### Added
|
|
3296
3579
|
|
|
3297
3580
|
- **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))
|
|
3298
|
-
|
|
3299
3581
|
- **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))
|
|
3300
3582
|
|
|
3301
3583
|
### Fixed
|
|
3302
3584
|
|
|
3303
3585
|
- **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))
|
|
3304
|
-
|
|
3305
3586
|
- **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))
|
|
3306
|
-
|
|
3307
3587
|
- **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))
|
|
3308
|
-
|
|
3309
3588
|
- **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))
|
|
3310
3589
|
|
|
3311
3590
|
## [0.22.3] - 2025-12-16
|
|
@@ -3313,9 +3592,7 @@
|
|
|
3313
3592
|
### Added
|
|
3314
3593
|
|
|
3315
3594
|
- **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))
|
|
3316
|
-
|
|
3317
3595
|
- **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))
|
|
3318
|
-
|
|
3319
3596
|
- **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))
|
|
3320
3597
|
|
|
3321
3598
|
### Changed
|
|
@@ -3349,9 +3626,7 @@ _Dedicated to Peter's shoulder ([@steipete](https://twitter.com/steipete))_
|
|
|
3349
3626
|
### Fixed
|
|
3350
3627
|
|
|
3351
3628
|
- **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)
|
|
3352
|
-
|
|
3353
3629
|
- **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))
|
|
3354
|
-
|
|
3355
3630
|
- **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))
|
|
3356
3631
|
|
|
3357
3632
|
## [0.18.2] - 2025-12-11
|
|
@@ -3369,9 +3644,7 @@ _Dedicated to Peter's shoulder ([@steipete](https://twitter.com/steipete))_
|
|
|
3369
3644
|
### Fixed
|
|
3370
3645
|
|
|
3371
3646
|
- 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))
|
|
3372
|
-
|
|
3373
3647
|
- 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))
|
|
3374
|
-
|
|
3375
3648
|
- 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))
|
|
3376
3649
|
|
|
3377
3650
|
## [0.17.0] - 2025-12-09
|
|
@@ -3380,9 +3653,7 @@ _Dedicated to Peter's shoulder ([@steipete](https://twitter.com/steipete))_
|
|
|
3380
3653
|
|
|
3381
3654
|
- **`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.
|
|
3382
3655
|
- Added `validateToolCall(tools, toolCall)` helper that finds the tool by name and validates arguments.
|
|
3383
|
-
|
|
3384
3656
|
- **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)
|
|
3385
|
-
|
|
3386
3657
|
- **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))
|
|
3387
3658
|
|
|
3388
3659
|
### Breaking Changes
|
|
@@ -3408,7 +3679,6 @@ _Dedicated to Peter's shoulder ([@steipete](https://twitter.com/steipete))_
|
|
|
3408
3679
|
### Fixed
|
|
3409
3680
|
|
|
3410
3681
|
- **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.
|
|
3411
|
-
|
|
3412
3682
|
- **Fixed Claude Opus 4.5 cache pricing** (was 3x too expensive)
|
|
3413
3683
|
- Corrected cache_read: $1.50 → $0.50 per MTok
|
|
3414
3684
|
- Corrected cache_write: $18.75 → $6.25 per MTok
|