Repository navigation
Conversation
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
The metadata lookup bypasses model-ID aliases, leaving valid aliases on fallback behavior.
Get a fresh assessment by requesting another Copilot review.
Review effort: Lite
Findings: 1
Open (1)
What changed in this PR
Updates Anthropic-compatible custom provider rows to use pi-ai adaptive-thinking metadata.
Changes:
- Adds Anthropic metadata overlays and fallback behavior.
- Preserves explicit mappings and adds adaptive-thinking tests.
| File | Summary |
|---|---|
packages/agent-runtime/src/provider-binding.ts |
Applies Anthropic compatibility metadata. |
packages/agent-runtime/src/provider-binding.test.ts |
Tests adaptive metadata and fallback behavior. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| ? (ANTHROPIC_MODELS as Record<string, Model<Api> | undefined>)[ | ||
| provider.modelId | ||
| ] |
|
已处理 Copilot 的 review 意见:
验证: |
|
Review 结论:Request changes,当前不建议合入。
我在 latest main + 本 PR 的合成候选上验证了:
本 PR 新增从 pi-ai 内置目录读取模型兼容元数据,但 ADR 0134 和 runtime spec 明确规定 models.dev 是唯一模型元数据来源。若这是有意的窄例外,请同步 ADR/spec 说明边界;否则应将 adaptive 映射纳入 models.dev-owned 配置。 本地验证:
|
c2d3617 to
de66d71
Compare
|
Thanks for the precise review — all three items are addressed in the rebased head (de66d71):
Validation on latest main + PR head: |
de66d71 to
b919a12
Compare
|
Follow-up on the force-push to |
b919a12 to
a637ba8
Compare
…ic_messages rows A custom Anthropic-compatible provider resolves its model config from models.dev or the generic fallback, and neither carries the xhigh/max entries of thinkingLevelMap nor compat.forceAdaptiveThinking. pi-ai's Anthropic adapter then has no way to honor those effort levels: streamSimple only reaches the effort-capable path when forceAdaptiveThinking is set, and mapThinkingLevelToEffort() falls back to "high" for xhigh/max without a thinkingLevelMap translation. The provider-neutral reasoning level already reaches streamSimple via the pi-agent-core loop, so the only missing piece is the model metadata. Adopt pi-ai's own generated catalog (ANTHROPIC_MODELS) for the exact model id: merge the built-in thinkingLevelMap under the resolved config and set forceAdaptiveThinking only when pi-ai marks that model adaptive. Unknown ids and budget-era Claude models match nothing, and a models.dev mapping (including off: null) still wins, so request shapes for other providers stay untouched. Refs vastsa#869.
…s rule A custom row may configure the model with a namespaced, regional, or gateway-variant alias (anthropic/claude-opus-4-8, claude-opus-4-8@region, proxy/claude-opus-4-8-agent-thinking). This lookup reads pi-ai catalog metadata and never decides binding identity, so use catalogModelIdsMatch -- the metadata alias rule that also collapses -thinking/-agent/-latest variants -- instead of the strict modelIdsMatch, which missed those variants and let xhigh/max fall back to high on gateways that append them. Adds variant regression cases and documents the narrow models.dev metadata exception in the runtime spec, in the English source and the zh-CN mirror.
a637ba8 to
e590ba1
Compare
|
Small follow-ups since the re-review:
|

