@zhushanwen/subagent-core 0.5.1 → 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 (318) 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-Dv4QhSJ_.d.cts → engine-discovery-scan-ocpM8FmI.d.cts} +835 -668
  6. package/dist/{types-Dv4QhSJ_.d.ts → engine-discovery-scan-ocpM8FmI.d.ts} +835 -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 +14123 -15467
  20. package/dist/index.d.cts +1179 -1540
  21. package/dist/index.d.ts +1179 -1540
  22. package/dist/index.js +7694 -10986
  23. package/dist.bundle/index.cjs +33485 -0
  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__/agent-registry.test.ts +1 -1
  30. package/src/execution/__tests__/alive-store.test.ts +1 -1
  31. package/src/execution/__tests__/chat-engine-routing.test.ts +62 -28
  32. package/src/execution/__tests__/chat-round-first-round-watchdog.test.ts +255 -0
  33. package/src/execution/__tests__/collect-budget.test.ts +291 -0
  34. package/src/execution/__tests__/collect-coordinator-service.test.ts +316 -0
  35. package/src/execution/__tests__/collect-coordinator.test.ts +371 -0
  36. package/src/execution/__tests__/collect-mixed-dispatch.test.ts +229 -0
  37. package/src/execution/__tests__/config-collect-sync.test.ts +120 -0
  38. package/src/execution/__tests__/config.test.ts +1 -1
  39. package/src/execution/__tests__/delivery-methods.test.ts +179 -237
  40. package/src/execution/__tests__/execute-and-await-worktree.test.ts +0 -2
  41. package/src/execution/__tests__/execute-nesting.test.ts +20 -13
  42. package/src/execution/__tests__/explicit-agent-ref-guard.test.ts +21 -34
  43. package/src/execution/__tests__/finalized-marker.test.ts +1 -1
  44. package/src/execution/__tests__/gc-timer.test.ts +8 -23
  45. package/src/execution/__tests__/get-record-for-action-restart.test.ts +20 -10
  46. package/src/execution/__tests__/helpers/fake-engine-port.ts +187 -0
  47. package/src/execution/__tests__/helpers/spawn-mock.ts +36 -9
  48. package/src/execution/__tests__/helpers/subagent-service-mocks.ts +1 -1
  49. package/src/execution/__tests__/idle-gc.test.ts +200 -0
  50. package/src/execution/__tests__/lifecycle-predicates.test.ts +26 -21
  51. package/src/execution/__tests__/manifest-store-tmp-recovery.test.ts +1 -1
  52. package/src/execution/__tests__/nested-visibility-env-propagation.test.ts +5 -2
  53. package/src/execution/__tests__/notify-batch.test.ts +500 -0
  54. package/src/execution/__tests__/notify-ledger.test.ts +27 -0
  55. package/src/execution/__tests__/reconcile-sweep.test.ts +200 -0
  56. package/src/execution/__tests__/record-entry-collect.test.ts +102 -0
  57. package/src/execution/__tests__/record-store.test.ts +60 -6
  58. package/src/execution/__tests__/recursive-visibility-baseline.test.ts +20 -13
  59. package/src/execution/__tests__/relay-env.test.ts +12 -1
  60. package/src/execution/__tests__/round-supervisor.test.ts +293 -0
  61. package/src/execution/__tests__/session-file-gc.test.ts +1 -1
  62. package/src/execution/__tests__/session-pending.test.ts +119 -17
  63. package/src/execution/__tests__/start-collect-guard.test.ts +255 -0
  64. package/src/execution/__tests__/stream-sink-retirement.test.ts +10 -10
  65. package/src/execution/__tests__/subagent-actions-core.test.ts +6 -0
  66. package/src/execution/__tests__/subagent-service-multiproc-guard.test.ts +14 -11
  67. package/src/execution/__tests__/subagent-service-notify-gate.test.ts +33 -30
  68. package/src/execution/__tests__/subagent-service-parent-guard.test.ts +2 -9
  69. package/src/execution/__tests__/subagent-service-recovery-bounds.test.ts +59 -129
  70. package/src/execution/__tests__/subagent-service.test.ts +2 -2
  71. package/src/execution/__tests__/subprocess-agent-runner-routing.test.ts +109 -7
  72. package/src/execution/__tests__/subprocess-agent-runner.test.ts +108 -36
  73. package/src/execution/__tests__/sync-collect-recovery.test.ts +1102 -0
  74. package/src/execution/__tests__/tombstone-store.test.ts +1 -1
  75. package/src/execution/__tests__/workflow-state-root.test.ts +232 -0
  76. package/src/execution/__tests__/worktree-git-ops.test.ts +1 -1
  77. package/src/execution/__tests__/worktree-reconcile-aging.test.ts +2 -2
  78. package/src/execution/__tests__/worktree-reconcile.integration.test.ts +1 -1
  79. package/src/execution/__tests__/worktree-registry.test.ts +1 -1
  80. package/src/execution/agent-registry.ts +6 -2
  81. package/src/execution/collect-coordinator.ts +200 -0
  82. package/src/execution/config.ts +77 -5
  83. package/src/execution/dialog-queue.ts +6 -73
  84. package/src/execution/engine/__tests__/common/capability-gate.test.ts +115 -15
  85. package/src/execution/engine/__tests__/common/errors.test.ts +11 -18
  86. package/src/execution/engine/__tests__/common/event-journal.test.ts +1 -1
  87. package/src/execution/engine/__tests__/common/kill-chain.test.ts +7 -0
  88. package/src/execution/engine/__tests__/common/nesting-guard.test.ts +9 -3
  89. package/src/execution/engine/__tests__/common/pool-manager.test.ts +2 -2
  90. package/src/execution/engine/__tests__/common/session-view-service.test.ts +90 -3
  91. package/src/execution/engine/__tests__/conformance/H9-test-disposition.md +116 -0
  92. package/src/execution/engine/__tests__/conformance/__fixtures__/engine-protocol/fake-engine-protocol.mjs +377 -0
  93. package/src/execution/engine/__tests__/conformance/__fixtures__/engine-protocol/recorded.fixture.json +331 -0
  94. package/src/execution/engine/__tests__/conformance/__fixtures__/engine-protocol/smoke-run.fixture.json +213 -0
  95. package/src/execution/engine/__tests__/conformance/chat-round-protocol.test.ts +230 -0
  96. package/src/execution/engine/__tests__/conformance/contract.abort.test.ts +69 -42
  97. package/src/execution/engine/__tests__/conformance/contract.agent-events.test.ts +4 -81
  98. package/src/execution/engine/__tests__/conformance/contract.probe.test.ts +67 -44
  99. package/src/execution/engine/__tests__/conformance/contract.read-degradation.test.ts +82 -55
  100. package/src/execution/engine/__tests__/conformance/engine-conformance.live.test.ts +133 -70
  101. package/src/execution/engine/__tests__/conformance/engine-crash.test.ts +143 -0
  102. package/src/execution/engine/__tests__/conformance/fake-engine-capabilities.ts +19 -0
  103. package/src/execution/engine/__tests__/conformance/golden-replay.pi.test.ts +8 -3
  104. package/src/execution/engine/__tests__/conformance/golden-replay.zcode.test.ts +6 -5
  105. package/src/execution/engine/__tests__/conformance/protocol-blackbox.test.ts +398 -0
  106. package/src/execution/engine/__tests__/conformance/registry-fork-filter.test.ts +221 -0
  107. package/src/execution/engine/__tests__/conformance/round-liveness-supervisor.test.ts +302 -0
  108. package/src/execution/engine/__tests__/conformance/static-spawn-guard.test.ts +58 -0
  109. package/src/execution/engine/__tests__/engine-discovery-scan.test.ts +558 -0
  110. package/src/execution/engine/__tests__/host-task-spec.test.ts +45 -0
  111. package/src/execution/engine/__tests__/model-ref-split.test.ts +74 -0
  112. package/src/execution/engine/__tests__/registry.test.ts +206 -1
  113. package/src/execution/engine/__tests__/routing.test.ts +97 -0
  114. package/src/execution/engine/__tests__/run-failure-worktree-cleanup.test.ts +97 -0
  115. package/src/execution/engine/client/__tests__/__fixtures__/fake-engine.mjs +294 -0
  116. package/src/execution/engine/client/__tests__/engine-client.test.ts +516 -0
  117. package/src/execution/engine/client/__tests__/mirror.test.ts +67 -0
  118. package/src/execution/engine/client/__tests__/pid-file.test.ts +257 -0
  119. package/src/execution/engine/client/__tests__/protocol-closure.test.ts +95 -0
  120. package/src/execution/engine/client/__tests__/remote-engine.test.ts +457 -0
  121. package/src/execution/engine/client/client-options.ts +103 -0
  122. package/src/execution/engine/client/engine-client.ts +687 -0
  123. package/src/execution/engine/client/mirror.ts +167 -0
  124. package/src/execution/engine/client/pid-file.ts +392 -0
  125. package/src/execution/engine/client/reaper.ts +95 -0
  126. package/src/execution/engine/client/remote-engine.ts +441 -0
  127. package/src/execution/engine/client/reverse-router.ts +255 -0
  128. package/src/execution/engine/common/capability-gate.ts +109 -22
  129. package/src/execution/engine/common/errors.ts +9 -25
  130. package/src/execution/engine/common/event-journal.ts +4 -50
  131. package/src/execution/engine/common/journal-replay.ts +3 -1
  132. package/src/execution/engine/common/kill-chain.ts +18 -251
  133. package/src/execution/engine/common/nesting-guard.ts +18 -114
  134. package/src/execution/engine/common/pool-manager.ts +4 -0
  135. package/src/execution/engine/common/session-view-service.ts +56 -84
  136. package/src/execution/engine/config.ts +151 -0
  137. package/src/execution/engine/d8-compat.ts +346 -0
  138. package/src/execution/engine/engine-discovery-roots.ts +107 -0
  139. package/src/execution/engine/engine-discovery-scan.ts +269 -0
  140. package/src/execution/engine/engine-discovery.ts +30 -7
  141. package/src/execution/engine/engine-inspect-package.ts +282 -0
  142. package/src/execution/engine/engine-manifest.ts +244 -0
  143. package/src/execution/engine/host/__tests__/host-askuser-endpoint.test.ts +123 -0
  144. package/src/execution/engine/host/__tests__/host-bridge.test.ts +135 -0
  145. package/src/execution/engine/host/__tests__/spawned-children.test.ts +73 -0
  146. package/src/execution/engine/host/host-bridge.ts +150 -0
  147. package/src/execution/engine/host/host-ui-endpoint.ts +47 -0
  148. package/src/execution/engine/host/pi-host-binding.ts +91 -0
  149. package/src/execution/engine/host/spawned-children.ts +139 -0
  150. package/src/execution/engine/host-task-spec.ts +29 -2
  151. package/src/execution/engine/model-validation.ts +55 -2
  152. package/src/execution/engine/paths.ts +16 -41
  153. package/src/execution/engine/port.ts +48 -2
  154. package/src/execution/engine/registry.ts +153 -34
  155. package/src/execution/engine/routing.ts +225 -52
  156. package/src/execution/engine/types.ts +25 -200
  157. package/src/execution/execution-record.ts +7 -0
  158. package/src/execution/finalize-record.ts +40 -11
  159. package/src/execution/idle-gc.ts +89 -14
  160. package/src/execution/lifecycle-manager.ts +10 -7
  161. package/src/execution/lifecycle-predicates.ts +10 -8
  162. package/src/execution/notifier.ts +234 -25
  163. package/src/execution/notify-host.ts +21 -1
  164. package/src/execution/record-entry.ts +16 -0
  165. package/src/execution/record-store.ts +189 -31
  166. package/src/execution/relay-env.ts +19 -36
  167. package/src/execution/round-supervisor/domain.ts +89 -0
  168. package/src/execution/round-supervisor/index.ts +33 -0
  169. package/src/execution/round-supervisor/notify-accounting.ts +87 -0
  170. package/src/execution/round-supervisor/reconcile-sweep.ts +235 -0
  171. package/src/execution/round-supervisor/service-binding.test.ts +661 -0
  172. package/src/execution/round-supervisor/service-binding.ts +273 -0
  173. package/src/execution/round-supervisor/supervisor.ts +426 -0
  174. package/src/execution/session-pending.ts +68 -74
  175. package/src/execution/settled-watchdog.ts +39 -0
  176. package/src/execution/subagent-actions-core.ts +62 -6
  177. package/src/execution/subagent-service.ts +1161 -406
  178. package/src/execution/subprocess-agent-runner.ts +16 -8
  179. package/src/execution/sync-rebuild.ts +87 -0
  180. package/src/execution/types.ts +104 -117
  181. package/src/execution/ui-channels.ts +13 -214
  182. package/src/execution/ui-request-handler-factory.ts +7 -4
  183. package/src/execution/ui-request-observability.ts +2 -2
  184. package/src/execution/workflow-state-root.ts +67 -0
  185. package/src/execution/worktree-git-ops.ts +5 -0
  186. package/src/execution/worktree-manager.ts +11 -1
  187. package/src/index.ts +55 -26
  188. package/src/orchestration/__tests__/config-loader.test.ts +1 -1
  189. package/src/orchestration/__tests__/execute-agent-call.test.ts +1 -1
  190. package/src/orchestration/__tests__/file-run-store-prune.test.ts +1 -1
  191. package/src/orchestration/__tests__/file-run-store-throttle.test.ts +1 -1
  192. package/src/orchestration/__tests__/review-fix-loop-scriptpath-failfast.test.ts +1 -1
  193. package/src/orchestration/__tests__/script-generate.test.ts +5 -5
  194. package/src/orchestration/__tests__/skill-discovery.test.ts +2 -2
  195. package/src/orchestration/__tests__/workflow-files.test.ts +10 -10
  196. package/src/orchestration/__tests__/workflow-script-registry-impl.test.ts +1 -1
  197. package/src/orchestration/execute-agent-call.ts +1 -1
  198. package/src/orchestration/file-run-store.ts +144 -59
  199. package/src/orchestration/models/types.ts +43 -42
  200. package/src/shared/__tests__/atomic-write.test.ts +1 -1
  201. package/src/shared/__tests__/resource-discovery-host-roots.test.ts +5 -5
  202. package/src/shared/zcode-model-ref.ts +31 -0
  203. package/dist/chunk-43ONBFZX.js +0 -240
  204. package/dist/chunk-A4IVZWVX.js +0 -31
  205. package/dist/chunk-APZY4IME.js +0 -27
  206. package/dist/chunk-V3VHZ2VX.js +0 -59
  207. package/dist/execution/engine/engines/zcode/constants.cjs +0 -107
  208. package/dist/execution/engine/engines/zcode/constants.d.cts +0 -135
  209. package/dist/execution/engine/engines/zcode/constants.d.ts +0 -135
  210. package/dist/execution/engine/engines/zcode/constants.js +0 -54
  211. package/dist/execution/engine/engines/zcode/reader.cjs +0 -276
  212. package/dist/execution/engine/engines/zcode/reader.d.cts +0 -21
  213. package/dist/execution/engine/engines/zcode/reader.d.ts +0 -21
  214. package/dist/execution/engine/engines/zcode/reader.js +0 -9
  215. package/src/__tests__/append-system-prompt-assembly.test.ts +0 -243
  216. package/src/__tests__/fr4-get-state-handshake.test.ts +0 -125
  217. package/src/__tests__/session-runner.test.ts +0 -69
  218. package/src/execution/__tests__/ask-user-transit-e2e.test.ts +0 -490
  219. package/src/execution/__tests__/chatmode-first-round-closure-spawn.test.ts +0 -191
  220. package/src/execution/__tests__/descendant-sweep-guards.test.ts +0 -220
  221. package/src/execution/__tests__/descendant-sweep.test.ts +0 -269
  222. package/src/execution/__tests__/engine-model-validation.test.ts +0 -741
  223. package/src/execution/__tests__/epipe-fallback.test.ts +0 -248
  224. package/src/execution/__tests__/execution-runtime-face.test.ts +0 -272
  225. package/src/execution/__tests__/get-state-handshake.test.ts +0 -127
  226. package/src/execution/__tests__/helpers/session-runner-mocks.ts +0 -113
  227. package/src/execution/__tests__/keep-alive-no-progress.test.ts +0 -280
  228. package/src/execution/__tests__/kill-all-escalation.test.ts +0 -196
  229. package/src/execution/__tests__/max-turns-to-watchdog-ms.test.ts +0 -113
  230. package/src/execution/__tests__/output-collector.test.ts +0 -469
  231. package/src/execution/__tests__/pi-invocation.test.ts +0 -134
  232. package/src/execution/__tests__/recursive-visibility-env.test.ts +0 -149
  233. package/src/execution/__tests__/rpc-mode.test.ts +0 -89
  234. package/src/execution/__tests__/run-and-finalize-anchoring.test.ts +0 -387
  235. package/src/execution/__tests__/run-and-finalize-chatmode.test.ts +0 -277
  236. package/src/execution/__tests__/run-spawn-chatmode-settled.test.ts +0 -254
  237. package/src/execution/__tests__/run-spawn-edges.test.ts +0 -1079
  238. package/src/execution/__tests__/run-spawn-integration.test.ts +0 -933
  239. package/src/execution/__tests__/run-spawn-resume.test.ts +0 -322
  240. package/src/execution/__tests__/run-spawn-rpc-mode.test.ts +0 -196
  241. package/src/execution/__tests__/run-spawn-stdout-callback-throw.test.ts +0 -207
  242. package/src/execution/__tests__/service-kill-escalation.test.ts +0 -91
  243. package/src/execution/__tests__/session-runner-branch-cache-lru.test.ts +0 -110
  244. package/src/execution/__tests__/session-runner-close-prune.test.ts +0 -181
  245. package/src/execution/__tests__/session-runner-dispatch.test.ts +0 -489
  246. package/src/execution/__tests__/session-runner-epipe.test.ts +0 -179
  247. package/src/execution/__tests__/session-runner-heartbeat-idle-fallback.test.ts +0 -227
  248. package/src/execution/__tests__/session-runner-lifecycle-helpers.test.ts +0 -290
  249. package/src/execution/__tests__/session-runner-schema-env.test.ts +0 -352
  250. package/src/execution/__tests__/settled-watchdog.test.ts +0 -524
  251. package/src/execution/__tests__/spawn-args.test.ts +0 -446
  252. package/src/execution/__tests__/spawn-event-adapter-rpc.test.ts +0 -192
  253. package/src/execution/__tests__/spawn-event-adapter.test.ts +0 -167
  254. package/src/execution/__tests__/spawn-worktree-guidance.test.ts +0 -208
  255. package/src/execution/__tests__/spawned-children.test.ts +0 -236
  256. package/src/execution/__tests__/start-sync-model-guard.test.ts +0 -150
  257. package/src/execution/__tests__/stdin-writer.test.ts +0 -464
  258. package/src/execution/__tests__/subagent-service-message-close.test.ts +0 -693
  259. package/src/execution/__tests__/temp-prompt.test.ts +0 -53
  260. package/src/execution/__tests__/timeout-integration.test.ts +0 -616
  261. package/src/execution/__tests__/turn-limiter-semantics.test.ts +0 -194
  262. package/src/execution/__tests__/turn-limiter.test.ts +0 -65
  263. package/src/execution/__tests__/ui-request-handler.test.ts +0 -205
  264. package/src/execution/__tests__/ui-request-queue.test.ts +0 -298
  265. package/src/execution/__tests__/worktree-pid-registration.integration.test.ts +0 -230
  266. package/src/execution/engine/__tests__/common/schema-emulation.test.ts +0 -128
  267. package/src/execution/engine/__tests__/common/session-view-service-zcode-dbpath.test.ts +0 -149
  268. package/src/execution/engine/__tests__/conformance/__fixtures__/pi-golden-events.json +0 -28
  269. package/src/execution/engine/__tests__/conformance/zcode-appserver-harness.ts +0 -128
  270. package/src/execution/engine/__tests__/paths.test.ts +0 -39
  271. package/src/execution/engine/common/schema-emulation.ts +0 -189
  272. package/src/execution/engine/common/session-view-projection.ts +0 -51
  273. package/src/execution/engine/engines/pi/__tests__/pi-engine.test.ts +0 -615
  274. package/src/execution/engine/engines/pi/__tests__/reader.test.ts +0 -155
  275. package/src/execution/engine/engines/pi/__tests__/spawn-opts-direct.test.ts +0 -257
  276. package/src/execution/engine/engines/pi/argv-mirror.ts +0 -135
  277. package/src/execution/engine/engines/pi/get-state-handshake.ts +0 -179
  278. package/src/execution/engine/engines/pi/output-collector.ts +0 -317
  279. package/src/execution/engine/engines/pi/pi-engine.ts +0 -811
  280. package/src/execution/engine/engines/pi/pi-invocation.ts +0 -120
  281. package/src/execution/engine/engines/pi/reader.ts +0 -59
  282. package/src/execution/engine/engines/pi/registration.ts +0 -37
  283. package/src/execution/engine/engines/pi/session-runner.ts +0 -2840
  284. package/src/execution/engine/engines/pi/spawn-event-adapter.ts +0 -404
  285. package/src/execution/engine/engines/pi/stdin-writer.ts +0 -199
  286. package/src/execution/engine/engines/pi/temp-prompt.ts +0 -62
  287. package/src/execution/engine/engines/pi/turn-limiter.ts +0 -102
  288. package/src/execution/engine/engines/zcode/__tests__/__fixtures__/fake-appserver.mjs +0 -301
  289. package/src/execution/engine/engines/zcode/__tests__/__fixtures__/zcode-golden-appserver.json +0 -36
  290. package/src/execution/engine/engines/zcode/__tests__/appserver-launcher.test.ts +0 -321
  291. package/src/execution/engine/engines/zcode/__tests__/connection.test.ts +0 -473
  292. package/src/execution/engine/engines/zcode/__tests__/parser.test.ts +0 -43
  293. package/src/execution/engine/engines/zcode/__tests__/preparer.test.ts +0 -124
  294. package/src/execution/engine/engines/zcode/__tests__/reader.test.ts +0 -210
  295. package/src/execution/engine/engines/zcode/__tests__/registration.test.ts +0 -71
  296. package/src/execution/engine/engines/zcode/__tests__/session-channel-dispose-harvest.test.ts +0 -247
  297. package/src/execution/engine/engines/zcode/__tests__/session-channel-turn-timers.test.ts +0 -451
  298. package/src/execution/engine/engines/zcode/__tests__/session-channel.test.ts +0 -792
  299. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-appserver.test.ts +0 -782
  300. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-degrade.test.ts +0 -168
  301. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-dispose.test.ts +0 -210
  302. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-retry.test.ts +0 -353
  303. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-status.test.ts +0 -282
  304. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-timeout.test.ts +0 -372
  305. package/src/execution/engine/engines/zcode/__tests__/zcode-engine.live.test.ts +0 -145
  306. package/src/execution/engine/engines/zcode/appserver-launcher.ts +0 -167
  307. package/src/execution/engine/engines/zcode/connection.ts +0 -598
  308. package/src/execution/engine/engines/zcode/constants.ts +0 -176
  309. package/src/execution/engine/engines/zcode/golden-sample.ts +0 -47
  310. package/src/execution/engine/engines/zcode/parser.ts +0 -102
  311. package/src/execution/engine/engines/zcode/preparer.ts +0 -235
  312. package/src/execution/engine/engines/zcode/reader.ts +0 -381
  313. package/src/execution/engine/engines/zcode/registration.ts +0 -37
  314. package/src/execution/engine/engines/zcode/session-channel.ts +0 -968
  315. package/src/execution/engine/engines/zcode/zcode-engine.ts +0 -1431
  316. package/src/execution/round-settlement.ts +0 -93
  317. package/src/execution/ui-request-queue.ts +0 -215
  318. package/src/shared/schema-env.ts +0 -44
