@zhushanwen/pi-subagent-workflow 8.6.0 → 8.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 (347) hide show
  1. package/package.json +9 -13
  2. package/relay/relay.mjs +1 -1
  3. package/src/host/__tests__/pi-host.test.ts +214 -0
  4. package/src/host/pi-host.ts +109 -0
  5. package/src/index.ts +89 -32
  6. package/src/injectors/__tests__/engine-awareness.test.ts +292 -0
  7. package/src/injectors/__tests__/engine-section-stability.test.ts +341 -0
  8. package/src/injectors/__tests__/subagent-list-injector.test.ts +5 -5
  9. package/src/injectors/__tests__/workflow-list-injector.test.ts +5 -5
  10. package/src/injectors/engine-awareness.ts +123 -0
  11. package/src/injectors/model-list-injector.ts +1 -1
  12. package/src/injectors/subagent-list-injector.ts +8 -8
  13. package/src/injectors/workflow-list-injector.ts +8 -8
  14. package/src/interface/__tests__/detectors.test.ts +3 -3
  15. package/src/interface/__tests__/subagent-tool-path-guard.test.ts +2 -2
  16. package/src/interface/__tests__/tool-workflow-script-generate.test.ts +2 -2
  17. package/src/interface/__tests__/tool-workflow-throw-paths.test.ts +1 -1
  18. package/src/interface/bg-notify-render.ts +4 -4
  19. package/src/interface/commands.ts +3 -3
  20. package/src/interface/format.ts +2 -2
  21. package/src/interface/helpers.ts +1 -1
  22. package/src/interface/list-component.ts +4 -4
  23. package/src/interface/list-shared.ts +2 -2
  24. package/src/interface/list-view.ts +2 -2
  25. package/src/interface/subagent-actions.ts +263 -11
  26. package/src/interface/subagent-tool-schema.ts +20 -13
  27. package/src/interface/subagent-tool.ts +11 -6
  28. package/src/interface/subagents.ts +3 -3
  29. package/src/interface/tool-render.ts +34 -2
  30. package/src/interface/tool-workflow-script.ts +4 -4
  31. package/src/interface/tool-workflow.ts +6 -6
  32. package/src/interface/views/WorkflowsView.ts +5 -5
  33. package/src/interface/views/__tests__/WorkflowsView-signature.test.ts +3 -3
  34. package/src/interface/views/__tests__/detail-content-session-file.test.ts +2 -2
  35. package/src/interface/views/detail-content.ts +4 -4
  36. package/src/interface/views/format.ts +4 -4
  37. package/src/{orchestration/jsonl-run-store.ts → jsonl-run-store.ts} +11 -11
  38. package/src/execution/__tests__/__fixtures__/notifier-golden-snapshots.json +0 -53
  39. package/src/execution/__tests__/__fixtures__/truncline.snapshot.json +0 -1
  40. package/src/execution/__tests__/agent-registry.test.ts +0 -363
  41. package/src/execution/__tests__/agent-result-mapper.test.ts +0 -150
  42. package/src/execution/__tests__/alive-store.test.ts +0 -147
  43. package/src/execution/__tests__/ask-user-transit-e2e.test.ts +0 -490
  44. package/src/execution/__tests__/before-agent-start-injection.test.ts +0 -132
  45. package/src/execution/__tests__/bg-notify-render.test.ts +0 -329
  46. package/src/execution/__tests__/channel-registry-handshake.test.ts +0 -243
  47. package/src/execution/__tests__/chat-engine-routing.test.ts +0 -601
  48. package/src/execution/__tests__/chatmode-first-round-closure-service.test.ts +0 -365
  49. package/src/execution/__tests__/chatmode-first-round-closure-spawn.test.ts +0 -190
  50. package/src/execution/__tests__/chatmode-round-notify-real-chain.test.ts +0 -215
  51. package/src/execution/__tests__/concurrency-pool.test.ts +0 -250
  52. package/src/execution/__tests__/config.test.ts +0 -110
  53. package/src/execution/__tests__/conversation-wiring.test.ts +0 -198
  54. package/src/execution/__tests__/crash-recovery.test.ts +0 -320
  55. package/src/execution/__tests__/delivery-methods.test.ts +0 -422
  56. package/src/execution/__tests__/dialog-queue.test.ts +0 -299
  57. package/src/execution/__tests__/epipe-fallback.test.ts +0 -241
  58. package/src/execution/__tests__/execute-and-await-worktree.test.ts +0 -243
  59. package/src/execution/__tests__/execute-nesting.test.ts +0 -323
  60. package/src/execution/__tests__/execute-options-mapper.test.ts +0 -200
  61. package/src/execution/__tests__/execution-record.test.ts +0 -1394
  62. package/src/execution/__tests__/explicit-agent-ref-guard.test.ts +0 -171
  63. package/src/execution/__tests__/finalize-record.test.ts +0 -368
  64. package/src/execution/__tests__/finalized-marker.test.ts +0 -82
  65. package/src/execution/__tests__/format-schema-instruction.test.ts +0 -169
  66. package/src/execution/__tests__/format.test.ts +0 -458
  67. package/src/execution/__tests__/gc-timer.test.ts +0 -184
  68. package/src/execution/__tests__/get-record-for-action-restart.test.ts +0 -254
  69. package/src/execution/__tests__/gui-mode-dispatch.test.ts +0 -59
  70. package/src/execution/__tests__/helpers/mock-extension-api.ts +0 -30
  71. package/src/execution/__tests__/helpers/spawn-mock.ts +0 -242
  72. package/src/execution/__tests__/host-mode.test.ts +0 -87
  73. package/src/execution/__tests__/index-session-start-identity.test.ts +0 -371
  74. package/src/execution/__tests__/index-session-start.test.ts +0 -672
  75. package/src/execution/__tests__/lifecycle-manager-lock.test.ts +0 -211
  76. package/src/execution/__tests__/lifecycle-manager.test.ts +0 -383
  77. package/src/execution/__tests__/lifecycle-predicates.test.ts +0 -116
  78. package/src/execution/__tests__/list-component.test.ts +0 -401
  79. package/src/execution/__tests__/list-fields.test.ts +0 -140
  80. package/src/execution/__tests__/manifest-parentid.test.ts +0 -117
  81. package/src/execution/__tests__/model-resolver.test.ts +0 -465
  82. package/src/execution/__tests__/nested-visibility-env-propagation.test.ts +0 -287
  83. package/src/execution/__tests__/nested-visibility.test.ts +0 -325
  84. package/src/execution/__tests__/notifier-flush.test.ts +0 -612
  85. package/src/execution/__tests__/notifier-golden-snapshot.test.ts +0 -261
  86. package/src/execution/__tests__/notify-ledger.test.ts +0 -826
  87. package/src/execution/__tests__/one-shot-upgrade.test.ts +0 -205
  88. package/src/execution/__tests__/output-collector.test.ts +0 -358
  89. package/src/execution/__tests__/parent-child-matrix.test.ts +0 -336
  90. package/src/execution/__tests__/path-encoding.test.ts +0 -104
  91. package/src/execution/__tests__/pi-invocation.test.ts +0 -134
  92. package/src/execution/__tests__/record-store.test.ts +0 -1057
  93. package/src/execution/__tests__/records-cwd-isolation.test.ts +0 -91
  94. package/src/execution/__tests__/recursive-visibility-baseline.test.ts +0 -339
  95. package/src/execution/__tests__/recursive-visibility-env.test.ts +0 -273
  96. package/src/execution/__tests__/relay-agent.test.ts +0 -448
  97. package/src/execution/__tests__/relay-env.test.ts +0 -42
  98. package/src/execution/__tests__/resource-policy.test.ts +0 -109
  99. package/src/execution/__tests__/rpc-mode.test.ts +0 -89
  100. package/src/execution/__tests__/run-and-finalize-chatmode.test.ts +0 -267
  101. package/src/execution/__tests__/run-spawn-chatmode-settled.test.ts +0 -253
  102. package/src/execution/__tests__/run-spawn-edges.test.ts +0 -687
  103. package/src/execution/__tests__/run-spawn-integration.test.ts +0 -933
  104. package/src/execution/__tests__/run-spawn-resume.test.ts +0 -322
  105. package/src/execution/__tests__/run-spawn-rpc-mode.test.ts +0 -196
  106. package/src/execution/__tests__/run-spawn-stdout-callback-throw.test.ts +0 -199
  107. package/src/execution/__tests__/sdk-contract.test.ts +0 -273
  108. package/src/execution/__tests__/session-context-resolver.test.ts +0 -167
  109. package/src/execution/__tests__/session-file-gc.test.ts +0 -293
  110. package/src/execution/__tests__/session-pending.test.ts +0 -197
  111. package/src/execution/__tests__/session-reconstructor.test.ts +0 -379
  112. package/src/execution/__tests__/session-runner-epipe.test.ts +0 -178
  113. package/src/execution/__tests__/session-runner-schema-env.test.ts +0 -350
  114. package/src/execution/__tests__/session-start-reaper.test.ts +0 -233
  115. package/src/execution/__tests__/spawn-args.test.ts +0 -445
  116. package/src/execution/__tests__/spawn-event-adapter-rpc.test.ts +0 -189
  117. package/src/execution/__tests__/spawn-event-adapter.test.ts +0 -167
  118. package/src/execution/__tests__/spawn-worktree-guidance.test.ts +0 -207
  119. package/src/execution/__tests__/spawned-children.test.ts +0 -92
  120. package/src/execution/__tests__/start-sync-model-guard.test.ts +0 -150
  121. package/src/execution/__tests__/startup-config-declaration.test.ts +0 -35
  122. package/src/execution/__tests__/status-refactor.test.ts +0 -345
  123. package/src/execution/__tests__/stdin-writer.test.ts +0 -463
  124. package/src/execution/__tests__/stream-sink-retirement.test.ts +0 -261
  125. package/src/execution/__tests__/subagent-service-abort.test.ts +0 -60
  126. package/src/execution/__tests__/subagent-service-message-close.test.ts +0 -629
  127. package/src/execution/__tests__/subagent-service-parent-guard.test.ts +0 -180
  128. package/src/execution/__tests__/subagent-service.test.ts +0 -788
  129. package/src/execution/__tests__/subprocess-agent-runner-routing.test.ts +0 -310
  130. package/src/execution/__tests__/subprocess-agent-runner.test.ts +0 -599
  131. package/src/execution/__tests__/temp-prompt.test.ts +0 -53
  132. package/src/execution/__tests__/timeout-integration.test.ts +0 -615
  133. package/src/execution/__tests__/tombstone-store.test.ts +0 -73
  134. package/src/execution/__tests__/tool-action.test.ts +0 -476
  135. package/src/execution/__tests__/truncline-snapshot.test.ts +0 -81
  136. package/src/execution/__tests__/turn-limiter-semantics.test.ts +0 -194
  137. package/src/execution/__tests__/turn-limiter.test.ts +0 -65
  138. package/src/execution/__tests__/ui-channels.test.ts +0 -187
  139. package/src/execution/__tests__/ui-interaction-model.test.ts +0 -67
  140. package/src/execution/__tests__/ui-request-handler-factory.test.ts +0 -370
  141. package/src/execution/__tests__/ui-request-handler.test.ts +0 -204
  142. package/src/execution/__tests__/ui-request-observability.test.ts +0 -114
  143. package/src/execution/__tests__/ui-request-queue.test.ts +0 -133
  144. package/src/execution/__tests__/worktree-manager.test.ts +0 -633
  145. package/src/execution/__tests__/worktree-pid-registration.integration.test.ts +0 -229
  146. package/src/execution/__tests__/worktree-reconcile.integration.test.ts +0 -181
  147. package/src/execution/__tests__/worktree-registry.test.ts +0 -199
  148. package/src/execution/agent-registry.ts +0 -199
  149. package/src/execution/agent-result-mapper.ts +0 -90
  150. package/src/execution/alive-store.ts +0 -92
  151. package/src/execution/argv-mirror.ts +0 -113
  152. package/src/execution/best-effort.ts +0 -38
  153. package/src/execution/channel-registry-access.ts +0 -144
  154. package/src/execution/concurrency-pool.ts +0 -116
  155. package/src/execution/config.ts +0 -96
  156. package/src/execution/dialog-queue.ts +0 -330
  157. package/src/execution/engine/__tests__/common/data-dir.test.ts +0 -53
  158. package/src/execution/engine/__tests__/common/errors.test.ts +0 -132
  159. package/src/execution/engine/__tests__/common/event-journal.test.ts +0 -177
  160. package/src/execution/engine/__tests__/common/kill-chain.test.ts +0 -192
  161. package/src/execution/engine/__tests__/common/nesting-guard.test.ts +0 -81
  162. package/src/execution/engine/__tests__/common/persona-router.test.ts +0 -123
  163. package/src/execution/engine/__tests__/common/pool-manager.test.ts +0 -154
  164. package/src/execution/engine/__tests__/common/schema-emulation.test.ts +0 -128
  165. package/src/execution/engine/__tests__/conformance/__fixtures__/pi-golden-events.json +0 -28
  166. package/src/execution/engine/__tests__/conformance/agent-event-invariants.ts +0 -141
  167. package/src/execution/engine/__tests__/conformance/contract.abort.test.ts +0 -109
  168. package/src/execution/engine/__tests__/conformance/contract.agent-events.test.ts +0 -101
  169. package/src/execution/engine/__tests__/conformance/contract.probe.test.ts +0 -77
  170. package/src/execution/engine/__tests__/conformance/contract.read-degradation.test.ts +0 -104
  171. package/src/execution/engine/__tests__/conformance/contract.relay.test.ts +0 -342
  172. package/src/execution/engine/__tests__/conformance/engine-conformance.live.test.ts +0 -201
  173. package/src/execution/engine/__tests__/conformance/golden-replay.pi.test.ts +0 -76
  174. package/src/execution/engine/__tests__/conformance/golden-replay.zcode.test.ts +0 -79
  175. package/src/execution/engine/__tests__/engine-discovery.test.ts +0 -87
  176. package/src/execution/engine/__tests__/engines-declaration.test.ts +0 -36
  177. package/src/execution/engine/__tests__/model-prompt.test.ts +0 -85
  178. package/src/execution/engine/__tests__/paths.test.ts +0 -39
  179. package/src/execution/engine/__tests__/registry.test.ts +0 -120
  180. package/src/execution/engine/__tests__/routing.test.ts +0 -231
  181. package/src/execution/engine/common/data-dir.ts +0 -62
  182. package/src/execution/engine/common/errors.ts +0 -183
  183. package/src/execution/engine/common/event-journal.ts +0 -254
  184. package/src/execution/engine/common/journal-replay.ts +0 -62
  185. package/src/execution/engine/common/kill-chain.ts +0 -221
  186. package/src/execution/engine/common/nesting-guard.ts +0 -50
  187. package/src/execution/engine/common/persona-router.ts +0 -108
  188. package/src/execution/engine/common/pool-manager.ts +0 -226
  189. package/src/execution/engine/common/schema-emulation.ts +0 -189
  190. package/src/execution/engine/common/session-view-projection.ts +0 -51
  191. package/src/execution/engine/engine-discovery.ts +0 -65
  192. package/src/execution/engine/engines/pi/__tests__/pi-engine.test.ts +0 -469
  193. package/src/execution/engine/engines/pi/__tests__/reader.test.ts +0 -155
  194. package/src/execution/engine/engines/pi/__tests__/task-spec-mapper.test.ts +0 -164
  195. package/src/execution/engine/engines/pi/pi-engine.ts +0 -415
  196. package/src/execution/engine/engines/pi/reader.ts +0 -48
  197. package/src/execution/engine/engines/pi/registration.ts +0 -35
  198. package/src/execution/engine/engines/pi/task-spec-mapper.ts +0 -100
  199. package/src/execution/engine/engines/zcode/__tests__/__fixtures__/zcode-golden-spawn.json +0 -39
  200. package/src/execution/engine/engines/zcode/__tests__/launcher.test.ts +0 -150
  201. package/src/execution/engine/engines/zcode/__tests__/parser.test.ts +0 -246
  202. package/src/execution/engine/engines/zcode/__tests__/preparer.test.ts +0 -228
  203. package/src/execution/engine/engines/zcode/__tests__/reader.test.ts +0 -210
  204. package/src/execution/engine/engines/zcode/__tests__/registration.test.ts +0 -64
  205. package/src/execution/engine/engines/zcode/__tests__/zcode-engine.live.test.ts +0 -127
  206. package/src/execution/engine/engines/zcode/__tests__/zcode-engine.test.ts +0 -580
  207. package/src/execution/engine/engines/zcode/constants.ts +0 -43
  208. package/src/execution/engine/engines/zcode/golden-sample.ts +0 -39
  209. package/src/execution/engine/engines/zcode/launcher.ts +0 -161
  210. package/src/execution/engine/engines/zcode/parser.ts +0 -436
  211. package/src/execution/engine/engines/zcode/preparer.ts +0 -363
  212. package/src/execution/engine/engines/zcode/reader.ts +0 -381
  213. package/src/execution/engine/engines/zcode/registration.ts +0 -37
  214. package/src/execution/engine/engines/zcode/zcode-engine.ts +0 -658
  215. package/src/execution/engine/host-task-spec.ts +0 -47
  216. package/src/execution/engine/model-prompt.ts +0 -59
  217. package/src/execution/engine/paths.ts +0 -42
  218. package/src/execution/engine/port.ts +0 -153
  219. package/src/execution/engine/registry.ts +0 -123
  220. package/src/execution/engine/routing.ts +0 -218
  221. package/src/execution/engine/types.ts +0 -309
  222. package/src/execution/execute-options-mapper.ts +0 -112
  223. package/src/execution/execution-record.ts +0 -965
  224. package/src/execution/finalize-record.ts +0 -251
  225. package/src/execution/finalized-marker.ts +0 -51
  226. package/src/execution/get-state-handshake.ts +0 -104
  227. package/src/execution/host-mode.ts +0 -56
  228. package/src/execution/idle-gc.ts +0 -47
  229. package/src/execution/lifecycle-manager.ts +0 -513
  230. package/src/execution/lifecycle-predicates.ts +0 -65
  231. package/src/execution/manifest-store.ts +0 -256
  232. package/src/execution/model-config-service.ts +0 -219
  233. package/src/execution/model-resolver.ts +0 -248
  234. package/src/execution/notifier.ts +0 -330
  235. package/src/execution/notify-ledger.ts +0 -580
  236. package/src/execution/output-collector.ts +0 -228
  237. package/src/execution/path-encoding.ts +0 -60
  238. package/src/execution/pi-invocation.ts +0 -120
  239. package/src/execution/record-entry.ts +0 -132
  240. package/src/execution/record-store.ts +0 -1234
  241. package/src/execution/relay-env.ts +0 -37
  242. package/src/execution/session-context-resolver.ts +0 -64
  243. package/src/execution/session-file-gc.ts +0 -120
  244. package/src/execution/session-pending.ts +0 -164
  245. package/src/execution/session-reconstructor.ts +0 -678
  246. package/src/execution/session-runner.ts +0 -1781
  247. package/src/execution/sessions-index.ts +0 -304
  248. package/src/execution/spawn-event-adapter.ts +0 -363
  249. package/src/execution/stdin-writer.ts +0 -198
  250. package/src/execution/stream-sink.ts +0 -126
  251. package/src/execution/subagent-service.ts +0 -2141
  252. package/src/execution/subprocess-agent-runner.ts +0 -317
  253. package/src/execution/temp-prompt.ts +0 -62
  254. package/src/execution/tombstone-store.ts +0 -72
  255. package/src/execution/turn-limiter.ts +0 -102
  256. package/src/execution/types.ts +0 -973
  257. package/src/execution/ui-channels.ts +0 -216
  258. package/src/execution/ui-interaction-model.ts +0 -48
  259. package/src/execution/ui-request-handler-factory.ts +0 -212
  260. package/src/execution/ui-request-observability.ts +0 -81
  261. package/src/execution/ui-request-queue.ts +0 -184
  262. package/src/execution/worktree-manager.ts +0 -688
  263. package/src/execution/worktree-registry.ts +0 -222
  264. package/src/orchestration/__tests__/__fixtures__/worker-template.snapshot.txt +0 -349
  265. package/src/orchestration/__tests__/agent-call-catch-fallback.test.ts +0 -202
  266. package/src/orchestration/__tests__/agent-call-stream.test.ts +0 -152
  267. package/src/orchestration/__tests__/args-validator.test.ts +0 -143
  268. package/src/orchestration/__tests__/config-loader.test.ts +0 -503
  269. package/src/orchestration/__tests__/error-recovery-handlers.test.ts +0 -809
  270. package/src/orchestration/__tests__/error-recovery-postmessage-defense.test.ts +0 -405
  271. package/src/orchestration/__tests__/error-recovery-serialize-failed-result.test.ts +0 -56
  272. package/src/orchestration/__tests__/error-recovery-workflow-call.test.ts +0 -166
  273. package/src/orchestration/__tests__/execute-agent-call.test.ts +0 -451
  274. package/src/orchestration/__tests__/jsonl-run-store-corrupt-entry.test.ts +0 -150
  275. package/src/orchestration/__tests__/jsonl-run-store-loadall-sources.test.ts +0 -171
  276. package/src/orchestration/__tests__/jsonl-run-store-retention.test.ts +0 -202
  277. package/src/orchestration/__tests__/jsonl-run-store-session-file.test.ts +0 -1030
  278. package/src/orchestration/__tests__/launcher-nested-workflow.test.ts +0 -600
  279. package/src/orchestration/__tests__/lifecycle-runid-injection.test.ts +0 -96
  280. package/src/orchestration/__tests__/lifecycle.test.ts +0 -659
  281. package/src/orchestration/__tests__/non-cloneable-return-e2e.test.ts +0 -95
  282. package/src/orchestration/__tests__/review-fix-loop-e2e.test.ts +0 -2025
  283. package/src/orchestration/__tests__/script-lint.test.ts +0 -831
  284. package/src/orchestration/__tests__/skill-discovery.test.ts +0 -201
  285. package/src/orchestration/__tests__/test-mocks.ts +0 -197
  286. package/src/orchestration/__tests__/worker-exit-without-result.test.ts +0 -368
  287. package/src/orchestration/__tests__/worker-host.test.ts +0 -120
  288. package/src/orchestration/__tests__/worker-returnmeta-passthrough.test.ts +0 -164
  289. package/src/orchestration/__tests__/worker-script-builder-runtime.test.ts +0 -563
  290. package/src/orchestration/__tests__/worker-script-builder.test.ts +0 -309
  291. package/src/orchestration/__tests__/worker-script-template-snapshot.test.ts +0 -129
  292. package/src/orchestration/__tests__/workflow-nesting-e2e.test.ts +0 -317
  293. package/src/orchestration/__tests__/workflow-script-lint-memo.test.ts +0 -110
  294. package/src/orchestration/__tests__/workflows-e2e.test.ts +0 -537
  295. package/src/orchestration/agent-opts-resolver.ts +0 -174
  296. package/src/orchestration/args-validator.ts +0 -127
  297. package/src/orchestration/config-loader.ts +0 -315
  298. package/src/orchestration/error-recovery.ts +0 -1018
  299. package/src/orchestration/execute-agent-call.ts +0 -256
  300. package/src/orchestration/launcher.ts +0 -455
  301. package/src/orchestration/lifecycle.ts +0 -399
  302. package/src/orchestration/models/__tests__/budget.test.ts +0 -307
  303. package/src/orchestration/models/__tests__/trace.test.ts +0 -408
  304. package/src/orchestration/models/agent-call.ts +0 -83
  305. package/src/orchestration/models/budget.ts +0 -118
  306. package/src/orchestration/models/ports.ts +0 -164
  307. package/src/orchestration/models/run-runtime.ts +0 -104
  308. package/src/orchestration/models/run-spec.ts +0 -83
  309. package/src/orchestration/models/run-state.ts +0 -44
  310. package/src/orchestration/models/trace.ts +0 -183
  311. package/src/orchestration/models/types.ts +0 -301
  312. package/src/orchestration/models/workflow-run.ts +0 -254
  313. package/src/orchestration/models/workflow-script-registry.ts +0 -35
  314. package/src/orchestration/models/workflow-script.ts +0 -117
  315. package/src/orchestration/script-lint.ts +0 -766
  316. package/src/orchestration/skill-discovery.ts +0 -115
  317. package/src/orchestration/worker-handle.ts +0 -115
  318. package/src/orchestration/worker-host.ts +0 -98
  319. package/src/orchestration/worker-script-builder.ts +0 -421
  320. package/src/orchestration/workflow-files.ts +0 -85
  321. package/src/orchestration/workflow-script-registry-impl.ts +0 -133
  322. package/src/shared/__tests__/agent-ref.test.ts +0 -34
  323. package/src/shared/__tests__/meta-parser.test.ts +0 -304
  324. package/src/shared/__tests__/model-ref.test.ts +0 -306
  325. package/src/shared/__tests__/resource-discovery-manifest-cache.test.ts +0 -280
  326. package/src/shared/__tests__/resource-discovery.test.ts +0 -736
  327. package/src/shared/__tests__/resource-meta.test.ts +0 -51
  328. package/src/shared/__tests__/schema-jsonify.test.ts +0 -81
  329. package/src/shared/__tests__/timer-delay.test.ts +0 -61
  330. package/src/shared/agent-event.ts +0 -13
  331. package/src/shared/agent-ref.ts +0 -57
  332. package/src/shared/meta-parser.ts +0 -261
  333. package/src/shared/model-ref.ts +0 -286
  334. package/src/shared/resource-discovery.ts +0 -811
  335. package/src/shared/resource-meta.ts +0 -65
  336. package/src/shared/schema-env.ts +0 -44
  337. package/src/shared/schema-jsonify.ts +0 -58
  338. package/src/shared/timer-delay.ts +0 -54
  339. package/src/shared/xml-injection.ts +0 -35
  340. package/workflows/README.md +0 -81
  341. package/workflows/_shared/agent-refs.cjs +0 -40
  342. package/workflows/chain.js +0 -131
  343. package/workflows/map-reduce.js +0 -174
  344. package/workflows/parallel.js +0 -148
  345. package/workflows/review-fix-loop-utils.cjs +0 -1309
  346. package/workflows/review-fix-loop.js +0 -1404
  347. package/workflows/scatter-gather.js +0 -178
