@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
@@ -1,243 +0,0 @@
1
- /**
2
- * writeAppendSystemPromptFile 组装矩阵(W2 移交 CRAP 43.1;私有函数,经公共
3
- * runSpawn 驱动,与 spawn-worktree-guidance.test.ts 同 mock 模式——mock
4
- * temp-prompt 捕获 appendParts.join 后的完整 content)。
5
- *
6
- * 覆盖分支(session-runner.ts g. 段):
7
- * - agentConfig.systemPrompt / appendSystemPrompt 片段 / maxTurns wrap-up hint 的注入与顺序
8
- * - ask_user RPC 提示的 mode 门控(rpc=gui 响应 / json=headless 不注入)
9
- * - maxTurns 缺省/0 → 不注入 wrap-up hint
10
- * - fork depth(env block Depth 行)与 ask_user+wrap-up 的组合互不干扰
11
- *
12
- * worktree 分支(WORKTREE_GUIDANCE_PROMPT)已由 spawn-worktree-guidance.test.ts
13
- * 覆盖,此处不重复。
14
- */
15
- import type { PassThrough } from "node:stream";
16
-
17
- import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
18
-
19
- const captured = vi.hoisted(() => ({ content: "", calls: 0 }));
20
-
21
- vi.mock("node:child_process", async () => {
22
- const { EventEmitter } = await import("node:events");
23
- const { PassThrough } = await import("node:stream");
24
-
25
- class FakeChild extends EventEmitter {
26
- pid = 12345;
27
- stdout = new PassThrough();
28
- stdin = new PassThrough();
29
- stderr = new PassThrough();
30
- killed = false;
31
- killSignal: string | undefined;
32
- kill(sig?: string): boolean {
33
- this.killed = true;
34
- this.killSignal = sig;
35
- return true;
36
- }
37
- }
38
-
39
- return {
40
- spawn: vi.fn(() => new FakeChild()),
41
- execFileSync: vi.fn(() => ""),
42
- };
43
- });
44
-
45
- vi.mock("node:fs", async () => {
46
- const actual = await import("node:fs");
47
- return {
48
- default: {
49
- ...actual,
50
- mkdirSync: vi.fn(),
51
- existsSync: vi.fn(() => false),
52
- appendFileSync: vi.fn(),
53
- writeFileSync: vi.fn(),
54
- readdirSync: vi.fn(() => []),
55
- },
56
- mkdirSync: vi.fn(),
57
- existsSync: vi.fn(() => false),
58
- appendFileSync: vi.fn(),
59
- writeFileSync: vi.fn(),
60
- readdirSync: vi.fn(() => []),
61
- promises: actual.promises,
62
- };
63
- });
64
-
65
- vi.mock("../execution/alive-store.ts", () => ({
66
- writeAliveMarker: vi.fn(),
67
- }));
68
-
69
- vi.mock("../execution/engine/engines/pi/temp-prompt.ts", () => ({
70
- writePromptToTempFile: vi.fn(async (agent: string, content: string) => {
71
- captured.calls++;
72
- captured.content = content;
73
- const safeName = agent.replace(/[^\w.-]+/g, "_");
74
- return { dir: `/tmp/fake-${safeName}`, filePath: `/tmp/fake-${safeName}/prompt.md` };
75
- }),
76
- cleanupTempPrompt: vi.fn(async () => {}),
77
- }));
78
-
79
- import { spawn } from "node:child_process";
80
-
81
- import { createRecord } from "../execution/execution-record.ts";
82
- import { runSpawn, type RunOptions, type SessionRunnerContext } from "../execution/engine/engines/pi/session-runner.ts";
83
-
84
- const mockSpawn = vi.mocked(spawn);
85
-
86
- interface FakeChild {
87
- pid: number;
88
- stdout: PassThrough;
89
- stderr: PassThrough;
90
- killed: boolean;
91
- killSignal: string | undefined;
92
- emit(event: string, ...args: unknown[]): boolean;
93
- }
94
-
95
- function getLastSpawnedChild(): FakeChild {
96
- const result = mockSpawn.mock.results.at(-1);
97
- if (!result) throw new Error("spawn was not called yet");
98
- return result.value as FakeChild;
99
- }
100
-
101
- /** 等待第 targetCount 次 spawn 发生(同测试多次 runSpawn 时按基线递增等待)。 */
102
- async function waitForSpawn(targetCount = 1, timeoutMs = 1000): Promise<void> {
103
- const start = Date.now();
104
- while (mockSpawn.mock.results.length < targetCount) {
105
- if (Date.now() - start > timeoutMs) {
106
- throw new Error(`spawn #${targetCount} not called within ${timeoutMs}ms`);
107
- }
108
- await new Promise((r) => setTimeout(r, 5));
109
- }
110
- }
111
-
112
- let seq = 0;
113
-
114
- function makeRecord() {
115
- seq += 1;
116
- return createRecord(`append-asm-${seq}`, {
117
- agent: "general-purpose",
118
- model: "test/model",
119
- mode: "background",
120
- task: "test task",
121
- slug: "append-asm",
122
- startedAt: Date.now(),
123
- rootSessionId: "s1",
124
- parentRecordId: undefined,
125
- depth: 0,
126
- });
127
- }
128
-
129
- function makeRunOpts(overrides: Partial<RunOptions> = {}): RunOptions {
130
- return {
131
- resolved: { model: { provider: "test", id: "model", name: "Model", reasoning: false }, thinkingLevel: undefined },
132
- agentConfig: undefined,
133
- appendSystemPrompt: undefined,
134
- skillPath: undefined,
135
- schema: undefined,
136
- maxTurns: undefined,
137
- graceTurns: undefined,
138
- signal: undefined,
139
- onEvent: undefined,
140
- ...overrides,
141
- };
142
- }
143
-
144
- function makeCtx(overrides: Partial<SessionRunnerContext> = {}): SessionRunnerContext {
145
- return {
146
- cwd: "/fake/cwd",
147
- agentDir: "/fake/agent",
148
- skillDirs: [],
149
- mainCwd: "/fake/cwd",
150
- sessionRootId: "root-session-test",
151
- rootCwd: "/fake/cwd",
152
- ...overrides,
153
- };
154
- }
155
-
156
- /** 跑一次 runSpawn 并捕获 appendSystemPrompt content(完成后释放子进程)。 */
157
- async function captureAppendContent(opts: RunOptions, ctx: SessionRunnerContext): Promise<string> {
158
- const baseline = mockSpawn.mock.results.length;
159
- const resultPromise = runSpawn(makeRecord(), "test task", opts, ctx);
160
- await waitForSpawn(baseline + 1);
161
- const content = captured.content;
162
- const child = getLastSpawnedChild();
163
- child.emit("close", 0);
164
- await resultPromise;
165
- return content;
166
- }
167
-
168
- describe("writeAppendSystemPromptFile 组装(经 runSpawn 驱动)", () => {
169
- beforeEach(() => {
170
- vi.clearAllMocks();
171
- captured.content = "";
172
- captured.calls = 0;
173
- });
174
-
175
- afterEach(() => {
176
- vi.restoreAllMocks();
177
- });
178
-
179
- it("全片段组装:env block → agent body → 调用方片段 → wrap-up hint,顺序稳定", async () => {
180
- const content = await captureAppendContent(
181
- makeRunOpts({
182
- agentConfig: { name: "worker", systemPrompt: "AGENT-BODY-MARKER" },
183
- appendSystemPrompt: ["FRAG-ONE", "FRAG-TWO"],
184
- maxTurns: 5,
185
- }),
186
- makeCtx(),
187
- );
188
- expect(content).toContain("AGENT-BODY-MARKER");
189
- expect(content).toContain("FRAG-ONE");
190
- expect(content).toContain("FRAG-TWO");
191
- // maxTurns>0 → 注入 wrap-up 收尾提示(rpc steer 未接通的启动期补偿)
192
- expect(content).toContain("You have a turn limit");
193
- // 顺序:env block 最前,agent body 在调用方片段前,hint 在其后
194
- const envIdx = content.indexOf("--- environment");
195
- const bodyIdx = content.indexOf("AGENT-BODY-MARKER");
196
- const fragIdx = content.indexOf("FRAG-ONE");
197
- const hintIdx = content.indexOf("You have a turn limit");
198
- expect(envIdx).toBeLessThan(bodyIdx);
199
- expect(bodyIdx).toBeLessThan(fragIdx);
200
- expect(fragIdx).toBeLessThan(hintIdx);
201
- });
202
-
203
- it("maxTurns 缺省/0 → 不注入 wrap-up hint(不限时不预告收尾)", async () => {
204
- const undefinedCase = await captureAppendContent(makeRunOpts(), makeCtx());
205
- expect(undefinedCase).not.toContain("You have a turn limit");
206
- const zeroCase = await captureAppendContent(makeRunOpts({ maxTurns: 0 }), makeCtx());
207
- expect(zeroCase).not.toContain("You have a turn limit");
208
- });
209
-
210
- it("ask_user RPC 提示 mode 门控:rpc(gui 响应)注入,json(headless)不注入", async () => {
211
- const opts = makeRunOpts({ agentConfig: { name: "worker", systemPrompt: "", tools: ["ask_user"] } });
212
- const rpcContent = await captureAppendContent(opts, makeCtx({ mode: "rpc" }));
213
- expect(rpcContent).toContain("ask_user Tool Availability");
214
- const jsonContent = await captureAppendContent(opts, makeCtx({ mode: "json" }));
215
- // headless 无 UI 通道,注入会误导 LLM(W4 守卫)
216
- expect(jsonContent).not.toContain("ask_user Tool Availability");
217
- });
218
-
219
- it("mode 响应但 tools 不含 ask_user → 不注入", async () => {
220
- const content = await captureAppendContent(
221
- makeRunOpts({ agentConfig: { name: "worker", systemPrompt: "", tools: ["read", "bash"] } }),
222
- makeCtx({ mode: "rpc" }),
223
- );
224
- expect(content).not.toContain("ask_user Tool Availability");
225
- });
226
-
227
- it("fork 场景:parentForkDepth 传入 → env block 带 Depth 行(buildEnvBlock 取 max 语义)", async () => {
228
- const content = await captureAppendContent(
229
- makeRunOpts({ fork: true, parentForkDepth: 2 }),
230
- makeCtx(),
231
- );
232
- expect(content).toContain("Depth:");
233
- // 无 fork 无嵌套时不出现 Depth 行
234
- const plain = await captureAppendContent(makeRunOpts(), makeCtx());
235
- expect(plain).not.toContain("Depth:");
236
- });
237
-
238
- it("env block 恒为第一段:最小配置也落盘(writePromptToTempFile 必被调用)", async () => {
239
- await captureAppendContent(makeRunOpts(), makeCtx());
240
- expect(captured.calls).toBe(1);
241
- expect(captured.content).toContain("Working directory: /fake/cwd");
242
- });
243
- });
@@ -1,125 +0,0 @@
1
- import { describe, expect,it } from "vitest";
2
-
3
- import { parseSpawnLine } from "../execution/engine/engines/pi/spawn-event-adapter";
4
- import { sendGetStateCommand } from "../execution/engine/engines/pi/stdin-writer";
5
-
6
- describe("FR-4: get_state RPC handshake", () => {
7
- describe("sendGetStateCommand", () => {
8
- it("should write get_state command to stdin", () => {
9
- const written: string[] = [];
10
- const child = {
11
- stdin: {
12
- destroyed: false,
13
- write: (data: string) => {
14
- written.push(data);
15
- return true;
16
- },
17
- },
18
- } as unknown as Parameters<typeof sendGetStateCommand>[0];
19
-
20
- const id = sendGetStateCommand(child);
21
-
22
- expect(written).toHaveLength(1);
23
- const parsed = JSON.parse(written[0]);
24
- expect(parsed.type).toBe("get_state");
25
- expect(parsed.id).toBe(id);
26
- expect(typeof parsed.id).toBe("string");
27
- });
28
-
29
- it("should not write if stdin is destroyed", () => {
30
- const written: string[] = [];
31
- const child = {
32
- stdin: {
33
- destroyed: true,
34
- write: (data: string) => {
35
- written.push(data);
36
- return true;
37
- },
38
- },
39
- } as unknown as Parameters<typeof sendGetStateCommand>[0];
40
-
41
- sendGetStateCommand(child);
42
-
43
- expect(written).toHaveLength(0);
44
- });
45
-
46
- it("should not write if stdin is null", () => {
47
- const child = {
48
- stdin: null,
49
- } as unknown as Parameters<typeof sendGetStateCommand>[0];
50
-
51
- // Should not throw
52
- sendGetStateCommand(child);
53
- });
54
- });
55
-
56
- describe("parseSpawnLine: get_state response", () => {
57
- it("should parse get_state response correctly", () => {
58
- const line = JSON.stringify({
59
- type: "response",
60
- command: "get_state",
61
- success: true,
62
- id: "test-req-id",
63
- data: {
64
- sessionFile: "/path/to/session.jsonl",
65
- sessionId: "session-123",
66
- },
67
- });
68
-
69
- const parsed = parseSpawnLine(line);
70
- expect(parsed).not.toBeNull();
71
- expect(parsed!.kind).toBe("response");
72
- if (parsed!.kind === "response") {
73
- expect(parsed!.command).toBe("get_state");
74
- expect(parsed!.success).toBe(true);
75
- expect(parsed!.id).toBe("test-req-id");
76
- expect(parsed!.data).toEqual({
77
- sessionFile: "/path/to/session.jsonl",
78
- sessionId: "session-123",
79
- });
80
- }
81
- });
82
-
83
- it("should parse get_state error response", () => {
84
- const line = JSON.stringify({
85
- type: "response",
86
- command: "get_state",
87
- success: false,
88
- id: "test-req-id",
89
- error: "session not initialized",
90
- });
91
-
92
- const parsed = parseSpawnLine(line);
93
- expect(parsed).not.toBeNull();
94
- expect(parsed!.kind).toBe("response");
95
- if (parsed!.kind === "response") {
96
- expect(parsed!.command).toBe("get_state");
97
- expect(parsed!.success).toBe(false);
98
- expect(parsed!.error).toBe("session not initialized");
99
- }
100
- });
101
-
102
- it("should parse get_state response without id (notification)", () => {
103
- const line = JSON.stringify({
104
- type: "response",
105
- command: "get_state",
106
- success: true,
107
- data: { sessionId: "session-456" },
108
- });
109
-
110
- const parsed = parseSpawnLine(line);
111
- expect(parsed).not.toBeNull();
112
- expect(parsed!.kind).toBe("response");
113
- if (parsed!.kind === "response") {
114
- expect(parsed!.command).toBe("get_state");
115
- expect(parsed!.id).toBeUndefined();
116
- }
117
- });
118
- });
119
-
120
- // [B8] 删除原 "get_state response matching in stdout pump" describe 块(3 case):
121
- // 该块在测试内重写了 session-runner 的 response matching 逻辑(Map<id,resolver> +
122
- // delete + resolver(data)),断言的是测试自己复制的逻辑而非生产代码——tautological
123
- // (同义反复),无法捕获生产 matching 的真实回归。真实覆盖已在 run-spawn-rpc-mode.test.ts
124
- // (端到端跑 session-runner 的 stdout pump + get_state 握手)中存在,此处删除不减覆盖。
125
- });
@@ -1,69 +0,0 @@
1
- /**
2
- * session-runner message_update 分流测试。
3
- *
4
- * 核心回归点:toolcall_delta(工具入参 JSON 增量)不得被当成 text_delta
5
- * forward 到 subagent overlay 的 streaming content——否则 assistant 正文会
6
- * 原样流出 {"path":"..."}{"command":"..."} 工具参数 JSON 串,表现为对话末尾
7
- * JSON 与 text 混杂、无 ICON+title 工具卡片前缀(用户实际报告的现象)。
8
- *
9
- * 根因:pi-ai AssistantMessageEvent 的 type 集合含 text_delta / thinking_delta /
10
- * toolcall_delta / signature_delta 等(见 @earendil-works/pi-ai types.d.ts)。
11
- * 旧实现 `ame?.delta !== undefined` 反向排除(只拦 thinking_delta),toolcall_delta
12
- * 因带 delta 字段被误判为 text_delta。正向判定(只放行 text_delta)根治。
13
- */
14
- import { describe, it, expect } from "vitest";
15
- import { mapAssistantMessageDelta } from "../execution/engine/engines/pi/session-runner.js";
16
-
17
- describe("mapAssistantMessageDelta: assistantMessageEvent → streaming 事件分流", () => {
18
- it("text_delta → forward 为 text_delta", () => {
19
- expect(mapAssistantMessageDelta({ type: "text_delta", delta: "hello" })).toEqual({
20
- type: "text_delta",
21
- delta: "hello",
22
- });
23
- });
24
-
25
- it("thinking_delta → forward 为 thinking_delta(走独立通道,不进 text stream)", () => {
26
- expect(mapAssistantMessageDelta({ type: "thinking_delta", delta: "思考" })).toEqual({
27
- type: "thinking_delta",
28
- delta: "思考",
29
- });
30
- });
31
-
32
- it("thinking_delta 缺 delta 兜底空串(不抛错,与旧实现行为一致)", () => {
33
- expect(mapAssistantMessageDelta({ type: "thinking_delta" })).toEqual({
34
- type: "thinking_delta",
35
- delta: "",
36
- });
37
- });
38
-
39
- it("toolcall_delta → null(工具入参 JSON 增量绝不混入 text)", () => {
40
- // 核心回归:旧实现 ame?.delta !== undefined 会把 toolcall_delta 当 text_delta
41
- expect(mapAssistantMessageDelta({ type: "toolcall_delta", delta: '{"path":"/x"}' })).toBeNull();
42
- });
43
-
44
- it("toolcall_delta 的部分 JSON 片段也不混入(流式累积的中间态)", () => {
45
- expect(mapAssistantMessageDelta({ type: "toolcall_delta", delta: '{"path":"' })).toBeNull();
46
- expect(mapAssistantMessageDelta({ type: "toolcall_delta", delta: "/Users/foo/bar" })).toBeNull();
47
- expect(mapAssistantMessageDelta({ type: "toolcall_delta", delta: '"}}' })).toBeNull();
48
- });
49
-
50
- it("其他带 delta 的 type(signature_delta 等未来扩展)也不混入 text", () => {
51
- expect(mapAssistantMessageDelta({ type: "signature_delta", delta: "sig-xyz" })).toBeNull();
52
- });
53
-
54
- it("非 delta 事件(start/end/done 等)返回 null", () => {
55
- expect(mapAssistantMessageDelta({ type: "text_start" })).toBeNull();
56
- expect(mapAssistantMessageDelta({ type: "text_end" })).toBeNull();
57
- expect(mapAssistantMessageDelta({ type: "toolcall_start" })).toBeNull();
58
- expect(mapAssistantMessageDelta({ type: "toolcall_end" })).toBeNull();
59
- expect(mapAssistantMessageDelta({ type: "done" })).toBeNull();
60
- });
61
-
62
- it("缺 type 或缺 delta 的异常输入返回 null(不抛错)", () => {
63
- expect(mapAssistantMessageDelta({})).toBeNull();
64
- // text_delta 缺 delta → null(无法 forward 空 delta 增量)
65
- expect(mapAssistantMessageDelta({ type: "text_delta" })).toBeNull();
66
- // 有 delta 无 type → null(未知来源,不放行)
67
- expect(mapAssistantMessageDelta({ delta: "x" })).toBeNull();
68
- });
69
- });