@@ -169,6 +169,14 @@ fork 与上游改了同一处(常见于 TUI 视觉/UX、core 加固逻辑)
169169| ` packages/core/src/{session.ts,session/run-coordinator.ts,session/execution.ts,session/execution/local.ts} ` (v2 ` SessionV2.wait ` 实现) | 低 | 保留:实现 ` SessionV2.wait ` (原 stub 恒 ` OperationUnavailableError ` )。逐字对齐上游 in-flight 提交 ` 5e90a68d6a ` (wip(core): v2 subagent foundations):` SessionRunCoordinator.awaitIdle ` (await entry ` done ` + ` Effect.exit ` 吞掉失败/中断、循环复查 successor 直到 idle,空闲即 no-op、不发起 drain),` SessionExecution.awaitIdle ` 透传,` SessionV2.wait ` 委托并收窄为 ` NotFoundError ` ,server handler 移除死的 503 映射,literals 移除 ` "wait" ` (对齐 ` bd8d858bf7 ` 前态)。语义限制:仅覆盖本进程持有的执行;测试为 fork 补充(上游 wip 无测试):` packages/core/test/session-run-coordinator.test.ts ` (awaitIdle 4 例)+ ` packages/opencode/test/server/httpapi-session.test.ts ` (wait 改期望 204)(上游该分支合入后按上游版本对齐) |
170170| `packages/{schema,core,protocol,server}/src/**` + `packages/sdk/js/src/v2/gen` (v2 `SessionV2.skill` 实现) | 中 | 保留:实现 `SessionV2.skill`(原 stub 恒 `OperationUnavailableError`)。逐字移植上游 in-flight 提交 `23adaaaeab`(feat(core): add native skill activation):durable `SessionEvent.Skill.Activated` + `SessionMessage.Skill` + projector/message-updater/to-llm-message/compaction 全链路,`SessionV2.skill` 经 `locations.get(session.location)` 解析 `SkillV2.list()`、未命中报 `Session.SkillNotFoundError`、`resume !== false` 时 fork `execution.resume`,协议新增 `POST /api/session/:sessionID/skill`(404 `SkillNotFoundError`)+ server handler + SDK v2 重新生成。未移植部分:TUI skill UX(依赖上游更新的 useLocation 管线)、report skill、cli daemon、plugin skill.ts、packages/client gen。测试为 fork 补充:`packages/core/test/session-create.test.ts`(activates a known skill as a durable skill message)+ httpapi-exercise/httpapi-session 覆盖;manifest 计数随 durable 事件 +1(60/90/90/36)(上游该分支合入后按上游版本对齐) |
171171| `packages/{core,protocol,server}/src/**` + `packages/sdk/js/src/v2/gen` (v2 `SessionV2.shell` 实现) | 中 | 保留:实现 `SessionV2.shell`(原 stub 恒 `OperationUnavailableError`)。结构逐字对齐上游提交 `bd8d858bf7`(feat(core): implement V2 session.shell):`KeyedMutex` 按 Session 串行、`activeShells` 抑制 shell 期间 prompt wake、`execution.awaitIdle` 等待在跑 drain、durable `Shell.Started`/`Shell.Ended`(事件在 HEAD 已入 manifest,计数不变)、`Effect.ensuring` 清理 + `execution.wake`,协议新增 `POST /api/session/:sessionID/shell`(404 `SessionNotFoundError`)+ server handler + SDK v2 重新生成。唯一偏离:`runShellCommand` 内部用 HEAD 已有原语 `AppProcess.run` + `Shell.preferred`/`Shell.args`(v1 用户 shell 语义:config shell、TERM=dumb、extendEnv、stdin ignore、forceKillAfter 3s、合并输出、1MiB 截断、`AppProcessError` 捕获为输出文本)替代上游尚未移植的 location `Shell.Service`(`5ae93092aa`);`core/src/shell.ts` 保持原样。测试为 fork 补充:`packages/core/test/session-create.test.ts`(shell 3 例)+ httpapi-exercise/httpapi-session 覆盖(上游 `5ae93092aa`+`bd8d858bf7` 移植后取上游版本) |
172+ | ` packages/core/src/v1/config/migrate.ts ` (v1 provider 可用性列表 → v2 策略迁移) | 低 | 保留:补全 V1 ` disabled_providers ` /` enabled_providers ` → ` experimental.policies ` 的 ` provider.use ` 降级。此前 ` isV1 ` 识别这两个键但 ` migrate() ` 静默丢弃,V1 deny/allowlist 加载即丢失。新增 ` experimental() ` helper,映射顺序按 ` specs/v2/provider-policy.md:248-291 ` :disabled→逐条 deny;enabled→` deny * ` +逐条 allow;显式 ` experimental.policies ` 后置(last-match-wins 下显式优先)。测试 ` packages/core/test/config/config.test.ts ` (migrates legacy provider availability lists into policies)。属规格已规定的正确性修复,偏离面小(上游若实现同等迁移则取上游版本) |
173+ | ` packages/core/src/session/runner/model.ts ` (v2 runner 原生 Google/Gemini 路由) | 中 | 保留:` fromCatalogModel ` 新增 ` @ai-sdk/google ` → ` Gemini.route ` 原生分支(` x-goog-api-key ` 头鉴权),` supported() ` 纳入该包;复用 ` packages/llm ` 已有 ` Gemini.route ` ,零新协议。测试 ` packages/core/test/session-runner-model.test.ts ` (maps Google→Gemini route / x-goog-api-key auth / supported)。** 热点区** :落在 sync 清单 ` session/runner/* ` 上游高频重构区,上游若原生支持 Google 则取上游版本并移除本条目 |
174+ | ` packages/plugin/src/v2/effect/{context,event,index}.ts ` + ` packages/core/src/plugin/host.ts ` (插件 ` ctx.event.subscribe ` ) | 中 | 保留:实现 PLAN.md 阶段 8 的插件事件订阅。经 ` EventManifest.Latest ` (SDK 事件类型字符串与内部 ` definition.type ` 同名)解析订阅,payload 经 ` Schema.encodeUnknownSync ` 编码为 SDK 形状(进程内订阅者与远程 SDK 消费者拿到一致 encoded 侧),非 EventV2 定义的 SDK 类型(如 ` server.instance.disposed ` )返回空流。effect ` PluginContext ` 增 ` event ` 成员并导出 ` Event ` /` EventMap ` 。测试 ` packages/core/test/plugin.test.ts ` (delivers encoded events to plugin subscribers)(上游若实现插件事件适配器则对抗审计,上游若已做可取上游版本) |
175+ | ` packages/plugin/src/v2/effect/{context,tool,index}.ts ` + ` packages/core/src/plugin/host.ts ` + ` packages/core/src/session/hooks.ts ` (插件 ` ctx.tool.hook ` 运行时钩子) | 中 | 保留(** 待复审** ):新增插件 ` ctx.tool.hook("execute.before"/"execute.after") ` ,桥接到 runner 实际调用的 ` SessionHooks ` (before 支持 ` args.update ` /` deny ` /` skip ` ,after 支持 ` context.add ` );` SessionHooks.register* ` 改为 scope-owned(` Effect.addFinalizer ` 卸载,插件移除即注销)。` PluginV2.node ` 增 ` SessionHooks.node ` 依赖。测试 ` packages/core/test/plugin.test.ts ` (registers tool execution hooks through the plugin context)。** 注意** :CONTEXT.md「Flagged ambiguities」将「V2 plugins 是否暴露等价 hook」列为「Decide separately」的搁置设计问题;本实现先行落地(本地先行),下次 sync 须复审是否应改为插件定义 Context Source 或收窄语义(上游若给出官方 hook 设计则取上游版本并移除本条目) |
176+ | ` packages/core/src/session/tool-permissions.ts ` + ` session/runner/llm.ts ` (per-session 工具权限覆盖接缝) | 低 | 保留(fork 自有,本地先行 B 路线基础):新增 Location 作用域 ` SessionToolPermissions ` (sessionID→` PermissionV2.Ruleset ` 内存 map),runner 在 ` tools.materialize ` 前先查覆盖、缺省回退 ` agent.info.permissions ` 。为子代理改走 durable 管线后保留「无显式权限则只读」(` SUBAGENT_READONLY_RULES ` )的 fork 安全默认而设(durable runner 原生只用 agent 权限,无 per-session 注入缝)。当前无消费方设置覆盖(行为不变),随 subagent durable 改写启用;` packages/core/test/session-runner.test.ts ` 全绿(空覆盖零回归)。上游若提供 per-session 工具权限机制则取上游版本 |
177+ | `packages/{schema,core,server,opencode}/src/**` (v2 子代理事件解耦 durable 管线) | 中 | 保留(**fork 抢先,接受偏离,上游合并时收敛**):`delegate_task` 子代理改走 durable 管线。location 作用域 `SubagentRunner` 不能静态依赖全局 `SessionV2`(`SessionV2 → LocationServiceMap → location图` 成环),故新增两个 **live** 事件 `session.next.subagent.requested`/`.result`(非 durable、不入 manifest 计数):`SubagentRunner` 设只读覆盖(`SessionToolPermissions`)后发 `Requested` 并等 `Result`;新增**全局** `SubagentExecutor`(`subagent/executor.ts`,`EventV2.subscribe` 异步消费、后台 fiber 经 `SessionV2.create→prompt→wait→读投影` 驱动子会话,回发 `Result` + durable `Spawned/Completed`),接在 `packages/server/routes.ts` 与 opencode instance server(与 `SessionV2.node` 同组)。镜像 fork 现有「location runner 被全局 `SessionExecution` 驱动」模式。支持 `background` 模式:`delegate_task` 传 `background=true` 时 `SubagentRunner` 发 `Requested` 后立即返回 `running`,执行器经 `BackgroundJob` 跟踪该子代理、驱动完成后把结果以 steer prompt 注入父会话。fork 现有 `subagent/` 手搓 loop 的 fork/resume 模式暂保留。测试 `packages/core/test/subagent-runner.test.ts`(端到端:父会话→子代理 durable 运行→返回文本)。**上游正以插件形态(`SubagentTool.Plugin` + `PluginRuntime`)做子代理入 V2,本实现为 fork 自有路线,上游该能力稳定合入后对抗审计收敛** |
178+ | ` packages/core/src/tool/mcp.ts ` + ` packages/opencode/src/mcp/v2.ts ` + instance server (v2 MCP 工具注册) | 中 | 保留(** fork 抢先,上游 dev 尚无 V2 MCP** ):依赖反转——core 定义 ` MCP.Service ` 接口(` tools() ` /` call() ` ,core 不碰 MCP 协议)+ 空默认全局节点 + ` MCP.toolNode ` (location 作用域,经 ` MCPClient ` 取工具、转 ` Tool.AnyTool ` 、` Tools.Service.register ` 注册,注册错误 ` orDie ` 避免污染 location图错误类型);opencode ` mcp/v2.ts ` 包裹现有 V1 ` MCP.Service ` 提供真实实现,经 ` buildLocationServiceMap([[MCP.node, MCPV2.node]]) ` 替换空节点。第一版 input 用通用 object schema(保留各 MCP 工具 JSON schema 给模型是后续)。测试 ` packages/core/test/tool-mcp.test.ts ` (MCP 工具注册进 V2 ToolRegistry)。上游提供 V2 MCP 后对抗审计收敛 |
179+ | ` packages/core/src/session.ts ` (v2 ` SessionV2.create ` parentID/title/location 继承) | 低 | 保留:逐字移植上游 in-flight 提交 ` 5e90a68d6a ` (wip(core): v2 subagent foundations)的 create 切片。` CreateInput ` 增 ` parentID ` /` title ` 、` location ` 改为可选(缺省且给定 parentID 时子会话继承父会话 location),` create ` 内解析父 location 并写入 ` parentID ` /` title ` 、` SessionV1.Event.Created ` 改用解析后的 location。是 v2 子代理持久化管线的前置基础(awaitIdle/wait 切片已在本清单前条登记)。` packages/core/test/session-create.test.ts ` 全绿(上游该分支合入后按上游版本对齐)。** 注** :` 5e90a68d6a ` 的 subagent 工具为 node 接线(location 作用域工具依赖全局 ` SessionV2 ` →未绑定 ` SessionExecution ` ),上游后续已放弃该接线、改为经 ` PluginInternal ` 注册的插件形态(` 1ea9137c01 ` );故本条仅移植 create 基础,subagent 工具本体待按上游插件形态适配移植 |
172180
173181### TUI 偏离(四批 23 轮审计打磨,全域)
174182
0 commit comments