feat(coding-agent): merge origin/main into model runtime facade
This commit is contained in:
@@ -8,69 +8,56 @@
|
||||
- Removed redundant `ModelRuntime.getAll()`, `find()`, `getSnapshot()`, and `getAuthOptions()` projections. Use the pi-ai `Models` methods `getModels()`, `getModel()`, `getProviders()`, and `checkAuth()` directly.
|
||||
- Replaced SDK request-auth assembly through `ModelRegistry.getApiKeyAndHeaders()` with `ModelRuntime.getAuth()`. Passing a provider ID returns provider-scoped auth; passing a model also resolves built-in, `models.json`, and extension model headers.
|
||||
- Changed extension-facing `ModelRegistry.refresh()` from synchronous `void` to `Promise<void>` because `models.json` loading is asynchronous. Extensions must await it before making synchronous registry reads.
|
||||
- Removed extension OAuth `modifyModels`. Provider catalogs are now composed independently of credentials; credential-specific availability belongs to canonical provider filtering. The legacy extension OAuth callback and credential types remain available from pi-ai's root and `oauth` subpath.
|
||||
- Moved canonical dynamic catalog refresh to async `ModelRuntime.refresh()`/pi-ai `Models.refresh()`. Legacy extension OAuth `modifyModels` remains supported as a synchronous compatibility projection after credential initialization.
|
||||
- Removed the `openai-responses` `compat.sendSessionIdHeader` flag from `models.json`. Session-affinity behavior is now controlled by `compat.sessionAffinityFormat` (`"openai"`, `"openai-nosession"`, or `"openrouter"`). Replace `sendSessionIdHeader: false` with `sessionAffinityFormat: "openai-nosession"` ([#6366](https://github.com/earendil-works/pi/issues/6366)).
|
||||
|
||||
#### SDK migration
|
||||
|
||||
Construct one `ModelRuntime` and pass it to `createAgentSession()`:
|
||||
|
||||
```typescript
|
||||
// Before
|
||||
const authStorage = AuthStorage.create(authPath);
|
||||
const modelRegistry = await ModelRegistry.create(authStorage, modelsPath);
|
||||
authStorage.setRuntimeApiKey("anthropic", apiKey);
|
||||
const { session } = await createAgentSession({ authStorage, modelRegistry });
|
||||
|
||||
// After
|
||||
const modelRuntime = await ModelRuntime.create({ authPath, modelsPath });
|
||||
// Or: ModelRuntime.create({ credentials: myCredentialStore, modelsPath })
|
||||
modelRuntime.setRuntimeApiKey("anthropic", apiKey);
|
||||
const { session } = await createAgentSession({ modelRuntime });
|
||||
```
|
||||
|
||||
Replace `ModelRegistry` projections with the corresponding `ModelRuntime`/pi-ai `Models` methods:
|
||||
|
||||
```typescript
|
||||
const allModels = modelRuntime.getModels();
|
||||
const model = modelRuntime.getModel(providerId, modelId);
|
||||
const availableModels = await modelRuntime.getAvailable();
|
||||
const authStatus = await modelRuntime.checkAuth(providerId);
|
||||
const requestAuth = await modelRuntime.getAuth(model); // Includes model headers
|
||||
|
||||
modelRuntime.registerProvider(providerId, providerConfig); // Still synchronous
|
||||
await modelRuntime.reloadConfig();
|
||||
```
|
||||
|
||||
`ModelRuntime.stream*()` resolves auth and configured headers itself. Do not call `getAuth(model)` before streaming merely to reconstruct request options. For SDK-level header interception, use the Models-only transform so auth is resolved once:
|
||||
|
||||
```typescript
|
||||
modelRuntime.streamSimple(model, context, {
|
||||
transformHeaders: async (headers) => ({
|
||||
...headers,
|
||||
"X-Request-ID": requestId,
|
||||
}),
|
||||
});
|
||||
```
|
||||
|
||||
Use `ModelRuntime` for model lookup, availability, provider auth, login/logout, runtime API-key overrides, provider registration, and config refresh. `ModelRegistry` remains a synchronous-read compatibility facade for extensions; SDK code should use `ModelRuntime`. Extensions that explicitly refresh it must await completion:
|
||||
|
||||
```typescript
|
||||
await ctx.modelRegistry.refresh();
|
||||
const models = ctx.modelRegistry.getAll();
|
||||
```
|
||||
### New Features
|
||||
|
||||
- **Cache-friendly dynamic tool loading** - Extensions can add tools during execution while supported Anthropic and OpenAI Responses models preserve prompt-cache prefixes. See [Dynamic Tool Loading](docs/extensions.md#dynamic-tool-loading).
|
||||
- **Message copy shortcut** - `Ctrl+X` copies the last assistant message in the transcript or the selected message in `/tree`, making older and branched messages directly copyable. See [Display and Message Queue](docs/keybindings.md#display-and-message-queue).
|
||||
- **Fable 5 `xhigh` and `max` thinking** - Native `xhigh` and `max` thinking levels are available across generated provider catalogs. See [Model Options](docs/usage.md#model-options).
|
||||
|
||||
### Added
|
||||
|
||||
- Added `ModelRuntime` as the canonical async SDK and internal model/auth facade while preserving the synchronous extension-facing `ModelRegistry` API. `ModelRuntime.create()` accepts any pi-ai `CredentialStore` through its `credentials` option.
|
||||
- Added provider-owned `/login` discovery directly from registered pi-ai providers, including ambient auth status and informational links.
|
||||
- Added the opt-in `max` thinking level across CLI, SDK, RPC, model selection, and themes. Custom themes can define `thinkingMax`; existing themes fall back to `thinkingXhigh`.
|
||||
- Added request-wide input-token pricing tiers to custom model costs in `models.json`, `modelOverrides`, and extension-registered providers.
|
||||
- Added file-backed dynamic catalogs in `models-store.json`, per-provider pi.dev catalog overlays, and Radius gateway support including offline migration from legacy credential-cached catalogs.
|
||||
- Added cache-friendly dynamic tool loading for extension tools activated by tool results. Supported Anthropic and OpenAI Responses models load definitions where they become available, preserving the cached prompt prefix. See [Dynamic Tool Loading](docs/extensions.md#dynamic-tool-loading) ([#6474](https://github.com/earendil-works/pi-mono/pull/6474)).
|
||||
- Added inherited native `xhigh` and `max` thinking levels for Claude Fable 5 across all generated provider catalogs ([#6490](https://github.com/earendil-works/pi-mono/pull/6490) by [@davidbrai](https://github.com/davidbrai)).
|
||||
- Added `Ctrl+X` to copy the last assistant message, or the selected message in `/tree`.
|
||||
|
||||
### Changed
|
||||
|
||||
- Changed `ModelRuntime` to compose built-in providers, immutable `models.json` configuration, and extension overlays through ad-hoc pi-ai provider methods.
|
||||
- Changed `ModelRuntime` to own final request assembly: `getAuth(model)` includes configured model headers, stream methods resolve auth once, and `before_provider_headers` runs as the Models-only header transform before provider dispatch.
|
||||
- Changed `/model` to render the current model snapshot immediately, refresh configured providers in the background, and update the open selector with partial results or timeout errors.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed inherited OpenRouter model context windows to use the top provider's actual context length ([#6481](https://github.com/earendil-works/pi-mono/pull/6481) by [@davidbrai](https://github.com/davidbrai)).
|
||||
- Fixed inherited OpenRouter OpenAI-compatible session IDs to use the `x-session-id` header instead of OpenAI-specific session-affinity fields ([#6366](https://github.com/earendil-works/pi/issues/6366)).
|
||||
- Fixed `Ctrl+V` to paste clipboard text when the pasteboard does not contain an image.
|
||||
- Fixed `/login amazon-bedrock` to prompt for and save a Bedrock API key instead of only displaying ambient AWS credential setup instructions.
|
||||
|
||||
## [0.80.6] - 2026-07-09
|
||||
|
||||
### New Features
|
||||
|
||||
- **`max` thinking level** - New opt-in thinking level above `xhigh`, natively supported on GPT-5.6 and adaptive Claude models, available across CLI (`--thinking max`), SDK, RPC, and model selection. Custom themes can define `thinkingMax`. See [CLI Reference](docs/usage.md#cli-reference).
|
||||
- **Input-based pricing tiers** - Request-wide input-token pricing tiers for accurate long-context cost accounting (e.g. GPT-5.4/5.5/5.6 long-context rates), also configurable for custom models in `models.json` and `modelOverrides`. See [Model Configuration](docs/models.md#model-configuration).
|
||||
|
||||
### Added
|
||||
|
||||
- Added the opt-in `max` thinking level across CLI, SDK, RPC, model selection, and themes. Custom themes can define `thinkingMax`; existing themes fall back to `thinkingXhigh`.
|
||||
- Added request-wide input-token pricing tiers to custom model costs in `models.json`, `modelOverrides`, and extension-registered providers.
|
||||
- Added `~` (home directory) expansion for the `shellPath` setting ([#6470](https://github.com/earendil-works/pi/pull/6470) by [@aaronkyriesenbach](https://github.com/aaronkyriesenbach)).
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed inherited post-compaction output-token budgeting to ignore stale assistant usage from before the compaction boundary ([#6464](https://github.com/earendil-works/pi/issues/6464)).
|
||||
- Fixed inherited GPT-5.4 and GPT-5.5 long-context cost accounting while retaining the intentional 272K default context limit for models that require an explicit override.
|
||||
- Fixed inherited GPT-5.6 metadata to keep direct OpenAI requests in the 272K short-context tier while exposing the Codex backend's 372K context window with long-context pricing, and removed the nonexistent bare `gpt-5.6` alias.
|
||||
- Fixed inherited Anthropic message conversion to preserve thinking blocks with empty thinking text but a valid signature instead of dropping them, avoiding thinking-block errors on newer Claude models ([#6457](https://github.com/earendil-works/pi/pull/6457) by [@davidbrai](https://github.com/davidbrai)).
|
||||
|
||||
## [0.80.5] - 2026-07-09
|
||||
|
||||
|
||||
Reference in New Issue
Block a user