Versioned request-header restoration metadata inside v10 cache rows so only markers written by the old id-only matcher can bypass an unrestorable marker through requestModelId. Current aliases whose live headers differ from their static base remain unresolved and are refetched or dropped.
Added catalog and startup-registry regressions for custom-header aliases while preserving legacy Copilot -1m cache recovery.
Fixes#6284
Copilot -1m long-context variants are synthesized with transport
headers and a requestModelId to a bundled base. The v10 cache omits
headers; the writer only matched a same-id static entry, so these
variants were flagged unrestorable and dropped on the next offline
read, vanishing from the picker with a "Could not restore model"
warning. The startup registry loader dropped them the same way.
Restore/match headers through requestModelId in the cache writer, the
model-manager restore path, and the coding-agent startup loader, and
bypass a stale unrestorable marker written by the old id-only writer.
Fixes#6284
- Parsed live named efforts, mandatory-thinking state, and model protocol metadata.
- Sent native Kimi named efforts and adaptive Anthropic override efforts without generic token budgets.
Fixes#5893
Recorded which cached model ids had headers omitted and which header sets cannot be reconstructed from current static inputs.
Fresh/offline cache reads now restore exact static headers before returning models. Dynamic-only or dynamically-augmented header models bypass fresh-cache reuse and refetch online; offline and failure fallbacks omit them instead of returning unusable models without required transport headers.
Bumped the cache schema to v10 and added static, dynamic, offline, and raw-persistence regressions.
Fixes#5780
Replaced the incomplete credential-header denylist with a default-deny cache boundary: no model header values are persisted because custom providers may use arbitrary authentication header names.
Bumped the cache schema to v9 and enabled SQLite secure_delete so older header-bearing rows are invalidated without leaving credential bytes in free pages. Added coverage for X-Goog-Api-Key, X-Access-Token, arbitrary headers, and physical scrubbing of pre-v9 cache rows.
Fixes#5780
Native /login and /logout (plus setup-wizard sign-in and RPC login)
refreshed model discovery with the default all-provider
online-if-uncached strategy, which reused a fresh authoritative cache row
and never re-ran fetchDynamicModels with the just-persisted credential,
so newly authenticated models stayed unavailable in-session and stale
endpoint data survived a relogin. Each auth-completion path now awaits a
provider-scoped refreshProvider(providerId, "online").
Also fixed writeModelCache serializing credential-bearing request headers
(Authorization, X-Api-Key, api-key, cookie, proxy-authorization) into the
plaintext models.db; they are now stripped before persistence and
re-derived on load from AuthStorage / provider config.
Fixes#5780
Replace the v2->current version UPDATE with a DELETE that clears every row not matching the active schema, so cache-schema bumps actually invalidate stale entries (including pre-V2 Codex rows that still lack remoteCompaction.v2StreamingEnabled).
Fixes#4146
Bump the model cache schema so fresh authoritative OpenAI Codex rows written before V2 remote compaction metadata are ignored and refreshed.
Add coverage for legacy cache rows that would otherwise skip Codex discovery and keep the legacy compaction path.
Fixes#4146
Fix all Windows-specific test failures caused by path handling problems
and EBUSY errors from unclosed SQLite database handles.
Root causes fixed:
1. POSIX path assumptions: replaced hard-coded file:///tmp, /repo, etc.
with pathToFileURL/path.resolve/path.join computed expectations
2. shortenPath() now normalizes backslashes to forward slashes after ~
and respects home directory boundaries
3. HistoryStorage.resetInstance() leaked its Database — added #close()
that finalizes all prepared statements and closes the DB
4. AgentStorage gained the same resetInstance()/#close() pattern
5. SqliteAuthCredentialStore.close() leaked one-off prepared statements
from inline this.#db.prepare() calls — wrapped each in try/finally
6. model-cache.ts used a process-global DB even for custom dbPath —
now opens/closes per-call via withModelCacheDb
7. createAgentSession leaked AuthStorage on construction failure —
added ownsAuthStorage cleanup in catch block
8. MnemopiBackend.removeDbFiles() now truly best-effort (catches errors)
9. TempDir retry window expanded from 4x10ms to 40x25ms
10. TempDir prefix convention: non-@ prefixes created dirs relative to
cwd instead of os.tmpdir() — all test temp dirs now use @ prefix
11. Shell-escaped interpolated paths in bash tool tests
12. git core.autocrlf false in autoresearch test repo init
All 522 previously-failing Windows tests now pass.
- Enabled Antigravity request envelopes to include requestId/labels and per-attempt responseId state.
- Enabled budget transport to send `thinkingBudget` and capped `maxOutputTokens` 65_536 for Gemini calls.
- Added budget-aware model profiles for Gemini flash/pro variants and updated effort routing expectations.
- Refreshed variant collapse to separate Gemini and Antigravity tables and heal stale snapshots.
- Applied a finite 64,000-token fallback for OpenAI completion requests when model maxTokens is unavailable.
- Refactored stream max-token computation to use a shared helper and preserve a finite cap when caller and model limits are null.
- Added regression coverage for null maxTokens flows and bumped the model-cache schema to invalidate entries using retired unknown-limit sentinels.
Concurrent omp --session restores after an unclean shutdown crashed
in SqliteAuthCredentialStore.#initializeSchema() with
SQLITE_BUSY_RECOVERY because the multi-statement schema run installed
PRAGMA busy_timeout=5000 AFTER PRAGMA journal_mode=WAL, the first
lock-taking statement during WAL recovery. Bun's default busy_timeout
is 0, so the lock conflict surfaces immediately.
- packages/ai/src/auth-storage.ts: hoisted PRAGMA busy_timeout to a
standalone first statement, dropped it from the multi-statement
schema run, wrapped SqliteAuthCredentialStore.open() in a 4-attempt
exponential-backoff retry loop on the SQLITE_BUSY family, and the
exhausted-retry error now includes the DB path. Exported
isSqliteBusyError(err) (matches code prefix 'SQLITE_BUSY').
- packages/coding-agent/src/session/agent-storage.ts: same hoist and
the existing retry loop now uses isSqliteBusyError so
SQLITE_BUSY_RECOVERY / _SNAPSHOT / _TIMEOUT also trigger backoff.
- Hoisted busy_timeout before journal_mode=WAL in every other shared
SQLite open path: history-storage, autoresearch/storage,
memories/storage, github-cache, report-tool-issue (auto-QA),
catalog/model-cache; stats/db.ts now sets busy_timeout at all.
- packages/ai/test/auth-storage-sqlite-busy.test.ts pins the contract:
isSqliteBusyError matches every BUSY extended code (rejects
SQLITE_LOCKED, non-errors, strings); open() leaves the connection in
WAL mode (proves busy_timeout ran before journal_mode); open() retries
through synthetic SQLITE_BUSY_RECOVERY; non-BUSY errors (SQLITE_CORRUPT)
short-circuit; exhausted retries throw an error mentioning the DB path
with exactly 3 sleeps for a 4-attempt budget.
Fixes#2421
- Added `variant-collapse.ts`: hand-table collapsing for providers exposing one logical model as several effort/thinking-suffixed upstream ids (Antigravity CCA `gemini-3.5-flash-extra-low`/`-low`/`gemini-3-flash-agent`, `gemini-3[.1]-pro-low|high`, `claude-*[-thinking]` pairs, `gpt-oss-120b-medium`) plus the automatic `X`/`X-thinking` pair rule (`deriveThinkingPairFamilies`), gated on same api and compatible pricing; exported from the package barrel and covered by `variant-collapse.test.ts`.
- Added `ThinkingConfig.effortRouting` and `suppressWhenOff` to `types.ts`, and `resolveWireModelId(model, effort)` to `model-thinking.ts` so request-time code resolves the outbound wire id while selection, caching, and usage attribution key on the logical id.
- Wired collapsing at every materialization point: Antigravity discovery (`collapseEffortVariants`, dropping `gemini-2.5-flash-thinking`/`gemini-3-pro-low` from the discovery denylist), the model-manager merge and cache paths (`collapseBuiltModelVariants`), and the catalog generator post-pass (`collapseEffortVariantsAcrossProviders`).
- Exempted collapsed specs from `applyGeneratedModelPolicies` re-derivation via `isVariantCollapsedSpec`, bumped the model cache schema to v5 to invalidate rows carrying raw member ids, and changed the `google-antigravity` default model from `gemini-3-pro-high` to `gemini-3.1-pro`.
- Recorded the catalog changelog block; its display-name-cleaning entry and the adjacent `cleanModelName` import in `generate-models.ts` belong to the upcoming name-cleaning commit but share contiguous changed runs with this one.
- Replaced minLevel/maxLevel range with explicit efforts array plus baked effortMap/supportsDisplay wire facts.
- Removed runtime enrichment layer and modelOmitsReasoningEffort; providers now read baked fields.
- Fixed dotted Opus 4.7/4.8 ids missing adaptive display via classifier-based predicates (#1373).
- Bumped model cache schema to v4 to invalidate pre-efforts rows.
- Centralized catalog and registry handling on `ModelSpec` and `buildModel`, resolving compatibility at model build time.
- Removed runtime compatibility detectors and switched provider request flows to direct `model.compat` reads.
- Added compat fields (`supportsReasoningParams`, `alwaysSendMaxTokens`, `strictResponsesPairing`, `whenThinking`).
- Persisted explicit compatibility overrides through `compatConfig` in discovery and cache merge paths.
Move bundled models, model cache/manager, thinking metadata, effort helpers,
provider descriptors/discovery, wire constants, and model identity utilities
into the new @oh-my-pi/pi-catalog package.
Update pi-ai to keep provider runtime/auth concerns, move catalog provider
metadata into CATALOG_PROVIDERS, and migrate coding-agent, agent, stats, docs,
and tests to import catalog values from pi-catalog.
Split coding-agent model registry helpers into discovery, roles, and models
config modules while preserving registry orchestration.
BREAKING CHANGE: @oh-my-pi/pi-ai no longer exports catalog subpaths such as
/models, /model-cache, /model-manager, /model-thinking, /effort,
/provider-models*, discovery helpers, and provider wire constants; use the
matching @oh-my-pi/pi-catalog subpaths instead.