@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,166 +0,0 @@
1
- // src/__tests__/pi-invocation.test.ts
2
- import * as fs from "node:fs";
3
- import * as os from "node:os";
4
- import * as path from "node:path";
5
-
6
- import { afterEach, beforeEach, describe, expect, it } from "vitest";
7
-
8
- import { getPiInvocation } from "../engine/engines/pi/pi-invocation.ts";
9
- import {
10
- RELAY_ENV_NODE,
11
- RELAY_ENV_RECORD_ID,
12
- RELAY_ENV_SCRIPT,
13
- RELAY_ENV_SESSION_ID,
14
- RELAY_ENV_SOCKET,
15
- } from "../relay-env.ts";
16
-
17
- // [验收门修复] getPiInvocation 的 relay 分支优先读宿主 RELAY env——根级 pnpm test
18
- // 进程若继承宿主(pi 子进程链)的 RELAY 身份,直连分支用例的 execPath/argv 断言
19
- // 会被改道(非自免疫,依赖 runner 环境)。文件级钩子对全部用例统一消毒:beforeEach
20
- // 删五键、afterEach 恢复原值——有泄漏无泄漏双向绿;第二组 relay 分支用例自设
21
- // RELAY_FULL 在清理之后执行,语义不受影响。
22
- const RELAY_ENV_KEYS = [
23
- RELAY_ENV_SOCKET,
24
- RELAY_ENV_NODE,
25
- RELAY_ENV_SCRIPT,
26
- RELAY_ENV_SESSION_ID,
27
- RELAY_ENV_RECORD_ID,
28
- ] as const;
29
- let savedRelayEnv: Record<string, string | undefined>;
30
- beforeEach(() => {
31
- savedRelayEnv = {};
32
- for (const key of RELAY_ENV_KEYS) savedRelayEnv[key] = process.env[key];
33
- for (const key of RELAY_ENV_KEYS) delete process.env[key];
34
- });
35
- afterEach(() => {
36
- for (const key of RELAY_ENV_KEYS) {
37
- const value = savedRelayEnv[key];
38
- if (value === undefined) delete process.env[key];
39
- else process.env[key] = value;
40
- }
41
- });
42
-
43
- describe("getPiInvocation", () => {
44
- const originalArgv = process.argv;
45
- const originalExecPath = process.execPath;
46
- let tmpScript: string;
47
-
48
- afterEach(() => {
49
- Object.defineProperty(process, "argv", { value: originalArgv, configurable: true });
50
- Object.defineProperty(process, "execPath", { value: originalExecPath, configurable: true });
51
- if (tmpScript && fs.existsSync(tmpScript)) fs.unlinkSync(tmpScript);
52
- });
53
-
54
- it("真实脚本路径存在 → node <script> <userArgs>", () => {
55
- // 创建真实临时脚本文件(避免 ESM spy 限制)
56
- tmpScript = path.join(os.tmpdir(), `pi-inv-test-${Date.now()}.mjs`);
57
- fs.writeFileSync(tmpScript, "// test");
58
- Object.defineProperty(process, "argv", { value: ["node", tmpScript], configurable: true });
59
- Object.defineProperty(process, "execPath", { value: "/usr/bin/node", configurable: true });
60
-
61
- const result = getPiInvocation(["--mode", "json", "Task: x"]);
62
- expect(result.command).toBe("/usr/bin/node");
63
- expect(result.args).toEqual([tmpScript, "--mode", "json", "Task: x"]);
64
- });
65
-
66
- it("bun 虚拟脚本(/$bunfs/root/)→ 退化到 pi-in-PATH", () => {
67
- tmpScript = "";
68
- const virtualScript = "/$bunfs/root/pi";
69
- Object.defineProperty(process, "argv", { value: ["bun", virtualScript], configurable: true });
70
- Object.defineProperty(process, "execPath", { value: "/usr/bin/bun", configurable: true });
71
-
72
- const result = getPiInvocation(["--mode", "json"]);
73
- expect(result.command).toBe("pi");
74
- expect(result.args).toEqual(["--mode", "json"]);
75
- });
76
-
77
- it("非通用 runtime(pi standalone binary)→ 直接 execPath", () => {
78
- tmpScript = "";
79
- Object.defineProperty(process, "argv", { value: ["/usr/bin/pi", "/nonexistent"], configurable: true });
80
- Object.defineProperty(process, "execPath", { value: "/usr/local/bin/pi-binary", configurable: true });
81
-
82
- const result = getPiInvocation(["--mode", "json"]);
83
- expect(result.command).toBe("/usr/local/bin/pi-binary");
84
- expect(result.args).toEqual(["--mode", "json"]);
85
- });
86
-
87
- it("node 通用 runtime + 脚本不存在 → pi-in-PATH", () => {
88
- tmpScript = "";
89
- Object.defineProperty(process, "argv", { value: ["node", "/nonexistent"], configurable: true });
90
- Object.defineProperty(process, "execPath", { value: "/usr/bin/node", configurable: true });
91
-
92
- const result = getPiInvocation(["--mode", "json"]);
93
- expect(result.command).toBe("pi");
94
- expect(result.args).toEqual(["--mode", "json"]);
95
- });
96
-
97
- it("空 userArgs 合法(仅 command + 空 args)", () => {
98
- tmpScript = "";
99
- Object.defineProperty(process, "argv", { value: ["node"], configurable: true });
100
- Object.defineProperty(process, "execPath", { value: "/usr/bin/node", configurable: true });
101
-
102
- const result = getPiInvocation([]);
103
- expect(result.command).toBe("pi");
104
- expect(result.args).toEqual([]);
105
- });
106
- });
107
-
108
- describe("getPiInvocation relay 分支(E 方案 §5.1)", () => {
109
- const originalArgv = process.argv;
110
- const originalExecPath = process.execPath;
111
- const RELAY_ENVS = [RELAY_ENV_SOCKET, RELAY_ENV_NODE, RELAY_ENV_SCRIPT] as const;
112
- /** 三 env 齐备的基准值(改 argv/execPath 隔离直连分支,只测 relay 判定本身)。 */
113
- const RELAY_FULL: Record<string, string> = {
114
- [RELAY_ENV_SOCKET]: "/tmp/relay-test.sock",
115
- [RELAY_ENV_NODE]: "/usr/bin/relay-node",
116
- [RELAY_ENV_SCRIPT]: "/opt/relay/relay.mjs",
117
- };
118
-
119
- afterEach(() => {
120
- Object.defineProperty(process, "argv", { value: originalArgv, configurable: true });
121
- Object.defineProperty(process, "execPath", { value: originalExecPath, configurable: true });
122
- for (const key of RELAY_ENVS) delete process.env[key];
123
- });
124
-
125
- /** 形态 1:三 env 齐备 + 默认 opts → relay invocation(command=NODE、args[0]=SCRIPT)。 */
126
- it("三 env 齐备(无 opts)→ 代理形态 <NODE> <SCRIPT> <userArgs>", () => {
127
- Object.assign(process.env, RELAY_FULL);
128
- const result = getPiInvocation(["--mode", "rpc"]);
129
- expect(result.command).toBe(RELAY_FULL[RELAY_ENV_NODE]);
130
- expect(result.args).toEqual([RELAY_FULL[RELAY_ENV_SCRIPT], "--mode", "rpc"]);
131
- });
132
-
133
- /** 形态 1 变体:opts.relay === true 显式开启,行为与缺省一致。 */
134
- it("三 env 齐备 + opts.relay=true → 同缺省(显式开启非必填)", () => {
135
- Object.assign(process.env, RELAY_FULL);
136
- const result = getPiInvocation(["--mode", "rpc"], { relay: true });
137
- expect(result.command).toBe(RELAY_FULL[RELAY_ENV_NODE]);
138
- expect(result.args[0]).toBe(RELAY_FULL[RELAY_ENV_SCRIPT]);
139
- });
140
-
141
- /** 形态 2:三缺一逐个枚举 → 回落现状直连(全有或全无,E-TUI 零回归)。 */
142
- it("三缺一(逐个枚举)→ 现状直连分支", () => {
143
- // 直连分支落到「node + 不存在脚本 → pi-in-PATH」可稳定断言(不依赖测试机 execPath 形态)
144
- Object.defineProperty(process, "argv", { value: ["node", "/nonexistent"], configurable: true });
145
- Object.defineProperty(process, "execPath", { value: "/usr/bin/node", configurable: true });
146
- for (const missing of RELAY_ENVS) {
147
- const partial = { ...RELAY_FULL };
148
- delete partial[missing];
149
- for (const key of RELAY_ENVS) delete process.env[key];
150
- Object.assign(process.env, partial);
151
- const result = getPiInvocation(["--mode", "rpc"]);
152
- expect(result.command).toBe("pi"); // 分支 3:通用 runtime + 脚本不存在 → PATH
153
- expect(result.args).toEqual(["--mode", "rpc"]);
154
- }
155
- });
156
-
157
- /** 形态 3:probe 排除——显式 relay:false 时即便三 env 齐备也直连。 */
158
- it("relay:false 强制直连(probe 语义:探 pi 本体,不探 runtime 健康)", () => {
159
- Object.assign(process.env, RELAY_FULL);
160
- Object.defineProperty(process, "argv", { value: ["node", "/nonexistent"], configurable: true });
161
- Object.defineProperty(process, "execPath", { value: "/usr/bin/node", configurable: true });
162
- const result = getPiInvocation(["--version"], { relay: false });
163
- expect(result.command).toBe("pi");
164
- expect(result.args).toEqual(["--version"]);
165
- });
166
- });
@@ -1,149 +0,0 @@
1
- // src/__tests__/recursive-visibility-env.test.ts
2
- //
3
- // 递归 subagent 跨层可见性:env 身份贯穿验证(设计 docs/design/recursive-subagent-visibility.md 场景 1b)。
4
- //
5
- // 验证 runSpawn 构造的 childEnv 含 4 个 PI_SUBAGENT_* 身份 env,值 = ctx.sessionRootId /
6
- // record.id / String(record.depth) / ctx.rootCwd([MF-3] 第 4 个:ROOT cwd,落盘目录编码键)。覆盖 opts.fork=true 与 opts.fork=false 两种(决策 2 无条件注入)。
7
- //
8
- // 这是场景 1(端到端三层嵌套全树可见)的「env 传递机制」确定性验证——不依赖 LLM 配合,
9
- // mock spawn 拦截 childEnv 直接断言。端到端可见性由场景 1(真实 pi CLI + recursive-worker agent)覆盖。
10
- //
11
- // mock 块与 fixture 收敛 __tests__/helpers/spawn-mock.ts(vi.mock 工厂 await import 转发,
12
- // 单源共享);vi.mocked 取回与收尾装配来自 helpers/session-runner-mocks.ts。
13
-
14
- import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
15
-
16
- import { getSubagentSessionDir } from "../path-encoding.ts";
17
-
18
- // ── mock modules(同 session-runner-schema-env.test.ts 模式,工厂单源在 spawn-mock.ts)──
19
-
20
- vi.mock("node:child_process", async () =>
21
- (await import("./helpers/spawn-mock.ts")).childProcessModule());
22
- vi.mock("node:fs", async () => (await import("./helpers/spawn-mock.ts")).fsModule());
23
- vi.mock("../alive-store.ts", async () =>
24
- (await import("./helpers/spawn-mock.ts")).aliveStoreModule());
25
- vi.mock("../engine/engines/pi/temp-prompt.ts", async () =>
26
- (await import("./helpers/spawn-mock.ts")).tempPromptModule());
27
-
28
- import { runSpawn } from "../engine/engines/pi/session-runner.ts";
29
- import {
30
- getLastSpawnEnv,
31
- makeRunOpts,
32
- makeVisibilityCtx,
33
- makeVisibilityRecord,
34
- waitForSpawn,
35
- } from "./helpers/spawn-mock.ts";
36
- import { closeLastChildAndAwait, takeSessionRunnerMocks } from "./helpers/session-runner-mocks.ts";
37
-
38
- const { mockSpawn, mockExistsSync } = takeSessionRunnerMocks();
39
-
40
- /** runSpawn 前奏装配:启动、等 spawn 落位、取回 childEnv(断言留在各用例)。 */
41
- async function spawnAndCaptureEnv(
42
- record: ReturnType<typeof makeVisibilityRecord>,
43
- task: string,
44
- opts: ReturnType<typeof makeRunOpts>,
45
- ctx: ReturnType<typeof makeVisibilityCtx>,
46
- ): Promise<{ resultPromise: Promise<unknown>; childEnv: Record<string, string | undefined> }> {
47
- const resultPromise = runSpawn(record, task, opts, ctx);
48
- await waitForSpawn(mockSpawn);
49
- return { resultPromise, childEnv: getLastSpawnEnv(mockSpawn) };
50
- }
51
-
52
- // ── runSpawn childEnv 身份 env 注入(场景 1b)──
53
-
54
- describe("runSpawn 跨进程身份 env 注入(递归可见性场景 1b)", () => {
55
- beforeEach(() => {
56
- vi.clearAllMocks();
57
- mockExistsSync.mockReturnValue(false);
58
- });
59
-
60
- afterEach(() => {
61
- vi.restoreAllMocks();
62
- });
63
-
64
- it("非 fork(fork=false/undefined):无条件注入 4 个身份 env(决策 2)", async () => {
65
- const record = makeVisibilityRecord({ id: "sa-aaa", depth: 0 });
66
- const ctx = makeVisibilityCtx({ sessionRootId: "root-main" });
67
- const opts = makeRunOpts({ fork: false });
68
-
69
- const { resultPromise, childEnv } = await spawnAndCaptureEnv(record, "test task", opts, ctx);
70
-
71
- expect(childEnv.PI_SUBAGENT_ROOT_SESSION_ID).toBe("root-main");
72
- expect(childEnv.PI_SUBAGENT_SELF_RECORD_ID).toBe("sa-aaa");
73
- expect(childEnv.PI_SUBAGENT_DEPTH).toBe("0");
74
- // [MF-3] 第 4 个贯穿 env:ROOT cwd(子进程落盘目录编码键)
75
- expect(childEnv.PI_SUBAGENT_ROOT_CWD).toBe("/fake/cwd");
76
- // fork=false 不注入 fork depth env(与既有行为一致,本测试不改变它)
77
- expect(childEnv.PI_SUBAGENT_FORK_DEPTH).toBeUndefined();
78
-
79
- await closeLastChildAndAwait(resultPromise);
80
- });
81
-
82
- it("fork=true:4 个身份 env 与 fork depth env 共存(决策 2 无条件注入不依赖 fork)", async () => {
83
- const record = makeVisibilityRecord({ id: "sa-bbb", depth: 2 });
84
- const ctx = makeVisibilityCtx({ sessionRootId: "root-main" });
85
- const opts = makeRunOpts({ fork: true, parentForkDepth: 1 });
86
-
87
- const { resultPromise, childEnv } = await spawnAndCaptureEnv(record, "test task", opts, ctx);
88
-
89
- // 身份 env 无条件存在(决策 2)
90
- expect(childEnv.PI_SUBAGENT_ROOT_SESSION_ID).toBe("root-main");
91
- expect(childEnv.PI_SUBAGENT_SELF_RECORD_ID).toBe("sa-bbb");
92
- expect(childEnv.PI_SUBAGENT_DEPTH).toBe("2");
93
- expect(childEnv.PI_SUBAGENT_ROOT_CWD).toBe("/fake/cwd");
94
- // fork depth env 同时存在(fork=true + parentForkDepth=1 → 2)
95
- expect(childEnv.PI_SUBAGENT_FORK_DEPTH).toBe("2");
96
-
97
- await closeLastChildAndAwait(resultPromise);
98
- });
99
-
100
- it("深层 record(depth=3):DEPTH env = String(record.depth),正确贯穿嵌套层级", async () => {
101
- const record = makeVisibilityRecord({ id: "sa-deep", depth: 3 });
102
- const ctx = makeVisibilityCtx({ sessionRootId: "root-topmost" });
103
-
104
- const { resultPromise, childEnv } = await spawnAndCaptureEnv(record, "test task", makeRunOpts(), ctx);
105
-
106
- expect(childEnv.PI_SUBAGENT_DEPTH).toBe("3");
107
- expect(childEnv.PI_SUBAGENT_SELF_RECORD_ID).toBe("sa-deep");
108
- expect(childEnv.PI_SUBAGENT_ROOT_SESSION_ID).toBe("root-topmost");
109
-
110
- await closeLastChildAndAwait(resultPromise);
111
- });
112
-
113
- it("ROOT_SESSION_ID 恒等于 ctx.sessionRootId(贯穿真 ROOT,非 record.rootSessionId)", async () => {
114
- // record.rootSessionId 是 createRecord 时写入的值(可能来自旧逻辑),但 env 注入用的是
115
- // ctx.sessionRootId(经 buildSessionRunnerContext 从 this.sessionRootId 透传,贯穿真 ROOT)。
116
- // 这保证深层 subagent 的子进程仍归顶层 ROOT(设计决策 1/3)。
117
- const record = makeVisibilityRecord({ id: "sa-ccc" }); // record.rootSessionId = fixture 默认值
118
- const ctx = makeVisibilityCtx({ sessionRootId: "real-root-session" });
119
-
120
- const { resultPromise, childEnv } = await spawnAndCaptureEnv(record, "test task", makeRunOpts(), ctx);
121
-
122
- // env 用 ctx.sessionRootId,不是 record.rootSessionId
123
- expect(childEnv.PI_SUBAGENT_ROOT_SESSION_ID).toBe("real-root-session");
124
- expect(childEnv.PI_SUBAGENT_ROOT_SESSION_ID).not.toBe(record.rootSessionId);
125
-
126
- await closeLastChildAndAwait(resultPromise);
127
- });
128
-
129
- it("[MF-3 回归] worktree 模式(mainCwd=checkout ≠ rootCwd):sessionDir 用 ROOT cwd 编码,深层 record 落盘到 ROOT 可扫描段", async () => {
130
- // 模拟 B(worktree 子进程)spawn C:ctx.cwd/mainCwd = checkout 路径,rootCwd = 真 ROOT cwd。
131
- // 旧实现 sessionDir 用 ctx.mainCwd 编码 → enc(checkout) 段,ROOT 磁盘重建扫不到(MF-3)。
132
- const rootCwd = "/root/project";
133
- const checkoutPath = "/var/folders/worktree/pi-subagents/--root-project--/branch";
134
- const agentDir = "/fake/agent";
135
- const record = makeVisibilityRecord({ id: "sa-deep", depth: 2 });
136
- const ctx = makeVisibilityCtx({ cwd: checkoutPath, mainCwd: checkoutPath, rootCwd, agentDir });
137
-
138
- const { resultPromise, childEnv } = await spawnAndCaptureEnv(record, "test task", makeRunOpts(), ctx);
139
- const spawnArgs = mockSpawn.mock.calls.at(-1)?.[1] as string[];
140
-
141
- // 第 4 个 env 贯穿 ROOT cwd
142
- expect(childEnv.PI_SUBAGENT_ROOT_CWD).toBe(rootCwd);
143
- // spawn --session-dir 指向 enc(ROOT cwd)(非 enc(checkout))
144
- expect(spawnArgs).toContain(getSubagentSessionDir(agentDir, rootCwd));
145
- expect(spawnArgs).not.toContain(getSubagentSessionDir(agentDir, checkoutPath));
146
-
147
- await closeLastChildAndAwait(resultPromise);
148
- });
149
- });
@@ -1,89 +0,0 @@
1
- // src/__tests__/rpc-mode.test.ts
2
- //
3
- // RPC 模式相关功能
4
- // 1. buildSpawnArgs 返回 --mode rpc(而非 json)
5
- // 2. parseSpawnLine 正确解析 Pi 原生 RpcResponse(type:response + command + success + data|error)
6
-
7
- import { describe, expect, it } from "vitest";
8
-
9
- import { buildSpawnArgs } from "../engine/engines/pi/session-runner.ts";
10
- import { parseSpawnLine } from "../engine/engines/pi/spawn-event-adapter.ts";
11
-
12
- describe("buildSpawnArgs - RPC mode", () => {
13
- const baseParams = {
14
- modelRef: { provider: "openai", id: "gpt-4" },
15
- thinkingLevel: undefined,
16
- agentTools: undefined,
17
- appendSystemPromptPath: undefined,
18
- sessionDir: "/tmp/sessions",
19
- forkSource: undefined,
20
- skillPaths: undefined,
21
- };
22
-
23
- it("生成 --mode rpc 参数(非 json)", () => {
24
- const args = buildSpawnArgs(baseParams);
25
- // 应包含 --mode rpc
26
- expect(args).toContain("--mode");
27
- const modeIdx = args.indexOf("--mode");
28
- expect(args[modeIdx + 1]).toBe("rpc");
29
- });
30
-
31
- it("不包含 --mode json", () => {
32
- const args = buildSpawnArgs(baseParams);
33
- const modeIdx = args.indexOf("--mode");
34
- expect(args[modeIdx + 1]).not.toBe("json");
35
- });
36
- });
37
-
38
- describe("parseSpawnLine - RpcResponse", () => {
39
- // Pi 原生 RpcResponse 格式(rpc-types.ts):{type:"response", id?, command, success, data?, error?}
40
- // W1 修复后 isRpcResponse 判 type:response + command:string + success:boolean(SR-1 根因 1b)
41
-
42
- it("解析 Pi 原生 success response(kind=response)", () => {
43
- const rpcResponse = JSON.stringify({
44
- type: "response",
45
- id: "req-123",
46
- command: "run",
47
- success: true,
48
- data: { answers: [{ question: "Q1", answer: "A1" }] },
49
- });
50
- const result = parseSpawnLine(rpcResponse);
51
- expect(result?.kind).toBe("response");
52
- if (result?.kind === "response") {
53
- expect(result.id).toBe("req-123");
54
- expect(result.command).toBe("run");
55
- expect(result.success).toBe(true);
56
- expect(result.data).toEqual({ answers: [{ question: "Q1", answer: "A1" }] });
57
- }
58
- });
59
-
60
- it("解析 Pi 原生 error response(kind=response)", () => {
61
- const rpcError = JSON.stringify({
62
- type: "response",
63
- id: "req-456",
64
- command: "run",
65
- success: false,
66
- error: "task failed: timeout",
67
- });
68
- const result = parseSpawnLine(rpcError);
69
- expect(result?.kind).toBe("response");
70
- if (result?.kind === "response") {
71
- expect(result.id).toBe("req-456");
72
- expect(result.success).toBe(false);
73
- expect(result.error).toBe("task failed: timeout");
74
- }
75
- });
76
-
77
- it("旧 JSON-RPC 2.0 格式不再归类为 response(W1 废弃)", () => {
78
- // SR-1: 旧 {jsonrpc:"2.0", id, result} 无 type:response 字段,应落入 invalid
79
- const oldRpc = JSON.stringify({ jsonrpc: "2.0", id: "req-old", result: { x: 1 } });
80
- const result = parseSpawnLine(oldRpc);
81
- expect(result?.kind).not.toBe("response");
82
- });
83
-
84
- it("非 response 类型的 JSON 不归类为 response", () => {
85
- const normalEvent = JSON.stringify({ type: "tool_execution_start", toolName: "bash" });
86
- const result = parseSpawnLine(normalEvent);
87
- expect(result?.kind).not.toBe("response");
88
- });
89
- });