@zhushanwen/pi-subagent-workflow 8.5.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 (336) hide show
  1. package/package.json +13 -16
  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 +142 -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 +157 -0
  16. package/src/interface/__tests__/subagent-tool-prompt.test.ts +12 -0
  17. package/src/interface/__tests__/tool-workflow-script-generate.test.ts +2 -2
  18. package/src/interface/__tests__/tool-workflow-throw-paths.test.ts +1 -1
  19. package/src/interface/bg-notify-render.ts +34 -13
  20. package/src/interface/commands.ts +3 -3
  21. package/src/interface/format.ts +2 -2
  22. package/src/interface/helpers.ts +3 -3
  23. package/src/interface/list-component.ts +4 -4
  24. package/src/interface/list-shared.ts +2 -2
  25. package/src/interface/list-view.ts +2 -2
  26. package/src/interface/subagent-actions.ts +288 -19
  27. package/src/interface/subagent-tool-schema.ts +163 -0
  28. package/src/interface/subagent-tool.ts +65 -129
  29. package/src/interface/subagents.ts +5 -5
  30. package/src/interface/tool-render.ts +34 -2
  31. package/src/interface/tool-workflow-script.ts +4 -4
  32. package/src/interface/tool-workflow.ts +6 -6
  33. package/src/interface/views/WorkflowsView.ts +5 -5
  34. package/src/interface/views/__tests__/WorkflowsView-signature.test.ts +3 -3
  35. package/src/interface/views/__tests__/detail-content-session-file.test.ts +2 -2
  36. package/src/interface/views/detail-content.ts +4 -4
  37. package/src/interface/views/format.ts +4 -4
  38. package/src/{orchestration/jsonl-run-store.ts → jsonl-run-store.ts} +132 -18
  39. package/src/execution/__tests__/__fixtures__/notifier-golden-snapshots.json +0 -53
  40. package/src/execution/__tests__/__fixtures__/truncline.snapshot.json +0 -1
  41. package/src/execution/__tests__/agent-registry.test.ts +0 -363
  42. package/src/execution/__tests__/agent-result-mapper.test.ts +0 -150
  43. package/src/execution/__tests__/alive-store.test.ts +0 -147
  44. package/src/execution/__tests__/ask-user-transit-e2e.test.ts +0 -490
  45. package/src/execution/__tests__/before-agent-start-injection.test.ts +0 -132
  46. package/src/execution/__tests__/bg-notify-render.test.ts +0 -256
  47. package/src/execution/__tests__/channel-registry-handshake.test.ts +0 -243
  48. package/src/execution/__tests__/chat-engine-routing.test.ts +0 -597
  49. package/src/execution/__tests__/chatmode-first-round-closure-service.test.ts +0 -365
  50. package/src/execution/__tests__/chatmode-first-round-closure-spawn.test.ts +0 -190
  51. package/src/execution/__tests__/chatmode-round-notify-real-chain.test.ts +0 -215
  52. package/src/execution/__tests__/concurrency-pool.test.ts +0 -250
  53. package/src/execution/__tests__/config.test.ts +0 -110
  54. package/src/execution/__tests__/conversation-wiring.test.ts +0 -198
  55. package/src/execution/__tests__/crash-recovery.test.ts +0 -320
  56. package/src/execution/__tests__/delivery-methods.test.ts +0 -385
  57. package/src/execution/__tests__/dialog-queue.test.ts +0 -299
  58. package/src/execution/__tests__/epipe-fallback.test.ts +0 -241
  59. package/src/execution/__tests__/execute-and-await-worktree.test.ts +0 -243
  60. package/src/execution/__tests__/execute-nesting.test.ts +0 -323
  61. package/src/execution/__tests__/execute-options-mapper.test.ts +0 -189
  62. package/src/execution/__tests__/execution-record.test.ts +0 -1284
  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 -138
  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 -238
  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 -593
  75. package/src/execution/__tests__/lifecycle-manager-lock.test.ts +0 -211
  76. package/src/execution/__tests__/lifecycle-manager.test.ts +0 -337
  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 -109
  80. package/src/execution/__tests__/manifest-parentid.test.ts +0 -117
  81. package/src/execution/__tests__/model-resolver.test.ts +0 -413
  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 -574
  85. package/src/execution/__tests__/notifier-golden-snapshot.test.ts +0 -261
  86. package/src/execution/__tests__/one-shot-upgrade.test.ts +0 -205
  87. package/src/execution/__tests__/output-collector.test.ts +0 -61
  88. package/src/execution/__tests__/parent-child-matrix.test.ts +0 -336
  89. package/src/execution/__tests__/path-encoding.test.ts +0 -104
  90. package/src/execution/__tests__/pi-invocation.test.ts +0 -134
  91. package/src/execution/__tests__/record-store.test.ts +0 -1057
  92. package/src/execution/__tests__/records-cwd-isolation.test.ts +0 -91
  93. package/src/execution/__tests__/recursive-visibility-baseline.test.ts +0 -339
  94. package/src/execution/__tests__/recursive-visibility-env.test.ts +0 -273
  95. package/src/execution/__tests__/relay-agent.test.ts +0 -448
  96. package/src/execution/__tests__/relay-env.test.ts +0 -42
  97. package/src/execution/__tests__/resource-policy.test.ts +0 -109
  98. package/src/execution/__tests__/rpc-mode.test.ts +0 -89
  99. package/src/execution/__tests__/run-and-finalize-chatmode.test.ts +0 -267
  100. package/src/execution/__tests__/run-spawn-chatmode-settled.test.ts +0 -253
  101. package/src/execution/__tests__/run-spawn-edges.test.ts +0 -644
  102. package/src/execution/__tests__/run-spawn-integration.test.ts +0 -933
  103. package/src/execution/__tests__/run-spawn-resume.test.ts +0 -322
  104. package/src/execution/__tests__/run-spawn-rpc-mode.test.ts +0 -196
  105. package/src/execution/__tests__/sdk-contract.test.ts +0 -273
  106. package/src/execution/__tests__/session-context-resolver.test.ts +0 -167
  107. package/src/execution/__tests__/session-file-gc.test.ts +0 -293
  108. package/src/execution/__tests__/session-pending.test.ts +0 -197
  109. package/src/execution/__tests__/session-reconstructor.test.ts +0 -379
  110. package/src/execution/__tests__/session-runner-epipe.test.ts +0 -178
  111. package/src/execution/__tests__/session-runner-schema-env.test.ts +0 -311
  112. package/src/execution/__tests__/session-start-reaper.test.ts +0 -233
  113. package/src/execution/__tests__/spawn-args.test.ts +0 -434
  114. package/src/execution/__tests__/spawn-event-adapter-rpc.test.ts +0 -189
  115. package/src/execution/__tests__/spawn-event-adapter.test.ts +0 -167
  116. package/src/execution/__tests__/spawn-worktree-guidance.test.ts +0 -207
  117. package/src/execution/__tests__/spawned-children.test.ts +0 -92
  118. package/src/execution/__tests__/startup-config-declaration.test.ts +0 -35
  119. package/src/execution/__tests__/status-refactor.test.ts +0 -345
  120. package/src/execution/__tests__/stdin-writer.test.ts +0 -463
  121. package/src/execution/__tests__/stream-sink-retirement.test.ts +0 -261
  122. package/src/execution/__tests__/subagent-service-abort.test.ts +0 -60
  123. package/src/execution/__tests__/subagent-service-message-close.test.ts +0 -629
  124. package/src/execution/__tests__/subagent-service-parent-guard.test.ts +0 -180
  125. package/src/execution/__tests__/subagent-service.test.ts +0 -788
  126. package/src/execution/__tests__/subprocess-agent-runner-routing.test.ts +0 -310
  127. package/src/execution/__tests__/subprocess-agent-runner.test.ts +0 -506
  128. package/src/execution/__tests__/temp-prompt.test.ts +0 -53
  129. package/src/execution/__tests__/timeout-integration.test.ts +0 -397
  130. package/src/execution/__tests__/tombstone-store.test.ts +0 -73
  131. package/src/execution/__tests__/tool-action.test.ts +0 -385
  132. package/src/execution/__tests__/truncline-snapshot.test.ts +0 -81
  133. package/src/execution/__tests__/turn-limiter-semantics.test.ts +0 -194
  134. package/src/execution/__tests__/turn-limiter.test.ts +0 -65
  135. package/src/execution/__tests__/ui-channels.test.ts +0 -187
  136. package/src/execution/__tests__/ui-interaction-model.test.ts +0 -67
  137. package/src/execution/__tests__/ui-request-handler-factory.test.ts +0 -370
  138. package/src/execution/__tests__/ui-request-handler.test.ts +0 -204
  139. package/src/execution/__tests__/ui-request-observability.test.ts +0 -114
  140. package/src/execution/__tests__/ui-request-queue.test.ts +0 -133
  141. package/src/execution/__tests__/worktree-manager.test.ts +0 -633
  142. package/src/execution/__tests__/worktree-pid-registration.integration.test.ts +0 -229
  143. package/src/execution/__tests__/worktree-reconcile.integration.test.ts +0 -181
  144. package/src/execution/__tests__/worktree-registry.test.ts +0 -199
  145. package/src/execution/agent-registry.ts +0 -193
  146. package/src/execution/agent-result-mapper.ts +0 -90
  147. package/src/execution/alive-store.ts +0 -92
  148. package/src/execution/argv-mirror.ts +0 -109
  149. package/src/execution/best-effort.ts +0 -38
  150. package/src/execution/channel-registry-access.ts +0 -144
  151. package/src/execution/concurrency-pool.ts +0 -116
  152. package/src/execution/config.ts +0 -96
  153. package/src/execution/dialog-queue.ts +0 -330
  154. package/src/execution/engine/__tests__/common/data-dir.test.ts +0 -53
  155. package/src/execution/engine/__tests__/common/errors.test.ts +0 -132
  156. package/src/execution/engine/__tests__/common/event-journal.test.ts +0 -177
  157. package/src/execution/engine/__tests__/common/kill-chain.test.ts +0 -192
  158. package/src/execution/engine/__tests__/common/nesting-guard.test.ts +0 -81
  159. package/src/execution/engine/__tests__/common/persona-router.test.ts +0 -123
  160. package/src/execution/engine/__tests__/common/pool-manager.test.ts +0 -154
  161. package/src/execution/engine/__tests__/common/schema-emulation.test.ts +0 -128
  162. package/src/execution/engine/__tests__/conformance/__fixtures__/pi-golden-events.json +0 -28
  163. package/src/execution/engine/__tests__/conformance/agent-event-invariants.ts +0 -141
  164. package/src/execution/engine/__tests__/conformance/contract.abort.test.ts +0 -109
  165. package/src/execution/engine/__tests__/conformance/contract.agent-events.test.ts +0 -101
  166. package/src/execution/engine/__tests__/conformance/contract.probe.test.ts +0 -77
  167. package/src/execution/engine/__tests__/conformance/contract.read-degradation.test.ts +0 -104
  168. package/src/execution/engine/__tests__/conformance/contract.relay.test.ts +0 -342
  169. package/src/execution/engine/__tests__/conformance/engine-conformance.live.test.ts +0 -201
  170. package/src/execution/engine/__tests__/conformance/golden-replay.pi.test.ts +0 -76
  171. package/src/execution/engine/__tests__/conformance/golden-replay.zcode.test.ts +0 -79
  172. package/src/execution/engine/__tests__/engine-discovery.test.ts +0 -87
  173. package/src/execution/engine/__tests__/engines-declaration.test.ts +0 -36
  174. package/src/execution/engine/__tests__/model-prompt.test.ts +0 -85
  175. package/src/execution/engine/__tests__/paths.test.ts +0 -39
  176. package/src/execution/engine/__tests__/registry.test.ts +0 -120
  177. package/src/execution/engine/__tests__/routing.test.ts +0 -231
  178. package/src/execution/engine/common/data-dir.ts +0 -62
  179. package/src/execution/engine/common/errors.ts +0 -183
  180. package/src/execution/engine/common/event-journal.ts +0 -254
  181. package/src/execution/engine/common/journal-replay.ts +0 -62
  182. package/src/execution/engine/common/kill-chain.ts +0 -221
  183. package/src/execution/engine/common/nesting-guard.ts +0 -50
  184. package/src/execution/engine/common/persona-router.ts +0 -108
  185. package/src/execution/engine/common/pool-manager.ts +0 -226
  186. package/src/execution/engine/common/schema-emulation.ts +0 -189
  187. package/src/execution/engine/common/session-view-projection.ts +0 -51
  188. package/src/execution/engine/engine-discovery.ts +0 -65
  189. package/src/execution/engine/engines/pi/__tests__/pi-engine.test.ts +0 -469
  190. package/src/execution/engine/engines/pi/__tests__/reader.test.ts +0 -155
  191. package/src/execution/engine/engines/pi/__tests__/task-spec-mapper.test.ts +0 -164
  192. package/src/execution/engine/engines/pi/pi-engine.ts +0 -415
  193. package/src/execution/engine/engines/pi/reader.ts +0 -48
  194. package/src/execution/engine/engines/pi/registration.ts +0 -35
  195. package/src/execution/engine/engines/pi/task-spec-mapper.ts +0 -100
  196. package/src/execution/engine/engines/zcode/__tests__/__fixtures__/zcode-golden-spawn.json +0 -39
  197. package/src/execution/engine/engines/zcode/__tests__/launcher.test.ts +0 -150
  198. package/src/execution/engine/engines/zcode/__tests__/parser.test.ts +0 -246
  199. package/src/execution/engine/engines/zcode/__tests__/preparer.test.ts +0 -228
  200. package/src/execution/engine/engines/zcode/__tests__/reader.test.ts +0 -210
  201. package/src/execution/engine/engines/zcode/__tests__/registration.test.ts +0 -64
  202. package/src/execution/engine/engines/zcode/__tests__/zcode-engine.live.test.ts +0 -127
  203. package/src/execution/engine/engines/zcode/__tests__/zcode-engine.test.ts +0 -567
  204. package/src/execution/engine/engines/zcode/constants.ts +0 -43
  205. package/src/execution/engine/engines/zcode/golden-sample.ts +0 -39
  206. package/src/execution/engine/engines/zcode/launcher.ts +0 -161
  207. package/src/execution/engine/engines/zcode/parser.ts +0 -436
  208. package/src/execution/engine/engines/zcode/preparer.ts +0 -363
  209. package/src/execution/engine/engines/zcode/reader.ts +0 -381
  210. package/src/execution/engine/engines/zcode/registration.ts +0 -37
  211. package/src/execution/engine/engines/zcode/zcode-engine.ts +0 -648
  212. package/src/execution/engine/host-task-spec.ts +0 -47
  213. package/src/execution/engine/model-prompt.ts +0 -59
  214. package/src/execution/engine/paths.ts +0 -42
  215. package/src/execution/engine/port.ts +0 -153
  216. package/src/execution/engine/registry.ts +0 -123
  217. package/src/execution/engine/routing.ts +0 -218
  218. package/src/execution/engine/types.ts +0 -304
  219. package/src/execution/execute-options-mapper.ts +0 -111
  220. package/src/execution/execution-record.ts +0 -906
  221. package/src/execution/finalize-record.ts +0 -251
  222. package/src/execution/finalized-marker.ts +0 -51
  223. package/src/execution/get-state-handshake.ts +0 -104
  224. package/src/execution/host-mode.ts +0 -56
  225. package/src/execution/idle-gc.ts +0 -47
  226. package/src/execution/lifecycle-manager.ts +0 -491
  227. package/src/execution/lifecycle-predicates.ts +0 -65
  228. package/src/execution/manifest-store.ts +0 -256
  229. package/src/execution/model-config-service.ts +0 -204
  230. package/src/execution/model-resolver.ts +0 -276
  231. package/src/execution/notifier.ts +0 -260
  232. package/src/execution/output-collector.ts +0 -88
  233. package/src/execution/path-encoding.ts +0 -60
  234. package/src/execution/pi-invocation.ts +0 -120
  235. package/src/execution/record-entry.ts +0 -132
  236. package/src/execution/record-store.ts +0 -1234
  237. package/src/execution/relay-env.ts +0 -37
  238. package/src/execution/session-context-resolver.ts +0 -64
  239. package/src/execution/session-file-gc.ts +0 -120
  240. package/src/execution/session-pending.ts +0 -164
  241. package/src/execution/session-reconstructor.ts +0 -678
  242. package/src/execution/session-runner.ts +0 -1548
  243. package/src/execution/sessions-index.ts +0 -304
  244. package/src/execution/spawn-event-adapter.ts +0 -363
  245. package/src/execution/stdin-writer.ts +0 -198
  246. package/src/execution/stream-sink.ts +0 -126
  247. package/src/execution/subagent-service.ts +0 -2119
  248. package/src/execution/subprocess-agent-runner.ts +0 -303
  249. package/src/execution/temp-prompt.ts +0 -62
  250. package/src/execution/tombstone-store.ts +0 -72
  251. package/src/execution/turn-limiter.ts +0 -102
  252. package/src/execution/types.ts +0 -910
  253. package/src/execution/ui-channels.ts +0 -216
  254. package/src/execution/ui-interaction-model.ts +0 -48
  255. package/src/execution/ui-request-handler-factory.ts +0 -212
  256. package/src/execution/ui-request-observability.ts +0 -81
  257. package/src/execution/ui-request-queue.ts +0 -174
  258. package/src/execution/worktree-manager.ts +0 -688
  259. package/src/execution/worktree-registry.ts +0 -222
  260. package/src/orchestration/__tests__/__fixtures__/worker-template.snapshot.txt +0 -336
  261. package/src/orchestration/__tests__/agent-call-catch-fallback.test.ts +0 -208
  262. package/src/orchestration/__tests__/agent-call-stream.test.ts +0 -157
  263. package/src/orchestration/__tests__/args-validator.test.ts +0 -143
  264. package/src/orchestration/__tests__/concurrency-gate.test.ts +0 -125
  265. package/src/orchestration/__tests__/config-loader.test.ts +0 -503
  266. package/src/orchestration/__tests__/error-recovery-handlers.test.ts +0 -724
  267. package/src/orchestration/__tests__/error-recovery-postmessage-defense.test.ts +0 -405
  268. package/src/orchestration/__tests__/error-recovery-serialize-failed-result.test.ts +0 -56
  269. package/src/orchestration/__tests__/error-recovery-workflow-call.test.ts +0 -166
  270. package/src/orchestration/__tests__/execute-agent-call.test.ts +0 -314
  271. package/src/orchestration/__tests__/jsonl-run-store-loadall-sources.test.ts +0 -171
  272. package/src/orchestration/__tests__/jsonl-run-store-session-file.test.ts +0 -1030
  273. package/src/orchestration/__tests__/launcher-nested-workflow.test.ts +0 -277
  274. package/src/orchestration/__tests__/lifecycle-runid-injection.test.ts +0 -96
  275. package/src/orchestration/__tests__/lifecycle.test.ts +0 -625
  276. package/src/orchestration/__tests__/review-fix-loop-e2e.test.ts +0 -1971
  277. package/src/orchestration/__tests__/script-lint.test.ts +0 -831
  278. package/src/orchestration/__tests__/skill-discovery.test.ts +0 -157
  279. package/src/orchestration/__tests__/test-mocks.ts +0 -197
  280. package/src/orchestration/__tests__/worker-host.test.ts +0 -120
  281. package/src/orchestration/__tests__/worker-returnmeta-passthrough.test.ts +0 -164
  282. package/src/orchestration/__tests__/worker-script-builder-runtime.test.ts +0 -520
  283. package/src/orchestration/__tests__/worker-script-builder.test.ts +0 -309
  284. package/src/orchestration/__tests__/worker-script-template-snapshot.test.ts +0 -110
  285. package/src/orchestration/__tests__/workflow-nesting-e2e.test.ts +0 -317
  286. package/src/orchestration/__tests__/workflow-script-lint-memo.test.ts +0 -110
  287. package/src/orchestration/__tests__/workflows-e2e.test.ts +0 -537
  288. package/src/orchestration/agent-opts-resolver.ts +0 -93
  289. package/src/orchestration/args-validator.ts +0 -127
  290. package/src/orchestration/concurrency-gate.ts +0 -69
  291. package/src/orchestration/config-loader.ts +0 -315
  292. package/src/orchestration/error-recovery.ts +0 -862
  293. package/src/orchestration/execute-agent-call.ts +0 -217
  294. package/src/orchestration/launcher.ts +0 -410
  295. package/src/orchestration/lifecycle.ts +0 -396
  296. package/src/orchestration/models/__tests__/budget.test.ts +0 -367
  297. package/src/orchestration/models/__tests__/trace.test.ts +0 -408
  298. package/src/orchestration/models/agent-call.ts +0 -83
  299. package/src/orchestration/models/budget.ts +0 -148
  300. package/src/orchestration/models/ports.ts +0 -164
  301. package/src/orchestration/models/run-runtime.ts +0 -89
  302. package/src/orchestration/models/run-spec.ts +0 -83
  303. package/src/orchestration/models/run-state.ts +0 -44
  304. package/src/orchestration/models/trace.ts +0 -183
  305. package/src/orchestration/models/types.ts +0 -292
  306. package/src/orchestration/models/workflow-run.ts +0 -254
  307. package/src/orchestration/models/workflow-script-registry.ts +0 -35
  308. package/src/orchestration/models/workflow-script.ts +0 -117
  309. package/src/orchestration/script-lint.ts +0 -766
  310. package/src/orchestration/skill-discovery.ts +0 -92
  311. package/src/orchestration/worker-handle.ts +0 -115
  312. package/src/orchestration/worker-host.ts +0 -98
  313. package/src/orchestration/worker-script-builder.ts +0 -408
  314. package/src/orchestration/workflow-files.ts +0 -85
  315. package/src/orchestration/workflow-script-registry-impl.ts +0 -133
  316. package/src/shared/__tests__/agent-ref.test.ts +0 -34
  317. package/src/shared/__tests__/meta-parser.test.ts +0 -304
  318. package/src/shared/__tests__/resource-discovery-manifest-cache.test.ts +0 -280
  319. package/src/shared/__tests__/resource-discovery.test.ts +0 -736
  320. package/src/shared/__tests__/resource-meta.test.ts +0 -51
  321. package/src/shared/__tests__/schema-jsonify.test.ts +0 -81
  322. package/src/shared/agent-event.ts +0 -13
  323. package/src/shared/agent-ref.ts +0 -57
  324. package/src/shared/meta-parser.ts +0 -261
  325. package/src/shared/resource-discovery.ts +0 -811
  326. package/src/shared/resource-meta.ts +0 -65
  327. package/src/shared/schema-jsonify.ts +0 -56
  328. package/src/shared/xml-injection.ts +0 -35
  329. package/workflows/README.md +0 -81
  330. package/workflows/_shared/agent-refs.cjs +0 -40
  331. package/workflows/chain.js +0 -131
  332. package/workflows/map-reduce.js +0 -174
  333. package/workflows/parallel.js +0 -148
  334. package/workflows/review-fix-loop-utils.cjs +0 -1307
  335. package/workflows/review-fix-loop.js +0 -1396
  336. package/workflows/scatter-gather.js +0 -178
