@zhushanwen/subagent-core 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (278) hide show
  1. package/README.md +1 -1
  2. package/dist/chunk-KXVBIVOU.js +16 -0
  3. package/dist/chunk-T2SYBW3I.js +24 -0
  4. package/dist/chunk-VURUAGMM.js +2305 -0
  5. package/dist/{types-C3fE3R9x.d.cts → engine-discovery-scan-ocpM8FmI.d.cts} +770 -668
  6. package/dist/{types-C3fE3R9x.d.ts → engine-discovery-scan-ocpM8FmI.d.ts} +770 -668
  7. package/dist/execution/engine/engine-discovery-scan.cjs +2210 -0
  8. package/dist/execution/engine/engine-discovery-scan.d.cts +4 -0
  9. package/dist/execution/engine/engine-discovery-scan.d.ts +4 -0
  10. package/dist/execution/engine/engine-discovery-scan.js +20 -0
  11. package/dist/execution/engine/paths.cjs +6 -23
  12. package/dist/execution/engine/paths.d.cts +1 -8
  13. package/dist/execution/engine/paths.d.ts +1 -8
  14. package/dist/execution/engine/paths.js +1 -1
  15. package/dist/execution/relay-env.cjs +12 -28
  16. package/dist/execution/relay-env.d.cts +1 -33
  17. package/dist/execution/relay-env.d.ts +1 -33
  18. package/dist/execution/relay-env.js +5 -3
  19. package/dist/index.cjs +14045 -16059
  20. package/dist/index.d.cts +1035 -1579
  21. package/dist/index.d.ts +1035 -1579
  22. package/dist/index.js +9838 -13800
  23. package/dist.bundle/index.cjs +28875 -30323
  24. package/package.json +20 -26
  25. package/src/__tests__/record-store-last-line.test.ts +16 -7
  26. package/src/core/error-message.ts +7 -6
  27. package/src/core/host-services.ts +8 -2
  28. package/src/core/notify-ports.ts +17 -2
  29. package/src/execution/__tests__/chat-engine-routing.test.ts +62 -28
  30. package/src/execution/__tests__/chat-round-first-round-watchdog.test.ts +255 -0
  31. package/src/execution/__tests__/collect-coordinator-service.test.ts +36 -47
  32. package/src/execution/__tests__/collect-mixed-dispatch.test.ts +20 -53
  33. package/src/execution/__tests__/delivery-methods.test.ts +179 -237
  34. package/src/execution/__tests__/execute-and-await-worktree.test.ts +0 -2
  35. package/src/execution/__tests__/execute-nesting.test.ts +20 -13
  36. package/src/execution/__tests__/explicit-agent-ref-guard.test.ts +20 -33
  37. package/src/execution/__tests__/gc-timer.test.ts +7 -22
  38. package/src/execution/__tests__/get-record-for-action-restart.test.ts +20 -10
  39. package/src/execution/__tests__/helpers/fake-engine-port.ts +187 -0
  40. package/src/execution/__tests__/helpers/spawn-mock.ts +36 -9
  41. package/src/execution/__tests__/helpers/subagent-service-mocks.ts +1 -1
  42. package/src/execution/__tests__/idle-gc.test.ts +200 -0
  43. package/src/execution/__tests__/lifecycle-predicates.test.ts +26 -21
  44. package/src/execution/__tests__/nested-visibility-env-propagation.test.ts +5 -2
  45. package/src/execution/__tests__/reconcile-sweep.test.ts +200 -0
  46. package/src/execution/__tests__/record-store.test.ts +60 -6
  47. package/src/execution/__tests__/recursive-visibility-baseline.test.ts +20 -13
  48. package/src/execution/__tests__/round-supervisor.test.ts +293 -0
  49. package/src/execution/__tests__/session-pending.test.ts +119 -17
  50. package/src/execution/__tests__/stream-sink-retirement.test.ts +10 -10
  51. package/src/execution/__tests__/subagent-service-multiproc-guard.test.ts +1 -11
  52. package/src/execution/__tests__/subagent-service-notify-gate.test.ts +33 -30
  53. package/src/execution/__tests__/subagent-service-parent-guard.test.ts +2 -9
  54. package/src/execution/__tests__/subagent-service-recovery-bounds.test.ts +59 -129
  55. package/src/execution/__tests__/subagent-service.test.ts +2 -2
  56. package/src/execution/__tests__/subprocess-agent-runner-routing.test.ts +109 -7
  57. package/src/execution/__tests__/subprocess-agent-runner.test.ts +108 -36
  58. package/src/execution/__tests__/sync-collect-recovery.test.ts +21 -36
  59. package/src/execution/__tests__/workflow-state-root.test.ts +232 -0
  60. package/src/execution/agent-registry.ts +6 -2
  61. package/src/execution/dialog-queue.ts +6 -73
  62. package/src/execution/engine/__tests__/common/capability-gate.test.ts +115 -15
  63. package/src/execution/engine/__tests__/common/errors.test.ts +11 -18
  64. package/src/execution/engine/__tests__/common/kill-chain.test.ts +7 -0
  65. package/src/execution/engine/__tests__/common/nesting-guard.test.ts +9 -3
  66. package/src/execution/engine/__tests__/common/session-view-service.test.ts +90 -3
  67. package/src/execution/engine/__tests__/conformance/H9-test-disposition.md +116 -0
  68. package/src/execution/engine/__tests__/conformance/__fixtures__/engine-protocol/fake-engine-protocol.mjs +377 -0
  69. package/src/execution/engine/__tests__/conformance/__fixtures__/engine-protocol/recorded.fixture.json +331 -0
  70. package/src/execution/engine/__tests__/conformance/__fixtures__/engine-protocol/smoke-run.fixture.json +213 -0
  71. package/src/execution/engine/__tests__/conformance/chat-round-protocol.test.ts +230 -0
  72. package/src/execution/engine/__tests__/conformance/contract.abort.test.ts +69 -42
  73. package/src/execution/engine/__tests__/conformance/contract.agent-events.test.ts +4 -81
  74. package/src/execution/engine/__tests__/conformance/contract.probe.test.ts +67 -44
  75. package/src/execution/engine/__tests__/conformance/contract.read-degradation.test.ts +81 -54
  76. package/src/execution/engine/__tests__/conformance/engine-conformance.live.test.ts +133 -70
  77. package/src/execution/engine/__tests__/conformance/engine-crash.test.ts +143 -0
  78. package/src/execution/engine/__tests__/conformance/fake-engine-capabilities.ts +19 -0
  79. package/src/execution/engine/__tests__/conformance/golden-replay.pi.test.ts +7 -2
  80. package/src/execution/engine/__tests__/conformance/golden-replay.zcode.test.ts +6 -5
  81. package/src/execution/engine/__tests__/conformance/protocol-blackbox.test.ts +398 -0
  82. package/src/execution/engine/__tests__/conformance/registry-fork-filter.test.ts +221 -0
  83. package/src/execution/engine/__tests__/conformance/round-liveness-supervisor.test.ts +302 -0
  84. package/src/execution/engine/__tests__/conformance/static-spawn-guard.test.ts +58 -0
  85. package/src/execution/engine/__tests__/engine-discovery-scan.test.ts +558 -0
  86. package/src/execution/engine/__tests__/host-task-spec.test.ts +45 -0
  87. package/src/execution/engine/__tests__/model-ref-split.test.ts +74 -0
  88. package/src/execution/engine/__tests__/registry.test.ts +206 -1
  89. package/src/execution/engine/__tests__/routing.test.ts +97 -0
  90. package/src/execution/engine/__tests__/run-failure-worktree-cleanup.test.ts +97 -0
  91. package/src/execution/engine/client/__tests__/__fixtures__/fake-engine.mjs +294 -0
  92. package/src/execution/engine/client/__tests__/engine-client.test.ts +516 -0
  93. package/src/execution/engine/client/__tests__/mirror.test.ts +67 -0
  94. package/src/execution/engine/client/__tests__/pid-file.test.ts +257 -0
  95. package/src/execution/engine/client/__tests__/protocol-closure.test.ts +95 -0
  96. package/src/execution/engine/client/__tests__/remote-engine.test.ts +457 -0
  97. package/src/execution/engine/client/client-options.ts +103 -0
  98. package/src/execution/engine/client/engine-client.ts +687 -0
  99. package/src/execution/engine/client/mirror.ts +167 -0
  100. package/src/execution/engine/client/pid-file.ts +392 -0
  101. package/src/execution/engine/client/reaper.ts +95 -0
  102. package/src/execution/engine/client/remote-engine.ts +441 -0
  103. package/src/execution/engine/client/reverse-router.ts +255 -0
  104. package/src/execution/engine/common/capability-gate.ts +109 -22
  105. package/src/execution/engine/common/errors.ts +9 -25
  106. package/src/execution/engine/common/event-journal.ts +4 -50
  107. package/src/execution/engine/common/journal-replay.ts +3 -1
  108. package/src/execution/engine/common/kill-chain.ts +18 -251
  109. package/src/execution/engine/common/nesting-guard.ts +18 -114
  110. package/src/execution/engine/common/pool-manager.ts +4 -0
  111. package/src/execution/engine/common/session-view-service.ts +56 -84
  112. package/src/execution/engine/config.ts +151 -0
  113. package/src/execution/engine/d8-compat.ts +346 -0
  114. package/src/execution/engine/engine-discovery-roots.ts +107 -0
  115. package/src/execution/engine/engine-discovery-scan.ts +269 -0
  116. package/src/execution/engine/engine-discovery.ts +30 -7
  117. package/src/execution/engine/engine-inspect-package.ts +282 -0
  118. package/src/execution/engine/engine-manifest.ts +244 -0
  119. package/src/execution/engine/host/__tests__/host-askuser-endpoint.test.ts +123 -0
  120. package/src/execution/engine/host/__tests__/host-bridge.test.ts +135 -0
  121. package/src/execution/engine/host/__tests__/spawned-children.test.ts +73 -0
  122. package/src/execution/engine/host/host-bridge.ts +150 -0
  123. package/src/execution/engine/host/host-ui-endpoint.ts +47 -0
  124. package/src/execution/engine/host/pi-host-binding.ts +91 -0
  125. package/src/execution/engine/host/spawned-children.ts +139 -0
  126. package/src/execution/engine/host-task-spec.ts +29 -2
  127. package/src/execution/engine/model-validation.ts +55 -2
  128. package/src/execution/engine/paths.ts +16 -41
  129. package/src/execution/engine/port.ts +48 -2
  130. package/src/execution/engine/registry.ts +153 -34
  131. package/src/execution/engine/routing.ts +225 -52
  132. package/src/execution/engine/types.ts +25 -200
  133. package/src/execution/finalize-record.ts +25 -0
  134. package/src/execution/idle-gc.ts +89 -14
  135. package/src/execution/lifecycle-manager.ts +10 -7
  136. package/src/execution/lifecycle-predicates.ts +10 -8
  137. package/src/execution/record-store.ts +29 -2
  138. package/src/execution/relay-env.ts +19 -36
  139. package/src/execution/round-supervisor/domain.ts +89 -0
  140. package/src/execution/round-supervisor/index.ts +33 -0
  141. package/src/execution/round-supervisor/notify-accounting.ts +87 -0
  142. package/src/execution/round-supervisor/reconcile-sweep.ts +235 -0
  143. package/src/execution/round-supervisor/service-binding.test.ts +661 -0
  144. package/src/execution/round-supervisor/service-binding.ts +273 -0
  145. package/src/execution/round-supervisor/supervisor.ts +426 -0
  146. package/src/execution/session-pending.ts +68 -74
  147. package/src/execution/settled-watchdog.ts +39 -0
  148. package/src/execution/subagent-service.ts +746 -400
  149. package/src/execution/subprocess-agent-runner.ts +16 -8
  150. package/src/execution/types.ts +41 -117
  151. package/src/execution/ui-channels.ts +13 -214
  152. package/src/execution/ui-request-handler-factory.ts +7 -4
  153. package/src/execution/ui-request-observability.ts +2 -2
  154. package/src/execution/workflow-state-root.ts +67 -0
  155. package/src/execution/worktree-git-ops.ts +5 -0
  156. package/src/execution/worktree-manager.ts +11 -1
  157. package/src/index.ts +55 -26
  158. package/src/orchestration/__tests__/execute-agent-call.test.ts +1 -1
  159. package/src/orchestration/execute-agent-call.ts +1 -1
  160. package/src/orchestration/file-run-store.ts +144 -59
  161. package/src/orchestration/models/types.ts +43 -42
  162. package/src/shared/zcode-model-ref.ts +31 -0
  163. package/dist/chunk-43ONBFZX.js +0 -240
  164. package/dist/chunk-A4IVZWVX.js +0 -31
  165. package/dist/chunk-APZY4IME.js +0 -27
  166. package/dist/chunk-V3VHZ2VX.js +0 -59
  167. package/dist/execution/engine/engines/zcode/constants.cjs +0 -107
  168. package/dist/execution/engine/engines/zcode/constants.d.cts +0 -135
  169. package/dist/execution/engine/engines/zcode/constants.d.ts +0 -135
  170. package/dist/execution/engine/engines/zcode/constants.js +0 -54
  171. package/dist/execution/engine/engines/zcode/reader.cjs +0 -276
  172. package/dist/execution/engine/engines/zcode/reader.d.cts +0 -21
  173. package/dist/execution/engine/engines/zcode/reader.d.ts +0 -21
  174. package/dist/execution/engine/engines/zcode/reader.js +0 -9
  175. package/src/__tests__/append-system-prompt-assembly.test.ts +0 -243
  176. package/src/__tests__/fr4-get-state-handshake.test.ts +0 -125
  177. package/src/__tests__/session-runner.test.ts +0 -69
  178. package/src/execution/__tests__/ask-user-transit-e2e.test.ts +0 -490
  179. package/src/execution/__tests__/chatmode-first-round-closure-spawn.test.ts +0 -191
  180. package/src/execution/__tests__/descendant-sweep-guards.test.ts +0 -220
  181. package/src/execution/__tests__/descendant-sweep.test.ts +0 -269
  182. package/src/execution/__tests__/engine-model-validation.test.ts +0 -741
  183. package/src/execution/__tests__/epipe-fallback.test.ts +0 -248
  184. package/src/execution/__tests__/execution-runtime-face.test.ts +0 -272
  185. package/src/execution/__tests__/get-state-handshake.test.ts +0 -127
  186. package/src/execution/__tests__/helpers/session-runner-mocks.ts +0 -113
  187. package/src/execution/__tests__/keep-alive-no-progress.test.ts +0 -280
  188. package/src/execution/__tests__/kill-all-escalation.test.ts +0 -196
  189. package/src/execution/__tests__/max-turns-to-watchdog-ms.test.ts +0 -113
  190. package/src/execution/__tests__/output-collector.test.ts +0 -469
  191. package/src/execution/__tests__/pi-invocation.test.ts +0 -166
  192. package/src/execution/__tests__/recursive-visibility-env.test.ts +0 -149
  193. package/src/execution/__tests__/rpc-mode.test.ts +0 -89
  194. package/src/execution/__tests__/run-and-finalize-anchoring.test.ts +0 -387
  195. package/src/execution/__tests__/run-and-finalize-chatmode.test.ts +0 -277
  196. package/src/execution/__tests__/run-spawn-chatmode-settled.test.ts +0 -254
  197. package/src/execution/__tests__/run-spawn-edges.test.ts +0 -1079
  198. package/src/execution/__tests__/run-spawn-integration.test.ts +0 -933
  199. package/src/execution/__tests__/run-spawn-resume.test.ts +0 -322
  200. package/src/execution/__tests__/run-spawn-rpc-mode.test.ts +0 -196
  201. package/src/execution/__tests__/run-spawn-stdout-callback-throw.test.ts +0 -207
  202. package/src/execution/__tests__/service-kill-escalation.test.ts +0 -91
  203. package/src/execution/__tests__/session-runner-branch-cache-lru.test.ts +0 -110
  204. package/src/execution/__tests__/session-runner-close-prune.test.ts +0 -181
  205. package/src/execution/__tests__/session-runner-dispatch.test.ts +0 -489
  206. package/src/execution/__tests__/session-runner-epipe.test.ts +0 -179
  207. package/src/execution/__tests__/session-runner-heartbeat-idle-fallback.test.ts +0 -227
  208. package/src/execution/__tests__/session-runner-lifecycle-helpers.test.ts +0 -290
  209. package/src/execution/__tests__/session-runner-schema-env.test.ts +0 -352
  210. package/src/execution/__tests__/settled-watchdog.test.ts +0 -524
  211. package/src/execution/__tests__/spawn-args.test.ts +0 -446
  212. package/src/execution/__tests__/spawn-event-adapter-rpc.test.ts +0 -192
  213. package/src/execution/__tests__/spawn-event-adapter.test.ts +0 -167
  214. package/src/execution/__tests__/spawn-worktree-guidance.test.ts +0 -208
  215. package/src/execution/__tests__/spawned-children.test.ts +0 -236
  216. package/src/execution/__tests__/start-sync-model-guard.test.ts +0 -150
  217. package/src/execution/__tests__/stdin-writer.test.ts +0 -464
  218. package/src/execution/__tests__/subagent-service-message-close.test.ts +0 -693
  219. package/src/execution/__tests__/temp-prompt.test.ts +0 -53
  220. package/src/execution/__tests__/timeout-integration.test.ts +0 -616
  221. package/src/execution/__tests__/turn-limiter-semantics.test.ts +0 -194
  222. package/src/execution/__tests__/turn-limiter.test.ts +0 -65
  223. package/src/execution/__tests__/ui-request-handler.test.ts +0 -205
  224. package/src/execution/__tests__/ui-request-queue.test.ts +0 -298
  225. package/src/execution/__tests__/worktree-pid-registration.integration.test.ts +0 -230
  226. package/src/execution/engine/__tests__/common/schema-emulation.test.ts +0 -128
  227. package/src/execution/engine/__tests__/common/session-view-service-zcode-dbpath.test.ts +0 -149
  228. package/src/execution/engine/__tests__/conformance/__fixtures__/pi-golden-events.json +0 -28
  229. package/src/execution/engine/__tests__/conformance/zcode-appserver-harness.ts +0 -128
  230. package/src/execution/engine/__tests__/paths.test.ts +0 -39
  231. package/src/execution/engine/common/schema-emulation.ts +0 -189
  232. package/src/execution/engine/common/session-view-projection.ts +0 -51
  233. package/src/execution/engine/engines/pi/__tests__/pi-engine.test.ts +0 -615
  234. package/src/execution/engine/engines/pi/__tests__/reader.test.ts +0 -155
  235. package/src/execution/engine/engines/pi/__tests__/spawn-opts-direct.test.ts +0 -257
  236. package/src/execution/engine/engines/pi/argv-mirror.ts +0 -135
  237. package/src/execution/engine/engines/pi/get-state-handshake.ts +0 -179
  238. package/src/execution/engine/engines/pi/output-collector.ts +0 -317
  239. package/src/execution/engine/engines/pi/pi-engine.ts +0 -811
  240. package/src/execution/engine/engines/pi/pi-invocation.ts +0 -120
  241. package/src/execution/engine/engines/pi/reader.ts +0 -59
  242. package/src/execution/engine/engines/pi/registration.ts +0 -37
  243. package/src/execution/engine/engines/pi/session-runner.ts +0 -2840
  244. package/src/execution/engine/engines/pi/spawn-event-adapter.ts +0 -404
  245. package/src/execution/engine/engines/pi/stdin-writer.ts +0 -199
  246. package/src/execution/engine/engines/pi/temp-prompt.ts +0 -62
  247. package/src/execution/engine/engines/pi/turn-limiter.ts +0 -102
  248. package/src/execution/engine/engines/zcode/__tests__/__fixtures__/fake-appserver.mjs +0 -301
  249. package/src/execution/engine/engines/zcode/__tests__/__fixtures__/zcode-golden-appserver.json +0 -36
  250. package/src/execution/engine/engines/zcode/__tests__/appserver-launcher.test.ts +0 -321
  251. package/src/execution/engine/engines/zcode/__tests__/connection.test.ts +0 -473
  252. package/src/execution/engine/engines/zcode/__tests__/parser.test.ts +0 -43
  253. package/src/execution/engine/engines/zcode/__tests__/preparer.test.ts +0 -124
  254. package/src/execution/engine/engines/zcode/__tests__/reader.test.ts +0 -210
  255. package/src/execution/engine/engines/zcode/__tests__/registration.test.ts +0 -71
  256. package/src/execution/engine/engines/zcode/__tests__/session-channel-dispose-harvest.test.ts +0 -247
  257. package/src/execution/engine/engines/zcode/__tests__/session-channel-turn-timers.test.ts +0 -451
  258. package/src/execution/engine/engines/zcode/__tests__/session-channel.test.ts +0 -792
  259. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-appserver.test.ts +0 -782
  260. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-degrade.test.ts +0 -168
  261. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-dispose.test.ts +0 -210
  262. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-retry.test.ts +0 -353
  263. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-status.test.ts +0 -282
  264. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-timeout.test.ts +0 -372
  265. package/src/execution/engine/engines/zcode/__tests__/zcode-engine.live.test.ts +0 -145
  266. package/src/execution/engine/engines/zcode/appserver-launcher.ts +0 -167
  267. package/src/execution/engine/engines/zcode/connection.ts +0 -598
  268. package/src/execution/engine/engines/zcode/constants.ts +0 -176
  269. package/src/execution/engine/engines/zcode/golden-sample.ts +0 -47
  270. package/src/execution/engine/engines/zcode/parser.ts +0 -102
  271. package/src/execution/engine/engines/zcode/preparer.ts +0 -235
  272. package/src/execution/engine/engines/zcode/reader.ts +0 -381
  273. package/src/execution/engine/engines/zcode/registration.ts +0 -37
  274. package/src/execution/engine/engines/zcode/session-channel.ts +0 -968
  275. package/src/execution/engine/engines/zcode/zcode-engine.ts +0 -1431
  276. package/src/execution/round-settlement.ts +0 -93
  277. package/src/execution/ui-request-queue.ts +0 -215
  278. package/src/shared/schema-env.ts +0 -44