@@ -1,473 +0,0 @@
1
- // connection.test.ts —— R2 连接层测试:全部跑 __fixtures__/fake-appserver.mjs 子进程
2
- // (移植自 zsw 仓 84b63a0^ fake-server 测试模式,vitest 形态改造),绝不 spawn 真
3
- // zcode.cjs。覆盖验收条款:四帧型分发逐型 / 请求-应答 id 关联(并发不串)/
4
- // requestRuntimePreferences 常量应答逐字段 / 未知反向回空 result / onClose 全部在途
5
- // reject(含 stderr 尾 400 截断)/ 惰性启动与进程死后重建 / stderr tee 落盘 /
6
- // protocol 自报忽略 / 无 jsonrpc 字段的帧收发(出站精确键集 = 对面 strict 拒未知键
7
- // 的镜像义务)/ env 惯例 / 关闭原语幂等。
8
-
9
- import { existsSync, mkdtempSync, readFileSync } from "node:fs";
10
- import { tmpdir } from "node:os";
11
- import { join } from "node:path";
12
- import { fileURLToPath } from "node:url";
13
-
14
- import { afterEach, describe, expect, it } from "vitest";
15
-
16
- import { ZCODE_APPSERVER_STDERR_TAIL_CHARS } from "../constants.ts";
17
- import {
18
- AppServerConnection,
19
- RUNTIME_PREFERENCES,
20
- buildAppServerEnv,
21
- isAppServerRpcError,
22
- } from "../connection.ts";
23
-
24
- const TMP = mkdtempSync(join(tmpdir(), "zcode-conn-"));
25
- const FAKE_CLI = fileURLToPath(new URL("./__fixtures__/fake-appserver.mjs", import.meta.url));
26
-
27
- const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));
28
-
29
- /** fake 侧事件流水条目(JSONL:boot/env/recv/reverse-answer)。 */
30
- interface StateEvent {
31
- seq: number;
32
- ev: string;
33
- [key: string]: unknown;
34
- }
35
-
36
- function readState(file: string): StateEvent[] {
37
- try {
38
- return readFileSync(file, "utf8")
39
- .trim()
40
- .split("\n")
41
- .filter(Boolean)
42
- .map((l) => JSON.parse(l) as StateEvent);
43
- } catch {
44
- return [];
45
- }
46
- }
47
-
48
- function isRecord(v: unknown): v is Record<string, unknown> {
49
- return typeof v === "object" && v !== null && !Array.isArray(v);
50
- }
51
-
52
- /** 轮询等待 fake 侧异步效果可见(fake 异步处理 stdin,不能假设即时)。 */
53
- async function waitFor(cond: () => boolean, ms = 5_000, step = 25): Promise<boolean> {
54
- const end = Date.now() + ms;
55
- while (Date.now() < end) {
56
- if (cond()) return true;
57
- await sleep(step);
58
- }
59
- return cond();
60
- }
61
-
62
- interface FakeHandle {
63
- conn: AppServerConnection;
64
- stateFile: string;
65
- stderrLog: string;
66
- cwd: string;
67
- }
68
-
69
- interface FakeOpts {
70
- /** FAKE_STDERR=1:启动时往 stderr 写两行。 */
71
- stderrLines?: boolean;
72
- /** FAKE_EXTRA_KEYS=1:fake 应答/推送帧携带未知键(客户端宽容解析断言)。 */
73
- extraKeys?: boolean;
74
- /** FAKE_PROTOCOL_PUSH=1:协议自报走 {method:'protocol'} 推送形态。 */
75
- protocolPush?: boolean;
76
- /** 基 env 预置引擎原生嵌套标记(nesting guard 剥离断言)。 */
77
- polluteNested?: boolean;
78
- /** 注入故障反向 handler(fire-and-forget catch 断言)。 */
79
- reverseHandlers?: Readonly<Record<string, (params: unknown) => unknown>>;
80
- }
81
-
82
- const CONNECTIONS: AppServerConnection[] = [];
83
- let connSeq = 0;
84
-
85
- /** 建一个连到 fake 的连接(env 面向子进程固化,测试间零共享状态)。 */
86
- function makeConnection(opts: FakeOpts = {}): FakeHandle {
87
- connSeq += 1;
88
- const stateFile = join(TMP, `state-${connSeq}.jsonl`);
89
- const stderrLog = join(TMP, `stderr-${connSeq}.log`);
90
- const cwd = join(TMP, `cwd-${connSeq}`);
91
- const base: NodeJS.ProcessEnv = {
92
- PATH: process.env.PATH ?? "",
93
- HOME: "/fake-host-home",
94
- FAKE_STATE_FILE: stateFile,
95
- ...(opts.stderrLines ? { FAKE_STDERR: "1" } : {}),
96
- ...(opts.extraKeys ? { FAKE_EXTRA_KEYS: "1" } : {}),
97
- ...(opts.protocolPush ? { FAKE_PROTOCOL_PUSH: "1" } : {}),
98
- ...(opts.polluteNested ? { ZSW_NESTED: "1", CLAUDECODE: "1", PI_SUBAGENT_DEPTH: "2" } : {}),
99
- };
100
- const conn = new AppServerConnection({
101
- cliPath: FAKE_CLI,
102
- cwd,
103
- env: buildAppServerEnv(base),
104
- stderrLogPath: stderrLog,
105
- ...(opts.reverseHandlers ? { reverseHandlers: opts.reverseHandlers } : {}),
106
- });
107
- CONNECTIONS.push(conn);
108
- return { conn, stateFile, stderrLog, cwd };
109
- }
110
-
111
- afterEach(async () => {
112
- await Promise.allSettled(CONNECTIONS.splice(0).map((c) => c.shutdown({ graceMs: 1_000 })));
113
- });
114
-
115
- // ------------------------------------------- 惰性启动与重建(D1 / 不变量 4)
116
-
117
- describe("惰性启动与惰性重建", () => {
118
- it("构造不 spawn:无流水、无 pid、alive=false(连接构建零成本)", async () => {
119
- const { conn, stateFile } = makeConnection();
120
- expect(conn.alive).toBe(false);
121
- expect(conn.pid).toBeUndefined();
122
- await sleep(80);
123
- expect(existsSync(stateFile)).toBe(false);
124
- expect(conn.pid).toBeUndefined();
125
- });
126
-
127
- it("首次请求才 spawn:boot 流水出现,argv 形态 = `app-server --cwd <dir>`(D10 基线,不带 --stdio/--surface)", async () => {
128
- const { conn, stateFile, cwd } = makeConnection();
129
- const r = await conn.request("test/echo", { marker: "first" });
130
- expect(r).toEqual({ marker: "first" });
131
- const boots = readState(stateFile).filter((e) => e.ev === "boot");
132
- expect(boots).toHaveLength(1);
133
- expect(boots[0].argv).toEqual(["app-server", "--cwd", cwd]);
134
- expect(conn.pid).toBeGreaterThan(0);
135
- expect(conn.alive).toBe(true);
136
- }, 10_000);
137
-
138
- it("进程死后下次请求自动重建(与惰性启动同路径):boot 两次、pid 变化", async () => {
139
- const { conn, stateFile } = makeConnection();
140
- await conn.request("test/echo", { n: 1 });
141
- const pidBefore = conn.pid;
142
- await expect(conn.request("test/suicide")).rejects.toThrow(/app-server/);
143
- expect(await waitFor(() => !conn.alive)).toBe(true);
144
- const r2 = await conn.request("test/echo", { n: 2 });
145
- expect(r2).toEqual({ n: 2 });
146
- const boots = readState(stateFile).filter((e) => e.ev === "boot");
147
- expect(boots).toHaveLength(2);
148
- expect(boots[1].pid).not.toBe(boots[0].pid);
149
- expect(conn.pid).not.toBe(pidBefore);
150
- }, 15_000);
151
-
152
- it("spawn 失败(nodeBin ENOENT)走同一收割路径:请求 reject 带 spawn 失败语境,连接不悬挂", async () => {
153
- const conn = new AppServerConnection({
154
- cliPath: FAKE_CLI,
155
- cwd: TMP,
156
- nodeBin: join(TMP, "no-such-node-bin"),
157
- env: { PATH: process.env.PATH ?? "" },
158
- stderrLogPath: join(TMP, "enoent.log"),
159
- });
160
- CONNECTIONS.push(conn);
161
- await expect(conn.request("test/echo", {})).rejects.toThrow(/spawn 失败/);
162
- expect(await waitFor(() => !conn.alive)).toBe(true);
163
- }, 10_000);
164
- });
165
-
166
- // ------------------------------------------- 四帧型分发(附录 A.1)
167
-
168
- describe("四帧型分发(NDJSON,无 jsonrpc 字段)", () => {
169
- it("客户端请求帧:出站精确键集 {id, method, params}——无 jsonrpc、无未知键(对面 strict 拒未知键)", async () => {
170
- const { conn, stateFile } = makeConnection();
171
- await conn.request("test/echo", { a: 1 });
172
- const frames = readState(stateFile)
173
- .map((e) => (e as Record<string, unknown>).frame)
174
- .filter((f): f is Record<string, unknown> => isRecord(f) && f.method === "test/echo");
175
- expect(frames).toHaveLength(1);
176
- expect(Object.keys(frames[0]).sort()).toEqual(["id", "method", "params"]);
177
- expect(typeof frames[0].id).toBe("number");
178
- expect("jsonrpc" in frames[0]).toBe(false);
179
- });
180
-
181
- it("应答帧(result):resolve 应答值;帧级未知键宽容解析(我们是客户端,strict 校验是对面)", async () => {
182
- const { conn } = makeConnection({ extraKeys: true });
183
- const r = await conn.request<{ marker: string }>("test/echo", { marker: "lenient" });
184
- expect(r).toEqual({ marker: "lenient" });
185
- // 推送帧携带未知键同样不破坏分发
186
- const received: unknown[] = [];
187
- conn.onNotification("test/notification", (p) => received.push(p));
188
- await conn.request("test/push", { pushMethod: "test/notification", pushParams: { delta: "hi" } });
189
- expect(received).toEqual([{ delta: "hi" }]);
190
- });
191
-
192
- it("应答帧(error):code/message/data 挂到 reject Error(A.3 错误码通道,-32602 zod 诊断随 data 带出)", async () => {
193
- const { conn } = makeConnection();
194
- const err = await conn
195
- .request("test/fail", {
196
- code: -32602,
197
- message: "Invalid params",
198
- data: [{ path: ["model"], message: "not an object" }],
199
- })
200
- .then(
201
- () => {
202
- throw new Error("should reject");
203
- },
204
- (e: unknown) => e,
205
- );
206
- expect(isAppServerRpcError(err)).toBe(true);
207
- if (isAppServerRpcError(err)) {
208
- expect(err.code).toBe(-32602);
209
- expect(err.data).toEqual([{ path: ["model"], message: "not an object" }]);
210
- expect(err.message).toContain("[-32602]");
211
- expect(err.message).toContain("Invalid params");
212
- }
213
- });
214
-
215
- it("服务端推送帧:onNotification(method) 收到 params;handler 异常不拖死帧泵;退订生效", async () => {
216
- const { conn } = makeConnection();
217
- const received: unknown[] = [];
218
- const receivedBoom: unknown[] = [];
219
- const receivedOff: unknown[] = [];
220
- conn.onNotification("test/notification", (params) => {
221
- received.push(params);
222
- });
223
- conn.onNotification("test/notification", (params) => {
224
- receivedBoom.push(params);
225
- throw new Error("handler boom");
226
- });
227
- const off = conn.onNotification("test/notification", (params) => {
228
- receivedOff.push(params);
229
- });
230
- off();
231
- await conn.request("test/push", { pushMethod: "test/notification", pushParams: { delta: "hello" } });
232
- await conn.request("test/push", { pushMethod: "test/notification", pushParams: { delta: "again" } });
233
- expect(received).toEqual([{ delta: "hello" }, { delta: "again" }]);
234
- expect(receivedBoom).toEqual([{ delta: "hello" }, { delta: "again" }]);
235
- expect(receivedOff).toEqual([]);
236
- // 抛过异常后连接仍可用
237
- const r = await conn.request("test/echo", { ok: 1 });
238
- expect(r).toEqual({ ok: 1 });
239
- });
240
- });
241
-
242
- // ------------------------------------------- 请求-应答 id 关联
243
-
244
- describe("请求-应答 id 关联", () => {
245
- it("并发多请求不串线:3 个在途请求各自 resolve 自己的回显;id 自增互异", async () => {
246
- const { conn, stateFile } = makeConnection();
247
- const [a, b, c] = await Promise.all([
248
- conn.request("test/delay-echo", { who: "a", delayMs: 60 }),
249
- conn.request("test/delay-echo", { who: "b", delayMs: 30 }),
250
- conn.request("test/echo", { who: "c" }),
251
- ]);
252
- expect(a).toEqual({ who: "a", delayMs: 60 });
253
- expect(b).toEqual({ who: "b", delayMs: 30 });
254
- expect(c).toEqual({ who: "c" });
255
- const ids = readState(stateFile)
256
- .map((e) => (e as Record<string, unknown>).frame)
257
- .filter((f): f is { id: number } => isRecord(f) && typeof f.method === "string" && typeof f.id === "number")
258
- .map((f) => f.id);
259
- expect(ids).toHaveLength(3);
260
- expect(new Set(ids).size).toBe(3);
261
- expect([...ids].sort((x, y) => x - y)).toEqual([1, 2, 3]);
262
- });
263
-
264
- it("超时预算参数化:小预算 reject 超时,pending 清理后后续请求正常", async () => {
265
- const { conn } = makeConnection();
266
- await expect(conn.request("test/delay-echo", { delayMs: 5_000 }, { timeoutMs: 120 })).rejects.toThrow(/超时/);
267
- const r = await conn.request("test/echo", { after: "timeout" });
268
- expect(r).toEqual({ after: "timeout" });
269
- }, 10_000);
270
- });
271
-
272
- // ------------------------------------------- 反向请求应答(D9)
273
-
274
- describe("反向请求应答(D9)", () => {
275
- it("session/requestRuntimePreferences → 常量表应答逐字段(真实协议:create 先发反向请求并等应答)", async () => {
276
- const { conn, stateFile } = makeConnection();
277
- const created = await conn.request<{ session: { sessionId: string } }>("session/create", {
278
- workspace: { workspacePath: "/w", workspaceKey: "ws-x" },
279
- mode: "yolo",
280
- });
281
- expect(typeof created.session.sessionId).toBe("string");
282
- const answers = readState(stateFile).filter((e) => e.ev === "reverse-answer");
283
- expect(answers).toHaveLength(1);
284
- const result = (answers[0].answer as { result?: Record<string, unknown> }).result;
285
- // 逐字段断言(D9 常量逐字来自旧实现实测)
286
- expect(result).toEqual({ ...RUNTIME_PREFERENCES });
287
- expect(result?.nativeSearchEnhancementsEnabled).toBe(true);
288
- expect(result?.memoryEnabled).toBe(false);
289
- expect(result?.askUserQuestionAutoResolutionEnabled).toBe(true);
290
- expect(result?.modelContextBudgetStrategy).toBe("preflight-v1");
291
- expect(Object.keys(result ?? {}).sort()).toEqual([
292
- "askUserQuestionAutoResolutionEnabled",
293
- "memoryEnabled",
294
- "modelContextBudgetStrategy",
295
- "nativeSearchEnhancementsEnabled",
296
- ]);
297
- // 反向应答帧出站精确键集 {id, result}(无 jsonrpc、无未知键)
298
- const answerFrame = readState(stateFile)
299
- .map((e) => (e as Record<string, unknown>).frame)
300
- .find((f): f is Record<string, unknown> => isRecord(f) && typeof f.id === "string");
301
- expect(answerFrame).toBeDefined();
302
- expect(Object.keys(answerFrame!).sort()).toEqual(["id", "result"]);
303
- });
304
-
305
- it("未知反向请求 → 回 {id, result:{}}(不答会 15s 超时断连,旧实测 -32022)", async () => {
306
- const { conn, stateFile } = makeConnection();
307
- await conn.request("test/reverse", { reverseMethod: "permission/request", reverseParams: { tool: "Bash" } });
308
- const answers = readState(stateFile).filter((e) => e.ev === "reverse-answer");
309
- expect(answers).toHaveLength(1);
310
- const answer = answers[0].answer as { result?: unknown; error?: unknown };
311
- expect(answer.result).toEqual({});
312
- expect(answer.error).toBeUndefined();
313
- });
314
-
315
- it("应答失败不拖死连接(fire-and-forget + catch):故障 handler → 回 error 帧,连接仍可用", async () => {
316
- const { conn, stateFile } = makeConnection({
317
- reverseHandlers: {
318
- "session/requestRuntimePreferences": () => {
319
- throw new Error("prefs boom");
320
- },
321
- },
322
- });
323
- const created = await conn.request("session/create", {});
324
- expect(created).toBeTruthy();
325
- const answers = readState(stateFile).filter((e) => e.ev === "reverse-answer");
326
- expect(answers).toHaveLength(1);
327
- const answer = answers[0].answer as { error?: { code?: number; message?: string } };
328
- expect(answer.error?.code).toBe(-32000);
329
- expect(answer.error?.message).toContain("prefs boom");
330
- const r = await conn.request("test/echo", { still: "alive" });
331
- expect(r).toEqual({ still: "alive" });
332
- });
333
- });
334
-
335
- // ------------------------------------------- 崩溃收割(onClose)
336
-
337
- describe("崩溃收割(onClose/exit)", () => {
338
- it("进程意外退出:全部在途 reject,错误信息附 stderr 尾(400 字符截断)", async () => {
339
- const { conn } = makeConnection();
340
- await conn.request("test/echo", { warm: true });
341
- const errors = await Promise.all(
342
- [
343
- conn.request("test/delay-echo", { who: "a", delayMs: 10_000 }),
344
- conn.request("test/delay-echo", { who: "b", delayMs: 10_000 }),
345
- conn.request("test/suicide"),
346
- ].map((p) => p.then(
347
- () => {
348
- throw new Error("should reject");
349
- },
350
- (e: unknown) => e,
351
- )),
352
- );
353
- expect(errors).toHaveLength(3);
354
- for (const err of errors) {
355
- expect(err).toBeInstanceOf(Error);
356
- const msg = (err as Error).message;
357
- expect(msg).toContain("app-server");
358
- expect(msg).toContain("code=1");
359
- expect(msg).toContain("CRASH-MARK-TAIL");
360
- // 截断到常量值:600 个 A 只保留尾部(< 400),整段噪声不允许进错误信息
361
- expect(msg).not.toMatch(new RegExp(`A{${ZCODE_APPSERVER_STDERR_TAIL_CHARS}}`));
362
- }
363
- expect(await waitFor(() => !conn.alive)).toBe(true);
364
- }, 15_000);
365
- });
366
-
367
- // ------------------------------------------- stderr tee 落盘
368
-
369
- describe("stderr tee 落盘", () => {
370
- it("stderr 实时 append 到参数化路径(引擎数据目录注入点;测试用 tmp)", async () => {
371
- const { conn, stderrLog } = makeConnection({ stderrLines: true });
372
- await conn.request("test/echo", {});
373
- const ok = await waitFor(() => {
374
- try {
375
- const text = readFileSync(stderrLog, "utf8");
376
- return text.includes("fake-appserver stderr line A") && text.includes("fake-appserver stderr line B");
377
- } catch {
378
- return false;
379
- }
380
- });
381
- expect(ok).toBe(true);
382
- });
383
- });
384
-
385
- // ------------------------------------------- env 惯例(构造注入面)
386
-
387
- describe("env 惯例(共享宿主 HOME 形态)", () => {
388
- it("buildAppServerEnv:HOME 正向透传(共享宿主)+ 遥测关闭 + nesting guard 剥离/注入(fake 侧 env 快照)", async () => {
389
- const { conn, stateFile } = makeConnection({ polluteNested: true });
390
- await conn.request("test/echo", {});
391
- const envEvents = readState(stateFile).filter((e) => e.ev === "env");
392
- expect(envEvents).toHaveLength(1);
393
- const snap = envEvents[0] as {
394
- home?: string;
395
- telemetry?: string;
396
- nested?: string;
397
- unifiedNested?: string;
398
- };
399
- // 共享宿主 HOME 契约(2026-09 起):base env 携带的宿主 HOME 值原样透传到子进程
400
- // env(不覆写、不剥离——db/plugins/MCP 全继承宿主 HOME)
401
- expect(snap.home).toBe("/fake-host-home");
402
- expect(snap.telemetry).toBe("false");
403
- expect(snap.nested).toBeUndefined();
404
- expect(snap.unifiedNested).toBe("1");
405
- });
406
- });
407
-
408
- // ------------------------------------------- 关闭原语(R4 dispose 的连接侧原语)
409
-
410
- describe("关闭原语", () => {
411
- it("close():同步 SIGTERM 面——进程随后死亡;幂等;只起过一代", async () => {
412
- const { conn, stateFile } = makeConnection();
413
- await conn.request("test/echo", {});
414
- expect(conn.alive).toBe(true);
415
- conn.close();
416
- conn.close();
417
- expect(await waitFor(() => !conn.alive)).toBe(true);
418
- expect(readState(stateFile).filter((e) => e.ev === "boot")).toHaveLength(1);
419
- }, 10_000);
420
-
421
- it("shutdown():杀链走完进程退出;幂等;之后首个请求自动重建(不变量 4:与崩溃重建同路径)", async () => {
422
- const { conn, stateFile } = makeConnection();
423
- await conn.request("test/echo", {});
424
- await conn.shutdown({ graceMs: 1_500 });
425
- await conn.shutdown();
426
- expect(await waitFor(() => !conn.alive)).toBe(true);
427
- const r = await conn.request("test/echo", { reborn: true });
428
- expect(r).toEqual({ reborn: true });
429
- expect(readState(stateFile).filter((e) => e.ev === "boot")).toHaveLength(2);
430
- }, 15_000);
431
-
432
- it("close() 后调 shutdown():await close 发起的同一杀链,resolve 不早于进程退出(幂等——同一 promise)", async () => {
433
- const { conn, stateFile } = makeConnection();
434
- await conn.request("test/echo", {});
435
- const pid = conn.pid;
436
- conn.close();
437
- let shutdownSettled = false;
438
- const shutdownPromise = conn.shutdown().then(() => {
439
- shutdownSettled = true;
440
- });
441
- await shutdownPromise;
442
- expect(shutdownSettled).toBe(true);
443
- // killChain 挂 exit 事件 resolve(Node exit 前已收尸)——shutdown resolve 时进程
444
- // 必已退出:kill(0) 探活抛 ESRCH 即「resolve 不早于杀链完成」的机制性证据
445
- expect(() => process.kill(pid ?? -1, 0)).toThrow(/ESRCH/);
446
- // 幂等:再次 shutdown 复用同一 promise,无新杀链、无新进程
447
- await conn.shutdown();
448
- expect(readState(stateFile).filter((e) => e.ev === "boot")).toHaveLength(1);
449
- }, 10_000);
450
- });
451
-
452
- // ------------------------------------------- protocol 自报与宽容解析
453
-
454
- describe("protocol 自报与宽容解析", () => {
455
- it("首帧 {protocol:{name,version}} 自报忽略不抛,protocolInfo 记录,连接可用", async () => {
456
- const { conn } = makeConnection();
457
- const r = await conn.request("test/echo", { ok: 1 });
458
- expect(r).toEqual({ ok: 1 });
459
- expect(conn.protocolInfo).toEqual({ name: "ZCode Protocol", version: 1 });
460
- });
461
-
462
- it("protocol 推送形态 {method:'protocol'} 同样收敛到 protocolInfo", async () => {
463
- const { conn } = makeConnection({ protocolPush: true });
464
- await conn.request("test/echo", {});
465
- expect(conn.protocolInfo).toEqual({ name: "ZCode Protocol", version: 1 });
466
- });
467
-
468
- it("坏行跳过不断流:非 JSON 行之后正常应答", async () => {
469
- const { conn } = makeConnection();
470
- const r = await conn.request("test/malformed-first", {});
471
- expect(r).toEqual({ survived: true });
472
- });
473
- });
@@ -1,43 +0,0 @@
1
- // parser.test.ts —— usage 字段映射(事件层 execution 版)+ coarse 事件合成不变量回归。
2
- // 原 stdout 有界收集/终 JSON 解析/运行失败文案一族(含 golden spawn 样本回归)已随
3
- // CLI spawn 链删除(2026-09 单一 app-server 形态——终态来自 session-channel 收尾帧,
4
- // 不经 stdout 解析);mapZcodeOutcomeUsage(终态层映射)经 zcode-engine-appserver.test.ts
5
- // 的 outcome.usage 断言覆盖。
6
-
7
- import { describe, expect, it } from "vitest";
8
-
9
- import { mapZcodeUsage, synthesizeCoarseEvents } from "../parser.ts";
10
-
11
- describe("mapZcodeUsage:字段名映射", () => {
12
- it("usage 字段名映射:inputTokens→input 等四项(cost 无来源不出现)", () => {
13
- const u = mapZcodeUsage({
14
- inputTokens: 10,
15
- outputTokens: 20,
16
- cacheReadTokens: 5,
17
- cacheWriteTokens: 0,
18
- });
19
- expect(u).toEqual({ input: 10, output: 20, cacheRead: 5, cacheWrite: 0 });
20
- expect(u !== undefined && "cost" in u).toBe(false);
21
- });
22
-
23
- it("usage 形状不完整时显式 undefined(不给残缺对象)", () => {
24
- expect(mapZcodeUsage(undefined)).toBeUndefined();
25
- expect(mapZcodeUsage("nope")).toBeUndefined();
26
- expect(mapZcodeUsage({})).toBeUndefined();
27
- });
28
- });
29
-
30
- describe("synthesizeCoarseEvents:coarse 不变量", () => {
31
- it("message_end(含 usage)在前、turn_end 最后", () => {
32
- const usage = { input: 1, output: 2, cacheRead: 0, cacheWrite: 0 };
33
- const evs = synthesizeCoarseEvents("ok", usage);
34
- expect(evs).toEqual([{ type: "message_end", usage }, { type: "turn_end" }]);
35
- });
36
-
37
- it("无 usage 时 message_end 不带残缺字段", () => {
38
- const evs = synthesizeCoarseEvents("ok");
39
- expect(evs[0]).toEqual({ type: "message_end" });
40
- expect("usage" in evs[0]!).toBe(false);
41
- expect(evs[evs.length - 1]).toEqual({ type: "turn_end" });
42
- });
43
- });
@@ -1,124 +0,0 @@
1
- // preparer.test.ts —— v2 单源模型解析 / 模型可发现性 / 凭据与模型前置错误。
2
- // 凭据源 = v2 config 单源(2026-08-25 拍板:不读 ~/.zcode/cli/config.json——GUI 不
3
- // 管理该文件,可能残留历史验证配置)。原 HOME 池化面(池目录 SSOT / 原子写 /
4
- // mtime 免重写 / 池 config 无 plugins 块)已随「共享宿主 HOME」重构删除(2026-09:
5
- // app-server 侧凭据经 appserver-launcher fs 拦截注入,不再建池写 config)。
6
-
7
- import * as fs from "node:fs";
8
- import * as os from "node:os";
9
- import * as path from "node:path";
10
-
11
- import { beforeEach, describe, expect, it } from "vitest";
12
-
13
- import { ZcodePrepareError, listZcodeModels, resolveZcodeModelRef } from "../preparer.ts";
14
-
15
- let tmpRoot: string;
16
- let v2Path: string;
17
-
18
- function writeJson(p: string, v: unknown): void {
19
- fs.mkdirSync(path.dirname(p), { recursive: true });
20
- fs.writeFileSync(p, JSON.stringify(v, null, 2));
21
- }
22
-
23
- const PROVIDER_A = "builtin:bigmodel-coding-plan";
24
- const PROVIDER_B = "e512d53e-test-provider";
25
-
26
- function seedSources(): void {
27
- writeJson(v2Path, {
28
- provider: {
29
- [PROVIDER_A]: { options: { apiKey: "key-a", baseURL: "https://a.example" }, models: { "GLM-5.3": {}, "GLM-5.2": {} } },
30
- [PROVIDER_B]: { name: "test-router", options: { apiKey: "key-b", baseURL: "https://b.example" }, models: { "mimo-v2.5-pro": {} } },
31
- "no-key-provider": { options: { baseURL: "https://x.example" }, models: { "M1": {} } },
32
- },
33
- });
34
- }
35
-
36
- beforeEach(() => {
37
- tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), "zcode-preparer-"));
38
- v2Path = path.join(tmpRoot, "v2-config.json");
39
- seedSources();
40
- });
41
-
42
- describe("resolveZcodeModelRef(v2 单源)", () => {
43
- it("显式全名解析 + 规范化", () => {
44
- expect(resolveZcodeModelRef(`${PROVIDER_B}/mimo-v2.5-pro`, { v2ConfigPath: v2Path })).toBe(
45
- `${PROVIDER_B}/mimo-v2.5-pro`,
46
- );
47
- });
48
-
49
- it("短名按默认 provider(builtin:bigmodel-coding-plan)解析", () => {
50
- expect(resolveZcodeModelRef("GLM-5.3", { v2ConfigPath: v2Path })).toBe(
51
- `${PROVIDER_A}/GLM-5.3`,
52
- );
53
- });
54
-
55
- it("未指定时落官方兜底(不受任何本机 CLI 配置影响)", () => {
56
- expect(resolveZcodeModelRef(undefined, { v2ConfigPath: v2Path })).toBe(
57
- `${PROVIDER_A}/GLM-5.3`,
58
- );
59
- });
60
-
61
- it("未知模型 → model_not_available(列该 provider 可用模型)", () => {
62
- try {
63
- resolveZcodeModelRef(`${PROVIDER_A}/nope`, { v2ConfigPath: v2Path });
64
- expect.unreachable("should throw");
65
- } catch (err) {
66
- expect(err).toBeInstanceOf(ZcodePrepareError);
67
- const e = err as ZcodePrepareError;
68
- expect(e.code).toBe("model_not_available");
69
- expect(e.message).toContain("GLM-5.3, GLM-5.2");
70
- }
71
- });
72
-
73
- it("未知 provider → model_not_available(列带凭据 provider)", () => {
74
- try {
75
- resolveZcodeModelRef("ghost/m", { v2ConfigPath: v2Path });
76
- expect.unreachable("should throw");
77
- } catch (err) {
78
- expect((err as ZcodePrepareError).code).toBe("model_not_available");
79
- expect((err as ZcodePrepareError).message).toContain(PROVIDER_A);
80
- expect((err as ZcodePrepareError).message).toContain(PROVIDER_B);
81
- }
82
- });
83
-
84
- it("provider 存在但无 apiKey → engine_credential_missing", () => {
85
- try {
86
- resolveZcodeModelRef("no-key-provider/M1", { v2ConfigPath: v2Path });
87
- expect.unreachable("should throw");
88
- } catch (err) {
89
- expect((err as ZcodePrepareError).code).toBe("engine_credential_missing");
90
- }
91
- });
92
-
93
- it("v2 无任何带 apiKey 的 provider → engine_credential_missing(指向配置说明)", () => {
94
- writeJson(v2Path, { provider: {} });
95
- try {
96
- resolveZcodeModelRef(undefined, { v2ConfigPath: v2Path });
97
- expect.unreachable("should throw");
98
- } catch (err) {
99
- const e = err as ZcodePrepareError;
100
- expect(e.code).toBe("engine_credential_missing");
101
- expect(e.message).toContain("ZCode 桌面端");
102
- expect(e.message).toContain("docs/research/agent-engine-zcode.md");
103
- }
104
- });
105
- });
106
-
107
- describe("listZcodeModels(U7 可发现性)", () => {
108
- it("聚合 v2 带凭据 provider × models(含 name 拼接),无凭据/空清单过滤", () => {
109
- const models = listZcodeModels({ v2ConfigPath: v2Path });
110
- const ids = models.map((m) => m.id);
111
- expect(ids).toContain(`${PROVIDER_A}/GLM-5.3`);
112
- expect(ids).toContain(`${PROVIDER_A}/GLM-5.2`);
113
- expect(ids).toContain(`${PROVIDER_B}/mimo-v2.5-pro`);
114
- // 无凭据 provider 不进清单
115
- expect(ids.some((id) => id.startsWith("no-key-provider/"))).toBe(false);
116
- // name = "<provider.name> · <model>"(v2 有 name 字段时)
117
- const withName = models.find((m) => m.id === `${PROVIDER_B}/mimo-v2.5-pro`);
118
- expect(withName?.name).toBe("test-router · mimo-v2.5-pro");
119
- });
120
-
121
- it("v2 不可读 → 空清单(fail-safe)", () => {
122
- expect(listZcodeModels({ v2ConfigPath: path.join(tmpRoot, "absent.json") })).toEqual([]);
123
- });
124
- });