@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,155 +0,0 @@
1
- // reader.test.ts —— PiEngine reader(P5):readPiSessionView 对 session-reconstructor
2
- // 的投影包装。断言三件事:①合法 JSONL → SessionView(turns/toolCalls strip 内部态/
3
- // usage 聚合/source='native');②reconstructor 降级条件(文件缺失/缺 identity/无
4
- // assistant)→ undefined 不 throw;③不泄漏 InternalToolCall 内部态(_status/startedTs)。
5
-
6
- import * as fs from "node:fs";
7
- import * as os from "node:os";
8
- import * as path from "node:path";
9
-
10
- import { beforeAll, describe, expect, it } from "vitest";
11
-
12
- import { readPiSessionView } from "../reader.ts";
13
-
14
- let tmpDir: string;
15
-
16
- beforeAll(() => {
17
- tmpDir = fs.mkdtempSync(join(os.tmpdir(), "pi-reader-"));
18
- });
19
-
20
- // node:path 的 join 在 ESM 测试里直接用(避免顶部 import 与 beforeAll 顺序问题)
21
- function join(...segs: string[]): string {
22
- return path.join(...segs);
23
- }
24
-
25
- /** 最小合法 subagent JSONL:header + identity + 一轮 assistant(text/thinking/toolCall)+ toolResult。 */
26
- function writeValidSession(file: string): void {
27
- const lines = [
28
- JSON.stringify({ type: "session", id: "pi-sess-1", cwd: "/proj", timestamp: "2026-08-25T10:00:00Z" }),
29
- JSON.stringify({
30
- type: "custom",
31
- customType: "subagent-identity",
32
- data: { id: "bg-1-abc", agent: "reviewer", mode: "background", task: "review code", slug: "rev", startedAt: 1756000000000 },
33
- }),
34
- JSON.stringify({
35
- type: "message",
36
- timestamp: "2026-08-25T10:00:01Z",
37
- message: {
38
- role: "assistant",
39
- timestamp: 1756000001000,
40
- content: [
41
- { type: "thinking", thinking: "let me look" },
42
- { type: "toolCall", id: "tc-1", name: "bash", arguments: { command: "ls" } },
43
- ],
44
- usage: { input: 10, output: 5, cacheRead: 1, cacheWrite: 2, cost: { total: 0.1 } },
45
- stopReason: "toolUse",
46
- },
47
- }),
48
- JSON.stringify({
49
- type: "message",
50
- timestamp: "2026-08-25T10:00:02Z",
51
- message: { role: "toolResult", toolCallId: "tc-1", toolName: "bash", content: [{ type: "text", text: "file-a" }], timestamp: 1756000002000 },
52
- }),
53
- JSON.stringify({
54
- type: "message",
55
- timestamp: "2026-08-25T10:00:03Z",
56
- message: {
57
- role: "assistant",
58
- timestamp: 1756000003000,
59
- content: [{ type: "text", text: "all good" }],
60
- usage: { input: 20, output: 8, cacheRead: 0, cacheWrite: 0, cost: { total: 0.05 } },
61
- stopReason: "stop",
62
- },
63
- }),
64
- ];
65
- fs.writeFileSync(file, `${lines.join("\n")}\n`, "utf8");
66
- }
67
-
68
- describe("readPiSessionView", () => {
69
- it("projects a valid subagent JSONL to a native SessionView", async () => {
70
- const file = join(tmpDir, "valid.jsonl");
71
- writeValidSession(file);
72
-
73
- const view = await readPiSessionView(file);
74
-
75
- expect(view).toBeDefined();
76
- expect(view?.engineId).toBe("pi");
77
- expect(view?.source).toBe("native");
78
- // 两轮 assistant message → 两个 turn(toolResult 不产 turn)
79
- expect(view?.turns).toHaveLength(2);
80
-
81
- const [turn1, turn2] = view?.turns ?? [];
82
- expect(turn1?.text).toBe("");
83
- expect(turn1?.thinking).toBe("let me look");
84
- expect(turn1?.toolCalls).toHaveLength(1);
85
- const tc = turn1?.toolCalls[0];
86
- expect(tc?.toolName).toBe("bash");
87
- expect(tc?.args).toEqual({ command: "ls" });
88
- expect(tc?.result).toEqual({ content: [{ type: "text", text: "file-a" }] });
89
- // InternalToolCall 内部态不泄漏(导出纯净形状)
90
- expect(tc).not.toHaveProperty("_status");
91
- expect(tc).not.toHaveProperty("startedTs");
92
- expect(turn1?.closed).toBe(true);
93
-
94
- expect(turn2?.text).toBe("all good");
95
- expect(turn2?.closed).toBe(true);
96
-
97
- // usage 聚合:两轮 usageDelta 之和(cost 浮点累加有精度噪声,用 toBeCloseTo)
98
- expect(view?.usage?.input).toBe(30)
99
- expect(view?.usage?.output).toBe(13)
100
- expect(view?.usage?.cacheRead).toBe(1)
101
- expect(view?.usage?.cacheWrite).toBe(2)
102
- expect(view?.usage?.cost).toBeCloseTo(0.15, 10)
103
- expect(view?.usage?.total).toBe(46);
104
- });
105
-
106
- it("returns undefined (no throw) when file is missing", async () => {
107
- await expect(readPiSessionView(join(tmpDir, "nope.jsonl"))).resolves.toBeUndefined();
108
- });
109
-
110
- it("returns undefined when identity entry is missing", async () => {
111
- const file = join(tmpDir, "no-identity.jsonl");
112
- fs.writeFileSync(
113
- file,
114
- `${JSON.stringify({ type: "session", id: "s" })}\n${JSON.stringify({
115
- type: "message",
116
- message: { role: "assistant", content: [{ type: "text", text: "hi" }], timestamp: 1 },
117
- })}\n`,
118
- "utf8",
119
- );
120
- await expect(readPiSessionView(file)).resolves.toBeUndefined();
121
- });
122
-
123
- it("returns undefined when no assistant message exists", async () => {
124
- const file = join(tmpDir, "no-assistant.jsonl");
125
- fs.writeFileSync(
126
- file,
127
- `${JSON.stringify({ type: "session", id: "s" })}\n${JSON.stringify({
128
- type: "custom",
129
- customType: "subagent-identity",
130
- data: { id: "bg-2", agent: "w", mode: "background", task: "t", startedAt: 1 },
131
- })}\n`,
132
- "utf8",
133
- );
134
- await expect(readPiSessionView(file)).resolves.toBeUndefined();
135
- });
136
-
137
- it("omits usage when no message carries it", async () => {
138
- const file = join(tmpDir, "no-usage.jsonl");
139
- fs.writeFileSync(
140
- file,
141
- `${JSON.stringify({ type: "session", id: "s" })}\n${JSON.stringify({
142
- type: "custom",
143
- customType: "subagent-identity",
144
- data: { id: "bg-3", agent: "w", mode: "background", task: "t", startedAt: 1 },
145
- })}\n${JSON.stringify({
146
- type: "message",
147
- message: { role: "assistant", content: [{ type: "text", text: "hi" }], stopReason: "stop", timestamp: 1 },
148
- })}\n`,
149
- "utf8",
150
- );
151
- const view = await readPiSessionView(file);
152
- expect(view?.turns).toHaveLength(1);
153
- expect(view?.usage).toBeUndefined();
154
- });
155
- });
@@ -1,257 +0,0 @@
1
- // src/execution/engine/engines/pi/__tests__/spawn-opts-direct.test.ts
2
- //
3
- // [D6 任务形状合流 / 实施期门⑤ ⛔ 硬门产物] pi 边界一次直出映射
4
- // (agentCallToExecuteOptions:AgentCallOpts → ExecuteOptions)的字段完整性对照表
5
- // 与逐字段断言。本文件取代已删除的两个往返保真测试:
6
- // - execution/__tests__/execute-options-mapper.test.ts(mapToExecuteOptions,18 用例)
7
- // - engines/pi/__tests__/task-spec-mapper.test.ts(spec 往返保真,12 用例)
8
- //
9
- // ════════════════════════════════════════════════════════════════════════
10
- // 字段完整性对照表(从两个被删 mapper 的现有测试提取字段全集,逐字段核对)
11
- // ════════════════════════════════════════════════════════════════════════
12
- //
13
- // 合流前链路(三形态两映射):
14
- // AgentCallOpts --mapToExecuteOptions--> ExecuteOptions
15
- // --executeOptionsToTaskSpec--> AgentTaskSpec --taskSpecToExecuteOptions--> ExecuteOptions
16
- // 合流后(单一形状一次直出):
17
- // AgentCallOpts --agentCallToExecuteOptions--> ExecuteOptions
18
- //
19
- // ┌────────────────────┬──────────────────────────────────────┬────────────────────────────────────┬──────────────┐
20
- // │ ExecuteOptions 字段 │ 合流前(两级链的合成语义) │ 合流后(一次直出) │ 断言用例 │
21
- // ├────────────────────┼──────────────────────────────────────┼────────────────────────────────────┼──────────────┤
22
- // │ task │ prompt→opts.task→spec.task(恒等往返)│ prompt 直取 │ D-01 │
23
- // │ slug │ description??agent??"workflow-agent" │ 同规则内联(截断 SLUG_MAX_LENGTH=35)│ D-02..D-05 │
24
- // │ │ 截断(mapToExecuteOptions) │ │ │
25
- // │ agent │ spec.agent ?? persona.agentRef │ agent 直取(agentRef 无写入方,裁撤) │ D-06 │
26
- // │ model │ 透传(显式 override,不与 ctxModel 混)│ 同 │ D-07 │
27
- // │ thinkingLevel │ spec.effort 恒等映射回 │ thinkingLevel 直取(恒等层删除) │ D-08 │
28
- // │ skillPath │ persona.skillPath 收拢/还原(恒等) │ skillPath 直取(平铺保留) │ D-09 │
29
- // │ appendSystemPrompt │ persona.appendSystemPrompt 收拢/还原 │ appendSystemPrompt 直取 │ D-10 │
30
- // │ schema │ 透传 │ 同 │ D-11 │
31
- // │ schemaEnv │ spec.schema 派生优先(stringifyCached │ schema 派生优先;无 schema 时 │ D-12..D-14 │
32
- // │ │ compact,与 resolver 同函数同缓存)+ │ schemaEnv 兜底(原 ctx.schemaEnv │ │
33
- // │ │ ctx.schemaEnv 兜底(源 = opts.schemaEnv)│ 通道的合流等价);均无 → undefined │ │
34
- // │ maxTurns │ 透传(预算语义:undefined = 不限) │ 同 │ D-15 │
35
- // │ graceTurns │ 透传(spec 字段) │ 同(合流形状可选字段) │ D-16 │
36
- // │ ctxModel │ RunContext.ctxModel 回填 │ 第 2 参直取(运行期件,不入声明) │ D-17 │
37
- // │ fork │ 透传 │ 同 │ D-18 │
38
- // │ worktree │ 透传(boolean | WorktreeHandle 三态) │ 同 │ D-19 │
39
- // │ cwd │ 透传 │ 同 │ D-20 │
40
- // │ conversation │ 透传(interact 控制面 task 标志) │ 同 │ D-21 │
41
- // │ idleTimeoutMs │ 透传(同上) │ 同 │ D-22 │
42
- // │ engine/engineFallback│ PiEngine.run 调用方追加(D9① 留痕) │ 同(不在本函数,pi-engine.test 覆盖) │ pi-engine.test│
43
- // │ signal/onComplete │ 不入 opts(port 设计删字段去向) │ 同(RunContext/编排侧各归其位) │ D-23 │
44
- // └────────────────────┴──────────────────────────────────────┴────────────────────────────────────┴──────────────┘
45
- //
46
- // 调用方扩展字段(引擎不消费,不入 spawn 参数):scene / timeoutMs(SAR mergeTimeoutSignal
47
- // 合并进 signal)/ skill(resolver 解析为 skillPath)/ engine(SAR 路由层)/ returnMeta
48
- // (worker 层)——不入本映射即正确(D-24 断言不泄漏)。
49
- // 已裁撤字段(D6 登记于 AgentCallOpts 类型注释):persona.agentRef、requires。
50
- //
51
- // 全字段直出快照断言(D-00)+ 逐字段用例双保险:快照锁全集、用例锁语义边界。
52
-
53
- import { describe, expect, it } from "vitest";
54
-
55
- import type { AgentCallOpts } from "../../../../../orchestration/models/types.ts";
56
- import { SLUG_MAX_LENGTH } from "../../../../../orchestration/models/types.ts";
57
- import type { ModelInfo } from "../../../../model-resolver.ts";
58
- import type { ExecuteOptions } from "../../../../types.ts";
59
- import { agentCallToExecuteOptions } from "../pi-engine.ts";
60
-
61
- /** 全字段样例(覆盖对照表全部直出映射点)。 */
62
- function makeFullCall(): AgentCallOpts {
63
- return {
64
- prompt: "review the diff",
65
- description: "review-diff",
66
- agent: "/agents/reviewer.md",
67
- model: "zai-coding-cn/glm-5.2",
68
- thinkingLevel: "high",
69
- skillPath: "/skills/code-review/SKILL.md",
70
- appendSystemPrompt: ["extra system prompt line"],
71
- schema: { type: "object", properties: { verdict: { type: "string" } }, required: ["verdict"] },
72
- maxTurns: 20,
73
- graceTurns: 3,
74
- fork: true,
75
- worktree: true,
76
- cwd: "/repo/worktree-x",
77
- conversation: true,
78
- idleTimeoutMs: 600_000,
79
- };
80
- }
81
-
82
- describe("agentCallToExecuteOptions(D6 一次直出:AgentCallOpts → pi spawn 编排参数)", () => {
83
- it("D-00 全字段直出快照(与合流前两级链的合成结果逐字段一致——原往返保真测试的直出等价物)", () => {
84
- const result = agentCallToExecuteOptions(makeFullCall());
85
- const expected: ExecuteOptions = {
86
- task: "review the diff",
87
- slug: "review-diff",
88
- agent: "/agents/reviewer.md",
89
- model: "zai-coding-cn/glm-5.2",
90
- thinkingLevel: "high",
91
- skillPath: "/skills/code-review/SKILL.md",
92
- appendSystemPrompt: ["extra system prompt line"],
93
- schema: { type: "object", properties: { verdict: { type: "string" } }, required: ["verdict"] },
94
- schemaEnv: JSON.stringify({ type: "object", properties: { verdict: { type: "string" } }, required: ["verdict"] }),
95
- maxTurns: 20,
96
- graceTurns: 3,
97
- ctxModel: undefined,
98
- fork: true,
99
- worktree: true,
100
- cwd: "/repo/worktree-x",
101
- conversation: true,
102
- idleTimeoutMs: 600_000,
103
- };
104
- expect(result).toEqual(expected);
105
- });
106
-
107
- // ── task / slug(D-01..D-05)──
108
-
109
- it("D-01 prompt → task", () => {
110
- expect(agentCallToExecuteOptions({ prompt: "do the thing" }).task).toBe("do the thing");
111
- });
112
-
113
- it("D-02 description → slug", () => {
114
- expect(agentCallToExecuteOptions({ prompt: "t", description: "fix-login" }).slug).toBe("fix-login");
115
- });
116
-
117
- it("D-03 description 缺失 → 回落 agent 名(保证 slug 非空)", () => {
118
- expect(agentCallToExecuteOptions({ prompt: "t", agent: "worker" }).slug).toBe("worker");
119
- });
120
-
121
- it("D-04 description 与 agent 均缺失 → 回落 'workflow-agent'", () => {
122
- expect(agentCallToExecuteOptions({ prompt: "t" }).slug).toBe("workflow-agent");
123
- });
124
-
125
- it("D-05 slug 截断:description > SLUG_MAX_LENGTH(35) 截到 35;= 35 不截(边界)", () => {
126
- expect(agentCallToExecuteOptions({ prompt: "t", description: "a".repeat(36) }).slug).toBe("a".repeat(35));
127
- expect(agentCallToExecuteOptions({ prompt: "t", description: "a".repeat(35) }).slug).toBe("a".repeat(35));
128
- expect(SLUG_MAX_LENGTH).toBe(35);
129
- });
130
-
131
- // ── 身份 / 模型 / 推理档位(D-06..D-08)──
132
-
133
- it("D-06 agent 直取(原 persona.agentRef 兜底随 PersonaSpec 裁撤——无生产写入方)", () => {
134
- expect(agentCallToExecuteOptions({ prompt: "t", agent: "/a.md" }).agent).toBe("/a.md");
135
- expect(agentCallToExecuteOptions({ prompt: "t" }).agent).toBeUndefined();
136
- });
137
-
138
- it("D-07 model:显式 override 透传;缺省 undefined(不与 ctxModel 混合)", () => {
139
- const ctxModel: ModelInfo = { id: "ctx-model", name: "Ctx", provider: "test", reasoning: false };
140
- expect(agentCallToExecuteOptions({ prompt: "t", model: "explicit-model" }, ctxModel).model).toBe("explicit-model");
141
- expect(agentCallToExecuteOptions({ prompt: "t" }, ctxModel).model).toBeUndefined();
142
- });
143
-
144
- it("D-08 thinkingLevel 直取(原 effort 恒等映射层删除,含 7 档外的缺省)", () => {
145
- for (const level of ["off", "low", "medium", "high", "max", undefined]) {
146
- expect(agentCallToExecuteOptions({ prompt: "t", thinkingLevel: level }).thinkingLevel).toBe(level);
147
- }
148
- });
149
-
150
- // ── persona 平铺字段(D-09..D-10)──
151
-
152
- it("D-09 skillPath 直取(原 persona 收拢/还原恒等)", () => {
153
- expect(agentCallToExecuteOptions({ prompt: "t", skillPath: "/s" }).skillPath).toBe("/s");
154
- expect(agentCallToExecuteOptions({ prompt: "t" }).skillPath).toBeUndefined();
155
- });
156
-
157
- it("D-10 appendSystemPrompt 直取(含空数组归一语义:空数组保持空数组——下游 spread no-op 等价)", () => {
158
- expect(agentCallToExecuteOptions({ prompt: "t", appendSystemPrompt: ["l1", "l2"] }).appendSystemPrompt).toEqual(["l1", "l2"]);
159
- expect(agentCallToExecuteOptions({ prompt: "t", appendSystemPrompt: [] }).appendSystemPrompt).toEqual([]);
160
- expect(agentCallToExecuteOptions({ prompt: "t" }).appendSystemPrompt).toBeUndefined();
161
- });
162
-
163
- // ── schema / schemaEnv(D-11..D-14)──
164
-
165
- it("D-11 schema 透传为原始对象引用", () => {
166
- const schema = { type: "object" };
167
- expect(agentCallToExecuteOptions({ prompt: "t", schema }).schema).toBe(schema);
168
- });
169
-
170
- it("D-12 schemaEnv 派生:与 agent-opts-resolver 同函数(stringifySchemaCached compact),逐字节等值", () => {
171
- const schema = { type: "object", properties: { a: { type: "number" } } };
172
- expect(agentCallToExecuteOptions({ prompt: "t", schema }).schemaEnv).toBe(JSON.stringify(schema));
173
- });
174
-
175
- it("D-13 派生优先:schema 存在时 opts.schemaEnv(stale 值)被忽略", () => {
176
- const schema = { type: "object" };
177
- expect(agentCallToExecuteOptions({ prompt: "t", schema, schemaEnv: "STALE" }).schemaEnv).toBe(JSON.stringify(schema));
178
- });
179
-
180
- it("D-14 schemaEnv 兜底/缺省:无 schema 时用 opts.schemaEnv(解耦形态,原 ctx 兜底通道等价);均无 → undefined(BC-6:childEnv 不注入)", () => {
181
- expect(agentCallToExecuteOptions({ prompt: "t", schemaEnv: '{"type":"object"}' }).schemaEnv).toBe('{"type":"object"}');
182
- expect(agentCallToExecuteOptions({ prompt: "t" }).schemaEnv).toBeUndefined();
183
- });
184
-
185
- // ── 轮数 / 运行期 / 隔离(D-15..D-20)──
186
-
187
- it("D-15 maxTurns 透传(undefined = 不限,不挂 turns 估算 watchdog)", () => {
188
- expect(agentCallToExecuteOptions({ prompt: "t", maxTurns: 20 }).maxTurns).toBe(20);
189
- expect(agentCallToExecuteOptions({ prompt: "t" }).maxTurns).toBeUndefined();
190
- });
191
-
192
- it("D-16 graceTurns 透传(合流形状可选字段,chat 域经 host-task-spec 填充)", () => {
193
- expect(agentCallToExecuteOptions({ prompt: "t", graceTurns: 3 }).graceTurns).toBe(3);
194
- expect(agentCallToExecuteOptions({ prompt: "t" }).graceTurns).toBeUndefined();
195
- });
196
-
197
- it("D-17 ctxModel 从第 2 参回填(运行期件不入任务声明——D-008 兼底链路)", () => {
198
- const ctxModel: ModelInfo = { id: "mimo-v2.5-pro", name: "MiMo", provider: "router-openai", reasoning: false };
199
- expect(agentCallToExecuteOptions({ prompt: "t" }, ctxModel).ctxModel).toBe(ctxModel);
200
- expect(agentCallToExecuteOptions({ prompt: "t" }).ctxModel).toBeUndefined();
201
- });
202
-
203
- it("D-18 fork 透传", () => {
204
- expect(agentCallToExecuteOptions({ prompt: "t", fork: true }).fork).toBe(true);
205
- });
206
-
207
- it("D-19 worktree 三态(true/false/WorktreeHandle)直出保持", () => {
208
- const handle = { path: "/wt", branch: "b", baseCommit: "c", mainCwd: "/repo" };
209
- for (const wt of [true, false, handle] as const) {
210
- expect(agentCallToExecuteOptions({ prompt: "t", worktree: wt }).worktree).toBe(wt);
211
- }
212
- });
213
-
214
- it("D-20 cwd 透传", () => {
215
- expect(agentCallToExecuteOptions({ prompt: "t", cwd: "/work" }).cwd).toBe("/work");
216
- });
217
-
218
- // ── 交互控制面(D-21..D-22)──
219
-
220
- it("D-21 conversation 透传(interact 控制面的 task 标志)", () => {
221
- expect(agentCallToExecuteOptions({ prompt: "t", conversation: true }).conversation).toBe(true);
222
- });
223
-
224
- it("D-22 idleTimeoutMs 透传", () => {
225
- expect(agentCallToExecuteOptions({ prompt: "t", idleTimeoutMs: 12345 }).idleTimeoutMs).toBe(12345);
226
- });
227
-
228
- // ── 声明边界(D-23..D-24)──
229
-
230
- it("D-23 运行期字段不入直出产物:signal/onComplete/engine/engineFallback 不由本函数产出(engine 由 run 调用方追加)", () => {
231
- const result = agentCallToExecuteOptions(makeFullCall()) as unknown as Record<string, unknown>;
232
- expect("signal" in result).toBe(false);
233
- expect("onComplete" in result).toBe(false);
234
- expect("engine" in result).toBe(false);
235
- expect("engineFallback" in result).toBe(false);
236
- });
237
-
238
- it("D-24 调用方扩展字段不泄漏进 spawn 参数:scene/timeoutMs/skill/engine/returnMeta/denyTools/permissionMode", () => {
239
- const result = agentCallToExecuteOptions({
240
- prompt: "t",
241
- scene: "coding",
242
- timeoutMs: 5000,
243
- skill: "code-review",
244
- engine: "pi",
245
- returnMeta: true,
246
- denyTools: ["bash"],
247
- permissionMode: "yolo",
248
- }) as unknown as Record<string, unknown>;
249
- expect("scene" in result).toBe(false);
250
- expect("timeoutMs" in result).toBe(false);
251
- expect("skill" in result).toBe(false);
252
- expect("engine" in result).toBe(false);
253
- expect("returnMeta" in result).toBe(false);
254
- expect("denyTools" in result).toBe(false);
255
- expect("permissionMode" in result).toBe(false);
256
- });
257
- });
@@ -1,135 +0,0 @@
1
- /**
2
- * 从主进程 argv 解析可镜像给子进程的 flag。
3
- *
4
- * 独立模块:argv 解析是独立职责,从 session-runner.ts 拆出避免该文件超行数上限。
5
- */
6
-
7
- /**
8
- * 镜像 flag 集合:从主进程 argv 解析出的可透传给子进程的 flag。
9
- * 面向 buildSpawnArgs 的入参形态(解析后)。undefined 字段语义与解析为空一致。
10
- */
11
- export interface MirrorFlags {
12
- noExtensions: boolean;
13
- approve: boolean;
14
- extensionPaths: string[];
15
- noContextFiles: boolean;
16
- }
17
-
18
- /**
19
- * 有值 flag 的解析规则表:成员是「后跟一个值」的 flag 名(含长短形式)。
20
- * 用于 parseMirrorFlagArgs 跳过其他 flag 的值时不误吃。
21
- */
22
- const VALUED_FLAGS = new Set<string>([
23
- "--extension", "-e",
24
- "--skill",
25
- "--model", "--system-prompt", "--append-system-prompt",
26
- "--tools", "-t", "--exclude-tools", "-xt",
27
- "--fork", "--session-dir", "--mode",
28
- "--thinking", "--models",
29
- ]);
30
-
31
- /** MirrorFlags 的布尔字段名(extensionPaths 数组字段单列,不进此表)。 */
32
- type MirrorBooleanKey = "noExtensions" | "approve" | "noContextFiles";
33
-
34
- /**
35
- * 布尔镜像 flag 表:token(长/短形式)→ MirrorFlags 布尔字段。
36
- * 用 Map 而非对象字面量查表——对象查表对 "__proto__"/"constructor" 等 token
37
- * 会命中原型链返回非 undefined,Map.get 无此陷阱。
38
- */
39
- const BOOLEAN_FLAGS = new Map<string, MirrorBooleanKey>([
40
- ["--no-extensions", "noExtensions"],
41
- ["-ne", "noExtensions"],
42
- ["--approve", "approve"],
43
- ["-a", "approve"],
44
- ["--no-context-files", "noContextFiles"],
45
- ["-nc", "noContextFiles"],
46
- ]);
47
-
48
- /** argv 中 flag 的起始索引:argv[0]=runtime, argv[1]=binary 路径。 */
49
- const ARGV_FLAG_START = 2;
50
-
51
- /**
52
- * 从主进程 argv 解析可镜像的 flag(--no-extensions/--approve/--extension/--no-context-files)。
53
- *
54
- * 数据源是主 pi 进程的 process.argv:子进程 spawn 的父就是主进程,
55
- * 主进程 argv 完整保留启动时收到的全部 flag(已运行时验证)。这让子进程
56
- * extension/approve 加载行为与主进程一致,且对任意 pi 宿主通用(不止 xyz-agent)。
57
- *
58
- * 解析规则:
59
- * - --no-extensions / -ne、--approve / -a:布尔 flag(查 BOOLEAN_FLAGS 表)
60
- * - --no-context-files / -nc:布尔 flag(镜像理由:--extension 镜像会把
61
- * @zhushanwen/pi-system-prompt 带进每个 subagent,该扩展靠子进程自己的
62
- * argv 检测此 flag 决定是否注入全局 AGENTS.md——不镜像则用户 opt-out
63
- * 在 subagent 路径失效)
64
- * - --extension / -e:支持 `--extension <path>`(空格)与 `--extension=<path>`(等号)
65
- * - 其他 flag(在 VALUED_FLAGS 中)的值不被误当 extension 路径
66
- * - positional 参数被忽略
67
- * - argv[0]/argv[1] 是 bun/pi binary 路径,从 argv[2:] 开始扫
68
- */
69
- // [perf] 进程内 process.argv 引用恒定(唯一调用点 session-runner 每次 spawn 传同一引用),
70
- // 解析结果按 argv 引用相等 memo——每次 spawn 免重复扫描/正则。测试传新数组引用不命中。
71
- let memoArgv: readonly string[] | undefined;
72
- let memoResult: MirrorFlags | undefined;
73
-
74
- export function mirrorMainProcessFlags(argv: readonly string[]): MirrorFlags {
75
- if (memoResult !== undefined && memoArgv === argv) return memoResult;
76
- const result = parseMirrorFlagArgs(
77
- argv.length > ARGV_FLAG_START ? argv.slice(ARGV_FLAG_START) : [],
78
- );
79
- memoArgv = argv;
80
- memoResult = result;
81
- return result;
82
- }
83
-
84
- /** 纯解析:扫描 flag 区段(argv[2:])构造 MirrorFlags,不做 memo。 */
85
- function parseMirrorFlagArgs(flagArgs: readonly string[]): MirrorFlags {
86
- const flags: Record<MirrorBooleanKey, boolean> = {
87
- noExtensions: false,
88
- approve: false,
89
- noContextFiles: false,
90
- };
91
- const extensionPaths: string[] = [];
92
-
93
- // argv[0]=runtime(bun), argv[1]=pi binary 路径;flag 从 argv[2] 起
94
- for (let i = 0; i < flagArgs.length; i++) {
95
- const tok = flagArgs[i];
96
- const booleanKey = BOOLEAN_FLAGS.get(tok);
97
- if (booleanKey !== undefined) {
98
- flags[booleanKey] = true;
99
- continue;
100
- }
101
- // 等号形式 --extension=path / -e=path
102
- const eqMatch = /^(--extension|-e)=(.*)$/.exec(tok);
103
- if (eqMatch) {
104
- const val = eqMatch[2];
105
- if (val) extensionPaths.push(val);
106
- continue;
107
- }
108
- // 空格形式 --extension <path> / -e <path>:值在下一个 token
109
- // [MF-7a] flag 判定收窄为 startsWith("--"):守卫原为 !startsWith("-"),把以单个
110
- // - 开头的合法路径(如相对路径 -weird-dir/x.md)误判为 flag 跳过——extension 路径
111
- // 静默丢失。pi CLI 的多字符长 flag 一律 -- 前缀,单 - 只接单字符短 flag(-e 本身),
112
- // 故「-- 开头才算 flag」不误吃真 flag 且放行 - 开头路径。
113
- if (tok === "--extension" || tok === "-e") {
114
- const next = flagArgs[i + 1];
115
- if (next !== undefined && !next.startsWith("--") && next.length > 0) {
116
- extensionPaths.push(next);
117
- i++; // 跳过值
118
- }
119
- continue;
120
- }
121
- // 其他有值 flag:跳过其值,避免误吃(如 --skill /a 的 /a)
122
- if (VALUED_FLAGS.has(tok)) {
123
- i++;
124
- continue;
125
- }
126
- // 其他情况(未知 flag、--flag=val 形式、positional)忽略
127
- }
128
-
129
- return {
130
- noExtensions: flags.noExtensions,
131
- approve: flags.approve,
132
- extensionPaths,
133
- noContextFiles: flags.noContextFiles,
134
- };
135
- }