@@ -1,193 +0,0 @@
1
- // src/execution/agent-registry.ts
2
- //
3
- // agent .md 文件发现与解析。
4
- //
5
- // 发现逻辑统一走 shared/resource-discovery(ADR-031),与 workflow 共享同一套
6
- // 扫描源前缀 + manifest 校验。hot-reload:每次调用重扫(mtime 缓存跳过未变文件)。
7
- //
8
- // builtin agent(包内 agents/*.md)走 pi.agents manifest(与 npm 包内发现规则一致)。
9
-
10
-
11
- import * as path from "node:path";
12
-
13
- import { getLogger } from "@zhushanwen/pi-extension-logger";
14
-
15
- import {
16
- getCachedFile,
17
- } from "../shared/resource-discovery.ts";
18
- import { normalizeRef, AGENT_REF_EXT } from "../shared/agent-ref.ts";
19
- import { parseResourceMeta } from "../shared/meta-parser.ts";
20
- import { lintAgentMeta } from "../orchestration/script-lint.ts";
21
- import type { AgentMeta } from "../shared/resource-meta.ts";
22
- import type { AgentConfig } from "./model-resolver.ts";
23
- import { hasEngine, listEngines, EngineNotFoundError } from "./engine/registry.ts";
24
-
25
- const logger = getLogger("subagents");
26
-
27
- /** mtime 缓存条目(跨 loadByPath 保留,靠 mtime 判失效)。 */
28
- interface FileCacheEntry {
29
- mtimeMs: number;
30
- config: AgentConfig;
31
- /** AgentMeta(W4 lint 用——cache-miss 时 lint 一次,warn 随 mtime 变化刷)。 */
32
- meta: AgentMeta | null;
33
- }
34
-
35
- // ============================================================
36
- // frontmatter 解析
37
- // ============================================================
38
-
39
- /** frontmatter 分隔符。 */
40
- const FM_DELIM = "---";
41
-
42
- /**
43
- * 解析 .md frontmatter(name/tools/model/thinkingLevel/defaultBackground)+ body(systemPrompt)。
44
- * 兼容简单 YAML(key: value 单行格式)。body 作为 systemPrompt。
45
- */
46
- export function parseAgentFrontmatter(filePath: string, content: string): AgentConfig {
47
- return parseAgentWithMeta(filePath, content).config;
48
- }
49
-
50
- /**
51
- * 解析 agent .md → { config, meta } 二元组(m5 T2:W4 lint 需要 AgentMeta——
52
- * AgentConfig 投影时 examples 被丢弃,meta 供 lintAgentMeta 使用)。
53
- */
54
- export function parseAgentWithMeta(
55
- filePath: string,
56
- content: string,
57
- ): { config: AgentConfig; meta: AgentMeta | null } {
58
- const name = path.basename(filePath, ".md");
59
-
60
- // 无 frontmatter → 整个内容作为 systemPrompt
61
- if (!content.startsWith(FM_DELIM)) {
62
- return { config: { name, systemPrompt: content.trim() }, meta: null };
63
- }
64
-
65
- const closeIdx = content.indexOf(FM_DELIM, FM_DELIM.length);
66
- if (closeIdx === -1) {
67
- // 未闭合 frontmatter:提取 name,其余作为 systemPrompt
68
- const yamlBlock = content.slice(FM_DELIM.length);
69
- return {
70
- config: {
71
- name: extractYamlField(yamlBlock, "name") ?? name,
72
- systemPrompt: content.trim(),
73
- },
74
- meta: null,
75
- };
76
- }
77
-
78
- const yamlBlock = content.slice(FM_DELIM.length, closeIdx);
79
- const body = content.slice(closeIdx + FM_DELIM.length).trim();
80
-
81
- // m2:结构化路由字段(name/model/tools)经 IF1 parseResourceMeta(统一 parser),
82
- // 消灭本地 frontmatter parser 与 subagent-list-injector 的重复。thinkingLevel/defaultBackground
83
- // 是执行配置(非 AgentMeta 路由字段),仍用 extractYamlField 取。
84
- const meta = parseResourceMeta(content, "agent");
85
- const agentMeta = meta?.kind === "agent" ? meta : null;
86
- // MF-3 regression fix:agentMeta=null(IF1 要求 name/description 必填,缺则 parseResourceMeta
87
- // 返 null)时,model/tools 不能静默丢失——fallback 用 extractYamlField 取(保留重构前行为)。
88
- // 注入路由可见性由 discovery/injector 按 available 标志决定,与本处(direct-path loadByPath)无关。
89
- const modelFallback = extractYamlField(yamlBlock, "model");
90
- const toolsFallbackRaw = extractYamlField(yamlBlock, "tools");
91
- const toolsFallback = toolsFallbackRaw
92
- ? toolsFallbackRaw.split(",").map((s) => s.trim()).filter(Boolean)
93
- : undefined;
94
- if (!agentMeta && /^model:|^tools:/m.test(yamlBlock)) {
95
- // m2 exec-review MINOR-2 + MF-3:IF1 未通过(缺 name/description)→ model/tools 经 legacy
96
- // fallback 取(direct-path loadByPath 不丢配置,与重构前一致);但结构化路由注入不可见,
97
- // 建议 agent 作者补 description 以满足 IF1。
98
- logger.warn(
99
- `[agent-registry] ${filePath}: agent frontmatter 缺 name/description(IF1 必填),` +
100
- "model/tools 经 legacy fallback 生效(直接路径不丢配置),但结构化路由不可见——请补充 description",
101
- );
102
- }
103
- const defaultBackgroundRaw = extractYamlField(yamlBlock, "defaultBackground");
104
- // engine 字段(D9):结构化优先(IF1),legacy fallback 与 model/tools 同判——
105
- // agentMeta 未通过 IF1 时配置不丢
106
- const engine = agentMeta?.engine ?? extractYamlField(yamlBlock, "engine");
107
- // 解析期校验(D9:未注册 id 前置暴露,不留到运行时神秘失败)。为什么在解析期而非
108
- // 路由期:配置错误的根源在 .md 文件,越早报错定位越准(错误含文件路径 + 注册清单)
109
- if (engine !== undefined && !hasEngine(engine)) {
110
- throw new EngineNotFoundError(engine, listEngines(), filePath);
111
- }
112
-
113
- return {
114
- config: {
115
- name: agentMeta?.name ?? name,
116
- systemPrompt: body,
117
- model: agentMeta?.model ?? modelFallback ?? undefined,
118
- thinkingLevel: extractYamlField(yamlBlock, "thinkingLevel") ?? undefined,
119
- ...(engine !== undefined ? { engine } : {}),
120
- tools: agentMeta?.tools && agentMeta.tools.length > 0
121
- ? agentMeta.tools
122
- : (toolsFallback && toolsFallback.length > 0 ? toolsFallback : undefined),
123
- defaultBackground: defaultBackgroundRaw === "true" ? true : undefined,
124
- },
125
- meta: agentMeta,
126
- };
127
- }
128
-
129
- /** 提取简单 `key: value` 字段,剥离引号。 */
130
- function extractYamlField(yaml: string, key: string): string | undefined {
131
- const regex = new RegExp(`^${key}:\\s*(.+)$`, "m");
132
- const match = yaml.match(regex);
133
- if (!match) return undefined;
134
- let value = match[1].trim();
135
- if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
136
- value = value.slice(1, -1);
137
- }
138
- return value || undefined;
139
- }
140
-
141
- // ============================================================
142
- // AgentRegistry
143
- // ============================================================
144
-
145
- export class AgentRegistry {
146
- /** 文件级 mtime 缓存(key=绝对路径,跨 loadByPath 保留)。 */
147
- private readonly fileCache = new Map<string, FileCacheEntry>();
148
-
149
- /**
150
- * 按绝对路径加载 agent(agentRef 统一解析入口——S2 路径统一)。
151
- *
152
- * - ~/ 前缀展开;相对路径/非 .md 引用返回 undefined(引用唯一形态 = 绝对路径)
153
- * - 文件不可读/不存在 → 驱逐缓存 + 返回 undefined(调用方给错误指引)
154
- * - mtime 未变复用 config 缓存;cache-miss 时 W4 lint 一次
155
- */
156
- loadByPath(ref: string, require?: boolean): AgentConfig | undefined {
157
- const filePath = normalizeRef(ref, AGENT_REF_EXT);
158
- if (filePath === null) {
159
- if (require) {
160
- throw new Error(
161
- `Invalid agent ref: ${ref}. Agent refs must be absolute paths to .md files (use <location> from <available_subagents>).`,
162
- );
163
- }
164
- return undefined;
165
- }
166
-
167
- const file = getCachedFile(filePath);
168
- if (file === null) {
169
- // ENOENT/不可读 → 驱逐(mtime 缓存下文件删除不自愈的修复)
170
- this.fileCache.delete(filePath);
171
- if (require) {
172
- throw new Error(
173
- `Agent file not found or unreadable: ${filePath}. Use an absolute path from <available_subagents> <location>.`,
174
- );
175
- }
176
- return undefined;
177
- }
178
-
179
- const cached = this.fileCache.get(filePath);
180
- if (cached && cached.mtimeMs === file.mtimeMs) {
181
- return cached.config;
182
- }
183
-
184
- const { config, meta } = parseAgentWithMeta(filePath, file.content);
185
- // W4 lint:cache-miss(parse 时一次)——warn 只随 mtime 变化刷
186
- const lintFindings = meta ? lintAgentMeta(meta) : [];
187
- for (const finding of lintFindings) {
188
- logger.warn(`[agent-registry] ${filePath}: ${finding.message}`);
189
- }
190
- this.fileCache.set(filePath, { mtimeMs: file.mtimeMs, config, meta });
191
- return config;
192
- }
193
- }
@@ -1,90 +0,0 @@
1
- // src/execution/agent-result-mapper.ts
2
- //
3
- // D-A10: subagents AgentResult → workflow AgentResult 映射。
4
- // 纯 DTO 映射函数——executeAndAwait 出口调,SAR 不感知形状差异。
5
- //
6
- // 接线层级:[模块内直调] —— SubagentService.executeAndAwait 出口调。
7
-
8
- import type { AgentResult as WorkflowAgentResult, AgentUsage as WorkflowAgentUsage, ToolCallEntry } from "../orchestration/models/types.ts";
9
- import type { AgentResult as SubagentsAgentResult, AgentUsageTotal, ToolCall } from "./types.ts";
10
-
11
- /** safeStringify 的 JSON 截断长度(字符),防大对象拼进 toolCalls 挤爆 trace。 */
12
- const TOOL_ARGS_JSON_MAX_CHARS = 500;
13
-
14
- /**
15
- * D-A10: subagents AgentResult → workflow AgentResult 映射。
16
- *
17
- * 字段映射表:
18
- * subagents → workflow
19
- * ─────────────────────────────────────────────
20
- * text → content
21
- * parsedOutput → parsedOutput(structured-output 契约,BC-8)
22
- * !success && error → error(失败时填,成功时 undefined)
23
- * !success && !error → error fallback(abort 路径:session-runner 设 success=false,error=undefined,
24
- * 若直接透传 undefined 则 executeAgentCall 的 `error===undefined` 误判 completed。H4 修复:synthesize fallback)
25
- * durationMs → durationMs
26
- * sessionId → sessionId
27
- * usage (AgentUsageTotal) → usage (AgentUsage: input/output/cacheRead/cacheWrite/cost/contextTokens/turns)
28
- * toolCalls (ToolCall[]) → toolCalls (ToolCallEntry[]: name/input)
29
- *
30
- * @param r subagents 管道产出的 AgentResult(runSpawn/collectResult 出口形状)
31
- * @returns workflow 编排层消费的 AgentResult(executeAgentCall/finalizeCall 入参形状)
32
- */
33
- export function mapToWorkflowAgentResult(
34
- r: SubagentsAgentResult,
35
- ): WorkflowAgentResult {
36
- return {
37
- content: r.text,
38
- parsedOutput: r.parsedOutput,
39
- error: r.success ? undefined : (r.error || "Agent call failed (aborted or unknown error)"),
40
- durationMs: r.durationMs,
41
- sessionId: r.sessionId,
42
- sessionFile: r.sessionFile,
43
- usage: r.usage ? mapUsage(r.usage, r.turns) : undefined,
44
- toolCalls: r.toolCalls ? mapToolCalls(r.toolCalls) : undefined,
45
- };
46
- }
47
-
48
- /**
49
- * AgentUsageTotal(subagents)→ AgentUsage(workflow)映射。
50
- *
51
- * subagents AgentUsageTotal: { input, output, cacheRead, cacheWrite, total, cost }
52
- * workflow AgentUsage: { input, output, cacheRead, cacheWrite, cost, contextTokens, turns }
53
- *
54
- * contextTokens ≈ total(subagents 的四项之和,近似上下文 token 量)。
55
- * turns 来自 AgentResult.turns(非 usage 内字段)。
56
- */
57
- function mapUsage(u: AgentUsageTotal, turns: number): WorkflowAgentUsage {
58
- return {
59
- input: u.input,
60
- output: u.output,
61
- cacheRead: u.cacheRead,
62
- cacheWrite: u.cacheWrite,
63
- cost: u.cost,
64
- contextTokens: u.total,
65
- turns,
66
- };
67
- }
68
-
69
- /**
70
- * ToolCall(subagents)→ ToolCallEntry(workflow)映射。
71
- *
72
- * subagents ToolCall: { toolName, args?, result?, isError? }
73
- * workflow ToolCallEntry: { name, input }
74
- */
75
- function mapToolCalls(calls: ToolCall[]): ToolCallEntry[] {
76
- return calls.map((c) => ({
77
- name: c.toolName,
78
- input: c.args === undefined ? "" : safeStringify(c.args),
79
- }));
80
- }
81
-
82
- /** 安全序列化(args 可能含循环引用或大对象,截断防 OOM)。 */
83
- function safeStringify(value: unknown): string {
84
- try {
85
- const s = JSON.stringify(value);
86
- return s.length > TOOL_ARGS_JSON_MAX_CHARS ? `${s.slice(0, TOOL_ARGS_JSON_MAX_CHARS)}...` : s;
87
- } catch {
88
- return String(value);
89
- }
90
- }
@@ -1,92 +0,0 @@
1
- // src/runtime/execution/alive-store.ts
2
- //
3
- // .alive sidecar 生产者 + pid 探活。
4
- //
5
- // 子进程启动时写 .alive(pid+id+startedAt),心跳检测时读它 + isProcessAlive
6
- // 判活。finalize/cancel 收尾时 remove。与 .cancelled/.finalized 构成三件套。
7
- //
8
- // 设计对齐 tombstone-store:单文件 sidecar、best-effort I/O、无全局 index。
9
-
10
- import * as fs from "node:fs";
11
-
12
- import type { AliveMarker } from "./types.ts";
13
-
14
- // ============================================================
15
- // 公开函数
16
- // ============================================================
17
-
18
- /**
19
- * 在 sessionFile 旁写 .alive sidecar(单行 JSON)。
20
- * 覆盖写——同一 sessionFile 只有最后一个 alive marker 有意义。
21
- */
22
- export function writeAliveMarker(sessionFile: string, marker: AliveMarker): void {
23
- const alivePath = `${sessionFile}.alive`;
24
- fs.writeFileSync(alivePath, `${JSON.stringify(marker)}\n`, "utf-8");
25
- }
26
-
27
- /**
28
- * 读 sessionFile 旁的 .alive sidecar。
29
- * 返回 undefined:不存在 / 损坏 / 解析失败。
30
- */
31
- export function readAliveMarker(sessionFile: string): AliveMarker | undefined {
32
- let raw: string;
33
- try {
34
- raw = fs.readFileSync(`${sessionFile}.alive`, "utf-8");
35
- } catch {
36
- return undefined;
37
- }
38
- try {
39
- const parsed = JSON.parse(raw) as Partial<AliveMarker>;
40
- if (
41
- typeof parsed.pid === "number" &&
42
- typeof parsed.id === "string" &&
43
- typeof parsed.startedAt === "number"
44
- ) {
45
- return parsed as AliveMarker;
46
- }
47
- return undefined;
48
- } catch {
49
- return undefined;
50
- }
51
- }
52
-
53
- /**
54
- * 删除 sessionFile 旁的 .alive sidecar。
55
- * best-effort:不存在不抛(finalize/cancel 收尾调,sidecar 可能已被清理)。
56
- */
57
- export function removeAliveMarker(sessionFile: string): void {
58
- try {
59
- fs.unlinkSync(`${sessionFile}.alive`);
60
- } catch {
61
- void 0; // best-effort
62
- }
63
- }
64
-
65
- /**
66
- * 检测 pid 是否存活。
67
- *
68
- * process.kill(pid, 0) 语义:不发信号,仅检查进程是否存在。
69
- * - 无异常 → 存活
70
- * - ESRCH(No such process)→ 死
71
- * - EPERM(Process exists but no permission)→ 存活(保守)
72
- * - 其他异常 → 保守判死 false,避免误删活进程
73
- */
74
- export function isProcessAlive(pid: number): boolean {
75
- try {
76
- process.kill(pid, 0);
77
- return true;
78
- } catch (err: unknown) {
79
- if (isErrnoException(err) && err.code === "EPERM") {
80
- return true; // 存在但无权限发信号 → 判活
81
- }
82
- return false; // ESRCH 或其他异常 → 保守判死
83
- }
84
- }
85
-
86
- // ============================================================
87
- // 内部工具
88
- // ============================================================
89
-
90
- function isErrnoException(err: unknown): err is NodeJS.ErrnoException {
91
- return err instanceof Error && "code" in err;
92
- }
@@ -1,109 +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
- * 用于 mirrorMainProcessFlags 跳过其他 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
- /** argv 中 flag 的起始索引:argv[0]=runtime, argv[1]=binary 路径。 */
32
- const ARGV_FLAG_START = 2;
33
-
34
- /**
35
- * 从主进程 argv 解析可镜像的 flag(--no-extensions/--approve/--extension/--no-context-files)。
36
- *
37
- * 数据源是主 pi 进程的 process.argv:子进程 spawn 的父就是主进程,
38
- * 主进程 argv 完整保留启动时收到的全部 flag(已运行时验证)。这让子进程
39
- * extension/approve 加载行为与主进程一致,且对任意 pi 宿主通用(不止 xyz-agent)。
40
- *
41
- * 解析规则:
42
- * - --no-extensions / -ne、--approve / -a:布尔 flag
43
- * - --no-context-files / -nc:布尔 flag(镜像理由:--extension 镜像会把
44
- * @zhushanwen/pi-system-prompt 带进每个 subagent,该扩展靠子进程自己的
45
- * argv 检测此 flag 决定是否注入全局 AGENTS.md——不镜像则用户 opt-out
46
- * 在 subagent 路径失效)
47
- * - --extension / -e:支持 `--extension <path>`(空格)与 `--extension=<path>`(等号)
48
- * - 其他 flag(在 VALUED_FLAGS 中)的值不被误当 extension 路径
49
- * - positional 参数被忽略
50
- * - argv[0]/argv[1] 是 bun/pi binary 路径,从 argv[2:] 开始扫
51
- */
52
- // [perf] 进程内 process.argv 引用恒定(唯一调用点 session-runner 每次 spawn 传同一引用),
53
- // 解析结果按 argv 引用相等 memo——每次 spawn 免重复扫描/正则。测试传新数组引用不命中。
54
- let memoArgv: readonly string[] | undefined;
55
- let memoResult: MirrorFlags | undefined;
56
-
57
- export function mirrorMainProcessFlags(argv: readonly string[]): MirrorFlags {
58
- if (memoResult !== undefined && memoArgv === argv) return memoResult;
59
- let hasNoExtensions = false;
60
- let hasApprove = false;
61
- let hasNoContextFiles = false;
62
- const extensionPaths: string[] = [];
63
-
64
- // argv[0]=runtime(bun), argv[1]=pi binary 路径;flag 从 argv[2] 起
65
- const flagArgs = argv.length > ARGV_FLAG_START ? argv.slice(ARGV_FLAG_START) : [];
66
-
67
- for (let i = 0; i < flagArgs.length; i++) {
68
- const tok = flagArgs[i];
69
- if (tok === "--no-extensions" || tok === "-ne") {
70
- hasNoExtensions = true;
71
- continue;
72
- }
73
- if (tok === "--approve" || tok === "-a") {
74
- hasApprove = true;
75
- continue;
76
- }
77
- if (tok === "--no-context-files" || tok === "-nc") {
78
- hasNoContextFiles = true;
79
- continue;
80
- }
81
- // 等号形式 --extension=path / -e=path
82
- const eqMatch = /^(--extension|-e)=(.*)$/.exec(tok);
83
- if (eqMatch) {
84
- const val = eqMatch[2];
85
- if (val) extensionPaths.push(val);
86
- continue;
87
- }
88
- // 空格形式 --extension <path> / -e <path>:值在下一个 token
89
- if (tok === "--extension" || tok === "-e") {
90
- const next = flagArgs[i + 1];
91
- if (next !== undefined && !next.startsWith("-") && next.length > 0) {
92
- extensionPaths.push(next);
93
- i++; // 跳过值
94
- }
95
- continue;
96
- }
97
- // 其他有值 flag:跳过其值,避免误吃(如 --skill /a 的 /a)
98
- if (VALUED_FLAGS.has(tok)) {
99
- i++;
100
- continue;
101
- }
102
- // 其他情况(未知 flag、--flag=val 形式、positional)忽略
103
- }
104
-
105
- const result = { noExtensions: hasNoExtensions, approve: hasApprove, extensionPaths, noContextFiles: hasNoContextFiles };
106
- memoArgv = argv;
107
- memoResult = result;
108
- return result;
109
- }
@@ -1,38 +0,0 @@
1
- // src/utils/best-effort.ts
2
- //
3
- // best-effort IO 清理的错误吞咽 helper。
4
- //
5
- // 用途:sidecar 写入 / worktree remove / alive marker 删除等次要 IO,失败不影响
6
- // 主流程(session 已完成或正在收尾)。这类 catch 故意吞错——但 taste/no-silent-catch
7
- // 规则禁止空 catch 或仅 console 的 catch。本 helper 提供一条「实质调用语句」让
8
- // catch 合规,同时把错误记录到 debug/error 便于排查。
9
- //
10
- // 规则绕过原理:taste/no-silent-catch 仅检查 CatchClause 直接 body 是否为空或仅
11
- // console 调用。本 helper 是普通函数调用(ExpressionStatement),既非空也非仅
12
- // console,故合规。helper 函数体内部经共享 logger 路由(不裸 console)。
13
-
14
- import { getLogger } from "@zhushanwen/pi-extension-logger";
15
-
16
- const logger = getLogger("subagents");
17
-
18
- /** 错误日志级别。debug = 次要清理(默认);error = 关键步骤但需继续后续清理。 */
19
- export type BestEffortLevel = "debug" | "error";
20
-
21
- /**
22
- * 吞咽 best-effort IO 的错误,按 level 经共享 logger 记录。
23
- *
24
- * - debug(默认):次要清理(sidecar/worktree/alive marker),失败属预期路径
25
- * - error:关键步骤抛错但需继续后续清理(如 finalizeRecord 的 B9 链:completeRecord
26
- * 抛错后仍要执行 finalized/cleanup,错误需可见但不阻断)
27
- *
28
- * 错误对象优先取 message(避免打印巨大堆栈/对象),其他类型原样传入。
29
- */
30
- export function bestEffort(err: unknown, context: string, level: BestEffortLevel = "debug"): void {
31
- const detail = err instanceof Error ? err.message : err;
32
- const msg = `[subagents] best-effort ${context} failed`;
33
- if (level === "error") {
34
- logger.error(msg, { detail });
35
- } else {
36
- logger.debug(msg, { detail });
37
- }
38
- }
@@ -1,144 +0,0 @@
1
- // src/execution/channel-registry-access.ts
2
- //
3
- // Channel registry 的访问入口(本扩展内部用 + 契约文档化导出)。
4
- //
5
- // ask-user 等扩展通过本模块注册 channel handler,让 subagent 子进程的 UI 请求
6
- // 能透传到主进程渲染。所有扩展各自直接读写
7
- // globalThis[Symbol.for("@zhushanwen/pi-subagents.channelHandshake")],
8
- // 拿到结构兼容 ChannelRegistryHandshake 的同一握手对象。
9
- //
10
- // ── 升级说明(决策 D 修复 M4)─────────────────────────────────
11
- // 历史问题:原协议槽位直接存 UiChannelRegistry 实例,谁先 session_start 谁创建。
12
- // ask-user 先到时会自建简化 registry 占位,劫持 canonical 槽位,subagent-workflow
13
- // 后到时拿到的是 ask-user 的非 canonical 实例,行为不一致。
14
- //
15
- // 修复:槽位从「存 registry 实例」升级为「存握手对象 {version, registry?, pending[]}」。
16
- // canonical registry 实例永远由 subagent-workflow 单一创建点(本模块的
17
- // getOrCreateChannelRegistry)实例化。ask-user 先到时只往 pending 推 handler,
18
- // 等 subagent-workflow 来 flush;subagent-workflow 先到时直接创建 registry 并
19
- // 接收后续 ask-user 推入的 pending。
20
- //
21
- // ── 跨扩展协议契约(必须与 ask-user 侧严格一致)──────────────
22
- // key 字面量: "@zhushanwen/pi-subagents.channelHandshake"
23
- // ↑ 必须与 ask-user/src/channel-registry-register.ts 完全一致
24
- // handshake 形状: ChannelRegistryHandshake(version=1)
25
- // version 守卫: slot.version !== 1 时 console.warn + 丢弃重建(向前兼容未来升级)
26
-
27
- import { getLogger } from "@zhushanwen/pi-extension-logger";
28
-
29
- import { createUiChannelRegistry, type UiChannelRegistry, type ChannelHandler } from "./ui-channels.ts";
30
-
31
- const logger = getLogger("subagents");
32
-
33
- /** 进程级 channel 握手的 globalThis key(Symbol.for 跨模块共享)。
34
- *
35
- * **协议契约**:字面量 `"@zhushanwen/pi-subagents.channelHandshake"` 必须与
36
- * ask-user 扩展的 `ask-user/src/channel-registry-register.ts` 完全一致——
37
- * 两边读写同一个 Symbol.for key 才能拿到同一握手对象。
38
- *
39
- * 改名历史:原 `CHANNEL_REGISTRY_KEY`(字面量 `...channelRegistry`)在决策 D
40
- * 中升级为 `CHANNEL_HANDSHAKE_KEY`(字面量 `...channelHandshake`),槽位形状
41
- * 从 registry 实例改为握手对象。 */
42
- export const CHANNEL_HANDSHAKE_KEY = Symbol.for("@zhushanwen/pi-subagents.channelHandshake");
43
-
44
- /** 握手版本。未来若形状不兼容升级,递增此常量并在 getOrCreateChannelRegistry
45
- * 的 version 守卫里加迁移逻辑。 */
46
- const HANDSHAKE_VERSION = 1 as const;
47
-
48
- /** pending channel handler 条目。ask-user 先到、registry 未就绪时临时存放。 */
49
- export interface ChannelRegistryHandshakePendingEntry {
50
- channel: string;
51
- handler: ChannelHandler;
52
- }
53
-
54
- /** 跨扩展 channel registry 握手对象(globalThis 槽位形状)。
55
- *
56
- * - `version`:协议版本,当前固定 1。读取时若 ≠1 视为不兼容,丢弃重建。
57
- * - `registry`:canonical UiChannelRegistry 实例。仅由 subagent-workflow 的
58
- * getOrCreateChannelRegistry 创建并填充。未就绪时为 undefined。
59
- * - `pending`:ask-user 在 registry 就绪前推入的 handler 条目。
60
- * subagent-workflow 创建 registry 后逐条 flush(注册),然后清空。 */
61
- export interface ChannelRegistryHandshake {
62
- version: typeof HANDSHAKE_VERSION;
63
- registry?: UiChannelRegistry;
64
- pending: ChannelRegistryHandshakePendingEntry[];
65
- }
66
-
67
- /** 读取握手槽位;若 version 不匹配则视为缺失(warn + 返回 undefined)。
68
- * 类型不安全的 globalThis 反射访问集中在本函数,外层逻辑保持类型严谨。 */
69
- function readHandshakeSlot(): ChannelRegistryHandshake | undefined {
70
- const slot = Reflect.get(globalThis, CHANNEL_HANDSHAKE_KEY) as unknown;
71
- if (slot === undefined) return undefined;
72
- // 形状校验:必须是对象且 version===1,否则视为不兼容
73
- if (typeof slot !== "object" || slot === null) {
74
- logger.warn(
75
- "[pi-subagent-workflow] channel handshake slot is not an object; discarding and recreating.",
76
- );
77
- return undefined;
78
- }
79
- // 断言目标含必填 version 字段(object/null 已守卫;version 值本身在下一行校验),
80
- // 对齐 format.ts extractAgentName 的必填字段断言先例,避免全可选断言零校验。
81
- const version = (slot as { version: unknown }).version;
82
- if (version !== HANDSHAKE_VERSION) {
83
- logger.warn(
84
- `[pi-subagent-workflow] channel handshake version mismatch (got ${String(
85
- version,
86
- )}, expected ${HANDSHAKE_VERSION}); discarding and recreating.`,
87
- );
88
- return undefined;
89
- }
90
- // version 正确,但 pending 可能被恶意/错误地塞了非数组;防御性处理
91
- const candidate = slot as ChannelRegistryHandshake;
92
- if (!Array.isArray(candidate.pending)) {
93
- logger.warn(
94
- "[pi-subagent-workflow] channel handshake pending is not an array; discarding and recreating.",
95
- );
96
- return undefined;
97
- }
98
- return candidate;
99
- }
100
-
101
- /** 将 pending 条目逐个注册进 registry,注册完清空 pending。
102
- * pending 内部 entry 的形状由 ask-user 侧保证,此处不再二次校验。 */
103
- function flushPending(registry: UiChannelRegistry, pending: ChannelRegistryHandshakePendingEntry[]): void {
104
- for (const entry of pending) {
105
- registry.register(entry.channel, entry.handler);
106
- }
107
- }
108
-
109
- /** 获取或创建进程级 channel registry(canonical 单例)。
110
- *
111
- * **唯一创建点**:canonical UiChannelRegistry 实例仅由本函数创建。
112
- * ask-user 扩展绝不自建 registry——它在 registry 未就绪时只往 slot.pending 推条目。
113
- *
114
- * 行为分支:
115
- * 1. 槽位不存在或 version ≠ 1 → warn(version 不匹配时)+ 建新 slot
116
- * `{version:1, pending:[], registry:<newly created>}`
117
- * 2. 槽位存在但 registry 未就绪(ask-user 先到过,塞过 pending)→
118
- * 创建 canonical registry + flush pending + 清空 pending
119
- * 3. 槽位存在且 registry 已就绪(本函数已被调用过)→
120
- * 直接返回同一实例引用(===),不重建、不重复 flush
121
- *
122
- * @returns 进程级 canonical UiChannelRegistry 单例(永不返回 undefined) */
123
- export function getOrCreateChannelRegistry(): UiChannelRegistry {
124
- let slot = readHandshakeSlot();
125
- if (slot === undefined) {
126
- // 分支 1:无合规槽位,新建并立即创建 canonical registry
127
- const registry = createUiChannelRegistry();
128
- slot = { version: HANDSHAKE_VERSION, registry, pending: [] };
129
- Reflect.set(globalThis, CHANNEL_HANDSHAKE_KEY, slot);
130
- return registry;
131
- }
132
- if (slot.registry === undefined) {
133
- // 分支 2:ask-user 先到过,flush pending 进 canonical registry
134
- const registry = createUiChannelRegistry();
135
- flushPending(registry, slot.pending);
136
- slot.pending = [];
137
- slot.registry = registry;
138
- return registry;
139
- }
140
- // 分支 3:registry 已就绪,返回同一实例
141
- return slot.registry;
142
- }
143
-
144
- export type { UiChannelRegistry, ChannelHandler };