Repository navigation
Releases: sky-valley/pi
Release list
v0.99.26 — tracking pi 0.99.2
Tracks pi 0.99.2 (upstream pin 5806068c2).
Highlights
- Anthropic workload identity federation: sign in with your identity token, no API key needed.
- Tools with bounded numbers or formats no longer break Anthropic strict mode.
- Every built-in tool schema now matches what pi sends, byte for byte.
Details
Upstream sync 3dd803d7e → 5806068c2 (pi 0.99.2). 50 changes on the union
range, 45 first-parent (merge 8f89293a2 carries the async-SQLite PR). 30
port — 26 of them added to the Scope queue — 20 n/a, 0 decide. One release
crossed (v0.99.2), confirmed by an explicit tag fetch and by
packages/ai/package.json.
Catalog: regenerated by executing JSON.stringify(MODELS) against the 0.99.2
build, after first reproducing the outgoing 0.99.1 catalog byte for byte.
1,523 → 1,529 models (+6, −0) across an unchanged 42 providers, 862,603 →
867,163 B: Claude Sonnet 5.5 and GPT-6.1 Sol on Bedrock, GPT-6.1 Sol on GitHub
Copilot (on Responses) and OpenCode, DeepSeek V4.1 Flash Fast on Baseten;
prices and limits moved for 24 more. No thinking-level, compat or api change.
This cycle:
- Anthropic workload identity federation. With
ANTHROPIC_FEDERATION_RULE_ID,ANTHROPIC_ORGANIZATION_IDand
ANTHROPIC_IDENTITY_TOKEN_FILEset (and no key), the anthropic provider
exchanges the identity token for a short-lived access token exactly as
Anthropic's SDK 0.124.0 does, shares it across requests, refreshes it
before it expires and drops it on a 401. Keys andANTHROPIC_AUTH_TOKEN
keep precedence;ANTHROPIC_SERVICE_ACCOUNT_IDand
ANTHROPIC_WORKSPACE_IDride along when set. - Bounded tools no longer break Anthropic strict mode. A strict-prefer
tool whose schema uses a keyword Anthropic's strict mode rejects (minimum,
maximum,maxItems,uniqueItems, an unlistedformat, …) is sent
non-strict instead of failing the whole request; a strict-require tool
fails naming the keyword. - An unreadable Retry-After backs off. A
Retry-Afteror
retry-after-msthat is not a finite delay falls back to the exponential
backoff instead of retrying at once or failing fast. - Tool schemas as pi sends them. A schema serializes in TypeBox's key
order (a decoded one in its own), and keyword values its typed fields
cannot hold are kept rather than dropped. Every built-in tool schema now
matches pi's byte for byte — which also fixed read/ls/find/grep declaring
their numeric parametersintegersince the port began; pi's arenumber. - The CLI starts without an API key when the provider is configured
another way (ANTHROPIC_AUTH_TOKEN, federation), gating on the provider's
auth check as pi does.
Queued for later slices: MCP (10 deltas, row 21), the durable harness
(Packages 19–23 and async SQLite storage, row 8), codemode, tool
orchestration, the remote catalog, virtual models, and Anthropic's headless
copy-code login (row 1).
Differential harness: re-pinned to 0.99.2 and 5806068c2 at 66 PASS / 0
KNOWN / 0 FAIL, all 66 against the published build, with a new scenario for
the Anthropic strict-keyword fallback.
v0.99.25 — tracking pi 0.99.1
Tracks pi 0.99.1 (upstream pin 3dd803d7e).
Highlights
- Fresh model catalog from pi 0.99.1: Claude Sonnet 5.5 and GPT-6.1 Sol, now the Codex default.
- Tools return structured results, and a script calling the bash tool gets up to 1 MiB of its output.
- Watch every raw provider stream event as it arrives, and Sign in with ChatGPT requests go out the way OpenAI accepts them.
Breaking: ai.Models gains the all-model accessors, and its Login takes a trailing *LoginOptions, as OAuthAuth.Login does (pass nil). ai.MergeSamplingParams is gone; the adapters merge sampling params themselves. chord/delta.Track returns the tracker without an error.
Details
Upstream sync 4259686d9 → 3dd803d7e (pi 0.99.1). 37 changes on the union
range, equal to first-parent (no merges). 15 port, 22 n/a, 0 decide. Two
releases crossed (v0.99.0 and v0.99.1), confirmed by an explicit tag fetch
and by packages/ai/package.json. First tag since v0.87.24, so it also
publishes the 09-24 → 09-29 cycles (pins 8676a0dcd, 49681e1b7,
2b0a123de, 6f7551516, 4259686d9), which crossed no release.
Catalog: regenerated by executing JSON.stringify(MODELS) against the 0.99.1
build, after first reproducing the outgoing 0.87.1 catalog byte for byte.
41 → 42 providers (typesafe, which serves only classifiers), 1,495 →
1,523 models (+59, −31), 823,821 → 862,603 B. Every entry is now typed
("type":"chat"). It drains the catalog-only queue 9 → 0: Claude Sonnet
5.5, GPT-6.1 Sol (off is not a level: OpenAI rejects effort "none"), and
OpenCode's qwen3.8-flash replaying empty thinking signatures.
This cycle:
- Sign in with ChatGPT requests. A request to OpenAI itself with a
credential that is not ansk-key leaves out the fields token sharing
rejects (max_output_tokens,temperature, the prompt-cache retention
settings). A usage-limit failure points at the ChatGPT usage page, and it
is not retried; the two temporary sign-in errors are.Models.Loginpasses
app options (LoginOptions, a device ID) to a provider's OAuth flow. The
sign-in flow itself waits on Scope queue row 1. - Scripts get the whole bash output. A shell tool's structured result
holds up to 1 MiB of output, not the model's 2000-line/50 KB view. Longer
output keeps its first and last 512 KiB around an omission marker, with
truncatedandfull_output_path. - Shell output decoded as pi decodes it. A leading byte-order mark is
dropped, invalid bytes show as U+FFFD per malformed sequence, and the
display limits count the decoded text. Before, the port kept raw bytes. - A full output that cannot be saved fails the call, with the cause and
how to fix it, rather than handing a script cut-off output marked
complete. pi can crash or hang there instead (D90). - GPT-6.1 Sol is the Codex default.
From the untagged cycles:
- Provider stream events.
StreamOptions.OnProviderStreamEventsees each
raw provider event, in order, before pi normalizes it (anthropic,
pi-messages, openai completions and responses, google), and the session
forwards them to observers. Porting it brought each adapter's stream
reading, error text and aborts in line with pi's SDKs. - OpenAI SDK 7.19.0. Stream reading, error bodies, header-name checks and
the 300 s headers timeout follow the SDK version pi now ships. - Structured tool results. Tools return structured content and error
results.agent.RunToolCallruns a tool call through the agent's hooks,
and nested calls are recorded on the result, the groundwork for codemode. - Model types.
ai.Model.Type, andModelsaccessors across chat, image
and classifier models; sessions refuse a non-chat model. - Pricing and defaults. 1-hour cache writes reported mid-stream are
priced, OpenAI's "fast" tier is priced like priority, and Kimi K3 is the
default on Fireworks, OpenCode Go and Together. A directStreamcall
applies the model's sampling defaults too. - Sessions are written to disk at the first user message, as pi writes
them. - chord takes pi's immutable delta tracker and the reset subscription
update.
Breaking: ai.Models gains the all-model accessors (GetAllModels,
GetModelsOfType, GetModelOfType, GetAllAvailable, GetAvailableOfType),
and its Login takes a trailing *LoginOptions, as OAuthAuth.Login does
(pass nil). ai.MergeSamplingParams is gone; the adapters merge sampling
params themselves. chord/delta.Track returns the tracker without an error,
and ValueError is an alias of the JSON value error.
Differential harness: re-pinned to 0.99.1 and 3dd803d7e at 65 PASS / 0
KNOWN / 0 FAIL, all 65 against the published build. The two src
scenarios flipped to dist, two sign-in scenarios were added, and the
OpenAI-endpoint scenarios use sk- keys so they keep covering the fields a
sign-in token drops.
v0.87.24 — tracking pi 0.87.1
Tracks pi 0.87.1 (upstream pin b313731b8).
Highlights
- Fresh model catalog from pi 0.87.1: Claude Opus 5.5, GPT-6 Sol and Luna, new Copilot models, and Grok 4.7 as the xAI default.
- Compaction done right: pi's refusal-proof summary prompts,
/newstarts clean, and resumed sessions pick up their compaction where they left off. - chord gets pi's new immutable delta tracker, and costs now match pi to the last bit on Apple Silicon.
Breaking: chord/delta's mutable tracker is gone, as upstream removed it — Track(root, opts...), State, Flush/Rebase/Discard/Dirty and WithMaxOverlapScan. Use Track(initial) → BeginChange() → Change.Prepare() → Tracker.Adopt(). Index and PathID are now int64.
Details
Upstream sync 95fbc0499 → b313731b8 (pi 0.87.1). 21 changes on the union
range, 19 first-parent — upstream's durable branch now carries the
first-parent line, so triage ran on the union. 11 port, 10 n/a, 0 decide.
One release crossed (v0.87.1), confirmed by an explicit tag fetch and by
packages/ai/package.json.
Catalog: regenerated by executing JSON.stringify(MODELS) against the 0.87.1
build, after first reproducing the outgoing 0.87.0 catalog byte for byte. 41
providers (unchanged), 1,445 → 1,495 models (+62, −12, 35 changed),
791,953 → 823,821 B. It drains the catalog-only queue 1 → 0: Claude Opus
5.5 (Anthropic and Copilot, effort up to max), GPT-6 Sol and Luna (OpenAI
and Copilot; reasoning off sends none), and Grok 4.7 with its long-context
price tiers, now the xai default.
Behaviour:
- Compaction prompts. The split-turn summary request uses pi's new
checkpoint wording and# Conversation/# Instructionsframing, which
upstream adopted to stop model refusals, and the summarization system
prompt says "AI assistant", as pi's has since v0.79.0. An empty summary is
kept and an aborted one discarded, as in pi. /newand resume.Session.ResetandLoadHistorykept the old
compaction, so the first request after/newsent the previous
conversation's summary and dropped the new prompt. Resuming a session file
now resumes its compaction (Session.LoadBranch): the next compaction
updates the stored summary instead of re-summarizing it as a user turn, and
usage recorded before a compaction no longer triggers another one.- Costs match pi to the last bit on arm64. Go fused multiply-adds in
ai.CalculateCostand Responses service-tier pricing, so about 1 in 6
computed costs differed from pi's in the final digit. - Anthropic reports Claude Code 2.1.280.
chord/deltagets pi's immutable tracker.Trackreturns aTracker;
BeginChangehands out aDraft,Prepareyields the ops,Adopt
commits them (PrepareReplacefor whole values).DiffRevisionsand
Overlapare exported, and the package builds on 32-bit.
Breaking: upstream deleted chord's mutable tracker, so chord/delta's
Track(root, opts...), State, Flush/Rebase/Discard/Dirty and
WithMaxOverlapScan are gone. Use Track(initial) →
BeginChange() → Change.Prepare() → Tracker.Adopt(). Index and PathID
are now int64.
Queued: packages/durable and the pico3 half of the tracker change (entry 8),
chord's replicated-state services (entry 11), and pi's three-point compaction
trigger timing (entry 12). difftest re-pinned to 0.87.1 / b313731b8: 60
PASS / 0 KNOWN / 0 FAIL, all 60 against the published build.
v0.87.23 — tracking pi 0.87.0
Tracks pi 0.87.0 (upstream pin 95fbc0499).
Highlights
- Fresh model catalog from pi 0.87.0: Grok 4.7 routes, image input limits on every vision model, and strict tool support that's opt-in per model.
- New agent loop hooks:
FinishTurnto end or extend a run,PrepareRequestto reshape each provider request. - Sessions honour
context_editentries, and tool-call text now matches pi exactly (no more escaped&&in replayed history).
Breaking: ShouldStopAfterTurn is removed (upstream removed it) — use FinishTurn returning agent.TurnEnd; ShouldStopAfterTurnContext is now AgentTurnContext.
Details
Upstream sync 8bfef4de8 → 95fbc0499 (pi 0.87.0). 17 changes; the union and
first-parent ranges agree. 7 port, 10 n/a, 0 decide. One release crossed
(v0.87.0), confirmed by an explicit tag fetch and by packages/ai/package.json.
Catalog: regenerated by executing JSON.stringify(MODELS) against the 0.87.0
build, after first reproducing the outgoing 0.86.1 catalog byte for byte. 41
providers (unchanged), 1,443 → 1,445 models (+4 — three Grok 4.7 routes and
Hy4-preview — −2, 1,270 changed), 667,778 → 791,953 B. It drains the
catalog-only queue 2 → 0: every one of the 960 vision models now carries
its image input limits (at exactly the resize profile the port already used,
so no resize decision moves), and strict tool support is stamped explicitly on
the 620 capable openai-completions models.
Behaviour:
- Strict tool support is opt-in. openai-completions no longer assumes an
OpenAI-compatible endpoint acceptsstricton tools; the catalog opts
capable models in. Measured per model, no catalog model's request
changes — only hand-built models without the compat key stop sending it. - Agent loop hooks.
FinishTurnruns after the assistant message and tool
results, beforeturn_end, and can end the run or ask for exactly one more
request;PrepareRequestruns before every provider request and can swap
the context, model or thinking level;PeekQueuedMessagespreviews the next
queued batch.ShouldStopAfterTurnis gone, as upstream removed it. - Session files honour
context_edit. An append-only edit can omit or
replace an earlier message in future model context without touching raw
history; retain-none compaction and the newest-compaction-only rule match
pi.SessionTree.BuildProjectionexposes each message's source entry. - Tool-call text is JSON.stringify's. Replayed tool-call arguments on
openai-completions and Responses, the compaction summary prompt, and token
estimates used to carry Go's\u0026-style escapes for&,<and>—
somake && ./runreached the model's history escaped, and tool schemas
over-counted tokens. Fixed across the board. - Smaller fixes: text files starting with "GIF" read as text, not images;
image-only user messages on openai-completions drop the empty text part some
providers reject;chord/deltagains them(permute) op.
Breaking: agent.AgentOptions.ShouldStopAfterTurn /
AgentLoopConfig.ShouldStopAfterTurn are removed and ShouldStopAfterTurnContext
is renamed AgentTurnContext. Use FinishTurn returning agent.TurnEnd (skip
error/aborted turns to keep the old normal-response-only behaviour).
Queued: the SessionManager/AgentSession half of the context-boundary work
(entry 12), chord's transactional replicated state (entry 11), and the Grok 4.7
default, which waits for the model to reach the catalog. difftest re-pinned to
0.87.0 / 95fbc0499: 60 PASS / 0 KNOWN / 0 FAIL.
v0.86.22 — tracking pi 0.86.1
Tracks pi 0.86.1 (upstream pin f5c946480).
Highlights
- Meta (with Muse) and Radius join the providers — 41 providers, 1,443 models.
- System prompts and tool loadouts can change mid-conversation on Anthropic, OpenAI and OpenAI Responses.
--continuereopens the session you last worked in, not just the newest one created; images are resized to each model's own limits.
Breaking: coding.ResizeImageDecision takes a *ai.ModelImageResizeOptions (mirrors pi's resizeImage).
Details
Upstream sync 590144609 → f5c946480 (pi 0.86.1). 46 changes in the union
range — first-parent shows 41 and hides five real mainline commits that arrive
as merge second parents, one of them a change this release ports. 10 port,
8 port-but-queued, 1 port-but-catalog, 27 n/a, 0 decide. Two release tags
crossed (v0.86.0 and v0.86.1). Neither showed up in git tag --contains until
the tags were fetched explicitly — the sync fetches origin main, which does not
bring them — so the version in packages/ai/package.json at each sha is what
confirmed them.
Catalog: regenerated by executing JSON.stringify(MODELS) against the 0.86.1
build, after first proving the method by reproducing the outgoing 0.85.1
catalog byte for byte. 39 → 41 providers (Meta and Radius), 1,354 →
1,443 models (+145, −56, 767 changed), 592,846 → 667,778 B. It drains the
catalog-only queue 10 → 1; every queued row landed as predicted, measured
per row — mid-conversation system-message support on 63 models, session
affinity on OpenRouter and Baseten, allowEmptySignature on Vercel AI Gateway
and Fireworks, 57 re-derived thinking maps, the DeepSeek Flash collapse, and
github-copilot/gpt-6-astra moving onto the Responses API.
Behaviour:
--continuereopens the session you last wrote to. It used to rank
sessions by the header timestamp, which is written once at creation, so a
session made minutes ago outranked one resumed and worked in all morning.
LatestSessionnow mirrors pi'sfindMostRecentSession: file mtime, lazy
header reads. Tied session listings also come back in pi's order.- Images are resized to the model's own profile as they enter the
transcript — at the read tool, on tool results, and (new) on images passed to
Session.Run, whose conversion and resize notes now reach the user text
instead of being dropped.Model.InputLimitscarries the profile; no model
sets one until the next regen, which will stamp the port's own historical
2000px / 4.5 MiB defaults onto every vision model. - Compaction no longer stalls when the trailing tool results alone exceed
the keep budget: the cut falls back to the assistant call that produced them
instead of keeping everything. - Cerebras is no longer sent
stricton tools, which it rejects. - Meta joins the providers with
META_API_KEY; its Muse subscription
sign-in is queued with the rest of OAuth acquisition. Model.PromptCachecarries prompt-cache lifetimes (14 Anthropic models); the
cache warmer that consumes them is queued.- Base64 decoding matches Node: stop at the first
=. Concatenated,
separately padded chunks used to decode to all of them — or, worse, to bytes
from neither. - The image scale note rounds like JS. "Multiply coordinates by N" rounded
exact ties to even wheretoFixedrounds them up, so a 2250px image read 1.12
instead of pi's 1.13 — about 20px off across a 2000px screenshot. LatestSession("", dir)applies no cwd filter, as pi's
findMostRecentSessiondoesn't for an empty cwd (SDK callers only).- API break (sanctioned, mirrors pi's
resizeImage):
coding.ResizeImageDecisiontakes a*ai.ModelImageResizeOptions.
Verification: every behaviour change observed red for a behavioural reason
first; all 12 commits green on their own. Three review gates found 9 issues, 3
of them filed by two gates, and every one reproduced before it was fixed. The
one worth knowing about: the new image-resize getter read the session's model
without the lock SetModel needs, a data race for any embedder that switches
models mid-turn — fixed before release, with a -race test. One finding is
recorded rather than fixed (K20: under a narrowed maxBytes, resize dimensions
differ from pi's because Go's encoders and Photon's differ in output size; not
live until a provider narrows it). Two carried oracles came due and were
re-captured from the build — the Responses HTTP-error table (now an oracle for
provider labels across all 35 rows) and the Anthropic response-model capture,
whose behavioural entries came back byte for byte. Differential harness
re-pinned to 0.86.1 / f5c946480 at 58 PASS / 0 KNOWN / 0 FAIL — after
fixing the harness itself, which had been feeding the new build a context shape
it no longer accepts and turned 46 scenarios red in one bump.
v0.85.21 — tracking pi 0.85.1
Tracks pi 0.85.1 (upstream pin 9767ba275).
Highlights
- Built-in tools (read, bash, powershell, edit, write) now prefer strict sampling by default — no more
PI_EXPERIMENTALgate. - GPT-5.6+ models use
prompt_cache_options: {ttl: "30m"}for long prompt caching;:maxnow parses as a thinking level in--model. - Model catalog regenerated from pi-ai 0.85.1: 1,354 models across 39 providers.
Breaking: coding.GetExperimentalToolSampling() is removed, following upstream — see migration below.
Details
Upstream sync 744a94d7d → 9767ba275 (pi 0.85.1). 19 first-parent changes, no
merge-smuggled commits: 3 ports, 2 port-but-catalog (the release commits), 1
port-but-queued, 13 n/a, 0 decide. Two release tags crossed (v0.85.0 and
v0.85.1), so the catalog was regenerated by executing JSON.stringify(MODELS)
against dist/models.generated.js on both npm builds rather than by reading
git, and endpoint-pinned at both ends — the outgoing catalog is byte-identical
to a fresh 0.84.4 derivation and the incoming one to a fresh 0.85.1 derivation,
so the committed diff is provably the upstream release diff. It drains the
catalog-only queue 7→0 (all seven queued deltas plus this cycle's gpt-6-astra
generator half are ancestors of the v0.85.1 tag). All four recorded regen
tripwires were checked: allowedFallbackModels entries still carry provider
so billing is unaffected, 4e69b0c28's OpenRouter reroute is live (15
anthropic/* models on anthropic-messages, :batch correctly excluded), 21
surviving models changed thinkingLevelMap, and grok-build-0.1 is gone.
Behaviour: strict sampling is now the default for built-in tools. Upstream
deleted PREFER_STRICT_TOOL_SAMPLING and the PI_EXPERIMENTAL gate that fed
it, so read, bash, powershell, edit and write carry
constrainedSampling: {json_schema, prefer} on every request rather than only
under an opt-in env var; grep, find and ls stay unconstrained. This changes the
tool definitions every request carries, not just experimental ones.
AreExperimentalFeaturesEnabled survives as published SDK surface even though
its only port-side consumer went with the gate.
Also: GPT-5.6+ models (anything with supportsExplicitPromptCacheMode) now own
long prompt-cache retention through prompt_cache_options: {ttl: "30m"} and
must not also send prompt_cache_retention: "24h", which stays the older
models' spelling — the port had been emitting both. And
defaultModelPerProvider["radius"] moves auto→balanced, the split-by-hunk
site the ledger flags as having caused a missed port twice; it fired correctly
this time.
One pre-existing parity bug was found by the cycle's own review and fixed
rather than deferred: validThinkingLevels carried six of pi's seven
VALID_THINKING_LEVELS, missing max. The port had taken the ai-side half of
upstream fbdd46389 and missed the resolver-side list, so
--model anthropic/claude-opus-4-8:max did not parse :max as a thinking
suffix — it resolved to a synthesized custom model whose id was literally
claude-opus-4-8:max, with a spurious "not found for provider" warning. The
covering test looped over six levels where upstream loops over seven, so it
pinned the omission instead of catching it; and because it only walked the
custom-id path — where a missing level is indistinguishable from a real custom
id — it could not have caught this at all. Both were fixed.
Breaking change. coding.GetExperimentalToolSampling() is removed. It
returned the strict-sampling config only when PI_EXPERIMENTAL=1 and nil
otherwise; upstream deleted both it and the constant behind it, and the mirror
ruling is that upstream deletes, we delete — no shim, no deprecation window.
Migration: if you called it to mirror the gate, drop the call, because the
built-in tools now carry that config unconditionally. If you wanted the value
itself, construct it — &ai.ConstrainedSamplingConfig{Type: ai.ConstrainedSamplingJSONSchema, Strict: ai.ConstrainedSamplingPrefer}.
AreExperimentalFeaturesEnabled() is unaffected and still exported.
Nothing else left the public surface. protocol.ValidationError and
protocol.Validator moved to internal/jsonstrict during the 2026-09-03
layering work but remain as type aliases with the same shape, so
&protocol.ValidationError{Msg: …} and protocol.Validator still compile —
verified against this tag, not assumed.
This tag rolls up more than its own cycle. It is the first release since
v0.84.20 (2026-08-29), and no tag was cut on 2026-09-01, 09-02, 09-03 or 09-04
because none of those cycles crossed an npm bump. So v0.85.21 also publishes
25 commits of earlier work: the chord delta + core layers and protocol v8
envelopes (both additive, beside v1), the Phase 0 parity ports, per-key compat
key resolution, the supportsMaxOutputTokens gate, the preflight-abort fix, and
the three answered dependency consults (Bedrock, Codex, session-backends) with
their mechanically-enforced dependency policy test. Those are described in
UPSTREAM.md and in their own commits; this entry covers the 09-07 cycle.
The differential harness is 51/51 dist-backed for the first time since the
0.84.2 era: 0.85.1 shipped both surfaces that had been holding 14 scenarios on
TypeScript source — supportsMaxOutputTokens and 4e69b0c28's beta-namespace
migration, which moves betas out of the header — so every scenario is once
again checked against the published build. 51 PASS / 0 KNOWN / 0 FAIL with an
empty known-divergence baseline. This also closes the Anthropic betas/URL
caveat the pin has carried since 2026-09-04.
v0.2.7 — models-runtime migration complete (pi-ai 0.80.2)
A pure-Go port of earendil-works/pi — the pi-ai unified LLM API, pi-agent-core agent loop, and pi-coding-agent, native in Go (no Node.js runtime).
Synced to upstream pi pin a2e3e9d8 / npm @earendil-works/pi-ai 0.80.2.
Highlights
- Models-runtime migration complete — auth substrate (credential store, provider auth, OAuth-under-lock), Models runtime (Provider interface,
CreateModels/CreateProvider,BuiltinModels), request-scoped auth resolution, andapi_key/envcredential alignment. - Catalog → 0.80.2 — 999 models across 35 providers, regenerated byte-identical from the integrity-verified npm build.
- OpenAI Responses terminal-event guard — no more silently-truncated streams.
- anthropic compat sourced from the catalog (no provider sniffing); header-only client auth; Vercel gateway routing ungated.
Every change byte-verified against the real pi npm build — 0 parity divergences, -race green. Full per-commit detail in docs/UPSTREAM.md; release history in docs/RELEASES.md.