问题背景(中文)
这是 #869 按 review 意见收窄后的重提。基于当前 main(0.15.6,pi-ai 0.87.1)确认:
state.thinkingLevel映射成 provider 中立的reasoning交给 streamFn(off → undefined),PI-Desktop 侧...options透传,因此 kimi / glm / deepseek 等 chat_completions 模型的档位下发已经正常,runtime 侧不再需要注入 reasoning(fix(runtime): forward thinking level to every provider via the neutral reasoning knob #869 中的这部分改动已删除)。claude-opus-4-8)。这类自定义 provider 的模型配置来自 models.dev 或 generic fallback,两者都不携带thinkingLevelMap的 xhigh/max 条目,也没有compat.forceAdaptiveThinking。pi-ai 的 Anthropic 适配器只有在forceAdaptiveThinking === true时才走output_config.effort路径,且mapThinkingLevelToEffort()对读不到thinkingLevelMap的 xhigh/max 一律回落"high"(pi-ai/dist/api/anthropic-messages.js,0.87.1 已复核逻辑不变)—— 即会话里调到 max,线上请求实际仍是 high。改动内容
buildProviderModel(packages/agent-runtime/src/provider-binding.ts):当 wire API 为anthropic-messages时,在 pi-ai 内置目录(ANTHROPIC_MODELS)中查找该模型,命中则采纳 pi-ai 自己生成的元数据 ——thinkingLevelMap(xhigh/max 条目)与compat.forceAdaptiveThinking。合并顺序为 catalog(models.dev / binding / generic)优先、内置目录只补缺:catalogModelIdsMatch(@pi-desktop/shared,与modelsDevCatalog.findModel同一套目录元数据别名规则):这里读的是元数据、不决定绑定身份,因此用目录级规则而非绑定身份用的modelIdsMatch——命名空间(anthropic/claude-opus-4-8)、区域后缀(@region)、大小写差异、网关变体后缀(proxy/claude-opus-4-8-agent-thinking等-thinking/-agent/-latest形式)都能命中;off: null,表示 off 时省略 reasoning)优先于内置默认值,语义保持「关闭时不下发」;anthropic-messages协议不经过此路径。runtime 侧不再注入
reasoning(pi 循环已覆盖),故 #869 中的runtime.ts改动不再保留。spec 边界(对应 ADR 0134)
models.dev 仍是唯一模型元数据来源。
docs/spec/03-runtime/11-provider-model-system.md§6.2 第 5 条和docs/spec/03-runtime/02-agent-runtime.md§5c(均含 zh-CN 镜像同步)明确这一窄例外:anthropic-messages行仅从匹配的 pi-ai Anthropic 记录采纳compat.forceAdaptiveThinking标志与thinkingLevelMap的 xhigh/max 条目(models.dev 不发布这两项);models.dev 有定义的值(含off: null)一律优先;目录不认识的 id 不匹配任何条目。测试(
packages/agent-runtime/src/provider-binding.test.ts,新增 10 条)claude-opus-4-8(models.dev 配置、无 thinkingLevelMap):构建出的模型带thinkingLevelMap: { xhigh: "xhigh", max: "max" }+compat.forceAdaptiveThinking: true;捕获请求体断言reasoning: "max"时线上收到thinking: { type: "adaptive" }+output_config: { effort: "max" };claude-haiku-4-5及claude-haiku-4-5-thinking变体:不会被误开 adaptive / thinkingLevelMap;proxy/my-gateway-claude-agent-thinking变体后缀形式):不会凭空生成 adaptive 元数据;{ off: null }映射能覆盖内置默认值;it.each× 7:anthropic/claude-opus-4-8、claude-opus-4-8@us-east、Anthropic/Claude-Opus-4-8、proxy/claude-opus-4-8-agent-thinking、claude-opus-4-8-thinking、claude-opus-4-8-agent、claude-opus-4-8-latest。验证方式
基于最新 main(
45471587,pi-ai 0.87.1):pnpm --filter @pi-desktop/agent-runtime typecheck:通过。pnpm lint:biome/node scripts/check-architecture.mjs/pnpm docs:check(80 对中英 spec 镜像):通过。node scripts/check-pr-base-main.mjs:通过(origin/main 是 head 祖先)。pnpm --filter @pi-desktop/agent-runtime exec vitest run src/provider-binding.test.ts:37/37 通过。pnpm --filter @pi-desktop/agent-runtime test:1011/1013。3 个失败文件(native-pi-session的 Windows 路径断言、hosted-search-compaction的 pi-coding-agent dist 解析、hosted-search-contract在满载下的超时——单跑通过)在未含本 PR 的基线对照中同样复现,属本机环境既有问题,与本改动无关。