diff --git a/internal/aiprompts/architecture.md b/internal/aiprompts/architecture.md index a3d8c9be9..ac1814aef 100644 --- a/internal/aiprompts/architecture.md +++ b/internal/aiprompts/architecture.md @@ -1425,7 +1425,10 @@ catalog grouping and display, but RuntimeCore must reject it before provider exe non-empty. Direct runtime config is authoritative only when it carries an explicit capability snapshot. Renderer `model/list` projection preserves Codex picker, reasoning-effort and input-modality fields while forwarding the selected catalog record's typed `providerId` and `capabilitySnapshot` unchanged. It also forwards known context/output limits. The -Renderer reads capabilities, task families, input/output modalities and runtime features from that snapshot and must not +optional `multiAgentVersion` is forwarded only when the catalog explicitly declares `disabled`, `v1`, or `v2`; absence +remains `null`, and provider name, model name, task family or tool capability must never infer a version. This model-declared +runtime support field does not replace the Grok-aligned provider route/readiness owner or Lime's Multi-Agent lifecycle +owner. The Renderer reads capabilities, task families, input/output modalities and runtime features from that snapshot and must not synthesize tools, streaming, JSON mode, function calling, capability provenance or limits. `inferred_hint` is excluded from executable `model/list` rather than being relabeled locally. Executable chat entries are checked by the same canonical `ModelTaskRequest + route_capability_gap` contract used by Turn admission: they must explicitly advertise the `chat` task @@ -2239,6 +2242,10 @@ interaction 和生产 mock fallback 继续为 `dead / deleted / forbidden-to-res `deprecationNotice` 已按 Desktop 产品范围裁决为 `product-scope-excluded`:它是 Codex 开发/设置诊断,不进入 对话通知链;旧实现无外部兼容负担时直接替换或删除,不恢复同名通知包装。 +Codex `server/diagnostics` 同样保持 `product-scope-excluded / forbidden-to-restore`。它只返回进程本地、无内容的 +上游诊断指标,Lime Desktop 没有对应用户流程;Electron 不新增诊断业务后端,也不把该接口的指标当作模型 +capability、provider readiness 或 sandbox enforcement 证据。 + Architecture impact: major; 本节新增了从 Turn-scoped 精确 delta producer、durable event、v2 notification、canonical Turn 到 Desktop Changes 的跨层数据流,并明确空 diff 清理与唯一事实源边界。Responsible developer confirmation: root, 2026-08-09. Confirmation content: 已核对 `apply_patch` 连续 mutation 校验、EventLog/projector 顺序、typed client 严格 diff --git a/internal/exec-plans/codex-alignment-v1-coordination-plan.md b/internal/exec-plans/codex-alignment-v1-coordination-plan.md index cbd68c8f4..e536cc977 100644 --- a/internal/exec-plans/codex-alignment-v1-coordination-plan.md +++ b/internal/exec-plans/codex-alignment-v1-coordination-plan.md @@ -4501,3 +4501,23 @@ Lime generated manifest。无 `compat`、`deprecated` 新增,旧 realtime GUI/ 边界写回架构、产品矩阵和 Renderer 守卫。下一刀从剩余 `28` 个 planned method 中选择具备真实 Desktop consumer 与唯一 current owner 的 surface,或回到 Windows 真机 sandbox evidence;不得用 Codex realtime/TUI surface 冒充 Grok 多模态对齐。 + +### 2026-08-10 Codex HEAD registry 与 current 字段增量审计 + +状态:in progress。 + +目标与窄写集:将 method matrix 从 Codex `c4f42d161ae44a8d696ee9fb595709661979d187` 增量审计到 +`c9c6c0daa994109cec50fddcb57d076fdf9e738c`,并只收敛已有 current boundary 的字段变化。写集限定为 +`app-server-protocol` Model/Hook types、Grok-aligned model catalog projection、Renderer model registry、method 产品矩阵、 +架构事实源和对应定向测试;不触碰 Windows runner 热区,不恢复 realtime/TUI,也不创建配置或诊断第二 owner。 + +增量裁决:Codex 新增的 `server/diagnostics` 只返回进程本地、无内容指标,没有 Lime Desktop 用户流程,归入 +`product-scope-excluded / forbidden-to-restore`;矩阵变为 `139 implemented / 28 planned / 54 excluded`,总数 +`221`,产品范围完成度仍为 `139 / 167 = 83.2%`。`model/list.multiAgentVersion` 从 model catalog 显式元数据透传, +缺失保持 `null`,禁止按 provider/model 名称或工具能力推断;Hook `executionMode` 直接来自冻结的 +`HookSnapshot`。`configRequirements.autoReview` 与 MCP hook handler 仍没有本轮授权的 current 配置 consumer, +不以协议字段存在冒充实现。 + +验证计划:生成 Rust schema 与 typed client,运行 App Server protocol/Hook/model 定向 Rust 测试、Renderer +model registry 与 method boundary Vitest、`npm run test:contracts`、`npm run governance:legacy-report`、typecheck、 +格式和 diff 检查。本切片不改变 GUI 交互、Electron/preload 或 Thread/Turn/Item producer,因此不重复运行 Gate B。 diff --git a/internal/exec-plans/release-v1.125.0-plan.md b/internal/exec-plans/release-v1.125.0-plan.md index 1b160bb06..12b837476 100644 --- a/internal/exec-plans/release-v1.125.0-plan.md +++ b/internal/exec-plans/release-v1.125.0-plan.md @@ -131,3 +131,12 @@ - 本地验证:`npm run typecheck` 通过;metadata controller/scheduler/context Vitest `30 passed; 0 failed`;本轮 ESLint `--max-warnings 0` 通过。 - 本机 packaged Plugin Gate B 复跑通过:evidence `plugin-package-electron-gate-b-summary.json`,`ok=true`、`providerRequestCount=2`、MCP elicitation accepted、provider final text observed、`productionMockFallbackHitCount=0`。 - 下一步:确认本轮 release candidate 后提交并推送完整 SHA,重新触发 `.github/workflows/build-windows-test.yml`,继续跟踪 Plugin Gate B 与 artifact;不移动已发布的 `v1.125.0` tag。 + +## Windows runner `31372663997` + +- 使用完整 SHA `fb465072fbe14551aeadee530bf36c9c165a06c4`;Windows path contract、sherpa runtime、Electron Windows x64 Squirrel package、N-1 installer download 与 installed Squirrel smoke 全部通过,仍仅失败于 Plugin Gate B 等待 `mcp_elicitation` 90 秒超时。 +- enabled provider 仍只有 `GET /v1/models`,disabled provider 收到后续 `/v1/chat/completions`;MCP ledger 只有 `initialize`。失败时 `thread.modelProvider` 保持 enabled provider,但 `thread.extra.providerSelector/providerName` 已回到 disabled provider。 +- 新证据修正竞态顺序:Renderer provider selection 先于 hydration fallback 排队,因此 selection 时还没有可取消句柄;`finalizeResolvedTopicDetail` 随后因为 canonical `AgentSessionDetail` 缺少 `execution_runtime`,把 current thread 错判为“缺少 runtime route”,再次从旧 session storage 生成 provider fallback。 +- 根因 owner:`readCanonicalThreadDetail` 已读取 current `Thread.modelProvider` 与 `Thread.extra.modelName`,但未投影 `AgentSessionDetail.execution_runtime`,使 hook 层失去 current route 事实源。 +- 修复:canonical Thread projection 从顶层 `modelProvider`(优先于可能 stale 的 extra provider)和 metadata `modelName` 构造 session execution runtime;保留 imported source markers;补顶层 current provider 覆盖 stale extra provider 的回归测试。 +- 本地验证:canonical projection/App Server session client/metadata controller Vitest `48 passed; 0 failed`;`npm run typecheck` 与 projection ESLint `--max-warnings 0` 通过;本机 packaged Plugin Gate B 复跑 `ok=true`、enabled provider request `2`、MCP elicitation/final text 完成、production mock fallback `0`。Windows packaged Gate B 待新完整 SHA 复核。 diff --git a/internal/refactor/v1/08-third-audit-gap-register.md b/internal/refactor/v1/08-third-audit-gap-register.md index 54ce0d0c0..9fb3a8c3c 100644 --- a/internal/refactor/v1/08-third-audit-gap-register.md +++ b/internal/refactor/v1/08-third-audit-gap-register.md @@ -70,7 +70,7 @@ serialization scope 和 v2 schema 绑定;README 还要求每条连接执行 已补 machine-readable method matrix: `internal/refactor/v1/fixtures/codex-method-product-scope.v0.1.json`。矩阵覆盖 Codex -注册表的 220 个方向化 method,每个只能标记为 `implemented`、`product-scope-excluded` +注册表的 221 个方向化 method,每个只能标记为 `implemented`、`product-scope-excluded` 或 `planned`,并由 `src/lib/governance/codexMethodProductScopeBoundary.test.ts` 固定方向计数、唯一性、 owner/evidence、planned gap、excluded rationale 和 Lime generated manifest 同方向契约。 diff --git a/internal/refactor/v1/11-codex-method-product-scope-matrix.md b/internal/refactor/v1/11-codex-method-product-scope-matrix.md index 68258f856..cb8c374c0 100644 --- a/internal/refactor/v1/11-codex-method-product-scope-matrix.md +++ b/internal/refactor/v1/11-codex-method-product-scope-matrix.md @@ -3,7 +3,7 @@ > status: `inventory-current / implementation-open` > owner: `app-server-protocol` + 对应 current domain owner > fixture: `internal/refactor/v1/fixtures/codex-method-product-scope.v0.1.json` -> upstream: `/Users/coso/Documents/dev/rust/codex@c4f42d161ae44a8d696ee9fb595709661979d187` +> upstream: `/Users/coso/Documents/dev/rust/codex@c9c6c0daa994109cec50fddcb57d076fdf9e738c` ## 目标 @@ -21,10 +21,11 @@ legacy 同义命令冒充协议对齐。矩阵覆盖 `clientRequest`、`serverRe | ------------------------ | ---: | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `implemented` | 139 | 连接握手、核心 Thread/Turn/Item、durable ordered Thread Section、thread subscription/lifecycle/content search/raw item injection/background terminals/elicitation/Guardian continuation、typed Collaboration Mode catalog、experimental feature catalog/enablement、Desktop permission profile catalog、Windows `windowsSandbox/readiness` current readiness、基础 Plugin catalog(list/read/install/uninstall/installed)与 Plugin Search、Hook discovery/lifecycle notifications、Skills list/config/extra roots/watcher、Apps exact catalog/read/installed 与 typed `app/list/updated` watcher、exact memory reset、connection-scoped process lifecycle、exact fs IO/watch、exact command/exec lifecycle、inline review/start 与 entered/exitedReviewMode boundary、`currentTime/read`、`item/permissions/requestApproval`、`item/tool/call`、typed `error`/`warning`、`item/commandExecution/terminalInteraction`、`item/autoApprovalReview/{started,completed}`、独立 `guardianWarning`、`turn/plan/updated`、精确 `turn/diff/updated`、`turn/moderationMetadata`、exact MCP resource/tool request/lifecycle notifications、typed approval/MCP server request 与 model control plane | | `planned` | 28 | Windows `windowsSandbox/setupStart`、`windows/worldWritableWarning`、`windowsSandbox/setupCompleted`、Plugin share、environment、fuzzy search、marketplace 与 external agent config;Windows readiness 已实现,但 runner enforcement/setup 仍未完成 | -| `product-scope-excluded` | 53 | Codex account/commerce、attestation、remote control、test-only、internal raw response、deprecated surface、Desktop 不消费的开发/设置 deprecation notice、外部 `config.toml` 专用 MCP reload、未安装远端 Plugin Skill 预览、`configRequirements/read`、单一全局 Provider capability read,以及 Codex realtime WebRTC/session surface | -| 合计 | 220 | `136` client request、`11` server request、`72` server notification、`1` client notification | +| `product-scope-excluded` | 54 | Codex account/commerce、attestation、remote control、test-only、internal raw response、process-local `server/diagnostics`、deprecated surface、Desktop 不消费的开发/设置 deprecation notice、外部 `config.toml` 专用 MCP reload、未安装远端 Plugin Skill 预览、`configRequirements/read`、单一全局 Provider capability read,以及 Codex realtime WebRTC/session surface | +| 合计 | 221 | `137` client request、`11` server request、`72` server notification、`1` client notification | `implemented` 只说明 method boundary 已存在并接入 current owner,不代表字段、恢复、GUI 或 Gate B 已全面 parity。 +当前上游 revision 相比上一版只新增 process-local `server/diagnostics`;它不进入 Lime Desktop manifest。 字段和 lifecycle 缺口继续由 Item inventory、gap register 与对应执行切片管理。 ## 产品裁决 @@ -36,6 +37,7 @@ legacy 同义命令冒充协议对齐。矩阵覆盖 `clientRequest`、`serverRe 5. Codex `thread/realtime/*` WebRTC/session control 与通知不进入 Lime Desktop,归入 `product-scope-excluded / forbidden-to-restore`;旧 realtime voice GUI 已退役,音频、语音和媒体能力继续由 Grok-aligned `model-provider` 与 `voice-core` / `media-runtime` 承接。Windows sandbox 属于产品范围;`windowsSandbox/readiness` 已进入 current,但 `windowsSandbox/setupStart`、两个 Windows 通知以及真实 restricted-token enforcement 仍为 `planned`,后续只能在既有 owner 补齐。Desktop review 已由 inline `review/start` current owner 承接,Codex TUI detached/background review 不进入 Lime。 6. `modelProvider/capabilities/read` 读取 Codex 单一全局 Provider;Lime 的 provider/model 选择绑定 Thread route。该空参数方法没有产品消费者,不能把静态全局值冒充当前 route truth,归入 excluded;能力继续由 executable model catalog、resolved route 与 provider lowering 承接。 7. Codex HEAD 的 durable ordered Thread Section 已进入 Lime current 主链:section/store/order、五个 exact method、typed client、冷启动恢复与 Desktop 分组/置顶均消费同一事实源。旧 `isPinned` metadata、Renderer 时间重排与 localStorage 收藏为 `dead / deleted / forbidden-to-restore`。 + 7a. Codex `server/diagnostics` 只提供无内容的进程本地诊断,Lime Desktop 没有对应用户流程;它保持 `product-scope-excluded / forbidden-to-restore`,不得新增 Electron 诊断后端或把日志指标当作模型/运行时 readiness。 8. `plugin/list`、`plugin/read`、`plugin/install`、`plugin/uninstall`、`plugin/installed` 和 `plugin/search` 已使用 exact Codex method、params/result wire、typed client 与公共 JSON-RPC/Electron 证据接入本地 Plugin catalog owner;Codex remote catalog、share、watcher 和 readiness 仍由 planned method 承接,不由这些基础方法冒充完成。 9. `hooks/list` 已接入 `tool-runtime` 唯一 discovery/trust owner、exact v2 contract、公共 JSON-RPC、command Hook sampling lifecycle、canonical Hook Item 恢复与真实 Electron Gate B;旧 raw config、默认信任、空 reporter 和 Renderer drift fallback 为 `dead / deleted / forbidden-to-restore`。 10. `skills/list` 已接入 `lime-skills::AgentSkillSnapshot` 唯一 discovery owner、exact `cwds + forceReload -> data[{cwd,skills,errors}]` contract、公共 JSON-RPC、typed clients 与 Renderer catalog projection;`skills/changed {}` 通过真实 Electron Gate B 驱动 GUI 自动刷新。singular `skill/list`、`SkillListResponse` 与 `get_local_skills_for_app` 为 `dead / deleted / forbidden-to-restore`。 @@ -62,7 +64,7 @@ legacy 同义命令冒充协议对齐。矩阵覆盖 `clientRequest`、`serverRe `src/lib/governance/codexMethodProductScopeBoundary.test.ts` 固定以下事实: -- 220 个方向化 identity 无遗漏、无重复,状态和方向计数稳定。 +- 221 个方向化 identity 无遗漏、无重复,状态和方向计数稳定。 - planned 必须写 gap,excluded 必须写 rationale,所有组必须写 owner/evidence/priority。 - `implemented` 必须能在 Lime generated manifest 找到同方向、同名 contract。 diff --git a/internal/refactor/v1/README.md b/internal/refactor/v1/README.md index d97f3e112..2c9c7bd49 100644 --- a/internal/refactor/v1/README.md +++ b/internal/refactor/v1/README.md @@ -45,7 +45,7 @@ Codex 对齐的是上图从协议到恢复的语义;grok-build 对齐的是 `m | 参考仓库 | commit | 允许借鉴 | | ------------------------------------------- | ------------------------------------------ | ----------------------------------------------------------------------------------------------------------- | -| `/Users/coso/Documents/dev/rust/codex` | `c4f42d161ae44a8d696ee9fb595709661979d187` | runtime、App Server、Thread/Turn/Item、工具、MCP、Skills、Plugins、Multi-Agent、恢复和测试语义 | +| `/Users/coso/Documents/dev/rust/codex` | `c9c6c0daa994109cec50fddcb57d076fdf9e738c` | runtime、App Server、Thread/Turn/Item、工具、MCP、Skills、Plugins、Multi-Agent、恢复和测试语义 | | `/Users/coso/Documents/dev/rust/grok-build` | `6e386420825bd44ae648c63e7c8cba12fcec9401` | model control plane:catalog、model selection/switch、capability、tool subset、retry/circuit breaker | | `/Users/coso/Documents/dev/js/opencode` | `fab213312927ea64cf968832c527206e8c944f9e` | provider wire plane:endpoint union、canonical content/lowering、媒体、协议 stream reducer、provider policy | @@ -55,11 +55,13 @@ Codex 对齐的是上图从协议到恢复的语义;grok-build 对齐的是 `m 同一主线只能有一个 reference lock;下游 fixture 和切片记录允许暂时落后,但必须显式登记: -| 位置 | 当前 revision | 口径 | -| ----------------------------------------------------------------------------------- | ------------- | -------------------------------------------------------------------- | -| 本表、`internal/test/snapshots/**`、`fixtures/codex-method-product-scope.v0.1.json` | `4c43465…` | 已对齐 lock | -| `fixtures/item-inventory.v0.1.json`、[09](09-tool-turn-snapshot-progress.md) | `9fc715c0…` | 落后 lock;升级必须重新执行 Item/tool 审计,禁止只改 hash 让守卫通过 | -| [04](04-execution-plan.md) 各切片记录、`internal/exec-plans/**` 历史证据 | 按当轮记录 | 历史 evidence,保留写入时的 revision,不回改 | +| 位置 | 当前 revision | 口径 | +| ------------------------------------------------------------------------ | ------------- | -------------------------------------------------------------------- | +| 本表、`fixtures/codex-method-product-scope.v0.1.json` | `c9c6c0d…` | 已对齐当前 Codex HEAD;本轮增量确认新增 1 条 excluded client request | +| `internal/test/snapshots/**` | `4c43465…` | 独立 Gate A 快照基线;升级必须重新生成场景映射 | +| `fixtures/item-inventory.v0.1.json` | `c4f42d16…` | 独立 Item/schema hash 基线;升级必须重新导出完整上游 schema | +| [09](09-tool-turn-snapshot-progress.md) | `9fc715c0…` | 历史 Tool/Hook 审计基线;current Hook 字段由后续切片单独收敛 | +| [04](04-execution-plan.md) 各切片记录、`internal/exec-plans/**` 历史证据 | 按当轮记录 | 历史 evidence,保留写入时的 revision,不回改 | `internal/research/refactor/v2/**` 与 `internal/exec-plans/project-gate-a-b-acceptance-plan.md` 是各自独立的基线,不受本 lock 约束。 diff --git a/internal/refactor/v1/fixtures/codex-method-product-scope.v0.1.json b/internal/refactor/v1/fixtures/codex-method-product-scope.v0.1.json index 544804d0e..33cda78bf 100644 --- a/internal/refactor/v1/fixtures/codex-method-product-scope.v0.1.json +++ b/internal/refactor/v1/fixtures/codex-method-product-scope.v0.1.json @@ -3,7 +3,7 @@ "kind": "codex-app-server-method-product-scope", "upstream": { "repository": "/Users/coso/Documents/dev/rust/codex", - "revision": "c4f42d161ae44a8d696ee9fb595709661979d187", + "revision": "c9c6c0daa994109cec50fddcb57d076fdf9e738c", "source": "codex-rs/app-server-protocol/src/protocol/common.rs" }, "lime": { @@ -12,16 +12,16 @@ }, "allowedStatuses": ["implemented", "product-scope-excluded", "planned"], "inventory": { - "total": 220, + "total": 221, "byDirection": { - "clientRequest": 136, + "clientRequest": 137, "serverRequest": 11, "serverNotification": 72, "clientNotification": 1 }, "byStatus": { "implemented": 139, - "product-scope-excluded": 53, + "product-scope-excluded": 54, "planned": 28 } }, @@ -56,6 +56,18 @@ ], "methods": ["initialized"] }, + { + "id": "server-diagnostics-excluded", + "direction": "clientRequest", + "productArea": "codex-internal", + "status": "product-scope-excluded", + "priority": "none", + "owner": "forbidden-to-restore guard", + "counterpartRule": "none", + "rationale": "Codex server/diagnostics only exposes process-local, content-free diagnostics for upstream development and does not have a Lime Desktop consumer or user workflow.", + "evidence": ["internal/refactor/v1/README.md"], + "methods": ["server/diagnostics"] + }, { "id": "thread-current", "direction": "clientRequest", @@ -396,11 +408,7 @@ "src/lib/api/appConfig.ts", "scripts/electron/mcp-config-fixture-smoke.mjs" ], - "methods": [ - "config/batchWrite", - "config/read", - "config/value/write" - ] + "methods": ["config/batchWrite", "config/read", "config/value/write"] }, { "id": "config-requirements-excluded", diff --git a/internal/refactor/v2/EVENT-PROJECTIONS.md b/internal/refactor/v2/EVENT-PROJECTIONS.md index 29a0f43f3..c4a5108ca 100644 --- a/internal/refactor/v2/EVENT-PROJECTIONS.md +++ b/internal/refactor/v2/EVENT-PROJECTIONS.md @@ -2,7 +2,7 @@ 状态:implementation in progress / coverage baseline -上游事实源是 Codex c4f42d161ae44a8d696ee9fb595709661979d187。表中的 72 个 notification 和 11 个 reverse request 是审计全集,不代表 Lime 会无条件复制所有 Codex 产品功能。xuanlan 原稿记录的 10 类 request 未包含当前 revision 的 currentTime/read,本文件以 Codex/v1 机器清单为准。 +上游事实源是 Codex c4f42d161ae44a8d696ee9fb595709661979d187。表中的 72 个 notification 和 11 个 reverse request 是审计全集,不代表 Lime 会无条件复制所有 Codex 产品功能。Codex c9c6c0daa994109cec50fddcb57d076fdf9e738c 的 method 增量只新增 `server/diagnostics` client request,notification 与 reverse request 集合未变化;xuanlan 原稿记录的 10 类 request 未包含当前 revision 的 currentTime/read,本文件以 Codex/v1 机器清单为准。 每项必须有且只有一种裁决: @@ -107,7 +107,7 @@ Guardian warning 当前已完成独立 producer:同一 turn 内连续 3 次 Gu | 64 | thread/realtime/transcript/delta | DX | product-scope-excluded | Grok-aligned STT 不复用 Codex realtime wire | | 65 | thread/realtime/transcript/done | DX | product-scope-excluded | Grok-aligned STT 不复用 Codex realtime wire | | 66 | thread/realtime/outputAudio/delta | DX | product-scope-excluded | 不在 Renderer 建立 Codex 音频播放队列 | -| 67 | thread/realtime/sdp | DX | product-scope-excluded | 不恢复 WebRTC/SDP 通道 | +| 67 | thread/realtime/sdp | DX | product-scope-excluded | 不恢复 WebRTC/SDP 通道 | | 68 | thread/realtime/error | DX | product-scope-excluded | 只记录脱敏 method/field 诊断 | | 69 | thread/realtime/closed | DX | product-scope-excluded | 只记录脱敏 method/field 诊断 | | 70 | windows/worldWritableWarning | GN | planned | Windows 安全摘要和设置入口 | diff --git a/lime-rs/crates/app-server-protocol/schema/json/app_server_protocol.schemas.json b/lime-rs/crates/app-server-protocol/schema/json/app_server_protocol.schemas.json index ee3234933..4aa503077 100644 --- a/lime-rs/crates/app-server-protocol/schema/json/app_server_protocol.schemas.json +++ b/lime-rs/crates/app-server-protocol/schema/json/app_server_protocol.schemas.json @@ -28446,6 +28446,13 @@ ], "type": "string" }, + "HookExecutionMode": { + "enum": [ + "async", + "sync" + ], + "type": "string" + }, "HookHandlerType": { "enum": [ "agent", @@ -28509,6 +28516,10 @@ "eventName": { "$ref": "#/$defs/HookEventName" }, + "executionMode": { + "$ref": "#/$defs/HookExecutionMode", + "default": "sync" + }, "handlerType": { "$ref": "#/$defs/HookHandlerType" }, @@ -28827,6 +28838,13 @@ ], "type": "string" }, + "HookExecutionMode": { + "enum": [ + "async", + "sync" + ], + "type": "string" + }, "HookHandlerType": { "enum": [ "agent", @@ -28864,6 +28882,10 @@ "eventName": { "$ref": "#/$defs/HookEventName" }, + "executionMode": { + "$ref": "#/$defs/HookExecutionMode", + "default": "sync" + }, "handlerType": { "$ref": "#/$defs/HookHandlerType" }, @@ -29026,6 +29048,13 @@ ], "type": "string" }, + "HookExecutionMode": { + "enum": [ + "async", + "sync" + ], + "type": "string" + }, "HookHandlerType": { "enum": [ "agent", @@ -29063,6 +29092,10 @@ "eventName": { "$ref": "#/$defs/HookEventName" }, + "executionMode": { + "$ref": "#/$defs/HookExecutionMode", + "default": "sync" + }, "handlerType": { "$ref": "#/$defs/HookHandlerType" }, @@ -38483,6 +38516,14 @@ ], "type": "object" }, + "MultiAgentVersion": { + "enum": [ + "disabled", + "v1", + "v2" + ], + "type": "string" + }, "ReasoningEffortOption": { "properties": { "description": { @@ -38569,6 +38610,16 @@ "model": { "type": "string" }, + "multiAgentVersion": { + "anyOf": [ + { + "$ref": "#/$defs/MultiAgentVersion" + }, + { + "type": "null" + } + ] + }, "providerId": { "type": "string" }, @@ -39304,6 +39355,16 @@ "model": { "type": "string" }, + "multiAgentVersion": { + "anyOf": [ + { + "$ref": "#/$defs/MultiAgentVersion" + }, + { + "type": "null" + } + ] + }, "providerId": { "type": "string" }, @@ -39523,6 +39584,14 @@ ], "type": "object" }, + "MultiAgentVersion": { + "enum": [ + "disabled", + "v1", + "v2" + ], + "type": "string" + }, "ReasoningEffortOption": { "properties": { "description": { @@ -42877,6 +42946,16 @@ "title": "ModelVerificationNotification", "type": "object" }, + "MultiAgentVersion": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "enum": [ + "disabled", + "v1", + "v2" + ], + "title": "MultiAgentVersion", + "type": "string" + }, "NonSteerableTurnKind": { "$schema": "https://json-schema.org/draft/2020-12/schema", "enum": [ diff --git a/lime-rs/crates/app-server-protocol/schema/json/manifest.json b/lime-rs/crates/app-server-protocol/schema/json/manifest.json index 0efbd2a87..8b02afab8 100644 --- a/lime-rs/crates/app-server-protocol/schema/json/manifest.json +++ b/lime-rs/crates/app-server-protocol/schema/json/manifest.json @@ -2355,6 +2355,7 @@ "ModelUpgradeInfo", "ModelVerification", "ModelVerificationNotification", + "MultiAgentVersion", "NonSteerableTurnKind", "OverriddenMetadata", "PatchApplyStatus", diff --git a/lime-rs/crates/app-server-protocol/schema/json/v2/HookMetadata.json b/lime-rs/crates/app-server-protocol/schema/json/v2/HookMetadata.json index 46452af74..b00594255 100644 --- a/lime-rs/crates/app-server-protocol/schema/json/v2/HookMetadata.json +++ b/lime-rs/crates/app-server-protocol/schema/json/v2/HookMetadata.json @@ -16,6 +16,13 @@ ], "type": "string" }, + "HookExecutionMode": { + "enum": [ + "async", + "sync" + ], + "type": "string" + }, "HookHandlerType": { "enum": [ "agent", @@ -79,6 +86,10 @@ "eventName": { "$ref": "#/$defs/HookEventName" }, + "executionMode": { + "$ref": "#/$defs/HookExecutionMode", + "default": "sync" + }, "handlerType": { "$ref": "#/$defs/HookHandlerType" }, diff --git a/lime-rs/crates/app-server-protocol/schema/json/v2/HooksListEntry.json b/lime-rs/crates/app-server-protocol/schema/json/v2/HooksListEntry.json index 0a316d310..fc69e2c9e 100644 --- a/lime-rs/crates/app-server-protocol/schema/json/v2/HooksListEntry.json +++ b/lime-rs/crates/app-server-protocol/schema/json/v2/HooksListEntry.json @@ -31,6 +31,13 @@ ], "type": "string" }, + "HookExecutionMode": { + "enum": [ + "async", + "sync" + ], + "type": "string" + }, "HookHandlerType": { "enum": [ "agent", @@ -68,6 +75,10 @@ "eventName": { "$ref": "#/$defs/HookEventName" }, + "executionMode": { + "$ref": "#/$defs/HookExecutionMode", + "default": "sync" + }, "handlerType": { "$ref": "#/$defs/HookHandlerType" }, diff --git a/lime-rs/crates/app-server-protocol/schema/json/v2/HooksListResponse.json b/lime-rs/crates/app-server-protocol/schema/json/v2/HooksListResponse.json index 6d248ea97..ab0ae0aec 100644 --- a/lime-rs/crates/app-server-protocol/schema/json/v2/HooksListResponse.json +++ b/lime-rs/crates/app-server-protocol/schema/json/v2/HooksListResponse.json @@ -31,6 +31,13 @@ ], "type": "string" }, + "HookExecutionMode": { + "enum": [ + "async", + "sync" + ], + "type": "string" + }, "HookHandlerType": { "enum": [ "agent", @@ -68,6 +75,10 @@ "eventName": { "$ref": "#/$defs/HookEventName" }, + "executionMode": { + "$ref": "#/$defs/HookExecutionMode", + "default": "sync" + }, "handlerType": { "$ref": "#/$defs/HookHandlerType" }, diff --git a/lime-rs/crates/app-server-protocol/schema/json/v2/Model.json b/lime-rs/crates/app-server-protocol/schema/json/v2/Model.json index 440b20cac..345c1d354 100644 --- a/lime-rs/crates/app-server-protocol/schema/json/v2/Model.json +++ b/lime-rs/crates/app-server-protocol/schema/json/v2/Model.json @@ -229,6 +229,14 @@ ], "type": "object" }, + "MultiAgentVersion": { + "enum": [ + "disabled", + "v1", + "v2" + ], + "type": "string" + }, "ReasoningEffortOption": { "properties": { "description": { @@ -315,6 +323,16 @@ "model": { "type": "string" }, + "multiAgentVersion": { + "anyOf": [ + { + "$ref": "#/$defs/MultiAgentVersion" + }, + { + "type": "null" + } + ] + }, "providerId": { "type": "string" }, diff --git a/lime-rs/crates/app-server-protocol/schema/json/v2/ModelListResponse.json b/lime-rs/crates/app-server-protocol/schema/json/v2/ModelListResponse.json index 31fc9f1ef..084ffeaef 100644 --- a/lime-rs/crates/app-server-protocol/schema/json/v2/ModelListResponse.json +++ b/lime-rs/crates/app-server-protocol/schema/json/v2/ModelListResponse.json @@ -133,6 +133,16 @@ "model": { "type": "string" }, + "multiAgentVersion": { + "anyOf": [ + { + "$ref": "#/$defs/MultiAgentVersion" + }, + { + "type": "null" + } + ] + }, "providerId": { "type": "string" }, @@ -352,6 +362,14 @@ ], "type": "object" }, + "MultiAgentVersion": { + "enum": [ + "disabled", + "v1", + "v2" + ], + "type": "string" + }, "ReasoningEffortOption": { "properties": { "description": { diff --git a/lime-rs/crates/app-server-protocol/schema/json/v2/MultiAgentVersion.json b/lime-rs/crates/app-server-protocol/schema/json/v2/MultiAgentVersion.json new file mode 100644 index 000000000..7ea9ede00 --- /dev/null +++ b/lime-rs/crates/app-server-protocol/schema/json/v2/MultiAgentVersion.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "enum": [ + "disabled", + "v1", + "v2" + ], + "title": "MultiAgentVersion", + "type": "string" +} diff --git a/lime-rs/crates/app-server-protocol/src/protocol/v2/hook.rs b/lime-rs/crates/app-server-protocol/src/protocol/v2/hook.rs index 7d96ae1eb..e49decd4a 100644 --- a/lime-rs/crates/app-server-protocol/src/protocol/v2/hook.rs +++ b/lime-rs/crates/app-server-protocol/src/protocol/v2/hook.rs @@ -42,6 +42,12 @@ hook_enum!(HookHandlerType { Agent, }); hook_enum!(HookExecutionMode { Sync, Async }); + +impl Default for HookExecutionMode { + fn default() -> Self { + Self::Sync + } +} hook_enum!(HookScope { Thread, Turn }); hook_enum!(HookSource { System, @@ -105,6 +111,8 @@ pub struct HookMetadata { pub key: String, pub event_name: HookEventName, pub handler_type: HookHandlerType, + #[serde(default)] + pub execution_mode: HookExecutionMode, pub matcher: Option, pub command: Option, pub timeout_sec: u64, @@ -126,6 +134,7 @@ impl From<&core::HookSnapshot> for HookMetadata { key: value.key.clone(), event_name: value.event_name.into(), handler_type: value.handler_type.into(), + execution_mode: value.execution_mode.into(), matcher: value.matcher.clone(), command: value.command.clone(), timeout_sec: value.timeout_sec, diff --git a/lime-rs/crates/app-server-protocol/src/protocol/v2/model.rs b/lime-rs/crates/app-server-protocol/src/protocol/v2/model.rs index 051980b3f..3830653bf 100644 --- a/lime-rs/crates/app-server-protocol/src/protocol/v2/model.rs +++ b/lime-rs/crates/app-server-protocol/src/protocol/v2/model.rs @@ -41,6 +41,14 @@ pub struct ModelUpgradeInfo { pub migration_markdown: Option, } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub enum MultiAgentVersion { + Disabled, + V1, + V2, +} + #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)] #[serde(rename_all = "camelCase")] pub struct ReasoningEffortOption { @@ -67,6 +75,7 @@ pub struct Model { pub context_window: Option, pub max_output_tokens: Option, pub supports_personality: bool, + pub multi_agent_version: Option, pub additional_speed_tiers: Vec, pub service_tiers: Vec, pub default_service_tier: Option, diff --git a/lime-rs/crates/app-server-protocol/src/protocol/v2/schema_types.rs b/lime-rs/crates/app-server-protocol/src/protocol/v2/schema_types.rs index dad62c1f3..c1268f4c8 100644 --- a/lime-rs/crates/app-server-protocol/src/protocol/v2/schema_types.rs +++ b/lime-rs/crates/app-server-protocol/src/protocol/v2/schema_types.rs @@ -144,6 +144,7 @@ pub const V2_SCHEMA_TYPE_NAMES: &[&str] = &[ "ModelAvailabilityNux", "ModelServiceTier", "ModelUpgradeInfo", + "MultiAgentVersion", "ReasoningEffortOption", "Model", "ModelListResponse", diff --git a/lime-rs/crates/app-server-protocol/src/protocol/v2/tests.rs b/lime-rs/crates/app-server-protocol/src/protocol/v2/tests.rs index de84078ce..1956b0734 100644 --- a/lime-rs/crates/app-server-protocol/src/protocol/v2/tests.rs +++ b/lime-rs/crates/app-server-protocol/src/protocol/v2/tests.rs @@ -690,6 +690,7 @@ fn model_list_keeps_codex_fields_with_multimodel_extensions() { context_window: Some(400_000), max_output_tokens: Some(128_000), supports_personality: false, + multi_agent_version: Some(MultiAgentVersion::V2), additional_speed_tiers: Vec::new(), service_tiers: Vec::new(), default_service_tier: None, @@ -734,6 +735,7 @@ fn model_list_keeps_codex_fields_with_multimodel_extensions() { "contextWindow": 400000, "maxOutputTokens": 128000, "supportsPersonality": false, + "multiAgentVersion": "v2", "additionalSpeedTiers": [], "serviceTiers": [], "defaultServiceTier": null, diff --git a/lime-rs/crates/app-server-protocol/src/schema_export/registry.rs b/lime-rs/crates/app-server-protocol/src/schema_export/registry.rs index 52f64debb..709030013 100644 --- a/lime-rs/crates/app-server-protocol/src/schema_export/registry.rs +++ b/lime-rs/crates/app-server-protocol/src/schema_export/registry.rs @@ -823,6 +823,7 @@ pub(super) fn v2_schemas() -> Vec { typed_schema::("ModelAvailabilityNux"), typed_schema::("ModelServiceTier"), typed_schema::("ModelUpgradeInfo"), + typed_schema::("MultiAgentVersion"), typed_schema::("ReasoningEffortOption"), typed_schema::("Model"), typed_schema::("ModelListResponse"), diff --git a/lime-rs/crates/app-server/src/runtime/model_providers/selection.rs b/lime-rs/crates/app-server/src/runtime/model_providers/selection.rs index 56a3a0c09..d42b5a7fc 100644 --- a/lime-rs/crates/app-server/src/runtime/model_providers/selection.rs +++ b/lime-rs/crates/app-server/src/runtime/model_providers/selection.rs @@ -1,10 +1,12 @@ use super::super::{ProviderModelCatalog, RuntimeCore, RuntimeCoreError}; +use app_server_protocol::protocol::v2::MultiAgentVersion; use app_server_protocol::protocol::v2::{ThreadSettings, ThreadSettingsUpdateParams}; use app_server_protocol::*; use base64::engine::general_purpose::URL_SAFE_NO_PAD; use base64::Engine; use lime_core::models::model_registry::{ - EnhancedModelMetadata, ModelCapabilityProvenance, ModelModality, ModelVisibility, + EnhancedModelMetadata, ModelCapabilityProvenance, ModelModality, ModelMultiAgentVersion, + ModelVisibility, }; impl RuntimeCore { @@ -575,6 +577,11 @@ fn model_from_catalog(provider_id: &str, metadata: EnhancedModelMetadata) -> Mod context_window: metadata.limits.context_length, max_output_tokens: metadata.limits.max_output_tokens, supports_personality: false, + multi_agent_version: metadata.multi_agent_version.map(|version| match version { + ModelMultiAgentVersion::Disabled => MultiAgentVersion::Disabled, + ModelMultiAgentVersion::V1 => MultiAgentVersion::V1, + ModelMultiAgentVersion::V2 => MultiAgentVersion::V2, + }), additional_speed_tiers: Vec::new(), service_tiers, default_service_tier, @@ -812,6 +819,22 @@ mod tests { assert_eq!(projected.max_output_tokens, Some(64_000)); } + #[test] + fn model_list_preserves_only_explicit_multi_agent_version() { + let implicit = model("openai", "implicit", ModelVisibility::List); + let mut explicit = model("openai", "explicit", ModelVisibility::List); + explicit.multi_agent_version = Some(ModelMultiAgentVersion::V2); + + assert_eq!( + model_from_catalog("openai", implicit).multi_agent_version, + None + ); + assert_eq!( + model_from_catalog("openai", explicit).multi_agent_version, + Some(MultiAgentVersion::V2) + ); + } + #[test] fn model_list_uses_codex_offset_pagination_boundaries() { let catalogs = vec![catalog( diff --git a/lime-rs/crates/app-server/tests/hooks_jsonrpc.rs b/lime-rs/crates/app-server/tests/hooks_jsonrpc.rs index bb2d3afb8..a5115db3b 100644 --- a/lime-rs/crates/app-server/tests/hooks_jsonrpc.rs +++ b/lime-rs/crates/app-server/tests/hooks_jsonrpc.rs @@ -170,6 +170,7 @@ additionalContextLimit = 4096 let hook = &entry["hooks"][0]; assert_eq!(hook["eventName"], "preToolUse"); assert_eq!(hook["handlerType"], "command"); + assert_eq!(hook["executionMode"], "sync"); assert_eq!(hook["matcher"], "Bash"); assert_eq!(hook["command"], "python3 /tmp/project-hook.py"); assert_eq!(hook["timeoutSec"], 7); diff --git a/lime-rs/crates/core/src/models/model_registry.rs b/lime-rs/crates/core/src/models/model_registry.rs index 75117d387..01a09b701 100644 --- a/lime-rs/crates/core/src/models/model_registry.rs +++ b/lime-rs/crates/core/src/models/model_registry.rs @@ -194,6 +194,15 @@ pub enum ModelRuntimeFeature { ImagesApi, } +/// 模型显式声明支持的 Multi-Agent runtime 版本。 +#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)] +#[serde(rename_all = "snake_case")] +pub enum ModelMultiAgentVersion { + Disabled, + V1, + V2, +} + /// 模型部署来源 #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)] #[serde(rename_all = "snake_case")] @@ -433,6 +442,9 @@ pub struct EnhancedModelMetadata { /// 运行时特性 #[serde(default)] pub runtime_features: Vec, + /// 模型显式声明支持的 Multi-Agent runtime;缺失时不得推断。 + #[serde(default)] + pub multi_agent_version: Option, /// 部署来源 #[serde(default)] pub deployment_source: ModelDeploymentSource, @@ -490,6 +502,7 @@ impl EnhancedModelMetadata { input_modalities: vec![], output_modalities: vec![], runtime_features: vec![], + multi_agent_version: None, deployment_source: ModelDeploymentSource::UserCloud, management_plane: ModelManagementPlane::LocalSettings, canonical_model_id: None, @@ -842,6 +855,7 @@ impl ModelsDevModel { input_modalities: vec![], output_modalities: vec![], runtime_features: vec![], + multi_agent_version: None, deployment_source: ModelDeploymentSource::UserCloud, management_plane: ModelManagementPlane::LocalSettings, canonical_model_id: None, diff --git a/lime-rs/crates/services/src/model_registry_service.rs b/lime-rs/crates/services/src/model_registry_service.rs index 2d9330e49..1087019d1 100644 --- a/lime-rs/crates/services/src/model_registry_service.rs +++ b/lime-rs/crates/services/src/model_registry_service.rs @@ -3444,6 +3444,7 @@ impl ModelRegistryService { input_modalities: taxonomy.input_modalities, output_modalities: taxonomy.output_modalities, runtime_features: taxonomy.runtime_features, + multi_agent_version: None, deployment_source: taxonomy.deployment_source, management_plane: taxonomy.management_plane, canonical_model_id: taxonomy.canonical_model_id, diff --git a/packages/app-server-client/src/generated/protocol-types.ts b/packages/app-server-client/src/generated/protocol-types.ts index 4ffe174d9..a00093b0c 100644 --- a/packages/app-server-client/src/generated/protocol-types.ts +++ b/packages/app-server-client/src/generated/protocol-types.ts @@ -6140,6 +6140,7 @@ export interface HookMetadata { displayOrder: number; enabled: boolean; eventName: HookEventName; + executionMode?: HookExecutionMode; handlerType: HookHandlerType; isManaged: boolean; key: string; @@ -7199,6 +7200,7 @@ export interface Model { isDefault: boolean; maxOutputTokens?: number | null; model: string; + multiAgentVersion?: MultiAgentVersion | null; providerId: string; serviceTiers: ModelServiceTier[]; supportedReasoningEfforts: ReasoningEffortOption[]; @@ -7587,6 +7589,8 @@ export interface ModelVerificationNotification { verifications: ModelVerification[]; } +export type MultiAgentVersion = "disabled" | "v1" | "v2"; + export type NonSteerableTurnKind = "compact" | "review"; export interface OpenDeepLinkPayload { @@ -10737,6 +10741,8 @@ export type HookEventName = | "subagentStop" | "userPromptSubmit"; +export type HookExecutionMode = "async" | "sync"; + export type HookHandlerType = "agent" | "command" | "prompt"; export type HookSource = @@ -10754,8 +10760,6 @@ export type HookSource = export type HookTrustStatus = "managed" | "modified" | "trusted" | "untrusted"; -export type HookExecutionMode = "async" | "sync"; - export type HookRunStatus = | "blocked" | "completed" diff --git a/src/lib/api/agentRuntime/appServerCanonicalThreadProjection.test.ts b/src/lib/api/agentRuntime/appServerCanonicalThreadProjection.test.ts index ea2c83176..1b63d9726 100644 --- a/src/lib/api/agentRuntime/appServerCanonicalThreadProjection.test.ts +++ b/src/lib/api/agentRuntime/appServerCanonicalThreadProjection.test.ts @@ -8,6 +8,33 @@ import { const CREATED_AT_SECONDS = 1_780_704_000; describe("appServerCanonicalThreadProjection", () => { + it("从 current Thread route 投影 execution runtime,并优先顶层 provider", () => { + const detail = readCanonicalThreadDetail({ + thread: { + id: "thread-current-route", + sessionId: "session-current-route", + status: { type: "idle" }, + createdAt: CREATED_AT_SECONDS, + updatedAt: CREATED_AT_SECONDS + 1, + modelProvider: "provider-enabled", + extra: { + providerSelector: "provider-stale-storage", + providerName: "provider-stale-storage", + modelName: "shared-model", + }, + turns: [], + }, + }); + + expect(detail?.execution_runtime).toMatchObject({ + session_id: "session-current-route", + provider_selector: "provider-enabled", + provider_name: "provider-stale-storage", + model_name: "shared-model", + source: "session", + }); + }); + it("从最新成功 update_plan 恢复 checklist,且不生成 Plan Item", () => { const detail = readCanonicalThreadDetail({ thread: { diff --git a/src/lib/api/agentRuntime/appServerCanonicalThreadProjection.ts b/src/lib/api/agentRuntime/appServerCanonicalThreadProjection.ts index 98694398e..4e05eb5b4 100644 --- a/src/lib/api/agentRuntime/appServerCanonicalThreadProjection.ts +++ b/src/lib/api/agentRuntime/appServerCanonicalThreadProjection.ts @@ -5,6 +5,7 @@ import type { AgentThreadTurn, AgentThreadTurnStatus, } from "../agentProtocol"; +import type { AgentSessionExecutionRuntime } from "../agentExecutionRuntime"; import type { AgentRuntimeProfileStatus, AgentSessionDetail, @@ -236,6 +237,11 @@ export function readCanonicalThreadDetail( execution_strategy: executionStrategyFromProtocol( metadataString(metadata, "executionStrategy", "execution_strategy"), ), + execution_runtime: canonicalThreadExecutionRuntime( + thread, + metadata, + sessionId, + ), messages_count: canonicalThreadMessageCount(rawTurns, metadata), messages: [], turns, @@ -666,6 +672,48 @@ function canonicalThreadMetadata( : undefined; } +function canonicalThreadExecutionRuntime( + thread: Record, + metadata: Record | undefined, + sessionId: string, +): AgentSessionExecutionRuntime | undefined { + const providerSelector = + readOptionalStringField(thread, "modelProvider", "model_provider") + ?.trim() || + metadataString(metadata, "providerSelector", "provider_selector"); + const providerName = metadataString( + metadata, + "providerName", + "provider_name", + ); + const modelName = metadataString(metadata, "modelName", "model_name"); + if (!providerSelector && !providerName && !modelName) { + return undefined; + } + + return { + session_id: sessionId, + provider_selector: providerSelector, + provider_name: providerName, + model_name: modelName, + source_client: metadataString(metadata, "sourceClient", "source_client"), + imported_continuation: metadataRecord( + metadata, + "importedContinuation", + "imported_continuation", + ), + imported_thread_settings: metadataRecord( + metadata, + "importedThreadSettings", + "imported_thread_settings", + ), + execution_strategy: executionStrategyFromProtocol( + metadataString(metadata, "executionStrategy", "execution_strategy"), + ), + source: "session", + }; +} + /** * Imported threads are restored from another client and need the complete * canonical history before the renderer builds its timeline. diff --git a/src/lib/api/modelRegistry.test.ts b/src/lib/api/modelRegistry.test.ts index ea7103017..4ad048f29 100644 --- a/src/lib/api/modelRegistry.test.ts +++ b/src/lib/api/modelRegistry.test.ts @@ -132,6 +132,7 @@ function createCatalogModel( contextWindow: null, maxOutputTokens: null, supportsPersonality: false, + multiAgentVersion: null, additionalSpeedTiers: [], serviceTiers: [], defaultServiceTier: null, @@ -336,6 +337,7 @@ describe("modelRegistry API", () => { }, contextWindow: 400_000, maxOutputTokens: 128_000, + multiAgentVersion: "v2", }), ], nextCursor: null, @@ -434,6 +436,7 @@ describe("modelRegistry API", () => { "json_schema", "reasoning", ], + multi_agent_version: "v2", limits: { context_length: 400_000, max_output_tokens: 128_000, diff --git a/src/lib/api/modelRegistry.ts b/src/lib/api/modelRegistry.ts index 3fbbe37ca..f860aa896 100644 --- a/src/lib/api/modelRegistry.ts +++ b/src/lib/api/modelRegistry.ts @@ -332,6 +332,7 @@ function toRegistryModel(model: Model): EnhancedModelMetadata { input_modalities: inputModalities, output_modalities: outputModalities, runtime_features: runtimeFeatures, + multi_agent_version: model.multiAgentVersion ?? null, deployment_source: "user_cloud", management_plane: "local_settings", canonical_model_id: route.modelId, diff --git a/src/lib/governance/codexMethodProductScopeBoundary.test.ts b/src/lib/governance/codexMethodProductScopeBoundary.test.ts index bf7bcb32f..62f1533f4 100644 --- a/src/lib/governance/codexMethodProductScopeBoundary.test.ts +++ b/src/lib/governance/codexMethodProductScopeBoundary.test.ts @@ -65,7 +65,7 @@ function manifestKind(direction: Direction) { } describe("Codex method product scope boundary", () => { - it("220 个上游方法必须且只能落入一个三态分类", () => { + it("221 个上游方法必须且只能落入一个三态分类", () => { const matrix = readJson(MATRIX_PATH); const entries = flatten(matrix); const identities = entries.map( @@ -99,7 +99,7 @@ describe("Codex method product scope boundary", () => { createHash("sha256") .update(identities.toSorted().join("\n")) .digest("hex"), - ).toBe("44c63050d2b736b40c2060ffba2783e64c5f81f17b5926cbe99da60a667c8dc9"); + ).toBe("a91f5bdaedc5382cd957b82b44824922c7594aa16b33293916b6f48af4d8f899"); }); it("每组必须声明 owner、证据、优先级以及 planned/excluded 原因", () => { @@ -180,4 +180,21 @@ describe("Codex method product scope boundary", () => { ).toBe(false); } }); + + it("Codex process-local diagnostics must stay outside the Desktop manifest", () => { + const matrix = readJson(MATRIX_PATH); + const manifest = readJson(MANIFEST_PATH); + const entry = flatten(matrix).find( + ({ direction, method }) => + direction === "clientRequest" && method === "server/diagnostics", + ); + + expect(entry?.status).toBe("product-scope-excluded"); + expect( + manifest.methods.some( + ({ kind, method }) => + kind === "request" && method === "server/diagnostics", + ), + ).toBe(false); + }); }); diff --git a/src/lib/types/modelRegistry.ts b/src/lib/types/modelRegistry.ts index 5e5233c86..47ec303fa 100644 --- a/src/lib/types/modelRegistry.ts +++ b/src/lib/types/modelRegistry.ts @@ -98,6 +98,9 @@ export type ModelRuntimeFeature = | "chat_completions_api" | "images_api"; +/** 模型显式声明支持的 Multi-Agent runtime 版本。 */ +export type ModelMultiAgentVersion = "disabled" | "v1" | "v2"; + /** 模型部署来源 */ export type ModelDeploymentSource = "local" | "user_cloud" | "oem_cloud"; @@ -204,6 +207,8 @@ export interface EnhancedModelMetadata { output_modalities?: ModelModality[]; /** 运行时特性 */ runtime_features?: ModelRuntimeFeature[]; + /** 模型显式声明支持的 Multi-Agent runtime;缺失时不得推断。 */ + multi_agent_version?: ModelMultiAgentVersion | null; /** 部署来源 */ deployment_source?: ModelDeploymentSource; /** 管理面 */