The concurrent prompt tests slept 10 ms and assumed the first prompt was streaming, and the reftable watcher test allowed 3 s for a real fs event. Both failed under full-suite load during the release run.
models.dev now lists the input rate as Kimi K3's cache write cost on Moonshot, which does not bill cache writes. Claude Haiku 5.5 uses adaptive thinking, so the metadata test now expects it.
models.dev loaders for opencode, opencode-go, google, minimax, and others built costs by hand and dropped tiers; they now use getModelsDevCost. OpenRouter prompt-length overrides and Vercel AI Gateway per-rate tiers are parsed into request-wide tiers. Rates a tier does not list keep the base price. OpenRouter time-of-day overrides are skipped.
Adds claude-haiku-5-5 to the anthropic provider with its prompt-length pricing tier (5x above 100k input tokens), adaptive thinking with xhigh/max effort, per-message effort, and mid-conversation system messages and tool changes. Bedrock requests detect Haiku 5.5 for adaptive thinking, native xhigh, block binding, and prompt caching.
Report idle, working, blocked, done, and error to terminals that support
the Program Status Protocol. ProcessTerminal sends the support query with
the keyboard query and reports only after the terminal answers before DA1;
PI_PROGRAM_STATUS=1|0 overrides detection. Interactive mode reports runs,
compaction, extension dialogs, and logins. agent_settled now carries
aborted so cancelled runs report idle.
closes#10607
The OAuth flow in pi-mcp takes a signal for every request, and an aborted
refresh no longer falls back to a new authorization. The streamable HTTP
transport closes its session with the last request's token instead of
asking the auth provider, which could refresh first.
The MCP extension owns one signal per session: it aborts sign-ins on Esc
and on session shutdown, replaces the generation counter, and shutdown
waits for aborted sign-ins to clean up. Requests to the authorization
server time out after 15s, and pi mcp login --timeout limits the whole
sign-in.
closes#10565
Termux reports process.platform as android, so the Linux-only branch skipped
termux-clipboard-get and Ctrl+V pasted nothing. Also show the Termux:API hint
when a Termux copy fails.
fixes#10391
Under `node --watch`, Node 24.19+ and 26.x post `{ "watch:require": [...] }`
on the worker message channel (nodejs/node#65044). The image resize code
treated the first message as the worker's reply, resolved it to `null`, and
dropped the image as "could not be resized below the inline image size limit".
Worker replies now carry a `type` marker, and the main thread ignores any
message without it. The reply type is now either a result or an error.
fixes#10527
Mistral reports transient server failures as finish_reason "error". Its
error message now includes "server error" so the retry classifier treats
it as retryable.
closes#10487
TERM_PROGRAM=herdr enables hyperlinks with image protocols off. Herdr is
checked before outer-terminal detection so leaked variables such as
KITTY_WINDOW_ID do not enable images inside Herdr panes.
closes#10573
Try 53692 first so forwarded setups keep working, then let the OS pick a
free loopback port when 53692 cannot be bound (e.g. Hyper-V/WSL port
exclusions on Windows). The authorize URL, paste prompt and token exchange
use the bound redirect URI.
closes#10571
Open the manager before startup connections finish and keep connection actions in the background. Serialize reconnects and replacements, wait for current readiness, and resolve the active connection when executing tools.
Adds the openai-decisions classifier API with gpt-6-luna on the openai provider. bool questions map to predicates with the criteria in the instructions, refusals fail the result, and gateway timeouts (504) are not retried. The model needs an API key and is hidden from availability while openai uses Sign in with ChatGPT.
Adds optional images to ClassifierContext. Models without image input and APIs that cannot send images return an error result. Codemode's models.classify() accepts images.
Moves the shared classifier HTTP code out of system-one-shared.ts into classifier-shared.ts.
Text items get ==> text N/M <== headers when there are several, and
console output is grouped into one <console_output> block. Console text
items are marked with console: true.
The idle check reads settings.contextRetentionMs from commit listeners,
reconciliation, and the expiry timer. A throwing settings getter escaped as an
unhandled rejection; it is now reported and the kept contexts are dropped.
runtime.context() keeps each conversation's last read range and derived
view. A later read by any of the conversation's tasks with the same head
marker scans and derives only the entries committed since, so a
generation no longer rereads and re-derives the whole transcript for
each model request. Busy conversations keep the range; idle ones for
settings.contextRetentionMs (default ten minutes), checked on task
changes and by one unreferenced timer where the runtime supports it.
Kept entries are frozen; each read returns its own view arrays.
Add openDurableObjectSqliteStorage(ctx.storage) in
@earendil-works/pi-durable/storage/sqlite/cloudflare: SQLite storage on
a SQLite-backed Cloudflare Durable Object, without per-row copies.
The faux provider's prompt-cache usage estimate compared the previous and
current prompt as two joined strings, character by character, on every
call. It now compares the prompts message by message and compares
characters only from the first differing message. Usage numbers are
unchanged.
A run's input is committed before the system prompt is rendered, so requests
started with the user message. Anthropic then sent the tool list at the top of
every request and each tool change invalidated the whole prompt cache. Context
derivation now moves a system message preceded only by user messages to the
front. A live e2e test gates the cache reuse across a tool change.
closes#10542
Replaces the WeakMap workaround. streamProxy and the agent and coding-agent test
mocks reimplemented AssistantMessageEventStream as plain EventStream subclasses;
they now use createAssistantMessageEventStream().
The response timing added private fields, which made test and host streams built on
EventStream no longer assignable to StreamFn. Keep the start in a WeakMap instead.
pi-ai's AssistantMessageEventStream sets AssistantMessage.durationMs with a
monotonic clock for every API implementation. The agent loop and the durable
tool task set ToolResultMessage.durationMs around execute(). Durable task
records carry startedAt/endedAt stamped by the Session. The coding agent's bash
renderer shows Took from the recorded duration, also after a reload.
closes#10549
buildAdditionalModelRequestFields only handled Claude, so the configured
thinking level never reached OpenAI models on Bedrock and they always ran at
Bedrock's default effort. gpt-oss now gets the flat reasoning_effort, clamped
to low/medium/high. Other GPT models (GPT-5.x, GPT-6) get nested
reasoning.effort, with minimal sent as low since Bedrock rejects it.
closes#9331
Increase estimated input size to leave more room when calculating
output limits. Verified against OpenRouter DeepSeek V4 Flash: the
same large input now succeeds with an explicit output limit.
Fixes#10497
runtime.context() keeps the range its last read scanned for the task
invocation. A later read with the same conversation and head marker scans
only entries committed after that range's tail and re-derives the view in
memory. A generation's request no longer rereads the whole transcript after
its prepare. The range is dropped when the invocation ends or sleeps.
Selection coordinates survived session switches and other transcript rebuilds, highlighting unrelated text in the new transcript. Reset selection and multi-click state before re-rendering session entries.
Based on #9310.
fixes#9311
Co-authored-by: xdagiz <xdagiz@protonmail.com>
A --tools list of only +name/-name entries changes the default tool
selection like the defaultTools setting, e.g. pi -t +codemode. Mixed
lists and patterns in modifiers are rejected, and /reload keeps tools
removed with -name removed.
StreamOptions.headers documents that caller values override provider
defaults, and every other provider applies model/caller headers after its
User-Agent default. The Codex provider set originator and User-Agent after
merging caller headers, so they could not be overridden. Set the defaults
first; Authorization and chatgpt-account-id stay fixed.
Co-authored-by: Lucas Meijer <308974+lucasmeijer@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: David Brailovsky <davidbrai@gmail.com>