Project canonical thread execution routes

This commit is contained in:
coso
2026-08-10 18:14:23 +08:00
parent fb465072fb
commit 88b5bf6a74
32 changed files with 401 additions and 28 deletions
+8 -1
View File
@@ -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 严格
@@ -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。
@@ -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 复核。
@@ -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 同方向契约。
@@ -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 cataloglist/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 configWindows 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 单一全局 ProviderLime 的 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 ownerCodex 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 必须写 gapexcluded 必须写 rationale,所有组必须写 owner/evidence/priority。
- `implemented` 必须能在 Lime generated manifest 找到同方向、同名 contract。
+8 -6
View File
@@ -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 planecatalog、model selection/switch、capability、tool subset、retry/circuit breaker |
| `/Users/coso/Documents/dev/js/opencode` | `fab213312927ea64cf968832c527206e8c944f9e` | provider wire planeendpoint 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 约束。
@@ -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",
+2 -2
View File
@@ -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 requestnotification 与 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 安全摘要和设置入口 |
@@ -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": [
@@ -2355,6 +2355,7 @@
"ModelUpgradeInfo",
"ModelVerification",
"ModelVerificationNotification",
"MultiAgentVersion",
"NonSteerableTurnKind",
"OverriddenMetadata",
"PatchApplyStatus",
@@ -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"
},
@@ -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"
},
@@ -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"
},
@@ -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"
},
@@ -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": {
@@ -0,0 +1,10 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"enum": [
"disabled",
"v1",
"v2"
],
"title": "MultiAgentVersion",
"type": "string"
}
@@ -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<String>,
pub command: Option<String>,
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,
@@ -41,6 +41,14 @@ pub struct ModelUpgradeInfo {
pub migration_markdown: Option<String>,
}
#[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<u32>,
pub max_output_tokens: Option<u32>,
pub supports_personality: bool,
pub multi_agent_version: Option<MultiAgentVersion>,
pub additional_speed_tiers: Vec<String>,
pub service_tiers: Vec<ModelServiceTier>,
pub default_service_tier: Option<String>,
@@ -144,6 +144,7 @@ pub const V2_SCHEMA_TYPE_NAMES: &[&str] = &[
"ModelAvailabilityNux",
"ModelServiceTier",
"ModelUpgradeInfo",
"MultiAgentVersion",
"ReasoningEffortOption",
"Model",
"ModelListResponse",
@@ -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,
@@ -823,6 +823,7 @@ pub(super) fn v2_schemas() -> Vec<GeneratedJsonSchema> {
typed_schema::<v2::ModelAvailabilityNux>("ModelAvailabilityNux"),
typed_schema::<v2::ModelServiceTier>("ModelServiceTier"),
typed_schema::<v2::ModelUpgradeInfo>("ModelUpgradeInfo"),
typed_schema::<v2::MultiAgentVersion>("MultiAgentVersion"),
typed_schema::<v2::ReasoningEffortOption>("ReasoningEffortOption"),
typed_schema::<v2::Model>("Model"),
typed_schema::<v2::ModelListResponse>("ModelListResponse"),
@@ -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(
@@ -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);
@@ -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<ModelRuntimeFeature>,
/// 模型显式声明支持的 Multi-Agent runtime;缺失时不得推断。
#[serde(default)]
pub multi_agent_version: Option<ModelMultiAgentVersion>,
/// 部署来源
#[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,
@@ -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,
@@ -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"
@@ -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: {
@@ -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<string, unknown>,
metadata: Record<string, unknown> | 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.
+3
View File
@@ -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,
+1
View File
@@ -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,
@@ -65,7 +65,7 @@ function manifestKind(direction: Direction) {
}
describe("Codex method product scope boundary", () => {
it("220 个上游方法必须且只能落入一个三态分类", () => {
it("221 个上游方法必须且只能落入一个三态分类", () => {
const matrix = readJson<Matrix>(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>(MATRIX_PATH);
const manifest = readJson<Manifest>(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);
});
});
+5
View File
@@ -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;
/** 管理面 */