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
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.
closes#10720
When a finished tool call's arguments text was not valid JSON, the
streaming parser kept only the fields before the error and the tool ran
with them. Finished calls are now parsed strictly (with the existing
string repair); on failure arguments are {} and argumentsError holds the
reason and raw text, which validateToolArguments reports to the model.
fixes#10897
MiMo Chat Completions rejects reasoning_effort "minimal" with a 400.
Xiaomi documents only thinking.type enabled/disabled and treats all effort
levels identically, so stop sending reasoning_effort and expose only the
off and high thinking levels.
fixes#10818
Proxies such as LiteLLM can send reasoning_content and content in one
stream delta. Reasoning was handled after content, so the message ended
up as [text, thinking]. Handle reasoning fields and reasoning_details
before content and tool calls.
fixes#10926
With an API key, GPT-6 models on the openai provider now keep reasoning.effort
fixed and send the thinking level as configuration_update input items. Each
reply records its level, so earlier items are rebuilt unchanged on every request.
Controlled by compat.supportsMidConvoEffort; skipped for Sign in with ChatGPT
and thinking off.
closes#10853
- Use opencode.ai/inference and opencode.ai/inference/go base URLs; /zen/go has no Gemini route (404)
- Add google-generative-ai support to the OpenCode Go provider
- Use Anthropic Messages for OpenCode Go minimax-m2.7; openai-completions now returns ModelProtocolUnsupported
- Remove test for opencode-go deepseek-v4-flash, which is no longer listed