- ai: StreamingJsonParser / ToolCallArgumentsStream read each argument delta once (tolerant,
immutable snapshots, linear cost); every provider, pi-messages and the faux provider use it
and keep stream state (partialJson, partialArgs, index, customInput, streamIndex, Bedrock
reasoning bytes) off the content blocks; grammar tool input appends per delta
- agent: streamProxy uses the same parser
- chord: Delta append ops own their text (ownedSlice), so ops and replicas no longer keep the
whole growing string alive
- durable, ai, mcp: bounded error excerpts and summaries own their characters
- coding-agent: tool calls render streamed arguments once per frame, not once per delta
With a sessionId, the faux provider reported newly cached prompt tokens
both as input and as cacheWrite, so input + cacheRead + cacheWrite
exceeded the estimated prompt. Every prompt token now goes either to
cacheRead or to cacheWrite, and input is 0 while caching is simulated.
Fix docs and `--help` drift: update the provider checklist to the
`src/api` layout, fix broken MCP anchors, and document `/mcp`, `pi mcp
add|remove`, `PI_CLEAR_ON_SHRINK`, and `"disabled"` timeouts.
closes#11243
This commit makes it so we store the responseModel (i.e. the "phyiscal"
model used) on each PiMessage. This allows e.g. Radius to know which
physical model was used by virtual models (like `cheap`). It's
especially important after we merged
https://github.com/earendil-works/pi/pull/11000
(9113094291), where Pi will drop thinking
traces when the model name doesn't match - with this change we can check
the physical model instead.
Knowing how annoying re-logins in corporate environments can be, I think
we can open the browser and copy the code to the clipboard (what the user
asks for) without forcing it upon users (which I assume was the reason
it was removed in 8f0e9251b9).
This change adds optional browser opening and code copying during
device-code login after an additional confirmation (usually Enter).
It should work for all providers, with an optional opt-out controlled
by the provider author, not user settings.
Fixes#9282.
A mid-conversation system message was placed before checking whether the
next assistant message converts to any blocks. When it did not (empty text,
or another model's reasoning-only reply), the update landed before a user
message and Claude rejected the request with a 400.
closes#11091
Use authoritative OpenRouter billing for Chat Completions and Anthropic Messages while retaining catalog component estimates and fallback behavior.
Fixes#9980
Add Usage.cost.totalFromProvider to record whether cost.total is the
billed cost reported by the provider or an estimate from catalog rates.
Catalog-derived totals set it to false; a missing value also means
false. combineUsage marks a sum as provider-reported only when both
parts are.
Move two post-release entries out of the 1.3.0 sections, add missing entries, duplicate user-facing ai and tui changes into coding-agent, and add New Features.
Jev (TypeSafe, Workers AI), Clef (Workers AI), and OpenRouter decision
models now accept ClassifierContext.images. Each service takes its own
wire form: TypeSafe assets with the opt-in header, Clef images data URLs,
or OpenRouter image_url parts in the state. A new SystemOneCompat
(imageInput, sendImageOptInHeader) selects the form; catalog entries set
it explicitly and models.json provider compat now applies to classifiers.
Adds Clef Omni and Jev 1.14 on Workers AI and fixes Clef Flash and
Workers AI Jev catalog pricing.
- ClientAttribution is { name, url, categories? } with required name and url, so
OpenRouter always gets an HTTP-Referer. identity.ts maps the fields to each
provider's headers; NVIDIA gets the name with its first letter upper-cased.
attribution: null turns it off. PI_ATTRIBUTION is pi's, including the
cli-agent category; agent-core, durable, and the coding agent use it.
- Categories are a string array, joined for OpenRouter.
- withClientIdentity() is a typed wrapper instead of a Proxy and keeps a
MutableModels mutable. Durable no longer caches wrappers in a WeakMap.
- The Codex originator stays pi; login agentName no longer follows attribution.
- Models and the coding agent's ModelRuntime add x-opencode-session for custom
providers pointing at OpenCode, replacing the coding agent's transformHeaders.
pi-ai gets a ClientIdentity request option and createModels() default that choose the User-Agent (detailed with version, short, or custom) and provider attribution headers for OpenRouter, NVIDIA NIM, and OpenCode. Attribution is off by default in pi-ai and on by default in pi-agent-core and pi-durable (HarnessOptions.identity). pi-coding-agent sets its identity from the telemetry setting instead of adding headers itself.
Sign in with ChatGPT on a ChatGPT Business plan can fail with
subscription_sharing_workplace_individual_usage_limit_exceeded. Only the
workspace admin can raise this limit, so retrying never helps.
- Mark the error as non-retryable
- Add a hint to the error message telling the user to ask their
workspace admin to increase the limit
models.dev deprecated several Baseten, GitHub Copilot, and Together models,
which broke type checks and the default-model test.
- Default GitHub Copilot model: gpt-5.4 -> gpt-6.1-sol
- Move Copilot live tests to gpt-6-luna/gpt-6-sol
- Remove tests and generator entries for retired models, including the
Together reasoning-only model list
The openai-codex provider authenticates with a ChatGPT account, and the
Codex backend rejects gpt-5.5 and gpt-5.3-codex-spark for those accounts
("not supported when using Codex with a ChatGPT account"). Remove them
from the catalog so model pickers stop offering models that always fail.
Codex e2e tests that used openai-codex/gpt-5.5 now use gpt-6.1-sol, the
openai-codex default. The context overflow test uses gpt-5.6-sol to keep
its prompt smaller.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
The incremental tools notice precedes the removal notice of the same message, so it now restates only removals announced by earlier messages. resolveTranscriptTools and hasNonAdditiveToolChanges share one scan for the last non-additive tool change.
Models with additional_tools declare every tool in additional_tools items, starting with one at the head of the input, like Codex. A later item replaces same-name definitions from earlier items but cannot replace a top-level tool or remove a tool, so removals are announced as text and later updates restate the tools that are still unavailable.
Tool search and Kimi tool messages move the top-level tool list once per removal or redeclared name and keep later loads anchored, instead of resending the current tool list on every load after the first removal.
fixes#10940
Copilot rejects request bodies over its byte-size limit with HTTP 413 and a generic
'failed to parse request' body, so the existing token-count heuristics never matched.
Treat any HTTP 413 as request-size overflow regardless of provider or body text, so
the agent compacts and retries instead of surfacing a raw API error.
Validated against the live Copilot API (40MB image payload): main classifies the 413
as a plain error, this branch detects it as overflow.
Replace the direct minimax allowlist with a denylist of the older M2, M2.1,
M2.5, and M2.5-highspeed models, applied where MiniMax models are built.
MiniMax models with models.dev effort levels use adaptive thinking with
output_config.effort and mark thinking off as unsupported, since
MiniMax-M3.1-Flash rejects thinking.type=disabled.
closes#11121
- pi-ai: AI_TELEMETRY_SCHEMA; pi.ai.request and pi.ai.poll spans around Models requests via a lazyStream observer
(no provider changes), first_chunk and block events (never per delta), usage/cost end attributes, provider_error
status with a bounded message, aborted stays ok; duration, first-chunk, token and cost metrics; option renamed
telemetryContext -> telemetry (a parent span)
- pi-telemetry: TelemetryContext carries readonly metrics and propagation capabilities on every span
- chord/context: Context.telemetry is always a TelemetrySpan (NOOP default); withTelemetry takes spans
- durable: DURABLE_TELEMETRY_SCHEMA; pi.durable.submit (inputs start their own trace linked to the caller) and
pi.durable.phase spans for every task phase; stored carriers on submissions and tasks (TaskOptions.trace, links);
entry, submission, checkpoint, replay and report events after commit; resumed tasks stay in their trace; phase
duration, active task and report metrics; failed phases carry fixed categories with bounded messages
* docs(ai,coding-agent): generate models.json reference from schemas
Add npm run generate:references, which renders docs/models-configuration.md
from the models.json TypeBox schemas, and describe provider and model fields
in those schemas. Overrides get their own descriptions without defaults, and
compat sections cover the Responses API aliases.
closes#10790
* Modify changelog
* docs(ai,coding-agent): use shared thinkingLevelMap and promptCache schemas
Replace the per-use schema helpers with fixed schemas whose descriptions
hold for both models and modelOverrides entries.
* feat(coding-agent): default NVIDIA to Nemotron 3.5 Super VL
Co-authored-by: prademacher-nvidia <235594174+prademacher-nvidia@users.noreply.github.com>
* docs(coding-agent): changelog for NVIDIA default model change
* fix(ai): run NVIDIA E2E tests against Nemotron 3.5 Super VL
---------
Co-authored-by: prademacher-nvidia <235594174+prademacher-nvidia@users.noreply.github.com>
Whitespace-only tool results (e.g. a bare \r\n from bash) were sent verbatim
to OpenAI Completions, OpenAI Responses, and Google providers. Some providers
reject that with a 400, which then repeats on every request in the session.
They now use the same placeholder as empty output.
closes#8720
When switching models, thinking blocks from earlier assistant messages
produced by a different model were sent as plain text. The new model saw
the old model's reasoning as part of its replies and could start writing
its own reasoning into the visible answer. These blocks are now dropped;
text and tool calls are kept.
closes#10995
Anthropic and Claude on Bedrock reject error tool results that contain
images. Instead of replacing the images with a note, each image in the
result is now replaced with a placeholder and the images are sent after
all tool results of the turn, in the same user message, under a caption
naming the tool call. Successful results, error results without images,
and non-Claude Bedrock models are unchanged.
closes#10794
Switch kimi-coding to OpenAI Chat Completions at api.kimi.com/coding/v1,
the protocol the official Kimi Code client uses. K3, K3-256K, and Kimi For
Coding accept tools declared in later system messages, so tools loaded
mid-conversation (e.g. by tool_search) keep the prompt cache. Highspeed
rejects tool-bearing system messages and keeps added tools top-level.
Re-lands b06c1f2 (reverted in 6a1f799b6) with MINIMUM_PI_VERSION bumped
to 1.2.1. Released clients implement only Anthropic Messages for
kimi-coding and ignore a model's api, so they must keep receiving the
last catalog published under 0.80.7.
closes#10720
Reverts b06c1f2. The pi.dev model catalog is served to every client
since 0.80.7, so released clients received kimi-coding models with
api openai-completions and baseUrl https://api.kimi.com/coding/v1.
Their kimi-coding provider only implements Anthropic Messages and
ignores model.api, so requests went to /coding/v1/v1/messages and
failed with 404. The change will re-land together with a bump of the
catalog's minimum pi version.
refs #10720, refs #10985
Both models accept thinking: {type: "disabled"}, but were treated like
Opus 5.5, which cannot turn thinking off. "off" now sends disabled
thinking without effort markers or block_binding, which Anthropic
rejects while thinking is disabled.
fixes#10753