@@ -0,0 +1,441 @@
1
+ // src/execution/engine/client/remote-engine.ts
2
+ //
3
+ // RemoteEngine:cli 形态 EnginePort 适配(W2,impl-plan §2.2「RemoteEngine 同步成员
4
+ // 形态映射」必写死)。把 core EnginePort 的 9 成员映射到 EngineClient 协议请求;
5
+ // 同步成员(capabilities / listModels / validateModel)**只读 manifest 注册期快照**
6
+ // ——单源化原则(设计 §3.3「同步成员清单」v6 减法):无握手缓存、无失效时机,
7
+ // initialize 应答仅诊断(warn 由 EngineClient 留痕)。
8
+ //
9
+ // 直接 implements EnginePort:SDK 契约类型与 core 中立类型是结构等价闭包,
10
+ // implements 即编译期结构互证(字段漂移在 typecheck 期报错,与 protocol-closure
11
+ // 双向可赋值断言同向)。
12
+ //
13
+ // W3 消费契约:routing/registry 的 cli 形态 EnginePort 实例 = 本类(先写后读)。
14
+
15
+ import {
16
+ CANCEL_SETTLE_GRACE_MS,
17
+ EngineSdkError,
18
+ type AgentCallOpts as SdkAgentCallOpts,
19
+ type AgentOutcome as SdkAgentOutcome,
20
+ type EngineHandleData as SdkEngineHandleData,
21
+ type InteractAction as SdkInteractAction,
22
+ type InteractResult as SdkInteractResult,
23
+ type ModelCatalogEntry,
24
+ type ProbeReport as SdkProbeReport,
25
+ type SessionView as SdkSessionView,
26
+ } from "@zhushanwen/subagent-engine-sdk";
27
+
28
+ import type { AgentCallOpts } from "../../../orchestration/models/types.ts";
29
+ import { assertGateCapabilitiesMatched } from "../common/capability-gate.ts";
30
+ import type {
31
+ EngineCapabilities,
32
+ EngineHandle,
33
+ EngineHandleData,
34
+ InteractAction,
35
+ InteractResult,
36
+ ProbeReport,
37
+ SessionView,
38
+ } from "../types.ts";
39
+ import type { ChatRoundRoute, EnginePort, EngineRunResult, RunContext } from "../port.ts";
40
+ import type { EngineClient, RunRoute } from "./engine-client.ts";
41
+
42
+ /** manifest 注册期快照(发现器/注册表读取,构造时注入——同步成员唯一源)。 */
43
+ export interface RemoteEngineManifestSnapshot {
44
+ /** manifest `capabilities`(同步能力位权威,注册期读,无缓存)。 */
45
+ capabilities: EngineCapabilities;
46
+ /**
47
+ * manifest `modelCatalog` 三态(§2.4:缺省 = 不注入保持 undefined;null 合法等价
48
+ * 省略;`models: []` 仅作者显式声明)。解析器**不得**把省略填成 `[]`——否则
49
+ * 「无枚举面」语义不可达(恒走 buildEmptyModelsHint 与事实不符)。
50
+ */
51
+ modelCatalog?: { dynamic: boolean; models: ModelCatalogEntry[] } | null;
52
+ }
53
+
54
+ export interface RemoteEngineOptions {
55
+ engineId: string;
56
+ client: EngineClient;
57
+ manifest: RemoteEngineManifestSnapshot;
58
+ /** 引擎数据根(协议 read.dataDir 必填:存量池时代相对 dbPath 定位需要它)。 */
59
+ dataDir: string;
60
+ hostKind: string;
61
+ hostVersion?: string;
62
+ /** L3 显式配置 engines.<id>.config(initialize.engineConfig 透传;EngineClient 消费)。 */
63
+ engineConfig?: Record<string, string>;
64
+ }
65
+
66
+ /** manifest 目录条目命中:id / canonicalRef / 任一 alias 与 ref 全等。 */
67
+ function matchCatalogEntry(
68
+ entries: ModelCatalogEntry[],
69
+ ref: string,
70
+ ): ModelCatalogEntry | undefined {
71
+ return entries.find(
72
+ (entry) =>
73
+ entry.id === ref || entry.canonicalRef === ref || entry.aliases?.includes(ref) === true,
74
+ );
75
+ }
76
+
77
+ /**
78
+ * cli 形态 EnginePort。构造同步、不 throw(缺包/坏包不在构造期报——descriptor
79
+ * 首次使用才解析,设计 §3.5.3 代理形态);真正的失败发生在首次协议调用。
80
+ */
81
+ export class RemoteEngine implements EnginePort {
82
+ readonly id: string;
83
+
84
+ private readonly opts: RemoteEngineOptions;
85
+
86
+ constructor(opts: RemoteEngineOptions) {
87
+ this.opts = opts;
88
+ this.id = opts.engineId;
89
+ if (opts.manifest.modelCatalog === undefined || opts.manifest.modelCatalog === null) {
90
+ // 同步成员形态映射(必写死):manifest 省略 modelCatalog → validateModel 成员
91
+ // **不实现**(消费方 model-validation.ts:62 `typeof validateModel !== "function"`
92
+ // → 跳过校验恒放行)。实例 own property 置 undefined 遮蔽原型方法——
93
+ // typeof engine.validateModel === "undefined"。
94
+ (this as unknown as { validateModel?: unknown }).validateModel = undefined;
95
+ }
96
+ }
97
+
98
+ /** 直读 manifest 注册期快照(无缓存——每次调用同值,快照不可变)。 */
99
+ capabilities(): EngineCapabilities {
100
+ return this.opts.manifest.capabilities;
101
+ }
102
+
103
+ /**
104
+ * listModels 三态映射(必写死):
105
+ * 省略 modelCatalog / models null → 返回 null(buildCoreAlignedHint 语义);
106
+ * 显式 `models: []` → 返回 [](buildEmptyModelsHint);
107
+ * 数组 → 原样返回。
108
+ */
109
+ listModels(): Array<{ id: string; name?: string }> | null {
110
+ const catalog = this.opts.manifest.modelCatalog;
111
+ if (catalog === undefined || catalog === null) return null;
112
+ return catalog.models;
113
+ }
114
+
115
+ /**
116
+ * validateModel 同源 manifest 判定(成员在 catalog 省略时已被构造器摘除):
117
+ * 命中(id/canonicalRef/alias 全等)→ {canonicalRef: entry.canonicalRef ?? entry.id};
118
+ * 未命中且 dynamic:false → throw engine_model_unknown(同步拒,record 不创建);
119
+ * 未命中且 dynamic:true → 放行,返回原样 ref(运行期以引擎为权威
120
+ * engine_model_mismatch;无斜杠 ref 的 core 侧拆分 = 契约变更④,归 W3)。
121
+ * modelRef undefined(查引擎缺省)对静态目录恒属未命中:dynamic:true 放行回空串
122
+ * (缺省模型无静态 canonical 形态,运行期自证);dynamic:false 同步拒。
123
+ */
124
+ validateModel(modelRef: string | undefined): { canonicalRef: string } {
125
+ const catalog = this.opts.manifest.modelCatalog;
126
+ if (!catalog || modelRef === undefined || modelRef.trim() === "") {
127
+ if (catalog?.dynamic === false) {
128
+ throw new EngineSdkError(
129
+ "engine_model_unknown",
130
+ `engine '${this.id}' declares a static model catalog (dynamic:false) and has no engine-default entry; `
131
+ + "an explicit `model` ref from the catalog is required.",
132
+ "Retry with an exact model id from the engine's model list (engine listModels), or declare "
133
+ + "the engine-default entry in the manifest modelCatalog.",
134
+ );
135
+ }
136
+ return { canonicalRef: modelRef ?? "" };
137
+ }
138
+ const entry = matchCatalogEntry(catalog.models, modelRef);
139
+ if (entry !== undefined) {
140
+ return { canonicalRef: entry.canonicalRef ?? entry.id };
141
+ }
142
+ if (catalog.dynamic === false) {
143
+ throw new EngineSdkError(
144
+ "engine_model_unknown",
145
+ `model '${modelRef}' is not in engine '${this.id}' static model catalog (dynamic:false)`,
146
+ "Retry with an exact model id from the engine's model list (engine listModels), "
147
+ + "or fix the manifest modelCatalog / upgrade the engine package.",
148
+ );
149
+ }
150
+ return { canonicalRef: modelRef };
151
+ }
152
+
153
+ async probe(probeOpts?: { force?: boolean }): Promise<ProbeReport> {
154
+ await this.opts.client.ensureConnected();
155
+ const report = (await this.opts.client.request("probe", {
156
+ force: probeOpts?.force ?? false,
157
+ })) as SdkProbeReport;
158
+ return report;
159
+ }
160
+
161
+ /**
162
+ * 协议 run 映射。task 收窄为引擎面子集(model/schemaEnv/cwd/engineFallback 改挂
163
+ * run.params.ctx,协议层单列——SDK AgentCallOpts 注释的字段裁决);事件经 run 作用域
164
+ * 路由分发(event 通知 / streamDelta / poolResolved / handleReady);abort → cancel
165
+ * 帧 + 3s 收敛窗口(超时杀链)。运行中失败不 reject——合成 error outcome + 正常
166
+ * handle 返回(EnginePort 契约:record 必须收尾);run 帧发出前的失败(连接/握手)
167
+ * reject。childSpawned/childStateChanged 镜像归 EngineClient(协议形态无
168
+ * ChildProcess 实例,ctx.onChildSpawned 不调用——W6 起生命周期谓词读镜像)。
169
+ */
170
+ async run(task: AgentCallOpts, ctx: RunContext): Promise<EngineRunResult> {
171
+ await this.opts.client.ensureConnected();
172
+
173
+ // [W3 契约⑤ run 期接线] gate 位方向判定②:同步面 assertTaskShapeSupported 读
174
+ // manifest 拦「少声明」;「多声明」(manifest 声明可用、引擎实态不符)gate 同步面
175
+ // 读不到,由握手应答发现——manifest 快照 vs initialize 应答 capabilities 逐 gate
176
+ // 位对照(common/capability-gate),命中抛 engine_capability_mismatch:本处位于
177
+ // run 帧发出前 → prepare 期失败 reject、不产生 handle,上层 executeViaEngine 经
178
+ // finalizeFailed → Step 3b cleanupWorktreeIfBound 清理 run 前已建的前置副作用。
179
+ // 每次 run 都对照(纯内存比较,幂等):崩溃重建重新握手后应答变化也能在下一 run
180
+ // 发现。非 gate 位不一致不进此判定(诊断面 warnOnManifestDiagnostics 已留痕)。
181
+ const answeredCaps = this.opts.client.getInitializeDiagnostics()?.capabilities;
182
+ if (answeredCaps !== undefined) {
183
+ assertGateCapabilitiesMatched(this.id, this.opts.manifest.capabilities, answeredCaps);
184
+ }
185
+
186
+ const runId = ctx.taskId;
187
+ const runParams = buildRunParams(task, ctx, runId);
188
+
189
+ const unregister = this.opts.client.registerRunRoute(runId, buildRunRouteHandlers(ctx));
190
+
191
+ // abort 分级:cancel 帧 → 等 CANCEL_SETTLE_GRACE_MS 收敛 → 杀链兜底。
192
+ const abort = wireAbortSignal(this.opts.client, runId, ctx);
193
+
194
+ try {
195
+ // wire 载荷收窄(帧 result unknown → 协议 RunResult 形态);SDK → core 结构
196
+ // 兼容由 implements EnginePort 在 typecheck 期互证。
197
+ const result = (await this.opts.client.request("run", runParams)) as {
198
+ handle: SdkEngineHandleData;
199
+ outcome: SdkAgentOutcome;
200
+ };
201
+ return { handle: { data: result.handle }, outcome: result.outcome };
202
+ } catch (err) {
203
+ if (abort.isCancelSent()) {
204
+ // cancel 后未收敛(杀链已杀)或引擎在 abort 期间报错:合成 abort 终态,不 reject
205
+ // (exitCode null = 被信号杀死,杀链判据)。
206
+ //
207
+ // [时序窗登记] 本合成 outcome 携 error + exitCode null——若它先于 cancel 域的
208
+ // CAS 终态化到达消费方,record 会先以 error 载体落 failed 形态而非 cancelled。
209
+ // 防护依据 = cancel 链 CAS 先行:cancelBackground 在 controller.abort() 后的
210
+ // **同一同步执行栈**内完成 tryTransition(cancelled) 抢锁终态化
211
+ // (subagent-service.ts cancelBackground),而本合成 outcome 的返回必须经异步
212
+ // 链(cancelRun RPC 往返 / 杀链 grace 后 run 请求 reject),时序上 CAS 恒先行,
213
+ // 窗极窄(仅存于 CAS 抢锁失败 = detached 已 finalize 的交错形态,该形态下
214
+ // 对方已终态化,本 outcome 无接管面)。不改本逻辑——改动会碰 run 域 cancel
215
+ // 语义(超修复范围),窗口登记于此供后续接管判据收敛时统一评估。
216
+ return {
217
+ handle: { data: this.synthesizeHandle(ctx.poolKey) },
218
+ outcome: abortedRunOutcome(this.id, runId, err),
219
+ };
220
+ }
221
+ if (isTransientRunFailure(err)) {
222
+ // 运行中失败(引擎崩溃 / 数据面故障杀链):合成 error outcome + 正常 handle。
223
+ return {
224
+ handle: { data: this.synthesizeHandle(ctx.poolKey) },
225
+ outcome: transientRunOutcome(this.id, err),
226
+ };
227
+ }
228
+ throw err; // prepare 期失败(连接/握手/model 拒)——进程创建前 reject,不产生 handle
229
+ } finally {
230
+ abort.dispose();
231
+ unregister();
232
+ }
233
+ }
234
+
235
+ async interact(handle: EngineHandle, action: InteractAction): Promise<InteractResult> {
236
+ await this.opts.client.ensureConnected();
237
+ const result = (await this.opts.client.request("interact", {
238
+ handle: handle.data,
239
+ action: action as SdkInteractAction,
240
+ })) as SdkInteractResult;
241
+ return result;
242
+ }
243
+
244
+ /**
245
+ * [W3 v1.x] chat 轮次反向通道路由注册(recordId 键,EnginePort 可选面实现):
246
+ * interact 续聊轮的 streamDelta / roundLifecycle 分发目标。薄委托 EngineClient
247
+ * 的 recordRoutes(键分发见 reverse-router.ts)。
248
+ */
249
+ registerChatRoundRoute(recordId: string, route: ChatRoundRoute): () => void {
250
+ return this.opts.client.registerRecordRoute(recordId, route as RunRoute);
251
+ }
252
+
253
+ /** 协议 read(dataDir 必填——引擎数据根,构造注入)。 */
254
+ async read(handle: EngineHandle): Promise<SessionView> {
255
+ await this.opts.client.ensureConnected();
256
+ const view = (await this.opts.client.request("read", {
257
+ handle: handle.data,
258
+ dataDir: this.opts.dataDir,
259
+ })) as SdkSessionView;
260
+ return view;
261
+ }
262
+
263
+ /** 协议 dispose(幂等)→ EngineClient 停机清理(镜像置死 + pidfile + 组杀兜底)。 */
264
+ async dispose(): Promise<void> {
265
+ await this.opts.client.dispose();
266
+ }
267
+
268
+ /** 运行中失败的合成 handle:handleReady 回填优先,缺省回退请求期 ctx。 */
269
+ private synthesizeHandle(poolKey: string): EngineHandleData {
270
+ const partial = this.opts.client.getPartialHandle();
271
+ const diag = this.opts.client.getInitializeDiagnostics();
272
+ return {
273
+ v: 1,
274
+ engineId: this.id,
275
+ sessionRef: partial?.sessionRef ?? {},
276
+ poolKey: partial?.poolKey ?? poolKey,
277
+ engineVersion: diag?.engineVersion,
278
+ adapterVersion: diag?.adapterVersion ?? `remote-engine/${this.id}`,
279
+ };
280
+ }
281
+ }
282
+
283
+ /**
284
+ * 运行中失败(合成 outcome)vs prepare 期失败(reject)的分界:EngineSdkError 的
285
+ * engine_crashed / engine_request_timeout / engine_handshake_timeout 三类由「run 帧
286
+ * 已受理后进程死亡/链路故障」产生;其余(engine_protocol_mismatch、engine_model_*、
287
+ * 未知错误)按 prepare 期失败上抛(调用方分诊)。进程组杀引发的 stdin 写失败同属
288
+ * engine_crashed(engine-client.request 统一包装)。
289
+ */
290
+ function isTransientRunFailure(err: unknown): boolean {
291
+ if (!(err instanceof EngineSdkError)) return false;
292
+ return (
293
+ err.code === "engine_crashed" ||
294
+ err.code === "engine_request_timeout" ||
295
+ err.code === "engine_handshake_timeout"
296
+ );
297
+ }
298
+
299
+ /** run 帧 wire 载荷(EngineClient.request("run") 入参形态)。 */
300
+ interface WireRunParams {
301
+ runId: string;
302
+ task: SdkAgentCallOpts;
303
+ ctx: {
304
+ poolKey: string;
305
+ cwd: string;
306
+ model: string | undefined;
307
+ schemaEnv: string | undefined;
308
+ ctxModel: string | undefined;
309
+ engineFallback: RunContext["engineFallback"];
310
+ streamMode: "stream" | undefined;
311
+ };
312
+ chat?: NonNullable<RunContext["chat"]>;
313
+ }
314
+
315
+ /**
316
+ * run 帧 wire 载荷构建。协议 ctx 承载(RunContext 字段映射表):cwd 取任务声明值
317
+ * (缺省进程 cwd);ctxModel 投影 canonical 词形(provider/id,ModelInfo 字段裁决)。
318
+ * [W3 v1.x] chat 会话形态参数直传(RunContext.chat → run.params.chat;结构由
319
+ * RunContext.chat 注释与 SDK RunChatParams 的 implements 互证承载)。非 chat 轮
320
+ * ctx.chat === undefined → wire 上不出现该键(协议 additive 语义)。
321
+ */
322
+ function buildRunParams(task: AgentCallOpts, ctx: RunContext, runId: string): WireRunParams {
323
+ const ctxModelRef = ctx.ctxModel ? `${ctx.ctxModel.provider}/${ctx.ctxModel.id}` : undefined;
324
+ return {
325
+ runId,
326
+ task: toSdkTaskSubset(task),
327
+ ctx: {
328
+ poolKey: ctx.poolKey,
329
+ cwd: task.cwd ?? process.cwd(),
330
+ model: task.model,
331
+ schemaEnv: ctx.schemaEnv ?? task.schemaEnv,
332
+ ctxModel: ctxModelRef,
333
+ engineFallback: ctx.engineFallback,
334
+ streamMode: ctx.stream !== undefined ? ("stream" as const) : undefined,
335
+ },
336
+ ...(ctx.chat !== undefined ? { chat: ctx.chat } : {}),
337
+ };
338
+ }
339
+
340
+ /** run 作用域事件路由(event / streamDelta / poolResolved / handleReady / roundLifecycle)。 */
341
+ function buildRunRouteHandlers(ctx: RunContext): RunRoute {
342
+ return {
343
+ onEvent: (event) => ctx.onEvent?.(event as Parameters<NonNullable<RunContext["onEvent"]>>[0]),
344
+ onStreamDelta: (delta) => ctx.stream?.onDelta(delta),
345
+ onPoolResolved: (poolKey) => ctx.onPoolResolved?.(poolKey),
346
+ onHandleReady: (partial) => ctx.onHandleReady?.(partial),
347
+ // [W3 v1.x] 首轮(run 会话形态)轮次生命周期帧(runId 键)→ 宿主消费口。
348
+ onRoundLifecycle: (phase) =>
349
+ ctx.onRoundLifecycle?.(phase as Parameters<NonNullable<RunContext["onRoundLifecycle"]>>[0]),
350
+ };
351
+ }
352
+
353
+ /** abort 接线的运行态句柄(isCancelSent 供 run catch 分支分诊;dispose 归 finally)。 */
354
+ interface AbortWiring {
355
+ isCancelSent(): boolean;
356
+ dispose(): void;
357
+ }
358
+
359
+ /**
360
+ * abort 分级接线:cancel 帧 → 等 CANCEL_SETTLE_GRACE_MS 收敛 → 杀链兜底。signal 已
361
+ * aborted 则立即进入收敛窗口;dispose 在 run 终态(finally)标记 settled 并清理
362
+ * timer / listener。
363
+ */
364
+ function wireAbortSignal(client: EngineClient, runId: string, ctx: RunContext): AbortWiring {
365
+ let cancelSent = false;
366
+ let settled = false;
367
+ let settleTimer: NodeJS.Timeout | undefined;
368
+ const onAbort = (): void => {
369
+ if (cancelSent || settled) return;
370
+ cancelSent = true;
371
+ void client.cancelRun(runId, "abort").catch(() => {
372
+ // 受理失败由收敛窗口兜底(进程死 → run 请求 reject → 合成终态)。
373
+ });
374
+ settleTimer = setTimeout(() => {
375
+ if (!settled) {
376
+ void client.killAll(`cancel did not settle within grace for run ${runId}`);
377
+ }
378
+ }, CANCEL_SETTLE_GRACE_MS);
379
+ };
380
+ if (ctx.signal !== undefined) {
381
+ if (ctx.signal.aborted) onAbort();
382
+ else ctx.signal.addEventListener("abort", onAbort, { once: true });
383
+ }
384
+ return {
385
+ isCancelSent: () => cancelSent,
386
+ dispose: () => {
387
+ settled = true;
388
+ if (settleTimer !== undefined) clearTimeout(settleTimer);
389
+ if (ctx.signal !== undefined) ctx.signal.removeEventListener("abort", onAbort);
390
+ },
391
+ };
392
+ }
393
+
394
+ /** abort 期合成 outcome(exitCode null = 被信号杀死,杀链判据)。 */
395
+ function abortedRunOutcome(engineId: string, runId: string, err: unknown): SdkAgentOutcome {
396
+ return {
397
+ content: "",
398
+ error: `engine_run_failed: run ${runId} aborted before terminal answer${
399
+ err instanceof Error ? ` (${err.message})` : ""
400
+ }`,
401
+ exitCode: null,
402
+ engineId,
403
+ };
404
+ }
405
+
406
+ /** 运行中失败合成 outcome(引擎崩溃 / 数据面故障杀链)。 */
407
+ function transientRunOutcome(engineId: string, err: unknown): SdkAgentOutcome {
408
+ return {
409
+ content: "",
410
+ error: err instanceof Error ? err.message : String(err),
411
+ exitCode: null,
412
+ engineId,
413
+ };
414
+ }
415
+
416
+ /** core AgentCallOpts → SDK 引擎面子集(宿主自持字段不透传,SDK 契约类型注释裁决)。 */
417
+ function toSdkTaskSubset(task: AgentCallOpts): SdkAgentCallOpts {
418
+ return {
419
+ prompt: task.prompt,
420
+ schema: task.schema,
421
+ thinkingLevel: task.thinkingLevel,
422
+ scene: task.scene,
423
+ maxTurns: task.maxTurns,
424
+ graceTurns: task.graceTurns,
425
+ skill: task.skill,
426
+ skillPath: task.skillPath,
427
+ description: task.description,
428
+ agent: task.agent,
429
+ appendSystemPrompt: task.appendSystemPrompt,
430
+ fork: task.fork,
431
+ // fork-from 源(fork-from 轮次 --fork 的协议载体,W3 断链修复):host-task-spec
432
+ // 已把 ExecuteOptions.forkFromSessionFile 改名为 task.forkSource,此处同名透传。
433
+ // 缺省 undefined 不落 wire(JSON 序列化丢弃,与相邻可选字段同语义)。
434
+ forkSource: task.forkSource,
435
+ worktree: task.worktree,
436
+ conversation: task.conversation,
437
+ idleTimeoutMs: task.idleTimeoutMs,
438
+ denyTools: task.denyTools,
439
+ permissionMode: task.permissionMode,
440
+ };
441
+ }