diff --git a/THIRD_PARTY_NOTICES.md b/THIRD_PARTY_NOTICES.md
index f9bd7afe4c..b863bd7258 100644
--- a/THIRD_PARTY_NOTICES.md
+++ b/THIRD_PARTY_NOTICES.md
@@ -139,7 +139,7 @@ External packages installed for runtime use or distributed inside the prebuilt b
pnpm applies local patches to the following packages at install time, so shipped artifacts carry modified copies; each patch file is the complete record of the modification:
-- `@earendil-works/pi-ai@0.85.1` — [`patches/@earendil-works__pi-ai@0.85.1.patch`](patches/@earendil-works__pi-ai@0.85.1.patch)
+- `@earendil-works/pi-ai@0.87.1` — [`patches/@earendil-works__pi-ai@0.87.1.patch`](patches/@earendil-works__pi-ai@0.87.1.patch)
- `@electron/osx-sign@1.3.3` — [`patches/@electron__osx-sign@1.3.3.patch`](patches/@electron__osx-sign@1.3.3.patch)
- `@fortune-sheet/core@1.0.4` — [`patches/@fortune-sheet__core@1.0.4.patch`](patches/@fortune-sheet__core@1.0.4.patch)
- `@fortune-sheet/react@1.0.4` — [`patches/@fortune-sheet__react@1.0.4.patch`](patches/@fortune-sheet__react@1.0.4.patch)
diff --git a/apps/cli/tests/profiles/headless/tests/fixtures/pi-ai-defaults.patch.yml b/apps/cli/tests/profiles/headless/tests/fixtures/pi-ai-defaults.patch.yml
index ec5e74d781..a14bbb4d37 100644
--- a/apps/cli/tests/profiles/headless/tests/fixtures/pi-ai-defaults.patch.yml
+++ b/apps/cli/tests/profiles/headless/tests/fixtures/pi-ai-defaults.patch.yml
@@ -16,7 +16,7 @@
baseURL: !!js process.env.DSH_SNAPSHOT_BASE_URL
reasoning: low
modelOverrides:
- deepseek-v4-flash:
+ deepseek-flash:
maxTokens: 1024
streamIdleTimeoutMs: 1000
@@ -25,7 +25,7 @@
agents:
- id: main
provider: deepseek
- model: deepseek-v4-flash
+ model: deepseek-flash
cwd: !!js process.cwd()
- id: agent-instructions
diff --git a/apps/cli/tests/profiles/headless/tests/headless.expected.e2e.ts b/apps/cli/tests/profiles/headless/tests/headless.expected.e2e.ts
index 33752b7812..d464f2863f 100644
--- a/apps/cli/tests/profiles/headless/tests/headless.expected.e2e.ts
+++ b/apps/cli/tests/profiles/headless/tests/headless.expected.e2e.ts
@@ -715,7 +715,7 @@ describe('headless stream-json snapshots', () => {
expect(header?.config).toMatchInlineSnapshot(`
{
"maxTokens": 1024,
- "model": "deepseek-v4-flash",
+ "model": "deepseek-flash",
"provider": "deepseek",
"reasoningEffort": "low",
}
diff --git a/apps/web/tests/expected/models-settings/empty.expected.md b/apps/web/tests/expected/models-settings/empty.expected.md
index 4ddb04a13b..5c2b5c0b72 100644
--- a/apps/web/tests/expected/models-settings/empty.expected.md
+++ b/apps/web/tests/expected/models-settings/empty.expected.md
@@ -33,6 +33,7 @@
- option "groq"
- option "huggingface"
- option "kimi-coding"
+ - option "meta"
- option "minimax"
- option "minimax-cn" [selected]
- option "mistral"
@@ -47,6 +48,7 @@
- option "qwen-token-plan"
- option "qwen-token-plan-cn"
- option "qwen-token-plan-individual"
+ - option "radius"
- option "together"
- option "vercel-ai-gateway"
- option "xai"
diff --git a/apps/web/tests/expected/onboarding-usable-provider/dismissed.expected.md b/apps/web/tests/expected/onboarding-usable-provider/dismissed.expected.md
index f955841948..e65df1f213 100644
--- a/apps/web/tests/expected/onboarding-usable-provider/dismissed.expected.md
+++ b/apps/web/tests/expected/onboarding-usable-provider/dismissed.expected.md
@@ -37,6 +37,7 @@
- option "groq"
- option "huggingface"
- option "kimi-coding"
+ - option "meta"
- option "minimax"
- option "minimax-cn" [selected]
- option "mistral"
@@ -51,6 +52,7 @@
- option "qwen-token-plan"
- option "qwen-token-plan-cn"
- option "qwen-token-plan-individual"
+ - option "radius"
- option "together"
- option "vercel-ai-gateway"
- option "xai"
diff --git a/packages/llm/llm-pi-ai/README.i18n.yaml b/packages/llm/llm-pi-ai/README.i18n.yaml
index 8afec3d794..19311117b6 100644
--- a/packages/llm/llm-pi-ai/README.i18n.yaml
+++ b/packages/llm/llm-pi-ai/README.i18n.yaml
@@ -54,8 +54,8 @@
en: 4da379c9be65c18a
zh: fd305d4bd3dfa452
/deepseek-ai-dsh-llm-pi-ai/understand-the-implementation/replay-and-vocabulary:
- en: ad7f22c0eba06eb0
- zh: 451ec5836425d7a1
+ en: 36e0c59a0f9f5980
+ zh: 90a62c4a9cd23429
/deepseek-ai-dsh-llm-pi-ai/further-exploration:
en: a2a2ccdeae59d408
zh: c47ee091aa90ad91
@@ -87,8 +87,8 @@
en: b6bd570c0159ba08
zh: 7d2d91eea6a8d830
/deepseek-ai-dsh-llm-pi-ai/known-limitations-and-deferred-work:
- en: b72e581a744cf2ab
- zh: d3b0bc7c8ec716fe
+ en: bb240ee5dd3f81c7
+ zh: 884506a36f4aac62
/deepseek-ai-dsh-llm-pi-ai/known-limitations-and-deferred-work/dev-note:
en: be67a4547256efbf
zh: 8c32799683ba292c
diff --git a/packages/llm/llm-pi-ai/README.md b/packages/llm/llm-pi-ai/README.md
index 7b1708b957..0e8a801b53 100644
--- a/packages/llm/llm-pi-ai/README.md
+++ b/packages/llm/llm-pi-ai/README.md
@@ -156,7 +156,7 @@ The plugin declares every installed catalog provider it can authenticate in the
### Replay and vocabulary
-Successful assistant responses store a versioned, lossless-JSON replay state beside the provider and model that produced them — response-level facts plus one per-block entry per streamed block. At request time, `LlmRuntime` passes replay state only when the same adapter instance owns both routes; the adapter validates it and restores native response ids, provider signatures, and optional `providerThinkingLevel` effort metadata, keeping absent effort metadata absent. Replay validates the requested model identity against the assistant source and separately restores an Anthropic response model when the provider resolved an alias or fallback. Absent or unusable replay state degrades to provider-neutral content while preserving the assistant source’s required provider and model. pi-ai tool-call arguments are parsed objects, so the adapter parses input and re-stringifies output to the harness raw-JSON convention; pi-ai in-stream error events map to terminal `finish` chunks.
+Successful assistant responses store a versioned, lossless-JSON replay state beside the provider and model that produced them — response-level facts plus one per-block entry per streamed block. At request time, `LlmRuntime` passes replay state only when the same adapter instance owns both routes; the adapter validates it and restores native response ids, provider signatures, and optional `providerThinkingLevel` effort metadata, keeping absent effort metadata absent. Replay validates the requested model identity against the assistant source and uses it to retain same-model signatures; provider-reported response models remain diagnostic metadata. Absent or unusable replay state degrades to provider-neutral content while preserving the assistant source’s required provider and model. pi-ai tool-call arguments are parsed objects, so the adapter parses input and re-stringifies output to the harness raw-JSON convention; pi-ai in-stream error events map to terminal `finish` chunks.
@@ -226,10 +226,10 @@ These limits define where the adapter stops and future work begins. They are cur
- **A modality declaration is not verified** — a model declaring `image` its gateway does not serve is refused by the provider after prompt admission. The durable image remains in history and the same misdeclared model can fail again; switching to a text-only model remains possible because the shared LLM runtime projects image references into stable text for that request.
- **An unauthenticated route depends on its protocol** — a route naming no credential resolves as configured-but-keyless, but pi-ai's OpenAI-compatible implementation still requires an API key or an `Authorization` header, so a keyless local server needs a placeholder credential referenced by `apiKeyEnv` or an `Authorization` entry in `headers`.
- **`GenerateOptions.stop` is unsupported** — pi-ai's common stream options cannot guarantee stop-sequence behavior across providers.
-- **Only a leading in-history `system` message becomes pi-ai's `systemPrompt`** — pi-ai has one system slot, so a later `system` message, or a leading one when `GenerateOptions.system` is also set, folds into a `user` message at its position; provider-specific placement of the prompt follows pi-ai rather than a harness-owned wire override. Images in system or assistant history, including the leading system message, fail with `UNSUPPORTED_CONTENT` on both conversion paths.
+- **Only a leading in-history `system` message becomes pi-ai's `systemPrompt`** — this adapter uses pi-ai's single `systemPrompt` input, so a later `system` message, or a leading one when `GenerateOptions.system` is also set, folds into a `user` message at its position; provider-specific placement of the prompt follows pi-ai rather than a harness-owned wire override. Images in system or assistant history, including the leading system message, fail with `UNSUPPORTED_CONTENT` on both conversion paths.
- **Provider HTTP status is unavailable** — pi-ai error events do not expose a stable HTTP status across providers.
- **Retry policy is provider-owned, not an SDK retry** — pi-ai SDK retries stay disabled so durable agent steps and `llm/retry` events own every visible attempt, and direct `ctx.llm.stream()` calls remain single-attempt.
-- **Streamed tool-call arguments are parsed once, when the call ends** — the installed pi-ai carries [`patches/@earendil-works__pi-ai@0.85.1.patch`](../../../patches/@earendil-works__pi-ai@0.85.1.patch), which removes the per-delta re-parse of the whole accumulated argument JSON in every stream adapter (upstream [earendil-works/pi#9265](https://github.com/earendil-works/pi/issues/9265)); unpatched, a multi-megabyte argument stream costs O(n²) CPU on the event loop and stalls every session in the process. Until `toolcall_end`, a pi-ai partial's tool-call `arguments` stays `{}`; this adapter reads only the delta strings and the finalized arguments. Re-apply or retire the patch on every pi-ai upgrade.
+- **Streamed tool-call arguments are parsed once, when the call ends** — the installed pi-ai carries [`patches/@earendil-works__pi-ai@0.87.1.patch`](../../../patches/@earendil-works__pi-ai@0.87.1.patch), which removes the per-delta re-parse of the whole accumulated argument JSON in every stream adapter (upstream [earendil-works/pi#9265](https://github.com/earendil-works/pi/issues/9265)); unpatched, a multi-megabyte argument stream costs O(n²) CPU on the event loop and stalls every session in the process. Until `toolcall_end`, a pi-ai partial's tool-call `arguments` stays `{}`; this adapter reads only the delta strings and the finalized arguments. Re-apply or retire the patch on every pi-ai upgrade.
### Dev Note
diff --git a/packages/llm/llm-pi-ai/README.zh.md b/packages/llm/llm-pi-ai/README.zh.md
index ed780ad235..5126fe25ed 100644
--- a/packages/llm/llm-pi-ai/README.zh.md
+++ b/packages/llm/llm-pi-ai/README.zh.md
@@ -156,7 +156,7 @@ Config 更新严格验证发生变化的 provider。初始加载将已存储的
### 回放与词汇
-成功 assistant 响应会存储带版本的、无损 JSON 回放状态,与产生它们的提供方和模型放在一起——响应级事实加每个流式块一条逐块条目。请求时,`LlmRuntime` 仅当同一适配器实例拥有两条路由时才传递回放状态;适配器校验它并恢复原生响应 id、提供方签名与可选的 `providerThinkingLevel` effort 元数据,缺失的 effort 元数据仍保持缺失。回放会对照 assistant 来源校验请求模型身份,并在提供方解析别名或回退时单独恢复 Anthropic 响应模型。回放状态缺失或无法使用时会降级为提供方无关内容,并保留 assistant 来源中必需的提供方和模型。pi-ai 工具调用参数是解析后的对象,因此适配器解析输入并重新字符串化输出,以符合 harness 原始 JSON 约定;pi-ai 流内错误事件映射为终止 `finish` 分片。
+成功 assistant 响应会存储带版本的、无损 JSON 回放状态,与产生它们的提供方和模型放在一起——响应级事实加每个流式块一条逐块条目。请求时,`LlmRuntime` 仅当同一适配器实例拥有两条路由时才传递回放状态;适配器校验它并恢复原生响应 id、提供方签名与可选的 `providerThinkingLevel` effort 元数据,缺失的 effort 元数据仍保持缺失。回放会对照 assistant 来源校验请求模型身份,并用它保留同模型签名;提供方报告的响应模型仅作为诊断元数据。回放状态缺失或无法使用时会降级为提供方无关内容,并保留 assistant 来源中必需的提供方和模型。pi-ai 工具调用参数是解析后的对象,因此适配器解析输入并重新字符串化输出,以符合 harness 原始 JSON 约定;pi-ai 流内错误事件映射为终止 `finish` 分片。
@@ -226,10 +226,10 @@ pi-ai 事件变成 harness 的推理、文本、工具调用、用量与 finish
- **模态声明不受校验**——声明 `image` 而其网关不支持的模型会在提示词准入后被提供方拒绝。持久图片仍留在历史中,同一误声明模型可能再次失败;切换到纯文本模型仍然可行,因为共享 LLM 运行时会针对该请求把图片引用投影为稳定文本。
- **未认证路由取决于其协议**——不点名凭据的路由解析为已配置但无密钥,但 pi-ai 的 OpenAI 兼容实现仍要求 API 密钥或 `Authorization` 标头,因此无密钥本地服务器需要由 `apiKeyEnv` 引用或 `headers` 中的 `Authorization` 条目提供的占位凭据。
- **不支持 `GenerateOptions.stop`**——pi-ai 的通用流式选项无法跨提供方保证停止序列行为。
-- **只有历史中首条 `system` 消息会成为 pi-ai 的 `systemPrompt`**——pi-ai 只有一个系统槽位,因此后续的 `system` 消息,或在同时设置了 `GenerateOptions.system` 时的首条消息,会在原位置折叠为 `user` 消息;系统提示词的提供方专属放置遵循 pi-ai,而非 harness 自有的协议覆盖。system 或 assistant 历史中的图片(包括首条系统消息中的图片)在两条转换路径上都会以 `UNSUPPORTED_CONTENT` 失败。
+- **只有历史中首条 `system` 消息会成为 pi-ai 的 `systemPrompt`**——本适配器使用 pi-ai 的单一 `systemPrompt` 输入,因此后续的 `system` 消息,或在同时设置了 `GenerateOptions.system` 时的首条消息,会在原位置折叠为 `user` 消息;系统提示词的提供方专属放置遵循 pi-ai,而非 harness 自有的协议覆盖。system 或 assistant 历史中的图片(包括首条系统消息中的图片)在两条转换路径上都会以 `UNSUPPORTED_CONTENT` 失败。
- **提供方 HTTP 状态不可用**——pi-ai 错误事件不跨提供方暴露稳定 HTTP 状态。
- **重试策略由提供方自有,而非 SDK 重试**——pi-ai SDK 重试保持禁用,因此持久 agent(智能体)步骤与 `llm/retry` 事件拥有每个可见尝试,直接 `ctx.llm.stream()` 调用仍是单次尝试。
-- **流式工具调用参数只在调用结束时解析一次**——安装的 pi-ai 带有 [`patches/@earendil-works__pi-ai@0.85.1.patch`](../../../patches/@earendil-works__pi-ai@0.85.1.patch),它移除了每个流适配器中对整段累计参数 JSON 的逐 delta 重新解析(上游 [earendil-works/pi#9265](https://github.com/earendil-works/pi/issues/9265));未打补丁时,数 MB 的参数流会在事件循环上消耗 O(n²) CPU,并使进程内所有会话停滞。在 `toolcall_end` 之前,pi-ai partial 的工具调用 `arguments` 保持为 `{}`;本适配器只读取 delta 字符串与最终参数。每次升级 pi-ai 时都要重新应用或撤销该补丁。
+- **流式工具调用参数只在调用结束时解析一次**——安装的 pi-ai 带有 [`patches/@earendil-works__pi-ai@0.87.1.patch`](../../../patches/@earendil-works__pi-ai@0.87.1.patch),它移除了每个流适配器中对整段累计参数 JSON 的逐 delta 重新解析(上游 [earendil-works/pi#9265](https://github.com/earendil-works/pi/issues/9265));未打补丁时,数 MB 的参数流会在事件循环上消耗 O(n²) CPU,并使进程内所有会话停滞。在 `toolcall_end` 之前,pi-ai partial 的工具调用 `arguments` 保持为 `{}`;本适配器只读取 delta 字符串与最终参数。每次升级 pi-ai 时都要重新应用或撤销该补丁。
### 开发备注
diff --git a/packages/llm/llm-pi-ai/package.json b/packages/llm/llm-pi-ai/package.json
index e186f0c3b9..129d3e744e 100644
--- a/packages/llm/llm-pi-ai/package.json
+++ b/packages/llm/llm-pi-ai/package.json
@@ -41,7 +41,7 @@
"@deepseek-ai/dsh-brand": "workspace:*",
"@deepseek-ai/dsh-util-values": "workspace:*",
"@deepseek-ai/schemastery": "workspace:~",
- "@earendil-works/pi-ai": "^0.85.1"
+ "@earendil-works/pi-ai": "^0.87.1"
},
"devDependencies": {
"@deepseek-ai/cordis": "workspace:~",
diff --git a/packages/llm/llm-pi-ai/src/catalog.ts b/packages/llm/llm-pi-ai/src/catalog.ts
index 191c77c0d2..9e626cc71f 100644
--- a/packages/llm/llm-pi-ai/src/catalog.ts
+++ b/packages/llm/llm-pi-ai/src/catalog.ts
@@ -20,6 +20,7 @@ import type {
BedrockCompat,
ChatTemplateKwargValue,
KnownApi,
+ MistralConversationsCompat,
Model,
ModelCost,
ModelThinkingLevel,
@@ -253,7 +254,8 @@ const COMPLETIONS_COMPAT_GATE = {
zaiToolStream: 'withhold',
supportsOpenAIGrammarTools: 'withhold',
sendSessionAffinityHeaders: 'withhold',
- deferredToolsMode: 'withhold',
+ supportsMidConvoSystemMessages: 'withhold',
+ supportsMidConvoToolAdditions: 'withhold',
sessionAffinityFormat: 'withhold',
} as const satisfies Record
@@ -268,6 +270,7 @@ const RESPONSES_COMPAT_GATE = {
supportsAdditionalTools: 'withhold',
supportsToolSearch: 'withhold',
supportsExplicitPromptCacheMode: 'withhold',
+ supportsMidConvoSystemMessages: 'withhold',
} as const satisfies Record
/** Disposition of every `AnthropicMessagesCompat` field; a drift gate like the one above. */
@@ -280,7 +283,9 @@ const ANTHROPIC_COMPAT_GATE = {
allowEmptySignature: 'offer',
supportsStrictTools: 'offer',
sendSessionAffinityHeaders: 'withhold',
- supportsToolReferences: 'withhold',
+ sessionAffinityFormat: 'withhold',
+ supportsMidConvoSystemMessages: 'withhold',
+ supportsMidConvoToolChanges: 'withhold',
supportsMidConvoEffort: 'withhold',
allowedFallbackModels: 'withhold',
} as const satisfies Record
@@ -290,6 +295,11 @@ const BEDROCK_COMPAT_GATE = {
supportsStrictMode: 'offer',
} as const satisfies Record
+/** Disposition of every `MistralConversationsCompat` field. */
+const MISTRAL_COMPAT_GATE = {
+ supportsMidConvoSystemMessages: 'withhold',
+} as const satisfies Record
+
/**
* Every wire protocol pi-ai gives a compat type. Derived from `Model.compat`'s
* own conditional rather than listed by hand, so a pi-ai release that gives a
@@ -309,6 +319,7 @@ type ApiWithCompat = { [K in KnownApi]: NonNullable['compat']> extends
* models declare.
*/
const COMPAT_GATES: Readonly>>> = {
+ 'mistral-conversations': MISTRAL_COMPAT_GATE,
'openai-completions': COMPLETIONS_COMPAT_GATE,
'openai-responses': RESPONSES_COMPAT_GATE,
'azure-openai-responses': RESPONSES_COMPAT_GATE,
diff --git a/packages/llm/llm-pi-ai/src/replay.ts b/packages/llm/llm-pi-ai/src/replay.ts
index 7df034522c..9012c56fca 100644
--- a/packages/llm/llm-pi-ai/src/replay.ts
+++ b/packages/llm/llm-pi-ai/src/replay.ts
@@ -10,7 +10,7 @@
import { LlmError } from '@deepseek-ai/dsh-llm'
import type { AssistantMessage as HarnessAssistantMessage, ModelMessageSource, ReplayEnvelope } from '@deepseek-ai/dsh-llm'
-import type { Api, AssistantMessage, Usage as PiUsage } from '@earendil-works/pi-ai'
+import type { Api, AssistantMessage, ToolCall, Usage as PiUsage } from '@earendil-works/pi-ai'
/** Per-block half of the pi-ai replay envelope, one entry per content block. */
export type PiAiReplayBlock =
@@ -26,7 +26,7 @@ export interface PiAiReplayResponse {
provider: string
/** Requested model identity, matching the durable assistant source. */
model: string
- /** Provider-reported model; only Anthropic replays it as the native model (reported in `message.model`, not `message.responseModel`). */
+ /** Provider-reported model; replay retains the requested model for signature matching. */
responseModel?: string
responseId?: string
/** Provider-native effort for historical replay; absence is preserved. */
@@ -41,11 +41,11 @@ interface PiAiReplayState {
}
/** Parse tool-call argument JSON; tolerate model malformations with {}. */
-function parseArguments(raw: string): Record {
+function parseArguments(raw: string): ToolCall['arguments'] {
try {
const parsed: unknown = JSON.parse(raw)
if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {
- return parsed as Record
+ return parsed as ToolCall['arguments']
}
} catch {
// fall through
@@ -75,15 +75,13 @@ function emptyPiUsage(): PiUsage {
* @returns the versioned lossless-JSON replay projection.
*/
export function toPiReplayState(message: AssistantMessage, requestedModel = message.model): ReplayEnvelope {
- const responseModel = message.api === 'anthropic-messages' && message.model !== requestedModel
- ? message.model : message.responseModel
const response: PiAiReplayResponse = {
kind: 'pi-ai',
version: 2,
api: message.api,
provider: message.provider,
model: requestedModel,
- ...responseModel === undefined ? {} : { responseModel },
+ ...message.responseModel === undefined ? {} : { responseModel: message.responseModel },
...message.responseId === undefined ? {} : { responseId: message.responseId },
...message.providerThinkingLevel === undefined ? {} : { providerThinkingLevel: message.providerThinkingLevel },
stopReason: message.stopReason,
@@ -221,9 +219,7 @@ function replayedAssistant(message: HarnessAssistantMessage, source: ModelMessag
content,
api: state.response.api,
provider: state.response.provider,
- // Anthropic reports aliases and fallbacks as model, unlike Completions' informational responseModel.
- model: state.response.api === 'anthropic-messages'
- ? state.response.responseModel ?? state.response.model : state.response.model,
+ model: state.response.model,
...state.response.responseModel === undefined ? {} : { responseModel: state.response.responseModel },
...state.response.responseId === undefined ? {} : { responseId: state.response.responseId },
...state.response.providerThinkingLevel === undefined ? {} : { providerThinkingLevel: state.response.providerThinkingLevel },
diff --git a/packages/llm/llm-pi-ai/tests/adapter.e2e.ts b/packages/llm/llm-pi-ai/tests/adapter.e2e.ts
index b9152f00aa..edb9a13165 100644
--- a/packages/llm/llm-pi-ai/tests/adapter.e2e.ts
+++ b/packages/llm/llm-pi-ai/tests/adapter.e2e.ts
@@ -13,7 +13,7 @@ import { assemble, type AssembledResult } from './assemble.ts'
* and exercises a replayed tool follow-up. Key-gated.
*/
-const FLASH = 'deepseek-v4-flash'
+const FLASH = 'deepseek-flash'
const contexts: Context[] = []
async function harness(_model: string, config: Partial = {}) {
diff --git a/packages/llm/llm-pi-ai/tests/adapter.spec.ts b/packages/llm/llm-pi-ai/tests/adapter.spec.ts
index 58b8d6afec..e99a753a6c 100644
--- a/packages/llm/llm-pi-ai/tests/adapter.spec.ts
+++ b/packages/llm/llm-pi-ai/tests/adapter.spec.ts
@@ -77,7 +77,7 @@ describe('PiAiAdapter provider routing', () => {
const server = await mockServer([{ events: textEvents }])
const ctx = await harness(server.url)
const result = await assemble(ctx, {
- model: 'deepseek-v4-flash',
+ model: 'deepseek-flash',
messages: [createUserMessage({
content: [{ type: 'text', text: 'hi' }],
source: { kind: 'model', provider: 'deepseek-official', model: 'deepseek-v4-flash' },
@@ -103,7 +103,7 @@ describe('PiAiAdapter provider routing', () => {
auth: memoryAuth(),
}))
- const prepared = await ctx.llm.prepareCall({ provider: 'deepseek', model: 'deepseek-v4-flash' })
+ const prepared = await ctx.llm.prepareCall({ provider: 'deepseek', model: 'deepseek-flash' })
providers = { deepseek: { apiKeyEnv: 'PI_TEST_KEY', baseURL: second.url } }
const chunks: unknown[] = []
for await (const chunk of prepared.stream({ ...prepared.config, messages: [] })) chunks.push(chunk)
@@ -118,7 +118,7 @@ describe('PiAiAdapter provider routing', () => {
const ctx = await harness(server.url, {
headers: { 'x-company': 'private', 'User-Agent': 'wrong' },
})
- await assemble(ctx, { model: 'deepseek-v4-flash', messages: [] })
+ await assemble(ctx, { model: 'deepseek-flash', messages: [] })
expect(server.headers[0]?.['x-company']).toBe('private')
expect(server.headers[0]?.['user-agent']).toBe(userAgent())
})
@@ -157,14 +157,14 @@ describe('PiAiAdapter provider routing', () => {
const ctx = await harness(server.url, { reasoning: 'max' })
await assemble(ctx, {
- model: 'deepseek-v4-flash',
+ model: 'deepseek-flash',
reasoningEffort: ReasoningEffortId('high'),
messages: [],
})
expect(server.requests[0]).toMatchObject({ reasoning_effort: 'high' })
await assemble(ctx, {
- model: 'deepseek-v4-flash',
+ model: 'deepseek-flash',
reasoningEffort: ReasoningEffortId('off'),
messages: [],
})
@@ -172,7 +172,7 @@ describe('PiAiAdapter provider routing', () => {
expect(server.requests[1]).not.toHaveProperty('reasoning_effort')
const unsupported = await assemble(ctx, {
- model: 'deepseek-v4-flash',
+ model: 'deepseek-flash',
reasoningEffort: ReasoningEffortId('xhigh'),
messages: [],
})
@@ -191,7 +191,7 @@ describe('PiAiAdapter provider routing', () => {
deepseek: { apiKeyEnv: 'PI_TEST_KEY', baseURL: server.url },
}))
- const result = await assemble(ctx, { model: 'deepseek-v4-flash', messages: [] })
+ const result = await assemble(ctx, { model: 'deepseek-flash', messages: [] })
expect(result.message.content).toEqual([{ type: 'text', text: 'hello' }])
})
@@ -215,7 +215,7 @@ describe('PiAiAdapter provider routing', () => {
it('reports unsupported stop sequences rather than silently ignoring them', async () => {
const server = await mockServer([])
const ctx = await harness(server.url)
- const result = await assemble(ctx, { model: 'deepseek-v4-flash', messages: [], stop: ['END'] })
+ const result = await assemble(ctx, { model: 'deepseek-flash', messages: [], stop: ['END'] })
expect(result.finish).toMatchObject({ kind: 'error', failure: { code: 'UNSUPPORTED_OPTION' } })
expect(server.requests).toEqual([])
})
@@ -383,14 +383,14 @@ describe('PiAiAdapter provider routing', () => {
] as const)('maps HTTP %s failures to %s', async (status, code) => {
const server = await mockServer([{ status, body: JSON.stringify({ error: { message: `provider ${status}` } }) }])
const ctx = await harness(server.url)
- const result = await assemble(ctx, { model: 'deepseek-v4-flash', messages: [] })
+ const result = await assemble(ctx, { model: 'deepseek-flash', messages: [] })
expect(result.finish).toMatchObject({ kind: 'error', failure: { code } })
expect(server.paths).toEqual(['/chat/completions'])
})
it('uses the resolved catalog context window for usage-based overflow detection', async () => {
- const model = getBuiltinModels('deepseek').find(candidate => candidate.id === 'deepseek-v4-flash')
- if (model === undefined) throw new Error('deepseek-v4-flash missing from pi-ai test catalog')
+ const model = getBuiltinModels('deepseek').find(candidate => candidate.id === 'deepseek-flash')
+ if (model === undefined) throw new Error('deepseek-flash missing from pi-ai test catalog')
const events = [
'{"choices":[{"delta":{"role":"assistant","content":""},"index":0,"finish_reason":null}]}',
JSON.stringify({
@@ -417,7 +417,7 @@ describe('PiAiAdapter provider routing', () => {
const server = await mockServer([{ events: textEvents, delayMs: 200 }])
const ctx = await harness(server.url, { streamIdleTimeoutMs: 20 })
- const result = await assemble(ctx, { model: 'deepseek-v4-flash', messages: [] })
+ const result = await assemble(ctx, { model: 'deepseek-flash', messages: [] })
expect(result.finish).toMatchObject({ kind: 'error', failure: { code: 'TIMEOUT' } })
await Promise.race([
server.responseClosed,
@@ -497,7 +497,7 @@ describe('provider profile lifecycle', () => {
providers: { deepseek: {}, openai: {} },
})
- await expect(ctx.llm.resolveModelInfo('deepseek', 'deepseek-v4-flash'))
+ await expect(ctx.llm.resolveModelInfo('deepseek', 'deepseek-flash'))
.resolves.toMatchObject({
reasoning: {
efforts: [
@@ -530,7 +530,7 @@ describe('provider profile lifecycle', () => {
await supported.plugin(LlmPiAi, {
providers: { deepseek: { reasoning: 'max' } },
})
- await expect(supported.llm.resolveModelInfo('deepseek', 'deepseek-v4-flash'))
+ await expect(supported.llm.resolveModelInfo('deepseek', 'deepseek-flash'))
.resolves.toMatchObject({ reasoning: { defaultEffort: ReasoningEffortId('max') } })
// A profile level this model cannot take DESCRIBES as no default rather
@@ -543,11 +543,11 @@ describe('provider profile lifecycle', () => {
await unsupported.plugin(LlmPiAi, {
providers: { deepseek: { reasoning: 'medium' } },
})
- const described = await unsupported.llm.resolveModelInfo('deepseek', 'deepseek-v4-flash')
+ const described = await unsupported.llm.resolveModelInfo('deepseek', 'deepseek-flash')
expect(described.reasoning?.defaultEffort).toBeUndefined()
expect(described.reasoning?.efforts.length).toBeGreaterThan(0)
await expect(assemble(unsupported, {
- provider: 'deepseek', model: 'deepseek-v4-flash', messages: [],
+ provider: 'deepseek', model: 'deepseek-flash', messages: [],
})).resolves.toMatchObject({
finish: { kind: 'error', failure: { code: 'UNSUPPORTED_REASONING_EFFORT' } },
})
@@ -557,7 +557,7 @@ describe('provider profile lifecycle', () => {
await disabled.plugin(LlmPiAi, {
providers: { deepseek: { reasoning: 'off' } },
})
- await expect(disabled.llm.resolveModelInfo('deepseek', 'deepseek-v4-flash'))
+ await expect(disabled.llm.resolveModelInfo('deepseek', 'deepseek-flash'))
.resolves.toMatchObject({ reasoning: { defaultEffort: ReasoningEffortId('off') } })
})
@@ -786,7 +786,7 @@ describe('provider profile lifecycle', () => {
// A profile that names no reference at all is the one case that defers to
// pi-ai's own provider-native discovery.
const ctx = await harness(server.url, { apiKeyEnv: undefined })
- await assemble(ctx, { model: 'deepseek-v4-flash', messages: [] })
+ await assemble(ctx, { model: 'deepseek-flash', messages: [] })
expect(server.headers[0]?.authorization).toBe('Bearer ambient-key')
})
@@ -794,7 +794,7 @@ describe('provider profile lifecycle', () => {
vi.stubEnv('PI_CUSTOM_REF_KEY', 'custom-ref-key')
const server = await mockServer([{ events: textEvents }])
const ctx = await harness(server.url, { apiKey: undefined, apiKeyEnv: 'PI_CUSTOM_REF_KEY' })
- await assemble(ctx, { model: 'deepseek-v4-flash', messages: [] })
+ await assemble(ctx, { model: 'deepseek-flash', messages: [] })
expect(server.headers[0]?.authorization).toBe('Bearer custom-ref-key')
})
@@ -806,9 +806,9 @@ describe('provider profile lifecycle', () => {
vi.stubEnv('DEEPSEEK_API_KEY', 'ambient-key')
const server = await mockServer([{ events: textEvents }])
const ctx = await harness(server.url, { apiKey: undefined, apiKeyEnv: 'PI_CUSTOM_REF_KEY' })
- const first = await assemble(ctx, { model: 'deepseek-v4-flash', messages: [] })
+ const first = await assemble(ctx, { model: 'deepseek-flash', messages: [] })
expect(first.finish).toMatchObject({ kind: 'error', failure: { code: 'MISSING_CREDENTIAL' } })
- const second = await assemble(ctx, { model: 'deepseek-v4-flash', messages: [] })
+ const second = await assemble(ctx, { model: 'deepseek-flash', messages: [] })
expect(second.finish.kind).toBe('error')
if (second.finish.kind !== 'error') throw new Error('expected an error finish')
expect(second.finish.failure.message).toMatch(/provider route "deepseek".*PI_CUSTOM_REF_KEY/s)
@@ -911,7 +911,7 @@ describe('provider profile lifecycle', () => {
await expect(drain({
provider: 'deepseek',
- model: 'deepseek-v4-flash',
+ model: 'deepseek-flash',
messages: [createUserMessage({
content: [{ type: 'image', attachment: IMAGE_REF }],
source: { kind: 'model', provider: 'deepseek-official', model: 'deepseek-v4-flash' },
@@ -956,7 +956,7 @@ describe('abort wiring', () => {
const drain = async (): Promise => {
for await (const _chunk of adapter.stream({
provider: 'deepseek',
- model: 'deepseek-v4-flash',
+ model: 'deepseek-flash',
messages: [message as never],
})) { /* drain */ }
}
@@ -977,7 +977,7 @@ describe('abort wiring', () => {
const drain = async (): Promise => {
for await (const _chunk of adapter.stream({
provider: 'deepseek',
- model: 'deepseek-v4-flash',
+ model: 'deepseek-flash',
messages: [message as never],
signal: controller.signal,
})) { /* drain */ }
@@ -993,7 +993,7 @@ describe('abort wiring', () => {
const chunks = []
for await (const chunk of adapter.stream({
provider: 'deepseek',
- model: 'deepseek-v4-flash',
+ model: 'deepseek-flash',
messages: [],
signal: controller.signal,
})) chunks.push(chunk)
@@ -1008,7 +1008,7 @@ describe('abort wiring', () => {
const ctx = await harness(server.url)
const controller = new AbortController()
controller.abort('already stopped')
- const result = await assemble(ctx, { model: 'deepseek-v4-flash', messages: [], signal: controller.signal })
+ const result = await assemble(ctx, { model: 'deepseek-flash', messages: [], signal: controller.signal })
expect(result.finish.kind).toBe('aborted')
})
@@ -1017,7 +1017,7 @@ describe('abort wiring', () => {
const ctx = await harness(server.url)
const controller = new AbortController()
const resultPromise = assemble(ctx, {
- model: 'deepseek-v4-flash', messages: [], signal: controller.signal,
+ model: 'deepseek-flash', messages: [], signal: controller.signal,
})
setTimeout(() => { controller.abort('stopped during stream') }, 10)
const result = await resultPromise
@@ -1027,7 +1027,7 @@ describe('abort wiring', () => {
it('aborts upstream when a consumer stops early', async () => {
const server = await mockServer([{ events: textEvents, delayMs: 30 }])
const ctx = await harness(server.url)
- for await (const chunk of ctx.llm.stream({ provider: 'deepseek', model: 'deepseek-v4-flash', messages: [] })) {
+ for await (const chunk of ctx.llm.stream({ provider: 'deepseek', model: 'deepseek-flash', messages: [] })) {
if (chunk.type === 'block-start') break
}
await new Promise(resolve => setTimeout(resolve, 20))
diff --git a/packages/llm/llm-pi-ai/tests/catalog.spec.ts b/packages/llm/llm-pi-ai/tests/catalog.spec.ts
index e574461018..e6f5330e9b 100644
--- a/packages/llm/llm-pi-ai/tests/catalog.spec.ts
+++ b/packages/llm/llm-pi-ai/tests/catalog.spec.ts
@@ -9,6 +9,7 @@ import { PiAiAdapter } from '@deepseek-ai/dsh-llm-pi-ai'
import type { ContextFormed } from '@deepseek-ai/dsh-llm'
import { getBuiltinModels } from '@earendil-works/pi-ai/providers/all'
import { AssistantMessageEventStream } from '@earendil-works/pi-ai/utils/event-stream'
+import { normalizeContext } from '@earendil-works/pi-ai/utils/transcript'
import type { Api, Model, OpenAICompletionsCompat, Provider } from '@earendil-works/pi-ai'
import { resolveProfiles } from '../src/config.ts'
import { createModels, createProvider, getSupportedThinkingLevels } from '../src/models.ts'
@@ -362,7 +363,7 @@ describe('hand-declared providers', () => {
auth: { apiKey: { name: 'Local', resolve: () => Promise.resolve({ auth: {}, source: 'Local' }) } },
api: { stream, streamSimple },
})
- const context = { messages: [] }
+ const context = normalizeContext({ messages: [] })
expect(provider.stream(model, context)).toBe(direct)
expect(provider.streamSimple(model, context)).toBe(simple)
@@ -545,7 +546,7 @@ describe('catalog routes with per-model configuration', () => {
if (built === undefined) throw new Error('the deepseek route built no provider')
const [model] = built.getModels()
if (model === undefined) throw new Error('the deepseek route resolved no models')
- const context = { messages: [{ role: 'user' as const, content: 'hi', timestamp: 0 }] }
+ const context = normalizeContext({ messages: [{ role: 'user', content: 'hi', timestamp: 0 }] })
// `stream` is interface-required and unused by the harness adapter, which
// only calls `streamSimple`; both must still reach the catalog provider.
@@ -1069,9 +1070,9 @@ describe('compat switches', () => {
it('refuses a valueless compat key on a model entry too', () => {
expect(() => resolveProfiles({
deepseek: {
- modelOverrides: { 'deepseek-v4-flash': { compat: { requiresReasoningContentOnAssistantMessages: null } } as never },
+ modelOverrides: { 'deepseek-flash': { compat: { requiresReasoningContentOnAssistantMessages: null } } as never },
},
- })).toThrow(/model "deepseek-v4-flash" sets compat "requiresReasoningContentOnAssistantMessages" with no value/)
+ })).toThrow(/model "deepseek-flash" sets compat "requiresReasoningContentOnAssistantMessages" with no value/)
})
it('serves the Responses compat type on every protocol pi-ai gives it to', () => {
@@ -1134,7 +1135,7 @@ describe('resolution snapshots', () => {
const inFlight = (async () => {
for await (const chunk of adapter.stream({
provider: 'deepseek',
- model: 'deepseek-v4-flash',
+ model: 'deepseek-flash',
messages: [],
})) chunks.push(chunk)
})()
@@ -1163,7 +1164,7 @@ describe('resolution snapshots', () => {
})
const drain = async (): Promise => {
for await (const _chunk of adapter.stream({
- provider: 'deepseek', model: 'deepseek-v4-flash', messages: [],
+ provider: 'deepseek', model: 'deepseek-flash', messages: [],
})) { /* drain */ }
}
diff --git a/packages/llm/llm-pi-ai/tests/compat-upgrade.spec.ts b/packages/llm/llm-pi-ai/tests/compat-upgrade.spec.ts
index 1dd72645cf..73fca353de 100644
--- a/packages/llm/llm-pi-ai/tests/compat-upgrade.spec.ts
+++ b/packages/llm/llm-pi-ai/tests/compat-upgrade.spec.ts
@@ -50,11 +50,21 @@ describe('pi-ai gateway compatibility declarations', () => {
expect(() => resolved(compat, 'anthropic-messages')).toThrow(/compat/)
})
- it.each(['supportsMidConvoEffort', 'allowedFallbackModels'])('withholds catalog-owned %s', (field) => {
+ it.each([
+ 'supportsMidConvoEffort', 'allowedFallbackModels', 'supportsMidConvoSystemMessages',
+ 'supportsMidConvoToolAdditions', 'supportsMidConvoToolChanges', 'sessionAffinityFormat',
+ ])('withholds catalog-owned %s', (field) => {
expect(() => resolved({ [field]: true }, 'anthropic-messages'))
.toThrow(/which is not configurable here/)
})
+ it('withholds Mistral conversation capabilities', () => {
+ expect(() => resolveProfiles({
+ mistral: { compat: { supportsMidConvoSystemMessages: true } as never },
+ }))
+ .toThrow(/which is not configurable here/)
+ })
+
it('keeps generic additions absent unless configured', () => {
expect(resolved({})).toBeUndefined()
})
diff --git a/packages/llm/llm-pi-ai/tests/convert.spec.ts b/packages/llm/llm-pi-ai/tests/convert.spec.ts
index 4ca36d762a..005c12596c 100644
--- a/packages/llm/llm-pi-ai/tests/convert.spec.ts
+++ b/packages/llm/llm-pi-ai/tests/convert.spec.ts
@@ -443,6 +443,33 @@ describe('toPiContext', () => {
expect(onDegrade).not.toHaveBeenCalled()
})
+ it('replays saved v2 Anthropic alias metadata with the requested model and signed thinking', () => {
+ const requestedModel = 'claude-haiku-4-5'
+ const responseModel = 'claude-haiku-4-5-20251001'
+ const replayState = {
+ response: {
+ kind: 'pi-ai', version: 2, api: 'anthropic-messages', provider: 'anthropic',
+ model: requestedModel, responseModel, stopReason: 'stop',
+ },
+ blocks: [{ type: 'reasoning', thinkingSignature: 'saved-signature' }],
+ }
+ const onDegrade = vi.fn()
+ const context = toPiContext({
+ provider: 'anthropic', model: requestedModel,
+ messages: [createMessage({
+ role: 'assistant', content: [{ type: 'reasoning', text: 'saved reasoning' }],
+ source: { kind: 'model', provider: 'anthropic', model: requestedModel, replayState },
+ })],
+ }, undefined, onDegrade)
+ const model = getBuiltinModels('anthropic').find(candidate => candidate.id === requestedModel)
+ if (model === undefined) throw new Error('missing Anthropic catalog model')
+ expect(onDegrade).not.toHaveBeenCalled()
+ expect(context.messages[0]).toMatchObject({ model: requestedModel, responseModel })
+ expect(transformMessages(context.messages, model)[0]).toMatchObject({
+ content: [{ type: 'thinking', thinking: 'saved reasoning', thinkingSignature: 'saved-signature' }],
+ })
+ })
+
it('replays all native block kinds when optional metadata is absent', () => {
const state = toPiReplayState(assistant({
content: [
@@ -660,11 +687,12 @@ describe('toPiContext', () => {
describe('toStreamChunks', () => {
it.each([
['claude-haiku-4-5', 'claude-haiku-4-5-20251001'],
- ['claude-fable-5', 'claude-opus-5'],
- ['claude-opus-5', 'claude-opus-5'],
- ])('replays Anthropic request %s with native response model %s', async (requestedModel, returnedModel) => {
+ ['claude-opus-5', 'kimi-for-coding'],
+ ['claude-opus-5', undefined],
+ ])('retains signed thinking for Anthropic request %s reported as %s', async (requestedModel, reportedModel) => {
const native = assistant({
- api: 'anthropic-messages', provider: 'anthropic', model: returnedModel,
+ api: 'anthropic-messages', provider: 'anthropic', model: requestedModel,
+ ...reportedModel === undefined ? {} : { responseModel: reportedModel },
providerThinkingLevel: 'high',
content: [{ type: 'thinking', thinking: 'reason', thinkingSignature: 'signed' }],
})
@@ -674,8 +702,10 @@ describe('toStreamChunks', () => {
const finish = chunks.find(chunk => chunk.type === 'finish')
const replayState: unknown = JSON.parse(JSON.stringify(finish?.replayState))
expect(replayState).toMatchObject({ response: { model: requestedModel } })
- if (requestedModel !== returnedModel) {
- expect(replayState).toMatchObject({ response: { responseModel: returnedModel } })
+ if (reportedModel === undefined) {
+ expect(finish?.replayState?.response).not.toHaveProperty('responseModel')
+ } else {
+ expect(replayState).toMatchObject({ response: { responseModel: reportedModel } })
}
const onDegrade = vi.fn()
const context = toPiContext({
@@ -687,16 +717,14 @@ describe('toStreamChunks', () => {
}, undefined, onDegrade)
expect(onDegrade).not.toHaveBeenCalled()
expect(context.messages[0]).toMatchObject({
- api: 'anthropic-messages', model: returnedModel, providerThinkingLevel: 'high',
+ api: 'anthropic-messages', model: requestedModel, providerThinkingLevel: 'high',
content: native.content,
})
- const catalog = getBuiltinModels('anthropic')
- const requested = catalog.find(model => model.id === requestedModel)
- const returned = catalog.find(model => model.id === returnedModel)
- if (requested === undefined || returned === undefined) throw new Error('missing Anthropic catalog model')
- expect(transformMessages(context.messages, returned)[0]).toMatchObject({ content: native.content })
- expect(transformMessages(context.messages, requested)[0]).toMatchObject({
- content: requestedModel === returnedModel ? native.content : [{ type: 'text', text: 'reason' }],
+ const requested = getBuiltinModels('anthropic').find(model => model.id === requestedModel)
+ if (requested === undefined) throw new Error('missing Anthropic catalog model')
+ expect(transformMessages(context.messages, requested)[0]).toMatchObject({ content: native.content })
+ expect(transformMessages(context.messages, { ...requested, id: 'other-model' })[0]).toMatchObject({
+ content: [{ type: 'text', text: 'reason' }],
})
})
diff --git a/packages/llm/llm-pi-ai/tests/dynamic-config.spec.ts b/packages/llm/llm-pi-ai/tests/dynamic-config.spec.ts
index ee0faca3ca..ae99592020 100644
--- a/packages/llm/llm-pi-ai/tests/dynamic-config.spec.ts
+++ b/packages/llm/llm-pi-ai/tests/dynamic-config.spec.ts
@@ -170,7 +170,7 @@ describe('request-level dynamic profiles', () => {
expect(ctx.llm.listProviders().map(provider => provider.id)).toEqual(['deepseek'])
await expect(ctx.llm.listModels('deepseek')).resolves.not.toHaveLength(0)
- const result = await assemble(ctx, { provider: 'deepseek', model: 'deepseek-v4-flash', messages: [] })
+ const result = await assemble(ctx, { provider: 'deepseek', model: 'deepseek-flash', messages: [] })
expect(result.message.content).toEqual([{ type: 'text', text: 'hello' }])
expect(server.headers[0]?.authorization).toBe('Bearer pk-from-settings')
@@ -197,7 +197,7 @@ describe('request-level dynamic profiles', () => {
})
expect(ctx.llm.listProviders().map(provider => provider.id)).toEqual(['openai', 'deepseek'])
- const result = await assemble(ctx, { provider: 'deepseek', model: 'deepseek-v4-flash', messages: [] })
+ const result = await assemble(ctx, { provider: 'deepseek', model: 'deepseek-flash', messages: [] })
expect(result.message.content).toEqual([{ type: 'text', text: 'hello' }])
expect(server.headers[0]?.authorization).toBe('Bearer live-key')
@@ -205,7 +205,7 @@ describe('request-level dynamic profiles', () => {
// composition route stays.
await configurations.get(ctx)!.replace(initialConfigs.get(ctx)!)
expect(ctx.llm.listProviders().map(provider => provider.id)).toEqual(['openai'])
- const removed = await assemble(ctx, { provider: 'deepseek', model: 'deepseek-v4-flash', messages: [] })
+ const removed = await assemble(ctx, { provider: 'deepseek', model: 'deepseek-flash', messages: [] })
expect(removed.finish).toMatchObject({ kind: 'error', failure: { code: 'NO_ADAPTER' } })
})
@@ -218,11 +218,11 @@ describe('request-level dynamic profiles', () => {
providers: { deepseek: { apiKeyEnv: 'PI_DYNAMIC_KEY', baseURL: server.url } },
})
- await assemble(ctx, { provider: 'deepseek', model: 'deepseek-v4-flash', messages: [] })
+ await assemble(ctx, { provider: 'deepseek', model: 'deepseek-flash', messages: [] })
expect(server.headers[0]?.authorization).toBe('Bearer pk-one')
await ctx.credentials.set(credentialRef('PI_DYNAMIC_KEY'), 'pk-two')
- await assemble(ctx, { provider: 'deepseek', model: 'deepseek-v4-flash', messages: [] })
+ await assemble(ctx, { provider: 'deepseek', model: 'deepseek-flash', messages: [] })
expect(server.headers[1]?.authorization).toBe('Bearer pk-two')
})
diff --git a/packages/llm/llm-pi-ai/tests/egress.spec.ts b/packages/llm/llm-pi-ai/tests/egress.spec.ts
index ba9c38c651..fa845610dc 100644
--- a/packages/llm/llm-pi-ai/tests/egress.spec.ts
+++ b/packages/llm/llm-pi-ai/tests/egress.spec.ts
@@ -46,7 +46,7 @@ async function streamOnce(): Promise {
await ctx.plugin(LlmPiAi, {
providers: { deepseek: { apiKeyEnv: 'PI_TEST_KEY', baseURL: 'http://pi-stream-probe.invalid' } },
})
- for await (const _chunk of ctx.llm.stream({ provider: 'deepseek', model: 'deepseek-v4-flash', messages: [] })) {
+ for await (const _chunk of ctx.llm.stream({ provider: 'deepseek', model: 'deepseek-flash', messages: [] })) {
// The endpoint never answers; the proxy record is the assertion.
}
} finally {
diff --git a/packages/llm/llm-pi-ai/tests/loader-composition.spec.ts b/packages/llm/llm-pi-ai/tests/loader-composition.spec.ts
index e9d1699c34..6beedfb3fb 100644
--- a/packages/llm/llm-pi-ai/tests/loader-composition.spec.ts
+++ b/packages/llm/llm-pi-ai/tests/loader-composition.spec.ts
@@ -105,7 +105,7 @@ describe('llm-pi-ai real dormant composition', () => {
expect(ctx.llm.listProviders().map(provider => provider.id)).toEqual(['deepseek'])
}, { timeout: 5000 })
- const result = await assemble(ctx, { provider: 'deepseek', model: 'deepseek-v4-flash', messages: [] })
+ const result = await assemble(ctx, { provider: 'deepseek', model: 'deepseek-flash', messages: [] })
expect(result.message.content).toEqual([{ type: 'text', text: 'hello' }])
expect(server.headers[0]?.authorization).toBe('Bearer key-from-store')
})
@@ -169,7 +169,7 @@ describe('llm-pi-ai real dormant composition', () => {
const truncated = await assemble(ctx, {
provider: 'deepseek',
- model: 'deepseek-v4-flash',
+ model: 'deepseek-flash',
messages: [],
})
expect(truncated.finish).toEqual({ kind: 'max-tokens' })
@@ -177,14 +177,14 @@ describe('llm-pi-ai real dormant composition', () => {
expect(truncated.message.source).toEqual({
kind: 'model',
provider: 'deepseek',
- model: 'deepseek-v4-flash',
+ model: 'deepseek-flash',
replayState: {
response: {
kind: 'pi-ai',
version: 2,
api: 'openai-completions',
provider: 'deepseek',
- model: 'deepseek-v4-flash',
+ model: 'deepseek-flash',
stopReason: 'length',
},
blocks: [{ type: 'text' }],
@@ -193,7 +193,7 @@ describe('llm-pi-ai real dormant composition', () => {
const continued = await assemble(ctx, {
provider: 'deepseek',
- model: 'deepseek-v4-flash',
+ model: 'deepseek-flash',
messages: [
truncated.message,
createUserMessage({ content: [{ type: 'text', text: 'continue' }], source: { kind: 'user' } }),
@@ -237,13 +237,13 @@ describe('llm-pi-ai real dormant composition', () => {
kind: 'model',
...{
provider: 'deepseek',
- model: 'deepseek-v4-flash',
+ model: 'deepseek-flash',
replayState: {
kind: 'pi-ai',
version: 1,
api: 'openai-completions',
provider: 'deepseek',
- model: 'deepseek-v4-flash',
+ model: 'deepseek-flash',
stopReason: 'length',
blocks: [{ type: 'text' }, { type: 'tool-call' }],
},
@@ -252,7 +252,7 @@ describe('llm-pi-ai real dormant composition', () => {
})
const continued = await assemble(ctx, {
provider: 'deepseek',
- model: 'deepseek-v4-flash',
+ model: 'deepseek-flash',
messages: [
poisoned,
createUserMessage({ content: [{ type: 'text', text: 'continue' }], source: { kind: 'user' } }),
diff --git a/packages/llm/llm-pi-ai/tests/tool-argument-streaming.spec.ts b/packages/llm/llm-pi-ai/tests/tool-argument-streaming.spec.ts
index 14a4e09a9b..42d9e28a8b 100644
--- a/packages/llm/llm-pi-ai/tests/tool-argument-streaming.spec.ts
+++ b/packages/llm/llm-pi-ai/tests/tool-argument-streaming.spec.ts
@@ -2,6 +2,7 @@ import { afterEach, describe, expect, it } from 'vitest'
import type { AssistantMessageEvent, Model } from '@earendil-works/pi-ai'
import { stream as streamCompletions } from '@earendil-works/pi-ai/api/openai-completions'
import { stream as streamResponses } from '@earendil-works/pi-ai/api/openai-responses'
+import { normalizeContext } from '@earendil-works/pi-ai/utils/transcript'
import { closeMockServers, mockServer } from './mock-server.ts'
afterEach(closeMockServers)
@@ -35,7 +36,7 @@ async function collect(events: AsyncIterable): Promise<{
return { partials, final }
}
-const context = { messages: [{ role: 'user' as const, content: 'hi', timestamp: 0 }] }
+const context = normalizeContext({ messages: [{ role: 'user', content: 'hi', timestamp: 0 }] })
describe('streamed tool-call arguments (patched pi-ai)', () => {
it('openai-completions parses arguments once, at the end of the call', async () => {
diff --git a/patches/@earendil-works__pi-ai@0.85.1.patch b/patches/@earendil-works__pi-ai@0.87.1.patch
similarity index 100%
rename from patches/@earendil-works__pi-ai@0.85.1.patch
rename to patches/@earendil-works__pi-ai@0.87.1.patch
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index a17f2bb826..f4d3188cbc 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -10,7 +10,7 @@ overrides:
'@deepseek-ai/schemastery': link:vendor/schemastery
patchedDependencies:
- '@earendil-works/pi-ai@0.85.1': b9bcce474fb2ac44633dff0fa722816a5bff5451b4575d5874035ea14ba70a4f
+ '@earendil-works/pi-ai@0.87.1': b9bcce474fb2ac44633dff0fa722816a5bff5451b4575d5874035ea14ba70a4f
'@electron/osx-sign@1.3.3': 280e7b2816caf01423097d24e79107a66afeb563a348630ce9928ae8499a5861
'@fortune-sheet/core@1.0.4': 8791a230763dbf853fd65d627c68c31de37209992851377855e16cf08ea70532
'@fortune-sheet/react@1.0.4': 2932e52e79afcd4ced08cfa123b5eded786c85043da32f622f3e80af6fc96c37
@@ -9673,8 +9673,8 @@ importers:
specifier: link:../../../vendor/schemastery
version: link:../../../vendor/schemastery
'@earendil-works/pi-ai':
- specifier: ^0.85.1
- version: 0.85.1(patch_hash=b9bcce474fb2ac44633dff0fa722816a5bff5451b4575d5874035ea14ba70a4f)(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(ws@8.21.0)(zod@4.4.3)
+ specifier: ^0.87.1
+ version: 0.87.1(patch_hash=b9bcce474fb2ac44633dff0fa722816a5bff5451b4575d5874035ea14ba70a4f)(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(ws@8.21.0)(zod@4.4.3)
devDependencies:
'@deepseek-ai/cordis':
specifier: workspace:~
@@ -14793,8 +14793,8 @@ packages:
'@modelcontextprotocol/sdk': ^1.29.0
zod: ^4.0.0
- '@anthropic-ai/sdk@0.123.0':
- resolution: {integrity: sha512-Y9oX9mPNGZClHQOFqrWRk43Srcu/UHuPq3rfxxOq7JgW0gi+lJA2MAOK4Ul3k/+AUrwRWFJvd0tK3oC0Pw25dw==}
+ '@anthropic-ai/sdk@0.124.0':
+ resolution: {integrity: sha512-cN5O8i9UVxHeOQAzj/XjshWXG8KiibJDw9OGpH2Z/eR3n/RBxdoLxDJOcfqAJWvjaMDFfHTBADU04hWRJVkDyA==}
hasBin: true
peerDependencies:
zod: ^3.25.0 || ^4.0.0
@@ -14826,105 +14826,84 @@ packages:
'@asamuzakjp/nwsapi@2.3.9':
resolution: {integrity: sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==}
- '@aws-crypto/crc32@5.2.0':
- resolution: {integrity: sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==}
- engines: {node: '>=16.0.0'}
-
- '@aws-crypto/sha256-browser@5.2.0':
- resolution: {integrity: sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==}
-
- '@aws-crypto/sha256-js@5.2.0':
- resolution: {integrity: sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==}
- engines: {node: '>=16.0.0'}
-
- '@aws-crypto/supports-web-crypto@5.2.0':
- resolution: {integrity: sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==}
-
- '@aws-crypto/util@5.2.0':
- resolution: {integrity: sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==}
-
- '@aws-sdk/client-bedrock-runtime@3.1048.0':
- resolution: {integrity: sha512-u+NT61JZEkRFtpL0CAw1N1dwxnaLgwVXQl/zjJxTGgLyS/jTIdg2SdoEoCTHxgDyCnqa1HEi9QOoE9/pYRNpOQ==}
+ '@aws-sdk/client-bedrock-runtime@3.1127.0':
+ resolution: {integrity: sha512-IDl/lrPb90aH+pZFHGNDmgH9nAUQj5PlZH1sJ3w7RikctyjHSnY3oNjZhrLoaBoQn/rNK0zsP6OHEqEhj2tdLA==}
engines: {node: '>=20.0.0'}
- '@aws-sdk/core@3.974.20':
- resolution: {integrity: sha512-7sDi2B2N3mc3nf1nz6FyEx/FCrJ1N1QnBmraHHQNabFaeAh2IaOOLml48/rHOD1bICHgTRkbBgNTvUzEr5Z35g==}
+ '@aws-sdk/core@3.978.1':
+ resolution: {integrity: sha512-LbY9aGsEiznDWmUc30Nwv3aIX/+dbwTx8KfS0yOC3NPYMO+O91e6jkT1azf34FwjOndq8/Q+RcVVZz5xnerwdg==}
engines: {node: '>=20.0.0'}
- '@aws-sdk/credential-provider-env@3.972.46':
- resolution: {integrity: sha512-+GPXVS2srMOlH74S+SmC1gVuP2TvUZ0siuC0onKO93q+udP+M72dmY8wJfVQ5CX9z/9X5A1HHwz5yRIGBtskvQ==}
+ '@aws-sdk/credential-provider-env@3.972.72':
+ resolution: {integrity: sha512-xTKO/FWJPozTIXbozVnVGoNBhaGba8TBcx+KyUjRVeOlXE+dUc7GTR1cLvu0uTdIdmemzaFbqqCshXeZA1fZew==}
engines: {node: '>=20.0.0'}
- '@aws-sdk/credential-provider-http@3.972.48':
- resolution: {integrity: sha512-fA5loSdlocacRxyUXtpoHSMuk5rsIKRDzQYVMnMxjcmFeZshaJlJ8lymy/hYKji6sne/UmNGj5pxuEs6kq/Qcg==}
+ '@aws-sdk/credential-provider-http@3.972.74':
+ resolution: {integrity: sha512-u91E/hT8f4d1xy0Jl7VG4nVKJ3lxbrZkoBTeSVoJdWBiSEUMwMS/9+e0H/aJVQV//Lt5wuzP+E69v4aRSsNTmw==}
engines: {node: '>=20.0.0'}
- '@aws-sdk/credential-provider-ini@3.972.53':
- resolution: {integrity: sha512-ZfdhIOR41q8TcWEnUac+gCOb+O2LBWdHLmjedXpXz4IEFW2ppNuFcm6p0sMTavpM+zD5TYfpH5Gp7guRyqSgsQ==}
+ '@aws-sdk/credential-provider-ini@3.973.17':
+ resolution: {integrity: sha512-ged4KXdBkvIC81bLvNHHuQKdKak/VXhQTR1NWYTTqW0474nlmsxy9O/vlgTIohDDWH3xpBdtVMZRyjb+DnocDA==}
engines: {node: '>=20.0.0'}
- '@aws-sdk/credential-provider-login@3.972.52':
- resolution: {integrity: sha512-9hu2oR0qH7Fst5Tzdx+UWxm+w5zCXtErTLtOOW5hwwQc170CLwOeniRxyFY6s9mHfGEfC5zFukNBdKBwJR8mhQ==}
+ '@aws-sdk/credential-provider-login@3.972.79':
+ resolution: {integrity: sha512-L+Z85anONJd8MaiuraO4wRxATCdEejBZ3K3eymzWI5JPXa9sOS9CkIm72PBKqXKX+Z9p9NGMX5AIMXm0LEflgw==}
engines: {node: '>=20.0.0'}
- '@aws-sdk/credential-provider-node@3.972.55':
- resolution: {integrity: sha512-zMGLa/dhESVqmCD7mmIFFKSwSFrJGScvCXcjvBZEVOOMauFS5JRQvLTMukFpMEFWiV6dTAlsen2ATDBulLPtbg==}
+ '@aws-sdk/credential-provider-node@3.972.84':
+ resolution: {integrity: sha512-oHt854odINVwzwsh+c5x69j0ajm4DbqqqVJ+O1ECsCIZeMDAbzFpXItaqP7UZstJj/ATdTk/KFSH0LaNAgV+kA==}
engines: {node: '>=20.0.0'}
- '@aws-sdk/credential-provider-process@3.972.46':
- resolution: {integrity: sha512-VUoNFBIjWrUN8NbFiQiuxQEgFjvziAlBRPK+ddh27aj65gk0BYu6bLZnrdrNZwpW6vAihtSUtEMQ1PUJ32QRPA==}
+ '@aws-sdk/credential-provider-process@3.972.72':
+ resolution: {integrity: sha512-rLIp2xbMjX/k9/od7APpqq1ZgXXnV0pOL1Th3ZsL8Wu0TRtBsDTVS8iPqcfRFcHakFxPvR04OSTv2ka2qOb/2A==}
engines: {node: '>=20.0.0'}
- '@aws-sdk/credential-provider-sso@3.972.52':
- resolution: {integrity: sha512-nb2/n4o/HQf+FVpVbZe9vCTFngmuDoIsltMgLAtjixaKzvzhB4J8WSDFyWgnErgLHk55ctWH+I4PU+LIHhyffg==}
+ '@aws-sdk/credential-provider-sso@3.973.16':
+ resolution: {integrity: sha512-IGihaJfFZYacJJr/odqILCoK7W/mvrZ7cuK7ECn3sAu4vLC6u0V8bS7mCGbdugJ8Aum2tnvqmx0F2MRFp2rn9g==}
engines: {node: '>=20.0.0'}
- '@aws-sdk/credential-provider-web-identity@3.972.52':
- resolution: {integrity: sha512-lKj6aRSGbqLmpYmM24bY7a1Xmfcq2vkE3hv8CSPYfc1yCu0BPu/XEJ1L4Fm61MsU6ULLNSG8UGsffNoFUBjESA==}
+ '@aws-sdk/credential-provider-web-identity@3.972.78':
+ resolution: {integrity: sha512-/y9WvNtlcPBGLR0qc1a+9J/xtYZfVczvLUOuXaVWylzttH7ewsxwHtjmiJSolNrVSDorIxHGHMU61CbonRkmwA==}
engines: {node: '>=20.0.0'}
- '@aws-sdk/eventstream-handler-node@3.972.21':
- resolution: {integrity: sha512-mVC0hOmwGJmNFezZ+wM8Sqfap/LjsMavEf2Evl0YWrLAcrdZOEdjnY8nRvgakVViWJSGm2eJxLuPVHGdeV06kA==}
+ '@aws-sdk/eventstream-handler-node@3.972.35':
+ resolution: {integrity: sha512-a8xilRoRaalvSPZdfrs0VY3/BPc0uYhXW56Z/k6nmZ5Vk430LHeowf9APIPq8utM3tMJSNGSSuJMlB9YrPsN+A==}
engines: {node: '>=20.0.0'}
- '@aws-sdk/middleware-eventstream@3.972.17':
- resolution: {integrity: sha512-tdbnXbw73ww62ABWP0G0Z/euvFowEEvAoi/zG4NaZo7HJFpfGho/Z65HyVzkJLT1cMsUregr4pTyxljlarT0wA==}
+ '@aws-sdk/middleware-eventstream@3.972.30':
+ resolution: {integrity: sha512-B6gvZlcnRBNWraKgyEjKsbhv+VjtbyHmpU7hmtTHzXpDSxHPpCJnYLpglEOOsF+SFne20DbZC5IVC1aNr2Pb4A==}
engines: {node: '>=20.0.0'}
- '@aws-sdk/middleware-websocket@3.972.28':
- resolution: {integrity: sha512-SCW06Zjugn86pq7+dxGnFcyWJuEWHT753HTU/Vj/OzVxP+NoShwdAr4ynxAcvWL883OgRVbSqW3ohnjIxwXjjw==}
+ '@aws-sdk/middleware-websocket@3.972.54':
+ resolution: {integrity: sha512-bhESdru8u8KosziH8jcVta/NM/dNreeRz2+2aU86si5bfBYOiJ6IiqD+9U4URUcU5WJO3Yw+jO3GLDIHlscXMQ==}
engines: {node: '>= 14.0.0'}
- '@aws-sdk/nested-clients@3.997.20':
- resolution: {integrity: sha512-IYJuLpXp2DEILVQpQOy0PMpkftv0AHEOCn52o0atyOaumA0CdWQ3klPyXdViGYLbNpESsVFMVybvHUeZAuiGxA==}
+ '@aws-sdk/nested-clients@3.997.46':
+ resolution: {integrity: sha512-oRxtBcka/JGHGs9l9p9IVajGoTP8vTPmoAzdHGy4Qcy9P5vPnDf6nhIeM/COQNY9k/OahImTRaLkHftoXvfcmQ==}
engines: {node: '>=20.0.0'}
- '@aws-sdk/signature-v4-multi-region@3.996.34':
- resolution: {integrity: sha512-mx1L5qlumSOt/nKM3BFaHE2HVkWwz0i4Bw0pyYO42FfX/FeLlo8YI6csC0gSPprEk6fTIqI+CZN9RwUwKd5krQ==}
+ '@aws-sdk/signature-v4-multi-region@3.996.47':
+ resolution: {integrity: sha512-Zk08macMvQTHzQJCLJVkOlviVoqwYMrpXv4lmLN7b7sAbiMoOK7Go0NYdR5UeF+MW8LIbRmwrNy9u/5VvX1U5g==}
engines: {node: '>=20.0.0'}
- '@aws-sdk/token-providers@3.1048.0':
- resolution: {integrity: sha512-k0y/GcuesuSfWyUM0WamrGyeZmltRYaPbHO82UDA6mZ/doB+FOHKutikPAtSXMn/hDz970cF+iRuuiYO9VEbAA==}
+ '@aws-sdk/token-providers@3.1127.0':
+ resolution: {integrity: sha512-Dv2TMWBshJ+tF6ahs2Sy5bh4Iabsd4GAQqVvE9XZmYmnoaVbpS2QKIKE/HRacc7bTtbjEEvP+laGzHvHlf1CiQ==}
engines: {node: '>=20.0.0'}
- '@aws-sdk/token-providers@3.1066.0':
- resolution: {integrity: sha512-UqEUJq7dqa44hneLDUcX7UJy95cg8YqEWyakRpvIPnrNS3Mq+UlQHgCDGu5pvwAPtlIW4qcYbvW6reG6++FyvA==}
+ '@aws-sdk/token-providers@3.1138.0':
+ resolution: {integrity: sha512-GpyAr0DD63YOEmYFM6Df+gJuIgC92MMTiBK4FTKfxii5MJ9ge20epR7LyroulscYlG89J+ZB2ivFDPjvfQhzdw==}
engines: {node: '>=20.0.0'}
- '@aws-sdk/types@3.973.12':
- resolution: {integrity: sha512-43ajd1NF0RMgX5k0hxCNUyEdrtFUsb2aHT2QvpktSC/2Eyb2Jr/JPVqdp0XIoaHWikZJq5tNWSLO6kB5q2eMCA==}
+ '@aws-sdk/types@3.974.6':
+ resolution: {integrity: sha512-v/clNZzZnDxGyvpHMOGpJKVXFAExJzUNAAjaWGdcx8QAcXLGwTaOkw33p5SHAi0YAioK32xB3hWwOekRVfmfKg==}
engines: {node: '>=20.0.0'}
- '@aws-sdk/util-locate-window@3.965.7':
- resolution: {integrity: sha512-M0D6oIpohdNHjc7udzTHEQyot0+0iuA36jc2I9Hps+f/GtKi2HO/pyijQnCnNcwZqLB5+rtn81z3eZK/GyjAmA==}
+ '@aws-sdk/xml-builder@3.972.41':
+ resolution: {integrity: sha512-ctjVSyCMegrWfXlx6VqzSBFI6UqmQ5ZlnfMhdLIiWmhoH8UAQxSCP5N3OpG7X3k4LnS7ou74C4mt20+bfTW2aQ==}
engines: {node: '>=20.0.0'}
- '@aws-sdk/xml-builder@3.972.29':
- resolution: {integrity: sha512-fk0niuGFxfi8yIJuMVM4mhwObkiQSuwZFj3tAPrLVx64Pk3BkrEIpqjzHKY4hKoEBUD6Jg/S74Zj9jy+5F3DnQ==}
- engines: {node: '>=20.0.0'}
-
- '@aws/lambda-invoke-store@0.2.4':
- resolution: {integrity: sha512-iY8yvjE0y651BixKNPgmv1WrQc+GZ142sb0z4gYnChDDY2YqI4P/jsSopBWrKfAt7LOJAkOXt7rC/hms+WclQQ==}
+ '@aws/lambda-invoke-store@0.3.0':
+ resolution: {integrity: sha512-sl4Bm6yiMNYrZKkqqDFWN0UfnWhlS8ivKxrYl+6t0gCLrqr8y3B2IqZZbFRkfaVVp7C/baApyh71P+LeE1A2sQ==}
engines: {node: '>=18.0.0'}
'@babel/code-frame@7.29.7':
@@ -15152,13 +15131,13 @@ packages:
search-insights:
optional: true
- '@earendil-works/pi-ai@0.85.1':
- resolution: {integrity: sha512-+VgVIJDkDO2efYJKEEqvPTH4zmnIaXdAppGbO+vKFA9qy5PdhFiAenuFAkU+oiCSfOC4dMHDyrjdQeL4ZoC5CQ==}
+ '@earendil-works/pi-ai@0.87.1':
+ resolution: {integrity: sha512-X/3PfQBnnoeVdO9Cv8zHghUMglzlgNZYGNzoPnbRoGnHl3Rw3TlA2UKSUB7BRHUOxMryHXYa8dnjWZlbRheDZA==}
engines: {node: '>=22.19.0'}
hasBin: true
- '@earendil-works/pi-telemetry@0.85.1':
- resolution: {integrity: sha512-Bg/YN6kA7Swja/NQxka8xFdecb4E/auIEGF2G5A25EaQXhRnPj300/7/KpgsDDMYUzHTDAv4RyUxaQPJKW81Rw==}
+ '@earendil-works/pi-telemetry@0.87.1':
+ resolution: {integrity: sha512-MC6TRQH5lgMXpcN+Vku2WMI2T8BsiUPzMQHGo81uqFZD3/9O79WWJAysEDGuzduP6R4tvtgwMLwmqIxynM10JQ==}
engines: {node: '>=22.19.0'}
'@electron-internal/extract-zip@1.0.5':
@@ -15737,8 +15716,8 @@ packages:
react: '>= 18.2'
react-dom: '>= 18.2'
- '@google/genai@1.52.0':
- resolution: {integrity: sha512-gwSvbpiN/17O9TbsqSsE/OzZcpv5Fo4RQjdngGgogtuB9RsyJ8ZHhX5KjHj1bp5N9snN2eK8LDGXSaWW2hof8Q==}
+ '@google/genai@2.21.0':
+ resolution: {integrity: sha512-+PDtco2/Z0ONdzCGekCoCT+O1VJS9xJQNN4XzQpXG/t3El/SWWMkCWlFRO1KmivOHPa4Q0VjUYu1HBKCZ/v33Q==}
engines: {node: '>=20.0.0'}
peerDependencies:
'@modelcontextprotocol/sdk': ^1.25.2
@@ -16294,9 +16273,6 @@ packages:
resolution: {integrity: sha512-oN+QwyX7VSHotibwubG3kpzbwKrfnyR6OOO+3Nk/53ADL7FmgHHz4TgrbaYKvvOw09u6QTx0oiH1cNCIOuN0CQ==}
engines: {node: '>= 20.19.0'}
- '@nodable/entities@2.2.0':
- resolution: {integrity: sha512-9uGyhaQavEUMC8AIddIjau4NsnsXhou+j5sBAGojCM1oxmQpVKTWR/9JxABD6UAv12vpIms55fPZKFQEhG6uBg==}
-
'@nodable/entities@3.0.0':
resolution: {integrity: sha512-8L9xFeTYKhm49xfIypoe2W5wV1m/3Z58kT+7kR9A8OyFxcPduI4VmxaUMQyKYrRjUoLLSXv6EKKID5Tvj9cUVw==}
@@ -17171,46 +17147,30 @@ packages:
resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==}
engines: {node: '>=18'}
- '@smithy/core@3.24.7':
- resolution: {integrity: sha512-KoUi4M1f3BG6kzN1FnCwL7oyFptTbyBJKjR6yhSib+JHRdUmM1o+VwsFtJ66NZCkCzVfJMWRHJNo0R0jznp0Pg==}
+ '@smithy/core@3.35.0':
+ resolution: {integrity: sha512-zRMhfkByhT2snNdr1si24vJitU6Cr9ix2MikUfWmkAgp4jrNP0GcKSP5YvwQ+TlI8AZXER5QOGJn3JsVtSD9/A==}
engines: {node: '>=18.0.0'}
- '@smithy/credential-provider-imds@4.3.9':
- resolution: {integrity: sha512-ZlfJ/4Fa3jYb+3eaohPfG9utX9HmdhFNcFtpoGAhUhdynAOmGXtmigbi7eEiONKM+ykHw8RwKuDEb85Lx7t7fA==}
+ '@smithy/credential-provider-imds@4.5.2':
+ resolution: {integrity: sha512-A9uSdn72ozbRUSit0eib0TW7nXuNPlaeM0zcGkJ+nE6tFcSDbnmtwoxbTCFBukVQcszDAyvsd7+rTduPTXpygg==}
engines: {node: '>=18.0.0'}
- '@smithy/fetch-http-handler@5.4.7':
- resolution: {integrity: sha512-NslaM2ir0N2hisDmzXLstPaVINZheh8SokyOC++kzFPloZucL2R7Y7bS57mSzx/1Fc/fqmn7twjkeezTTrV0EA==}
+ '@smithy/fetch-http-handler@5.8.0':
+ resolution: {integrity: sha512-ycSJu3tFAQ4v04CBB0agqFMVsSQ1iG3yw+SpgxRqKfaURpQD4CZ8Wn0zPMmSnOuTpTh65Vz+EA0rMrw089wvkA==}
engines: {node: '>=18.0.0'}
- '@smithy/is-array-buffer@2.2.0':
- resolution: {integrity: sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==}
- engines: {node: '>=14.0.0'}
-
- '@smithy/node-http-handler@4.7.3':
- resolution: {integrity: sha512-/jPhevcTFPMVl6KNjbaI47iOg1zxC7IsnX4PQDGVZKMFceOXtB8IEYaB7a9VvkP/3oC60WzTeKocvSI7vLT0vA==}
+ '@smithy/node-http-handler@4.12.1':
+ resolution: {integrity: sha512-ThMkboGeONWXAelq9FvGsuJC4rOi+qyC4/zhUF58xYpxUg5sQKx2VXZYJmtNjr4dSuBJ1HeJXETQILCz3wOHvw==}
engines: {node: '>=18.0.0'}
- '@smithy/node-http-handler@4.7.8':
- resolution: {integrity: sha512-f+DbsWUwSbtMu1a/j8Y93KiU1SRg9nyzfjereqn1BJ33QOTUXxdlYvVXMhAYl1vuR1Kmna5aIJe09KSIfyFNYw==}
+ '@smithy/signature-v4@5.7.4':
+ resolution: {integrity: sha512-tHy0K0VtqNd5Y7Y41h0a0Lhh0L1GzC08dTWg0F7vRJWFtTENg7IZikf3wQkanYIRdb7ngoIPMTmqgUi401fEeQ==}
engines: {node: '>=18.0.0'}
- '@smithy/signature-v4@5.4.7':
- resolution: {integrity: sha512-LwQZazFayImv+IOm0S0enoLeUJwmAlhGC5O6YCcLWezyu08dF46GOxPOq35OpBIHkgd7OvNvBStIFwVNyrvoBw==}
+ '@smithy/types@4.19.0':
+ resolution: {integrity: sha512-r7jh49VJxGerfAcTQA6gXcKc+98zOp/tqRwzYjgOE+iSQsP6cEU1hq2QzbuipmP68QtYdY9wKEhiCQZIzHgZ4Q==}
engines: {node: '>=18.0.0'}
- '@smithy/types@4.14.4':
- resolution: {integrity: sha512-B2S9+UGm1+/pHkcx3ZoLVX1a+pmSk8rqxRR+ZsNqZaJ5q9FWX9AFGQVM4qG5+OBeQUZVy99HY8HqW8gK/wgXzQ==}
- engines: {node: '>=18.0.0'}
-
- '@smithy/util-buffer-from@2.2.0':
- resolution: {integrity: sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==}
- engines: {node: '>=14.0.0'}
-
- '@smithy/util-utf8@2.3.0':
- resolution: {integrity: sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==}
- engines: {node: '>=14.0.0'}
-
'@stablelib/base64@1.0.1':
resolution: {integrity: sha512-1bnPQqSxSuc3Ii6MhBysoWCg58j97aUjuCSZrGSmDxNqtytIi0k8utUenAwTZN4V5mXXYGsVUI9zeBqy+jBOSQ==}
@@ -17917,6 +17877,10 @@ packages:
resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==}
engines: {node: '>= 14'}
+ agent-base@9.0.0:
+ resolution: {integrity: sha512-TQf59BsZnytt8GdJKLPfUZ54g/iaUL2OWDSFCCvMOhsHduDQxO8xC4PNeyIkVcA5KwL2phPSv0douC0fgWzmnA==}
+ engines: {node: '>= 20'}
+
agentkeepalive@4.6.0:
resolution: {integrity: sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==}
engines: {node: '>= 8.0.0'}
@@ -17966,9 +17930,6 @@ packages:
resolution: {integrity: sha512-BJ8/l4R5LRE7hW9WdSuGYrLSHi2ynxeFpDFbH0K/CgNeY/tyhk+vO6TYxXC5r5CpUhNVX310xzPsN/H9lCdfOA==}
engines: {node: '>=14'}
- anynum@1.0.0:
- resolution: {integrity: sha512-xjR9/zBVnUOP6ztMIIgShjsxui80nQUQH+5xJnvrYLs+90bF25/KJqaAi8mk+B4RDtX1Nspi6fmp4YTEts8SfA==}
-
anynum@1.0.1:
resolution: {integrity: sha512-N6//FLET/tXYNM/F6ABca1oH6fWB+KlTt909Le28WMDBk8oaT4vY17DCrwg2MvmuqUKt3Ni4N5dGJ/EoBgcO6A==}
@@ -19092,10 +19053,6 @@ packages:
resolution: {integrity: sha512-TBw6K/fxoQGGjCmZDw9w/ZwP3uDcnTM4YH/g+PFRWr8sbe5idXtxNN6vITh4+1ruCZaho6uBFurElsA7F0zzgw==}
hasBin: true
- fast-xml-parser@5.7.3:
- resolution: {integrity: sha512-C0AaNuC+mscy6vrAQKAc/rMq+zAPHodfHGZu4sGVehvAQt/JLG1O5zEcYcXSY5zSqr4YVgxsB+pHXTq0i7eDlg==}
- hasBin: true
-
fdir@6.5.0:
resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==}
engines: {node: '>=12.0.0'}
@@ -19417,6 +19374,10 @@ packages:
resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==}
engines: {node: '>= 14'}
+ http-proxy-agent@9.1.0:
+ resolution: {integrity: sha512-2NxoveTT58mjYT4n3RPTEfCZGLMbidoO8XEieXfpSYxu+PQJ1qpx4ypwH6N+uF9twBPIvRRgvkvW5HUTYWENig==}
+ engines: {node: '>= 20'}
+
http-proxy@1.18.1:
resolution: {integrity: sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==}
engines: {node: '>=8.0.0'}
@@ -19442,6 +19403,10 @@ packages:
resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==}
engines: {node: '>= 14'}
+ https-proxy-agent@9.1.0:
+ resolution: {integrity: sha512-ag87y7cJJ9/3+GxFr8Oy4O5faDsGRGnBGsJj/YjOSsSx/5eadKLYTMPlzuR6obgoCDDm0abAAZitXXQkMOPSpA==}
+ engines: {node: '>= 20'}
+
human-signals@8.0.1:
resolution: {integrity: sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ==}
engines: {node: '>=18.18.0'}
@@ -20752,6 +20717,15 @@ packages:
resolution: {integrity: sha512-5nnx0yGyVUcY6t9RnWcARWtwT9F1D8O9rt08htPvnd49W1IgZtmLkhu9WfMzQj1cFxjHIO6connUNVW5k7AVyQ==}
engines: {node: '>= 0.10'}
+ proxy-agent-negotiate@1.1.0:
+ resolution: {integrity: sha512-N8IBcM3UgCVzz2L2Lqv8DVntDnnC8/hiV4nEDUPkqq72TPUgYWjQc+bdZlBPZK9LzPAvOY//gAt0S0DApoOXWQ==}
+ engines: {node: '>= 20'}
+ peerDependencies:
+ kerberos: ^2.0.0
+ peerDependenciesMeta:
+ kerberos:
+ optional: true
+
psl@1.15.0:
resolution: {integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==}
@@ -21264,9 +21238,6 @@ packages:
strnum@1.1.2:
resolution: {integrity: sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==}
- strnum@2.4.0:
- resolution: {integrity: sha512-sHrVyWWdq28RbhjuJdZsA1SnGRJV6NiXbk6AXBxDOsgAcA+lmpUZCYjOdLBxkXMwis6RRe7dlZt4VlIWFVzkmg==}
-
strnum@2.4.2:
resolution: {integrity: sha512-rDG3Ah4TV0k1hWvLSzkZtMmLN9+eS+h3knq4MP6A42Y3Yh5qGNnOUs1jJkoSr8FG5dsL28c7KgkIBzSEykqtuw==}
@@ -21494,8 +21465,8 @@ packages:
resolution: {integrity: sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA==}
engines: {node: '>= 18'}
- typebox@1.3.7:
- resolution: {integrity: sha512-meKuifc33Pccx0O6PdIzYMq3Og8zvP4TIi/a+Bw3AEMZMxOD0+RHGQvpglEe6Zdy3wZ8nqn/j95h8LUZLk/6Hg==}
+ typebox@1.3.27:
+ resolution: {integrity: sha512-zu+jc1pcy4UiNThxikUr36f0Rybk9PEeCg/NE6adeWr/SKsdNO4EzZHYRDlv2YCVAfj3Odq3dESSo/jNyoBXzA==}
typescript-language-server@5.3.0:
resolution: {integrity: sha512-5puofxZHgFdAYtfNpmwCAvgtaYgg8wrUnH30m7Ze3QuguId5RNRadKASpOpyDxTyUdAF51FjhTdjntLw/EuWcQ==}
@@ -22214,7 +22185,7 @@ snapshots:
'@anthropic-ai/claude-agent-sdk-win32-arm64': 0.3.263
'@anthropic-ai/claude-agent-sdk-win32-x64': 0.3.263
- '@anthropic-ai/sdk@0.123.0(zod@4.4.3)':
+ '@anthropic-ai/sdk@0.124.0(zod@4.4.3)':
dependencies:
json-schema-to-ts: 3.1.1
standardwebhooks: 1.1.1
@@ -22247,228 +22218,187 @@ snapshots:
'@asamuzakjp/nwsapi@2.3.9': {}
- '@aws-crypto/crc32@5.2.0':
+ '@aws-sdk/client-bedrock-runtime@3.1127.0':
dependencies:
- '@aws-crypto/util': 5.2.0
- '@aws-sdk/types': 3.973.12
+ '@aws-sdk/core': 3.978.1
+ '@aws-sdk/credential-provider-node': 3.972.84
+ '@aws-sdk/eventstream-handler-node': 3.972.35
+ '@aws-sdk/middleware-eventstream': 3.972.30
+ '@aws-sdk/middleware-websocket': 3.972.54
+ '@aws-sdk/token-providers': 3.1127.0
+ '@aws-sdk/types': 3.974.6
+ '@smithy/core': 3.35.0
+ '@smithy/fetch-http-handler': 5.8.0
+ '@smithy/node-http-handler': 4.12.1
+ '@smithy/types': 4.19.0
tslib: 2.8.1
- '@aws-crypto/sha256-browser@5.2.0':
+ '@aws-sdk/core@3.978.1':
dependencies:
- '@aws-crypto/sha256-js': 5.2.0
- '@aws-crypto/supports-web-crypto': 5.2.0
- '@aws-crypto/util': 5.2.0
- '@aws-sdk/types': 3.973.12
- '@aws-sdk/util-locate-window': 3.965.7
- '@smithy/util-utf8': 2.3.0
- tslib: 2.8.1
-
- '@aws-crypto/sha256-js@5.2.0':
- dependencies:
- '@aws-crypto/util': 5.2.0
- '@aws-sdk/types': 3.973.12
- tslib: 2.8.1
-
- '@aws-crypto/supports-web-crypto@5.2.0':
- dependencies:
- tslib: 2.8.1
-
- '@aws-crypto/util@5.2.0':
- dependencies:
- '@aws-sdk/types': 3.973.12
- '@smithy/util-utf8': 2.3.0
- tslib: 2.8.1
-
- '@aws-sdk/client-bedrock-runtime@3.1048.0':
- dependencies:
- '@aws-crypto/sha256-browser': 5.2.0
- '@aws-crypto/sha256-js': 5.2.0
- '@aws-sdk/core': 3.974.20
- '@aws-sdk/credential-provider-node': 3.972.55
- '@aws-sdk/eventstream-handler-node': 3.972.21
- '@aws-sdk/middleware-eventstream': 3.972.17
- '@aws-sdk/middleware-websocket': 3.972.28
- '@aws-sdk/token-providers': 3.1048.0
- '@aws-sdk/types': 3.973.12
- '@smithy/core': 3.24.7
- '@smithy/fetch-http-handler': 5.4.7
- '@smithy/node-http-handler': 4.7.8
- '@smithy/types': 4.14.4
- tslib: 2.8.1
-
- '@aws-sdk/core@3.974.20':
- dependencies:
- '@aws-sdk/types': 3.973.12
- '@aws-sdk/xml-builder': 3.972.29
- '@aws/lambda-invoke-store': 0.2.4
- '@smithy/core': 3.24.7
- '@smithy/signature-v4': 5.4.7
- '@smithy/types': 4.14.4
+ '@aws-sdk/types': 3.974.6
+ '@aws-sdk/xml-builder': 3.972.41
+ '@aws/lambda-invoke-store': 0.3.0
+ '@smithy/core': 3.35.0
+ '@smithy/signature-v4': 5.7.4
+ '@smithy/types': 4.19.0
bowser: 2.14.1
tslib: 2.8.1
- '@aws-sdk/credential-provider-env@3.972.46':
+ '@aws-sdk/credential-provider-env@3.972.72':
dependencies:
- '@aws-sdk/core': 3.974.20
- '@aws-sdk/types': 3.973.12
- '@smithy/core': 3.24.7
- '@smithy/types': 4.14.4
+ '@aws-sdk/core': 3.978.1
+ '@aws-sdk/types': 3.974.6
+ '@smithy/core': 3.35.0
+ '@smithy/types': 4.19.0
tslib: 2.8.1
- '@aws-sdk/credential-provider-http@3.972.48':
+ '@aws-sdk/credential-provider-http@3.972.74':
dependencies:
- '@aws-sdk/core': 3.974.20
- '@aws-sdk/types': 3.973.12
- '@smithy/core': 3.24.7
- '@smithy/fetch-http-handler': 5.4.7
- '@smithy/node-http-handler': 4.7.8
- '@smithy/types': 4.14.4
+ '@aws-sdk/core': 3.978.1
+ '@aws-sdk/types': 3.974.6
+ '@smithy/core': 3.35.0
+ '@smithy/fetch-http-handler': 5.8.0
+ '@smithy/node-http-handler': 4.12.1
+ '@smithy/types': 4.19.0
tslib: 2.8.1
- '@aws-sdk/credential-provider-ini@3.972.53':
+ '@aws-sdk/credential-provider-ini@3.973.17':
dependencies:
- '@aws-sdk/core': 3.974.20
- '@aws-sdk/credential-provider-env': 3.972.46
- '@aws-sdk/credential-provider-http': 3.972.48
- '@aws-sdk/credential-provider-login': 3.972.52
- '@aws-sdk/credential-provider-process': 3.972.46
- '@aws-sdk/credential-provider-sso': 3.972.52
- '@aws-sdk/credential-provider-web-identity': 3.972.52
- '@aws-sdk/nested-clients': 3.997.20
- '@aws-sdk/types': 3.973.12
- '@smithy/core': 3.24.7
- '@smithy/credential-provider-imds': 4.3.9
- '@smithy/types': 4.14.4
+ '@aws-sdk/core': 3.978.1
+ '@aws-sdk/credential-provider-env': 3.972.72
+ '@aws-sdk/credential-provider-http': 3.972.74
+ '@aws-sdk/credential-provider-login': 3.972.79
+ '@aws-sdk/credential-provider-process': 3.972.72
+ '@aws-sdk/credential-provider-sso': 3.973.16
+ '@aws-sdk/credential-provider-web-identity': 3.972.78
+ '@aws-sdk/nested-clients': 3.997.46
+ '@aws-sdk/types': 3.974.6
+ '@smithy/core': 3.35.0
+ '@smithy/credential-provider-imds': 4.5.2
+ '@smithy/types': 4.19.0
tslib: 2.8.1
- '@aws-sdk/credential-provider-login@3.972.52':
+ '@aws-sdk/credential-provider-login@3.972.79':
dependencies:
- '@aws-sdk/core': 3.974.20
- '@aws-sdk/nested-clients': 3.997.20
- '@aws-sdk/types': 3.973.12
- '@smithy/core': 3.24.7
- '@smithy/types': 4.14.4
+ '@aws-sdk/core': 3.978.1
+ '@aws-sdk/nested-clients': 3.997.46
+ '@aws-sdk/types': 3.974.6
+ '@smithy/core': 3.35.0
+ '@smithy/types': 4.19.0
tslib: 2.8.1
- '@aws-sdk/credential-provider-node@3.972.55':
+ '@aws-sdk/credential-provider-node@3.972.84':
dependencies:
- '@aws-sdk/credential-provider-env': 3.972.46
- '@aws-sdk/credential-provider-http': 3.972.48
- '@aws-sdk/credential-provider-ini': 3.972.53
- '@aws-sdk/credential-provider-process': 3.972.46
- '@aws-sdk/credential-provider-sso': 3.972.52
- '@aws-sdk/credential-provider-web-identity': 3.972.52
- '@aws-sdk/types': 3.973.12
- '@smithy/core': 3.24.7
- '@smithy/credential-provider-imds': 4.3.9
- '@smithy/types': 4.14.4
+ '@aws-sdk/credential-provider-env': 3.972.72
+ '@aws-sdk/credential-provider-http': 3.972.74
+ '@aws-sdk/credential-provider-ini': 3.973.17
+ '@aws-sdk/credential-provider-process': 3.972.72
+ '@aws-sdk/credential-provider-sso': 3.973.16
+ '@aws-sdk/credential-provider-web-identity': 3.972.78
+ '@aws-sdk/types': 3.974.6
+ '@smithy/core': 3.35.0
+ '@smithy/credential-provider-imds': 4.5.2
+ '@smithy/types': 4.19.0
tslib: 2.8.1
- '@aws-sdk/credential-provider-process@3.972.46':
+ '@aws-sdk/credential-provider-process@3.972.72':
dependencies:
- '@aws-sdk/core': 3.974.20
- '@aws-sdk/types': 3.973.12
- '@smithy/core': 3.24.7
- '@smithy/types': 4.14.4
+ '@aws-sdk/core': 3.978.1
+ '@aws-sdk/types': 3.974.6
+ '@smithy/core': 3.35.0
+ '@smithy/types': 4.19.0
tslib: 2.8.1
- '@aws-sdk/credential-provider-sso@3.972.52':
+ '@aws-sdk/credential-provider-sso@3.973.16':
dependencies:
- '@aws-sdk/core': 3.974.20
- '@aws-sdk/nested-clients': 3.997.20
- '@aws-sdk/token-providers': 3.1066.0
- '@aws-sdk/types': 3.973.12
- '@smithy/core': 3.24.7
- '@smithy/types': 4.14.4
+ '@aws-sdk/core': 3.978.1
+ '@aws-sdk/nested-clients': 3.997.46
+ '@aws-sdk/token-providers': 3.1138.0
+ '@aws-sdk/types': 3.974.6
+ '@smithy/core': 3.35.0
+ '@smithy/types': 4.19.0
tslib: 2.8.1
- '@aws-sdk/credential-provider-web-identity@3.972.52':
+ '@aws-sdk/credential-provider-web-identity@3.972.78':
dependencies:
- '@aws-sdk/core': 3.974.20
- '@aws-sdk/nested-clients': 3.997.20
- '@aws-sdk/types': 3.973.12
- '@smithy/core': 3.24.7
- '@smithy/types': 4.14.4
+ '@aws-sdk/core': 3.978.1
+ '@aws-sdk/nested-clients': 3.997.46
+ '@aws-sdk/types': 3.974.6
+ '@smithy/core': 3.35.0
+ '@smithy/types': 4.19.0
tslib: 2.8.1
- '@aws-sdk/eventstream-handler-node@3.972.21':
+ '@aws-sdk/eventstream-handler-node@3.972.35':
dependencies:
- '@aws-sdk/types': 3.973.12
- '@smithy/core': 3.24.7
- '@smithy/types': 4.14.4
+ '@aws-sdk/types': 3.974.6
+ '@smithy/core': 3.35.0
+ '@smithy/types': 4.19.0
tslib: 2.8.1
- '@aws-sdk/middleware-eventstream@3.972.17':
+ '@aws-sdk/middleware-eventstream@3.972.30':
dependencies:
- '@aws-sdk/types': 3.973.12
- '@smithy/core': 3.24.7
- '@smithy/types': 4.14.4
+ '@aws-sdk/types': 3.974.6
+ '@smithy/core': 3.35.0
+ '@smithy/types': 4.19.0
tslib: 2.8.1
- '@aws-sdk/middleware-websocket@3.972.28':
+ '@aws-sdk/middleware-websocket@3.972.54':
dependencies:
- '@aws-sdk/core': 3.974.20
- '@aws-sdk/types': 3.973.12
- '@smithy/core': 3.24.7
- '@smithy/fetch-http-handler': 5.4.7
- '@smithy/signature-v4': 5.4.7
- '@smithy/types': 4.14.4
+ '@aws-sdk/core': 3.978.1
+ '@aws-sdk/types': 3.974.6
+ '@smithy/core': 3.35.0
+ '@smithy/fetch-http-handler': 5.8.0
+ '@smithy/signature-v4': 5.7.4
+ '@smithy/types': 4.19.0
tslib: 2.8.1
- '@aws-sdk/nested-clients@3.997.20':
+ '@aws-sdk/nested-clients@3.997.46':
dependencies:
- '@aws-crypto/sha256-browser': 5.2.0
- '@aws-crypto/sha256-js': 5.2.0
- '@aws-sdk/core': 3.974.20
- '@aws-sdk/signature-v4-multi-region': 3.996.34
- '@aws-sdk/types': 3.973.12
- '@smithy/core': 3.24.7
- '@smithy/fetch-http-handler': 5.4.7
- '@smithy/node-http-handler': 4.7.8
- '@smithy/types': 4.14.4
+ '@aws-sdk/core': 3.978.1
+ '@aws-sdk/signature-v4-multi-region': 3.996.47
+ '@aws-sdk/types': 3.974.6
+ '@smithy/core': 3.35.0
+ '@smithy/fetch-http-handler': 5.8.0
+ '@smithy/node-http-handler': 4.12.1
+ '@smithy/types': 4.19.0
tslib: 2.8.1
- '@aws-sdk/signature-v4-multi-region@3.996.34':
+ '@aws-sdk/signature-v4-multi-region@3.996.47':
dependencies:
- '@aws-sdk/types': 3.973.12
- '@smithy/signature-v4': 5.4.7
- '@smithy/types': 4.14.4
+ '@aws-sdk/types': 3.974.6
+ '@smithy/signature-v4': 5.7.4
+ '@smithy/types': 4.19.0
tslib: 2.8.1
- '@aws-sdk/token-providers@3.1048.0':
+ '@aws-sdk/token-providers@3.1127.0':
dependencies:
- '@aws-sdk/core': 3.974.20
- '@aws-sdk/nested-clients': 3.997.20
- '@aws-sdk/types': 3.973.12
- '@smithy/core': 3.24.7
- '@smithy/types': 4.14.4
+ '@aws-sdk/core': 3.978.1
+ '@aws-sdk/nested-clients': 3.997.46
+ '@aws-sdk/types': 3.974.6
+ '@smithy/core': 3.35.0
+ '@smithy/types': 4.19.0
tslib: 2.8.1
- '@aws-sdk/token-providers@3.1066.0':
+ '@aws-sdk/token-providers@3.1138.0':
dependencies:
- '@aws-sdk/core': 3.974.20
- '@aws-sdk/nested-clients': 3.997.20
- '@aws-sdk/types': 3.973.12
- '@smithy/core': 3.24.7
- '@smithy/types': 4.14.4
+ '@aws-sdk/core': 3.978.1
+ '@aws-sdk/nested-clients': 3.997.46
+ '@aws-sdk/types': 3.974.6
+ '@smithy/core': 3.35.0
+ '@smithy/types': 4.19.0
tslib: 2.8.1
- '@aws-sdk/types@3.973.12':
+ '@aws-sdk/types@3.974.6':
dependencies:
- '@smithy/types': 4.14.4
+ '@smithy/types': 4.19.0
tslib: 2.8.1
- '@aws-sdk/util-locate-window@3.965.7':
+ '@aws-sdk/xml-builder@3.972.41':
dependencies:
+ '@smithy/types': 4.19.0
tslib: 2.8.1
- '@aws-sdk/xml-builder@3.972.29':
- dependencies:
- '@smithy/types': 4.14.4
- fast-xml-parser: 5.7.3
- tslib: 2.8.1
-
- '@aws/lambda-invoke-store@0.2.4': {}
+ '@aws/lambda-invoke-store@0.3.0': {}
'@babel/code-frame@7.29.7':
dependencies:
@@ -22719,27 +22649,28 @@ snapshots:
transitivePeerDependencies:
- '@algolia/client-search'
- '@earendil-works/pi-ai@0.85.1(patch_hash=b9bcce474fb2ac44633dff0fa722816a5bff5451b4575d5874035ea14ba70a4f)(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(ws@8.21.0)(zod@4.4.3)':
+ '@earendil-works/pi-ai@0.87.1(patch_hash=b9bcce474fb2ac44633dff0fa722816a5bff5451b4575d5874035ea14ba70a4f)(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))(ws@8.21.0)(zod@4.4.3)':
dependencies:
- '@anthropic-ai/sdk': 0.123.0(zod@4.4.3)
- '@aws-sdk/client-bedrock-runtime': 3.1048.0
- '@earendil-works/pi-telemetry': 0.85.1
- '@google/genai': 1.52.0(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))
- '@smithy/node-http-handler': 4.7.3
- http-proxy-agent: 7.0.2
- https-proxy-agent: 7.0.6
+ '@anthropic-ai/sdk': 0.124.0(zod@4.4.3)
+ '@aws-sdk/client-bedrock-runtime': 3.1127.0
+ '@earendil-works/pi-telemetry': 0.87.1
+ '@google/genai': 2.21.0(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))
+ '@smithy/node-http-handler': 4.12.1
+ http-proxy-agent: 9.1.0
+ https-proxy-agent: 9.1.0
openai: 6.40.0(ws@8.21.0)(zod@4.4.3)
partial-json: 0.1.7
- typebox: 1.3.7
+ typebox: 1.3.27
transitivePeerDependencies:
- '@modelcontextprotocol/sdk'
- bufferutil
+ - kerberos
- supports-color
- utf-8-validate
- ws
- zod
- '@earendil-works/pi-telemetry@0.85.1': {}
+ '@earendil-works/pi-telemetry@0.87.1': {}
'@electron-internal/extract-zip@1.0.5': {}
@@ -23179,7 +23110,7 @@ snapshots:
react-dom: 18.3.1(react@18.3.1)
regenerator-runtime: 0.14.1
- '@google/genai@1.52.0(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))':
+ '@google/genai@2.21.0(@modelcontextprotocol/sdk@1.29.0(zod@4.4.3))':
dependencies:
google-auth-library: 10.7.0
p-retry: 4.6.2
@@ -23686,8 +23617,6 @@ snapshots:
'@noble/hashes@2.3.0': {}
- '@nodable/entities@2.2.0': {}
-
'@nodable/entities@3.0.0': {}
'@octokit/openapi-types@28.0.0': {}
@@ -24276,58 +24205,37 @@ snapshots:
'@sindresorhus/merge-streams@4.0.0': {}
- '@smithy/core@3.24.7':
+ '@smithy/core@3.35.0':
dependencies:
- '@aws-crypto/crc32': 5.2.0
- '@smithy/types': 4.14.4
+ '@smithy/types': 4.19.0
tslib: 2.8.1
- '@smithy/credential-provider-imds@4.3.9':
+ '@smithy/credential-provider-imds@4.5.2':
dependencies:
- '@smithy/core': 3.24.7
- '@smithy/types': 4.14.4
+ '@smithy/core': 3.35.0
+ '@smithy/types': 4.19.0
tslib: 2.8.1
- '@smithy/fetch-http-handler@5.4.7':
+ '@smithy/fetch-http-handler@5.8.0':
dependencies:
- '@smithy/core': 3.24.7
- '@smithy/types': 4.14.4
+ '@smithy/core': 3.35.0
+ '@smithy/types': 4.19.0
tslib: 2.8.1
- '@smithy/is-array-buffer@2.2.0':
+ '@smithy/node-http-handler@4.12.1':
dependencies:
+ '@smithy/core': 3.35.0
+ '@smithy/types': 4.19.0
tslib: 2.8.1
- '@smithy/node-http-handler@4.7.3':
+ '@smithy/signature-v4@5.7.4':
dependencies:
- '@smithy/core': 3.24.7
- '@smithy/types': 4.14.4
+ '@smithy/core': 3.35.0
+ '@smithy/types': 4.19.0
tslib: 2.8.1
- '@smithy/node-http-handler@4.7.8':
+ '@smithy/types@4.19.0':
dependencies:
- '@smithy/core': 3.24.7
- '@smithy/types': 4.14.4
- tslib: 2.8.1
-
- '@smithy/signature-v4@5.4.7':
- dependencies:
- '@smithy/core': 3.24.7
- '@smithy/types': 4.14.4
- tslib: 2.8.1
-
- '@smithy/types@4.14.4':
- dependencies:
- tslib: 2.8.1
-
- '@smithy/util-buffer-from@2.2.0':
- dependencies:
- '@smithy/is-array-buffer': 2.2.0
- tslib: 2.8.1
-
- '@smithy/util-utf8@2.3.0':
- dependencies:
- '@smithy/util-buffer-from': 2.2.0
tslib: 2.8.1
'@stablelib/base64@1.0.1': {}
@@ -25119,6 +25027,8 @@ snapshots:
agent-base@7.1.4: {}
+ agent-base@9.0.0: {}
+
agentkeepalive@4.6.0:
dependencies:
humanize-ms: 1.2.1
@@ -25174,8 +25084,6 @@ snapshots:
ansis@4.3.1: {}
- anynum@1.0.0: {}
-
anynum@1.0.1: {}
app-builder-lib@26.15.3(dmg-builder@26.15.3)(electron-builder-squirrel-windows@26.15.3):
@@ -26527,13 +26435,6 @@ snapshots:
strnum: 2.4.2
xml-naming: 0.3.0
- fast-xml-parser@5.7.3:
- dependencies:
- '@nodable/entities': 2.2.0
- fast-xml-builder: 1.2.0
- path-expression-matcher: 1.5.0
- strnum: 2.4.0
-
fdir@6.5.0(picomatch@4.0.4):
optionalDependencies:
picomatch: 4.0.4
@@ -26939,6 +26840,15 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ http-proxy-agent@9.1.0:
+ dependencies:
+ agent-base: 9.0.0
+ debug: 4.4.3(supports-color@9.4.0)
+ proxy-agent-negotiate: 1.1.0
+ transitivePeerDependencies:
+ - kerberos
+ - supports-color
+
http-proxy@1.18.1:
dependencies:
eventemitter3: 4.0.7
@@ -26989,6 +26899,15 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ https-proxy-agent@9.1.0:
+ dependencies:
+ agent-base: 9.0.0
+ debug: 4.4.3(supports-color@9.4.0)
+ proxy-agent-negotiate: 1.1.0
+ transitivePeerDependencies:
+ - kerberos
+ - supports-color
+
human-signals@8.0.1: {}
humanize-ms@1.2.1:
@@ -28375,6 +28294,8 @@ snapshots:
forwarded: 0.2.0
ipaddr.js: 1.9.1
+ proxy-agent-negotiate@1.1.0: {}
+
psl@1.15.0:
dependencies:
punycode: 2.3.1
@@ -29002,10 +28923,6 @@ snapshots:
strnum@1.1.2: {}
- strnum@2.4.0:
- dependencies:
- anynum: 1.0.0
-
strnum@2.4.2:
dependencies:
anynum: 1.0.1
@@ -29237,7 +29154,7 @@ snapshots:
media-typer: 1.1.1
mime-types: 3.0.2
- typebox@1.3.7: {}
+ typebox@1.3.27: {}
typescript-language-server@5.3.0:
dependencies:
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
index f3c6b2baf9..b9cf05ab45 100644
--- a/pnpm-workspace.yaml
+++ b/pnpm-workspace.yaml
@@ -64,8 +64,8 @@ minimumReleaseAgeExclude:
- '@deepseek-ai/libreoffice-kit-wasm@0.1.1'
# Fresh pi-ai releases carry the model catalog updates that are the whole
# point of bumping it; waiting out the release age would defeat that.
- - '@earendil-works/pi-ai@0.85.1'
- - '@earendil-works/pi-telemetry@0.85.1'
+ - '@earendil-works/pi-ai@0.87.1'
+ - '@earendil-works/pi-telemetry@0.87.1'
- node-addon-native-custom-loader@0.1.6
- node-addon-require-builtin-darwin-arm64@0.1.6
- node-addon-require-builtin-darwin-x64@0.1.6
@@ -98,7 +98,7 @@ minimumReleaseAgeExclude:
- '@trycua/cua-driver-win32-x64-msvc@0.28.0'
- '@trycua/cua-driver@0.28.0'
patchedDependencies:
- '@earendil-works/pi-ai@0.85.1': patches/@earendil-works__pi-ai@0.85.1.patch
+ '@earendil-works/pi-ai@0.87.1': patches/@earendil-works__pi-ai@0.87.1.patch
'@electron/osx-sign@1.3.3': patches/@electron__osx-sign@1.3.3.patch
'@fortune-sheet/core@1.0.4': patches/@fortune-sheet__core@1.0.4.patch
'@fortune-sheet/react@1.0.4': patches/@fortune-sheet__react@1.0.4.patch