Detect prompt cache misses per turn by comparing each assistant message's
cache reads against the previous request's prompt tokens (core/cache-stats.ts).
Significant misses emit a warning-colored transcript notice at the turn they
occur, noting idle gaps past the cache TTL and model switches when relevant.
/session gained cache statistics: a compact token/cache breakdown with hit
rate, a $-prefixed cost section with per-model cost breakdown, and the
cumulative cost re-billed due to cache misses.
Updates GitHub Copilot built-in model metadata so models with GitHub's extended 1M capability use contextWindow 1000000 in Pi, preventing early compaction and under-budgeting for Claude Opus 4.7/4.8 and GPT-5.3 Codex/5.4/5.5.
Verified against raw docs markdown extended-capabilities table and live /models reports.
closes#6439
Export both session storage implementations from @earendil-works/pi-agent-core
so they can be imported and extended directly instead of via repo workaround.
closes#6435
in cases where forking a session was not immediate due to extensions
slowing down teardown, it's possible for the user to select the
message to fork more than once and then create multiple session forks.
in this fix we close the forking menu before starting the fork process
to not allow such behavior.
fixes#6321
* copy native clipboard .node files to the clipboard package
under the bun binary packaging, require("@mariozechner/clipboard-linux-x64-gnu")
doesn't work so instead we rely on require("./clipboard.linux-x64-gnu.node")
for that we need to copy the .node files to the clipboard package dir
* fallback to xclip if native clipboard fails on x11
Allow callers to attach an opaque JSON object to the session header so
application context needed to rebuild a harness (for example an agent
profile reference) is readable from the first line alone, without
scanning session entries. The field is optional and ignored by readers
that do not use it; fork inherits the source metadata unless overridden.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Use the new provider-specific Xiaomi Token Plan catalogs from models.dev instead of cloning the API-billing Xiaomi catalog into every token-plan region. This removes API-billing-only models such as mimo-v2-omni from xiaomi-token-plan-{cn,ams,sgp}.
* fix(ai,agent): stop salvaging malformed tool-call argument JSON
Finalized tool-call arguments must strict-parse (allowing only lossless
string-escape repair). When the streamed JSON is truncated or malformed,
the raw JSON is preserved on ToolCall.malformedArguments, arguments
become {}, and the agent loop refuses to execute the call with an error
tool result instead of running it with silently salvaged partial
arguments. Partial parsing is now only used for streaming previews.
* fix(agent): fail tool calls from length-truncated assistant messages
Reverts the malformed-arguments tracking approach in favor of handling
truncation in the agent loop: when an assistant message stops with
"length", all tool calls in it are potentially borked (streamed
arguments are salvage-parsed), so none are executed. Each gets an error
tool result telling the model to re-issue the call, and the loop
continues. No new fields on ToolCall and no provider changes.
fixes#6284
* feat(coding-agent): add before_provider_headers extension hook
Extensions can already rewrite the request payload through before_provider_request, but there is no way to adjust the outgoing HTTP
headers of a provider call. This hook fills that gap for cases like request tracing, session correlation, or tenant routing.
Handlers mutate the headers map in place - a null value deletes a header - and the return value is ignored, so a handler cannot accidentally drop auth or attribution headers by
forgetting to spread.
* docs(coding-agent): document before_provider_headers extension hook
Add the before_provider_headers section and lifecycle-diagram entry to
extensions.md; drop the now-superseded proposal file.
OpenAI Completions and Responses providers unconditionally replaced empty
tool result text with "(see attached image)", even when the result had no
image content. This caused the model to hallucinate image attachments for
commands that produce no output (e.g. curl -s with SSL errors, grep with
no matches, true/false).
Now matches the Google provider behavior: "(see attached image)" is only
used when images are actually present; empty results get "(no tool output)".
Co-authored-by: tzwm <tzwm@users.noreply.github.com>
Co-authored-by: Mario Zechner <badlogicgames@gmail.com>
* feat(coding-agent): add InlineExtension type for named inline extension factories
* test(coding-agent): update utilities and add regression test for InlineExtension
The Message types require content to always be present, but untyped JS
extension tools, hand-built histories, and old or hand-edited session
files can violate that contract, crashing rendering, compaction, and
provider request conversion with 'content is not iterable'.
Normalize null/missing content to an empty array at the ingestion
boundaries instead of guarding every consumer:
- transformMessages (choke point before every provider request)
- createToolResultMessage in the agent loop
- session entry loading (message and custom_message entries)
- extension custom messages (sendCustomMessage, before_agent_start)
- message_end extension replacements
fixes#6259, fixes#6276
The uuidv7 prefix is timestamp-derived and nearly constant between calls, so slicing the first 8 chars degenerated short ids to full-UUID fallbacks. Regression from 80c918c2 which replaced randomUUID with uuidv7.
Switch vitest packages (ai, agent, coding-agent) to the dot reporter
with silent: passed-only so passing tests stay quiet while failing
tests still print their console output and full diffs. Add the
github-actions reporter on CI for inline annotations. Switch the tui
node:test runner to the dot reporter as well.
GitHub's device flow documents slow_down as a rate limit: a poll that
arrives inside the throttle window is answered with slow_down instead of
the token, and the response's interval field reports the new required
minimum ("adds 5 seconds to the last interval"). A client that only
tracks its own +5s increment can stay behind the server's ratcheting
requirement when its timers fire early - common with WSL/VM clock drift
(microsoft/WSL#10006) - so every subsequent poll keeps hitting the rate
limit and login appears to hang forever even after the browser reports
the device as authorized.
Adopt the server-provided interval when a slow_down poll result carries
one, falling back to the RFC 8628 section 3.5 +5s increment otherwise.
GitHub Copilot passes the interval field through.
This restores part of the #1994 mitigations that were lost in the #4788
device-code refactor.
refs #6187
The question extension tool blocks on ctx.ui.custom() but omitted
executionMode, so multiple question calls in one assistant turn ran
under the default parallel mode and raced on the editor slot. Only the
last question rendered; earlier calls hung pending forever.
Set executionMode: "sequential" so the agent loop serializes the
batch. Wrappers already propagate the field to the core.
closes#6189