@@ -1,184 +0,0 @@
1
- // src/execution/__tests__/gc-timer.test.ts
2
- //
3
- // [M8] idle record GC 定时器测试(subagent-service.ts startGcTimer,L485-507)。
4
- //
5
- // 背景:GC 定时器(1h interval 扫描 + isResumable && idleSince 30 天 TTL + store.archive)
6
- // 此前零测试覆盖——所有相关测试把 startGcTimer mock 成 no-op(index-session-start /
7
- // crash-recovery / stream-sink-guard / session-start-reaper / index-session-start-identity)。
8
- // 误判 isResumable/idleSince 会把可续聊 record 从内存错误归档(用户数据路径),
9
- // 或永不触发(内存驻留失效)——两个方向都无回归拦截。
10
- //
11
- // 本文件用真实 SubagentService + 真实 startGcTimer(不 mock GC 逻辑本身),仅 mock
12
- // session-runner(import 链依赖 + isResumable 的 hasLiveProcessHandle 查询点)与 logger。
13
- // timer 全部 vi.useFakeTimers,不真实等待。
14
-
15
- import type { ChildProcess } from "node:child_process";
16
- import * as fs from "node:fs";
17
- import * as os from "node:os";
18
- import * as path from "node:path";
19
-
20
- import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
21
-
22
- const { loggerMock } = vi.hoisted(() => ({
23
- loggerMock: { debug: vi.fn(), warn: vi.fn(), error: vi.fn(), info: vi.fn() },
24
- }));
25
- vi.mock("@zhushanwen/pi-extension-logger", () => ({ getLogger: () => loggerMock }));
26
-
27
- // mock session-runner:runSpawn/killAllSpawnedChildren 占位(import 链需要),
28
- // getChildByRecord 默认返回 undefined(无活进程 → isResumable=true),用例内按需覆盖。
29
- vi.mock("../session-runner.ts", () => ({
30
- runSpawn: vi.fn(),
31
- killAllSpawnedChildren: vi.fn(),
32
- getChildByRecord: vi.fn(() => undefined),
33
- spawnedChildren: new Map(),
34
- }));
35
-
36
- import { getChildByRecord } from "../session-runner.ts";
37
- import { createRecord } from "../execution-record.ts";
38
- import { ModelConfigService } from "../model-config-service.ts";
39
- import { RecordStore } from "../record-store.ts";
40
- import { SubagentService } from "../subagent-service.ts";
41
- import type { ExecutionRecord } from "../types.ts";
42
-
43
- const mockGetChildByRecord = vi.mocked(getChildByRecord);
44
-
45
- /** 与 startGcTimer 内部常量一致(1h 扫描 / 30 天 TTL)。 */
46
- const GC_INTERVAL_MS = 60 * 60 * 1000;
47
- const IDLE_TTL_MS = 30 * 24 * 60 * 60 * 1000;
48
-
49
- /** initSession 注入的最小 pi duck-type(同 subagent-service PiLike 形状,结构匹配即可)。 */
50
- interface PiStub {
51
- appendEntry(customType: string, data?: unknown): void;
52
- events: { emit(channel: string, data: unknown): void };
53
- sendMessage(
54
- message: { customType: string; content: string; display: boolean; details?: unknown },
55
- options?: { triggerTurn?: boolean; deliverAs?: "steer" | "followUp" | "nextTurn" },
56
- ): void;
57
- }
58
-
59
- function makePi(): PiStub {
60
- return {
61
- appendEntry: vi.fn(),
62
- events: { emit: vi.fn() },
63
- sendMessage: vi.fn(),
64
- };
65
- }
66
-
67
- /** 构造 running + 无活进程 + 指定 idleSince 的 record(GC 扫描的目标态)。
68
- * listAllActive 只返回 status==="running"(createRecord 初始即 running)。 */
69
- function makeIdleRecord(id: string, idleSince: number): ExecutionRecord {
70
- const record = createRecord(id, {
71
- agent: "general-purpose",
72
- model: "test/model",
73
- mode: "background",
74
- task: "test",
75
- slug: "test",
76
- startedAt: idleSince,
77
- rootSessionId: "root-session",
78
- chatMode: true,
79
- controller: new AbortController(),
80
- });
81
- record.idleSince = idleSince;
82
- return record;
83
- }
84
-
85
- /** 暴露私有字段供测试读取 store。 */
86
- interface ServiceInternals {
87
- store: RecordStore;
88
- }
89
-
90
- describe("[M8] idle record GC 定时器(startGcTimer)", () => {
91
- let agentDir: string;
92
- let service: SubagentService;
93
- let store: RecordStore;
94
-
95
- beforeEach(() => {
96
- vi.useFakeTimers();
97
- agentDir = fs.mkdtempSync(path.join(os.tmpdir(), "gc-timer-"));
98
- const modelService = new ModelConfigService({ agentDir, cwd: agentDir });
99
- service = new SubagentService({ cwd: agentDir, modelService });
100
- service.initSession({ pi: makePi(), sessionId: "root-session" });
101
- store = (service as unknown as ServiceInternals).store;
102
- mockGetChildByRecord.mockReset();
103
- // 默认无活进程(isResumable=true)——Path B:进程已回收、可冷路径 resume 的等待续聊态
104
- mockGetChildByRecord.mockImplementation(() => undefined);
105
- loggerMock.warn.mockClear();
106
- });
107
-
108
- afterEach(() => {
109
- service.dispose();
110
- fs.rmSync(agentDir, { recursive: true, force: true });
111
- vi.useRealTimers();
112
- });
113
-
114
- it("TTL 边界:超 1ms 归档、差 1ms 不归档(同一轮扫描)", () => {
115
- // idleSince 相对 interval 首次触发时刻(fake clock + 1h)构造:
116
- // over = fireAt - TTL - 1 → 扫描时 age = TTL + 1 > TTL → archive
117
- // under = fireAt - TTL + 1 → 扫描时 age = TTL - 1 ≤ TTL → 留内存
118
- const fireAt = Date.now() + GC_INTERVAL_MS;
119
- store.register(makeIdleRecord("sa-over", fireAt - IDLE_TTL_MS - 1));
120
- store.register(makeIdleRecord("sa-under", fireAt - IDLE_TTL_MS + 1));
121
-
122
- service.startGcTimer();
123
- vi.advanceTimersByTime(GC_INTERVAL_MS);
124
-
125
- expect(store.getMutable("sa-over")).toBeUndefined(); // archive 从内存移除
126
- expect(store.getMutable("sa-under")).toBeDefined(); // 未超 TTL 留内存
127
- expect(loggerMock.warn).toHaveBeenCalledTimes(1);
128
- expect(loggerMock.warn).toHaveBeenCalledWith(
129
- expect.stringContaining("GC: archiving idle record sa-over"),
130
- );
131
- });
132
-
133
- it("有活进程的 record 不归档(isResumable=false,即使 idleSince 超 TTL)", () => {
134
- const fireAt = Date.now() + GC_INTERVAL_MS;
135
- // Path A:进程保活等待续聊(idle timer armed、child 未 kill)——归档会让活进程失管
136
- store.register(makeIdleRecord("sa-live", fireAt - IDLE_TTL_MS - 1));
137
- mockGetChildByRecord.mockImplementation(
138
- (id: string): ChildProcess | undefined =>
139
- id === "sa-live" ? ({ killed: false } as unknown as ChildProcess) : undefined,
140
- );
141
-
142
- service.startGcTimer();
143
- vi.advanceTimersByTime(GC_INTERVAL_MS);
144
-
145
- expect(store.getMutable("sa-live")).toBeDefined(); // 有活进程 → 不归档
146
- expect(loggerMock.warn).not.toHaveBeenCalled();
147
- });
148
-
149
- it("每小时重复扫描:上一轮差 1ms 的 record 下一轮超龄被归档", () => {
150
- const fireAt = Date.now() + GC_INTERVAL_MS;
151
- store.register(makeIdleRecord("sa-late", fireAt - IDLE_TTL_MS + 1));
152
-
153
- service.startGcTimer();
154
- vi.advanceTimersByTime(GC_INTERVAL_MS);
155
- expect(store.getMutable("sa-late")).toBeDefined(); // 第一轮:age = TTL - 1,未到
156
-
157
- vi.advanceTimersByTime(GC_INTERVAL_MS); // 第二轮:age = TTL + 1h - 1 > TTL
158
- expect(store.getMutable("sa-late")).toBeUndefined();
159
- });
160
-
161
- it("startGcTimer 幂等:重复调用不产生第二个 interval", () => {
162
- const fireAt = Date.now() + GC_INTERVAL_MS;
163
- store.register(makeIdleRecord("sa-over", fireAt - IDLE_TTL_MS - 1));
164
-
165
- service.startGcTimer();
166
- service.startGcTimer(); // 已有 timer 直接 return(防重复 interval)
167
- vi.advanceTimersByTime(GC_INTERVAL_MS);
168
-
169
- // 同一 record 一轮只扫一次(重复 interval 会对同一 record 产生第二条 GC warn)
170
- expect(loggerMock.warn).toHaveBeenCalledTimes(1);
171
- });
172
-
173
- it("dispose 后 interval 停止:超 TTL record 不再被归档", () => {
174
- service.startGcTimer();
175
- vi.advanceTimersByTime(GC_INTERVAL_MS); // 第一轮正常触发
176
- service.dispose(); // stopGcTimer + disposeAllRecords
177
-
178
- // dispose 后塞入超 TTL record,interval 已停 → 无论推进多久都不归档
179
- store.register(makeIdleRecord("sa-after-dispose", Date.now() - IDLE_TTL_MS - 1));
180
- vi.advanceTimersByTime(GC_INTERVAL_MS * 10);
181
-
182
- expect(store.getMutable("sa-after-dispose")).toBeDefined();
183
- });
184
- });
@@ -1,254 +0,0 @@
1
- // src/execution/__tests__/get-record-for-action-restart.test.ts
2
- //
3
- // [M10] getRecordForAction 跨重启磁盘重建分支测试(subagent-service.ts L933-951)。
4
- //
5
- // 背景:内存 miss → collectRecords(1000,"all",undefined).find(status==="running") →
6
- // createRecord({chatMode: true}) → register → 回填 sessionFile/round。代码注释
7
- // (L946-949)自设强制约束「改动此处必须带 S3 回归场景(跨重启 message 续聊验证)」
8
- // ——该 S3 场景此前不存在,分支零测试。该分支含多个仅此处独有的决策:
9
- // - 无条件 chatMode: true(v4 A-3 跨重启恢复入口,V3 方案 A 方向)
10
- // - rootSessionFilter 传 undefined 后置校验(异树仍 throw not owned)
11
- // - sessionFile/round 从磁盘重建结果回填(round 无磁盘持久化 → undefined)
12
- //
13
- // fixture 构造参照 record-store.test.ts 的 writeSessionJsonl(真实 .jsonl 文件,
14
- // identity custom entry + assistant message;无 .alive sidecar → record-store
15
- // sidecar 矩阵分支 4 → status="running" 跨重启可续聊态)。
16
-
17
- import * as fs from "node:fs";
18
- import * as os from "node:os";
19
- import * as path from "node:path";
20
-
21
- import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
22
-
23
- const { loggerMock } = vi.hoisted(() => ({
24
- loggerMock: { debug: vi.fn(), warn: vi.fn(), error: vi.fn(), info: vi.fn() },
25
- }));
26
- vi.mock("@zhushanwen/pi-extension-logger", () => ({ getLogger: () => loggerMock }));
27
-
28
- // mock session-runner:import 链需要(getRecordForAction 本身不调 spawn,仅守卫读
29
- // hasLiveProcessHandle——默认无活进程,与跨重启场景一致)。
30
- vi.mock("../session-runner.ts", () => ({
31
- runSpawn: vi.fn(),
32
- killAllSpawnedChildren: vi.fn(),
33
- getChildByRecord: vi.fn(() => undefined),
34
- spawnedChildren: new Map(),
35
- }));
36
-
37
- import { writeFinalized } from "../finalized-marker.ts";
38
- import { ModelConfigService } from "../model-config-service.ts";
39
- import { getSubagentSessionDir } from "../path-encoding.ts";
40
- import { RecordStore } from "../record-store.ts";
41
- import { SubagentService } from "../subagent-service.ts";
42
-
43
- // 身份 env 名(与 subagent-service.ts 常量一致;beforeEach/afterEach 清理防泄漏——
44
- // 测试进程可能继承 subagent env,会污染 rootCwd 编码目录与 sessionRootId 基线)。
45
- const IDENTITY_ENV_KEYS = [
46
- "PI_SUBAGENT_ROOT_SESSION_ID",
47
- "PI_SUBAGENT_SELF_RECORD_ID",
48
- "PI_SUBAGENT_DEPTH",
49
- "PI_SUBAGENT_ROOT_CWD",
50
- "PI_SUBAGENT_FORK_DEPTH",
51
- ] as const;
52
-
53
- /** initSession 注入的最小 pi duck-type(同 subagent-service PiLike 形状,结构匹配即可)。 */
54
- interface PiStub {
55
- appendEntry(customType: string, data?: unknown): void;
56
- events: { emit(channel: string, data: unknown): void };
57
- sendMessage(
58
- message: { customType: string; content: string; display: boolean; details?: unknown },
59
- options?: { triggerTurn?: boolean; deliverAs?: "steer" | "followUp" | "nextTurn" },
60
- ): void;
61
- }
62
-
63
- function makePi(): PiStub {
64
- return {
65
- appendEntry: vi.fn(),
66
- events: { emit: vi.fn() },
67
- sendMessage: vi.fn(),
68
- };
69
- }
70
-
71
- /** 写一个最小合法 session.jsonl(session header + identity entry + 1 条 assistant message)。
72
- * 不写任何 sidecar(.alive/.cancelled/.finalized)→ sidecar 矩阵分支 4 → running。 */
73
- function writeSessionJsonl(
74
- sessionsDir: string,
75
- identity: {
76
- id: string;
77
- rootSessionId: string;
78
- parentRecordId?: string;
79
- depth?: number;
80
- chatMode?: boolean;
81
- worktree?: boolean;
82
- },
83
- ): string {
84
- const file = path.join(sessionsDir, `${identity.id}.jsonl`);
85
- const startedAt = 1_700_000_000_000;
86
- const lines = [
87
- JSON.stringify({
88
- type: "session",
89
- version: 3,
90
- id: "sess-uuid",
91
- timestamp: new Date(startedAt).toISOString(),
92
- cwd: "/tmp",
93
- }),
94
- JSON.stringify({
95
- type: "custom",
96
- id: "id-1",
97
- parentId: null,
98
- timestamp: new Date(startedAt).toISOString(),
99
- customType: "subagent-identity",
100
- data: {
101
- id: identity.id,
102
- agent: "general-purpose",
103
- mode: "background",
104
- task: "restart recovery task",
105
- slug: "restart-test",
106
- startedAt,
107
- rootSessionId: identity.rootSessionId,
108
- ...(identity.parentRecordId !== undefined ? { parentRecordId: identity.parentRecordId } : {}),
109
- ...(identity.depth !== undefined ? { depth: identity.depth } : {}),
110
- ...(identity.chatMode !== undefined ? { chatMode: identity.chatMode } : {}),
111
- ...(identity.worktree !== undefined ? { worktree: identity.worktree } : {}),
112
- },
113
- }),
114
- JSON.stringify({
115
- type: "message",
116
- id: "msg-1",
117
- parentId: "id-1",
118
- timestamp: new Date(startedAt + 1000).toISOString(),
119
- message: {
120
- role: "assistant",
121
- content: [{ type: "text", text: "first round done" }],
122
- usage: { input: 10, output: 20, cacheRead: 0, cacheWrite: 0 },
123
- stopReason: "stop",
124
- timestamp: startedAt + 1000,
125
- },
126
- }),
127
- ];
128
- fs.writeFileSync(file, `${lines.join("\n")}\n`, "utf-8");
129
- return file;
130
- }
131
-
132
- /** 暴露私有 store 供断言 register 副作用。 */
133
- interface ServiceInternals {
134
- store: RecordStore;
135
- }
136
-
137
- describe("[M10] getRecordForAction 跨重启磁盘重建(S3 回归场景)", () => {
138
- let agentDir: string;
139
- let sessionsDir: string;
140
- let service: SubagentService;
141
- let store: RecordStore;
142
-
143
- beforeEach(() => {
144
- for (const k of IDENTITY_ENV_KEYS) delete process.env[k];
145
- agentDir = fs.mkdtempSync(path.join(os.tmpdir(), "restart-recon-"));
146
- sessionsDir = getSubagentSessionDir(agentDir, agentDir);
147
- fs.mkdirSync(sessionsDir, { recursive: true });
148
-
149
- const modelService = new ModelConfigService({ agentDir, cwd: agentDir });
150
- service = new SubagentService({ cwd: agentDir, modelService });
151
- // 根进程身份:无 env → sessionRootId = sessionId(自己是 root)、execCtxBaseline = null
152
- service.initSession({ pi: makePi(), sessionId: "root-session" });
153
- store = (service as unknown as ServiceInternals).store;
154
- });
155
-
156
- afterEach(() => {
157
- service.dispose();
158
- // maxRetries:collectRecords 触发的 fire-and-forget sessions-index 写可能与删除
159
- // 并发(ENOTEMPTY 竞态,全量并行跑时机器负载高会放大窗口)
160
- fs.rmSync(agentDir, { recursive: true, force: true, maxRetries: 5, retryDelay: 20 });
161
- for (const k of IDENTITY_ENV_KEYS) delete process.env[k];
162
- });
163
-
164
- it("内存 miss + 磁盘 running(无 .alive)→ 重建 record:chatMode 无条件 true、sessionFile 回填、register 进内存", () => {
165
- // identity entry 故意不带 chatMode 字段——证明重建分支的无条件 chatMode:true
166
- //(不依赖磁盘是否记录过对话模式标志)
167
- const file = writeSessionJsonl(sessionsDir, { id: "sa-restart-1", rootSessionId: "root-session" });
168
- expect(store.getMutable("sa-restart-1")).toBeUndefined(); // 前置:内存确无
169
-
170
- const record = service.getRecordForAction("sa-restart-1");
171
-
172
- // [v4 A-3] 无条件 chatMode=true(跨重启恢复入口)
173
- expect(record.chatMode).toBe(true);
174
- // sessionFile 从磁盘重建结果回填
175
- expect(record.sessionFile).toBe(file);
176
- // round 从 found 回填:light 磁盘重建无 round(内存态字段,跨重启不恢复)→ undefined
177
- expect(record.round).toBeUndefined();
178
- // 身份字段从磁盘 identity entry 回填
179
- expect(record.agent).toBe("general-purpose");
180
- expect(record.task).toBe("restart recovery task");
181
- expect(record.slug).toBe("restart-test");
182
- expect(record.rootSessionId).toBe("root-session");
183
- expect(record.parentRecordId).toBeUndefined();
184
- expect(record.status).toBe("running");
185
- // register 生效:进内存,二次调用走内存命中(同一引用)
186
- expect(store.getMutable("sa-restart-1")).toBe(record);
187
- expect(service.getRecordForAction("sa-restart-1")).toBe(record);
188
- });
189
-
190
- it("rootSessionId 校验仍生效:异树 record(other-session)→ throw not found or not owned", () => {
191
- // rootSessionFilter 传 undefined(扫全量磁盘),异树 record 会被 find 命中并重建,
192
- // 但后置校验 record.rootSessionId !== this.sessionRootId 必须拦截
193
- writeSessionJsonl(sessionsDir, { id: "sa-foreign", rootSessionId: "other-session" });
194
-
195
- expect(() => service.getRecordForAction("sa-foreign")).toThrow(/not found or not owned/);
196
- });
197
-
198
- it("直接父校验仍生效:孙级 record(parentRecordId=sa-parent)→ 主进程 throw direct parent", () => {
199
- writeSessionJsonl(sessionsDir, {
200
- id: "sa-grand",
201
- rootSessionId: "root-session",
202
- parentRecordId: "sa-parent",
203
- depth: 2,
204
- });
205
-
206
- // 重建后 parentRecordId=sa-parent ≠ 主进程 baseline(undefined) → cross-layer 守卫拦截
207
- expect(() => service.getRecordForAction("sa-grand")).toThrow(/direct parent/);
208
- });
209
-
210
- it(".finalized sidecar(closed 终态)不重建 → throw not found or not owned", () => {
211
- const file = writeSessionJsonl(sessionsDir, { id: "sa-fin", rootSessionId: "root-session" });
212
- writeFinalized(file); // sidecar 矩阵分支 2 → status=closed → find(status==="running") miss
213
-
214
- expect(() => service.getRecordForAction("sa-fin")).toThrow(/not found or not owned/);
215
- expect(store.getMutable("sa-fin")).toBeUndefined(); // 未重建注册
216
- });
217
-
218
- // ============================================================
219
- // [review round2] 跨重启 worktree 绑定丢失防护
220
- // ============================================================
221
- // 场景:worktree:true + conversation:true 的 subagent 在父进程重启后续聊。WorktreeHandle
222
- // 不可序列化、重建后恒缺失,若无守卫 → 冷路径 resume 的 spawn cwd 静默回落主 repo
223
- //(隔离失效,正是 worktree 要防的并发写冲突场景)。
224
- it("[review round2] worktree record 跨重启重建 → hadWorktree 标记 + 续聊被拒(行动语言)", async () => {
225
- writeSessionJsonl(sessionsDir, {
226
- id: "sa-wt",
227
- rootSessionId: "root-session",
228
- worktree: true,
229
- });
230
-
231
- const record = service.getRecordForAction("sa-wt");
232
- // hadWorktree 从磁盘 identity entry 的 worktree 标志恢复
233
- expect(record.hadWorktree).toBe(true);
234
- // handle 无法恢复(不可序列化)
235
- expect(record.worktreeHandle).toBeUndefined();
236
-
237
- // 冷路径续聊(无活进程)→ resumeRound 守卫拒绝,不 spawn 回落主 repo
238
- await expect(service.deliverMessage(record, "resume after restart", false)).rejects.toThrow(
239
- /worktree isolation.*lost when the parent process restarted/,
240
- );
241
- });
242
-
243
- it("[review round2] 非 worktree record 跨重启重建 → 续聊不受 worktree 守卫拦截(向后兼容)", async () => {
244
- // identity entry 无 worktree 字段(旧文件)→ found.worktree undefined → hadWorktree false
245
- writeSessionJsonl(sessionsDir, { id: "sa-nowt", rootSessionId: "root-session" });
246
-
247
- const record = service.getRecordForAction("sa-nowt");
248
- expect(record.hadWorktree).toBe(false);
249
-
250
- // deliverMessage 冷路径不被 worktree 守卫拦截(resume 正常发起;后续 spawn 编排
251
- // 超出本用例关注点——runSpawn 在本文件是 no-op mock)
252
- await expect(service.deliverMessage(record, "resume normal", false)).resolves.toBeUndefined();
253
- });
254
- });
@@ -1,59 +0,0 @@
1
- // src/__tests__/gui-mode-dispatch.test.ts
2
- //
3
- // S6: ctx.mode RPC 分发契约测试。
4
- //
5
- // 审查发现:sdk-contract.test.ts 只测 ctx.model 透传,未覆盖 ctx.mode === "rpc"
6
- // 时 __gui__ 被填充、ctx.mode === "tui" 时不填充的 GUI 通道分发。
7
- //
8
- // adapter() 是纯函数,ctx.mode === "rpc" → details.__gui__ 被附加,
9
- // ctx.mode === "tui"/"json"/"print" → details.__gui__ 为 undefined。
10
-
11
- import type { GuiContext } from "@xyz-agent/extension-protocol";
12
- import { describe, expect, it } from "vitest";
13
-
14
- import type { AdapterInput } from "../../interface/subagent-actions.ts";
15
- import { adapter } from "../../interface/subagent-actions.ts";
16
-
17
- function makeStartInput(): AdapterInput {
18
- return {
19
- action: "start",
20
- domain: {
21
- subagentId: "test-id",
22
- sessionFile: "/test/session.jsonl",
23
- slug: "test-slug",
24
- response: { status: "started" },
25
- },
26
- } as unknown as AdapterInput;
27
- }
28
-
29
- describe("S6: ctx.mode dispatches __gui__ output correctly", () => {
30
- it("ctx.mode=rpc → details.__gui__ is populated", () => {
31
- const ctx = { mode: "rpc", hasUI: true } as GuiContext;
32
- const result = adapter(makeStartInput(), ctx);
33
- expect(result.details).toHaveProperty("__gui__");
34
- expect(result.details.__gui__).toBeDefined();
35
- });
36
-
37
- it("ctx.mode=tui → details.__gui__ is undefined (TUI renders differently)", () => {
38
- const ctx = { mode: "tui", hasUI: true } as GuiContext;
39
- const result = adapter(makeStartInput(), ctx);
40
- expect(result.details.__gui__).toBeUndefined();
41
- });
42
-
43
- it("ctx.mode=json → details.__gui__ is undefined (headless)", () => {
44
- const ctx = { mode: "json", hasUI: false } as GuiContext;
45
- const result = adapter(makeStartInput(), ctx);
46
- expect(result.details.__gui__).toBeUndefined();
47
- });
48
-
49
- it("ctx.mode=print → details.__gui__ is undefined (headless)", () => {
50
- const ctx = { mode: "print", hasUI: false } as GuiContext;
51
- const result = adapter(makeStartInput(), ctx);
52
- expect(result.details.__gui__).toBeUndefined();
53
- });
54
-
55
- it("ctx=undefined → details.__gui__ is undefined (backward compat)", () => {
56
- const result = adapter(makeStartInput(), undefined);
57
- expect(result.details.__gui__).toBeUndefined();
58
- });
59
- });
@@ -1,30 +0,0 @@
1
- /**
2
- * 创建一个结构兼容的 ExtensionAPI mock,供 sdk-contract / 注册契约测试用。
3
- *
4
- * ExtensionAPI 有 ~30 个必需方法(on/registerTool/registerCommand/...),逐个手写
5
- * 不现实。本 helper 用 Proxy 把所有未显式 override 的方法/属性短路为 no-op 函数,
6
- * 让对象**结构兼容** ExtensionAPI——避免 `as unknown as ExtensionAPI` 双重断言
7
- * (taste/no-unsafe-cast 规则禁止)。测试只需 override 关心的方法:
8
- *
9
- * const pi = mockExtensionApi({
10
- * registerCommand: (name) => { capturedName = name; },
11
- * });
12
- *
13
- * Proxy 的 trap 对所有属性访问返回 override 值或 no-op 函数,运行时安全
14
- * (注册 handler 只调用被 override 的方法,其余方法测试不触及)。
15
- */
16
- import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
17
-
18
- export function mockExtensionApi(
19
- overrides: Record<string, unknown> = {},
20
- ): ExtensionAPI {
21
- const noop = (): void => { /* test mock: method not invoked by this test */ };
22
- // Proxy<T> 泛型参数决定返回类型——直接声明为 ExtensionAPI,
23
- // TS 接受(Proxy handler 对 target 的类型不约束 T)。
24
- return new Proxy<ExtensionAPI>(overrides as ExtensionAPI, {
25
- get(target, prop: string | symbol): unknown {
26
- if (prop in target) return target[prop as keyof ExtensionAPI];
27
- return noop;
28
- },
29
- });
30
- }