@zhushanwen/subagent-core 0.2.0 → 0.5.1

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/README.md +45 -2
  2. package/agents/analyst.md +60 -0
  3. package/agents/coder.md +69 -0
  4. package/agents/debugger.md +66 -0
  5. package/agents/doc-reviewer.md +49 -0
  6. package/agents/explorer.md +63 -0
  7. package/agents/general-purpose.md +32 -0
  8. package/agents/orchestrator.md +61 -0
  9. package/agents/planner.md +53 -0
  10. package/agents/researcher.md +67 -0
  11. package/agents/reviewer.md +73 -0
  12. package/dist/chunk-43ONBFZX.js +240 -0
  13. package/dist/chunk-APZY4IME.js +27 -0
  14. package/dist/chunk-V3VHZ2VX.js +59 -0
  15. package/dist/execution/engine/engines/zcode/constants.cjs +62 -9
  16. package/dist/execution/engine/engines/zcode/constants.d.cts +116 -12
  17. package/dist/execution/engine/engines/zcode/constants.d.ts +116 -12
  18. package/dist/execution/engine/engines/zcode/constants.js +39 -7
  19. package/dist/execution/engine/engines/zcode/reader.d.cts +2 -1
  20. package/dist/execution/engine/engines/zcode/reader.d.ts +2 -1
  21. package/dist/execution/engine/engines/zcode/reader.js +4 -234
  22. package/dist/execution/engine/paths.js +7 -19
  23. package/dist/index.cjs +18234 -1277
  24. package/dist/index.d.cts +5646 -673
  25. package/dist/index.d.ts +5646 -673
  26. package/dist/index.js +17828 -1277
  27. package/dist/{types-BxyAidGf.d.cts → types-Dv4QhSJ_.d.cts} +678 -112
  28. package/dist/{types-BxyAidGf.d.ts → types-Dv4QhSJ_.d.ts} +678 -112
  29. package/package.json +7 -4
  30. package/src/__tests__/agent-opts-resolver-schema-prompt.test.ts +0 -1
  31. package/src/__tests__/append-system-prompt-assembly.test.ts +8 -7
  32. package/src/__tests__/fr4-get-state-handshake.test.ts +2 -2
  33. package/src/__tests__/m2-append-content-probe.test.ts +0 -1
  34. package/src/__tests__/manifest-store.test.ts +10 -9
  35. package/src/__tests__/record-store-cache.test.ts +0 -2
  36. package/src/__tests__/record-store-index.test.ts +1 -2
  37. package/src/__tests__/review-fix-loop-script.test.ts +93 -3
  38. package/src/__tests__/review-fix-loop-utils.test.ts +31 -10
  39. package/src/__tests__/robustness-low-batch1.test.ts +6 -5
  40. package/src/__tests__/robustness-medium-batch1.test.ts +2 -2
  41. package/src/__tests__/robustness-medium-batch2.test.ts +17 -6
  42. package/src/__tests__/robustness-medium-batch4.test.ts +2 -2
  43. package/src/__tests__/session-runner.test.ts +1 -1
  44. package/src/__tests__/smoke.test.ts +9 -2
  45. package/src/core/__tests__/host-services.test.ts +2 -2
  46. package/src/core/__tests__/logger.test.ts +1 -1
  47. package/src/core/error-message.ts +9 -0
  48. package/src/core/host-services.ts +21 -5
  49. package/src/core/notify-ports.ts +18 -5
  50. package/src/execution/__tests__/agent-profile.test.ts +232 -0
  51. package/src/execution/__tests__/agent-registry.test.ts +370 -0
  52. package/src/execution/__tests__/agent-result-mapper.test.ts +18 -2
  53. package/src/execution/__tests__/agents-assembly.test.ts +219 -0
  54. package/src/execution/__tests__/ask-user-transit-e2e.test.ts +6 -6
  55. package/src/execution/__tests__/chat-engine-routing.test.ts +136 -30
  56. package/src/execution/__tests__/chatmode-first-round-closure-spawn.test.ts +5 -4
  57. package/src/execution/__tests__/cold-resurrect.test.ts +283 -0
  58. package/src/execution/__tests__/create-concurrency-pool.test.ts +194 -0
  59. package/src/execution/__tests__/delivery-methods.test.ts +77 -62
  60. package/src/execution/__tests__/descendant-sweep-guards.test.ts +220 -0
  61. package/src/execution/__tests__/descendant-sweep.test.ts +269 -0
  62. package/src/execution/__tests__/dialog-queue.test.ts +199 -1
  63. package/src/execution/__tests__/engine-model-validation.test.ts +741 -0
  64. package/src/execution/__tests__/epipe-fallback.test.ts +31 -24
  65. package/src/execution/__tests__/execute-and-await-worktree.test.ts +21 -91
  66. package/src/execution/__tests__/execute-nesting.test.ts +34 -188
  67. package/src/execution/__tests__/execution-record.test.ts +217 -60
  68. package/src/execution/__tests__/execution-runtime-face.test.ts +272 -0
  69. package/src/execution/__tests__/explicit-agent-ref-guard.test.ts +3 -3
  70. package/src/execution/__tests__/finalize-record.test.ts +278 -16
  71. package/src/execution/__tests__/gc-timer.test.ts +57 -2
  72. package/src/execution/__tests__/get-record-for-action-restart.test.ts +14 -12
  73. package/src/execution/__tests__/get-state-handshake.test.ts +127 -0
  74. package/src/execution/__tests__/helpers/mock-extension-api.ts +1 -1
  75. package/src/execution/__tests__/helpers/session-runner-mocks.ts +113 -0
  76. package/src/execution/__tests__/helpers/spawn-mock.ts +150 -3
  77. package/src/execution/__tests__/helpers/subagent-service-mocks.ts +137 -0
  78. package/src/execution/__tests__/keep-alive-no-progress.test.ts +280 -0
  79. package/src/execution/__tests__/kill-all-escalation.test.ts +196 -0
  80. package/src/execution/__tests__/lifecycle-manager-idle-timer-identity.test.ts +117 -0
  81. package/src/execution/__tests__/lifecycle-manager.test.ts +39 -0
  82. package/src/execution/__tests__/lifecycle-predicates.test.ts +1 -2
  83. package/src/execution/__tests__/manifest-parentid.test.ts +4 -4
  84. package/src/execution/__tests__/manifest-store-tmp-recovery.test.ts +99 -0
  85. package/src/execution/__tests__/max-turns-to-watchdog-ms.test.ts +113 -0
  86. package/src/execution/__tests__/model-resolver.test.ts +2 -2
  87. package/src/execution/__tests__/nested-visibility-env-propagation.test.ts +23 -121
  88. package/src/execution/__tests__/nested-visibility.test.ts +2 -0
  89. package/src/execution/__tests__/notify-ledger.test.ts +1249 -0
  90. package/src/execution/__tests__/output-collector.test.ts +117 -6
  91. package/src/execution/__tests__/pi-invocation.test.ts +1 -1
  92. package/src/execution/__tests__/record-store-orphan-revive.test.ts +159 -0
  93. package/src/execution/__tests__/record-store.test.ts +89 -5
  94. package/src/execution/__tests__/records-cwd-isolation.test.ts +2 -2
  95. package/src/execution/__tests__/recursive-visibility-baseline.test.ts +29 -132
  96. package/src/execution/__tests__/recursive-visibility-env.test.ts +55 -179
  97. package/src/execution/__tests__/rpc-mode.test.ts +2 -2
  98. package/src/execution/__tests__/run-and-finalize-anchoring.test.ts +387 -0
  99. package/src/execution/__tests__/run-and-finalize-chatmode.test.ts +19 -9
  100. package/src/execution/__tests__/run-spawn-chatmode-settled.test.ts +5 -4
  101. package/src/execution/__tests__/run-spawn-edges.test.ts +418 -26
  102. package/src/execution/__tests__/run-spawn-integration.test.ts +3 -3
  103. package/src/execution/__tests__/run-spawn-resume.test.ts +2 -2
  104. package/src/execution/__tests__/run-spawn-rpc-mode.test.ts +2 -2
  105. package/src/execution/__tests__/run-spawn-stdout-callback-throw.test.ts +16 -8
  106. package/src/execution/__tests__/service-kill-escalation.test.ts +91 -0
  107. package/src/execution/__tests__/session-context-resolver.test.ts +0 -2
  108. package/src/execution/__tests__/session-file-gc.test.ts +35 -0
  109. package/src/execution/__tests__/session-pending.test.ts +471 -0
  110. package/src/execution/__tests__/session-reconstructor.test.ts +366 -15
  111. package/src/execution/__tests__/session-runner-branch-cache-lru.test.ts +110 -0
  112. package/src/execution/__tests__/session-runner-close-prune.test.ts +181 -0
  113. package/src/execution/__tests__/session-runner-dispatch.test.ts +489 -0
  114. package/src/execution/__tests__/session-runner-epipe.test.ts +4 -3
  115. package/src/execution/__tests__/session-runner-heartbeat-idle-fallback.test.ts +227 -0
  116. package/src/execution/__tests__/session-runner-lifecycle-helpers.test.ts +290 -0
  117. package/src/execution/__tests__/session-runner-schema-env.test.ts +7 -5
  118. package/src/execution/__tests__/settled-watchdog.test.ts +524 -0
  119. package/src/execution/__tests__/spawn-args.test.ts +11 -10
  120. package/src/execution/__tests__/spawn-event-adapter-rpc.test.ts +26 -23
  121. package/src/execution/__tests__/spawn-event-adapter.test.ts +1 -1
  122. package/src/execution/__tests__/spawn-worktree-guidance.test.ts +5 -4
  123. package/src/execution/__tests__/spawned-children.test.ts +155 -11
  124. package/src/execution/__tests__/start-sync-model-guard.test.ts +4 -4
  125. package/src/execution/__tests__/stdin-writer.test.ts +6 -4
  126. package/src/execution/__tests__/stream-sink-retirement.test.ts +6 -6
  127. package/src/execution/__tests__/subagent-actions-core.test.ts +1017 -0
  128. package/src/execution/__tests__/subagent-service-message-close.test.ts +99 -35
  129. package/src/execution/__tests__/subagent-service-multiproc-guard.test.ts +174 -0
  130. package/src/execution/__tests__/subagent-service-notify-gate.test.ts +271 -0
  131. package/src/execution/__tests__/subagent-service-parent-guard.test.ts +33 -29
  132. package/src/execution/__tests__/subagent-service-recovery-bounds.test.ts +341 -0
  133. package/src/execution/__tests__/subagent-service.test.ts +37 -30
  134. package/src/execution/__tests__/subprocess-agent-runner-routing.test.ts +88 -12
  135. package/src/execution/__tests__/subprocess-agent-runner-timeout.test.ts +75 -0
  136. package/src/execution/__tests__/subprocess-agent-runner.test.ts +22 -20
  137. package/src/execution/__tests__/temp-prompt.test.ts +1 -1
  138. package/src/execution/__tests__/timeout-integration.test.ts +13 -12
  139. package/src/execution/__tests__/turn-limiter-semantics.test.ts +1 -1
  140. package/src/execution/__tests__/turn-limiter.test.ts +1 -1
  141. package/src/execution/__tests__/ui-request-handler-factory.test.ts +107 -7
  142. package/src/execution/__tests__/ui-request-handler.test.ts +4 -3
  143. package/src/execution/__tests__/ui-request-queue.test.ts +167 -2
  144. package/src/execution/__tests__/worktree-git-ops.test.ts +571 -0
  145. package/src/execution/__tests__/worktree-manager.test.ts +14 -5
  146. package/src/execution/__tests__/worktree-pid-registration.integration.test.ts +4 -3
  147. package/src/execution/__tests__/worktree-reconcile-aging.test.ts +204 -0
  148. package/src/execution/agent-registry.ts +298 -30
  149. package/src/execution/agent-result-mapper.ts +3 -0
  150. package/src/execution/agents-assembly.ts +88 -0
  151. package/src/execution/cold-resurrect.ts +199 -0
  152. package/src/execution/concurrency-pool.ts +71 -9
  153. package/src/execution/dialog-queue.ts +101 -3
  154. package/src/execution/engine/__tests__/common/capability-gate.test.ts +91 -0
  155. package/src/execution/engine/__tests__/common/data-dir.test.ts +1 -1
  156. package/src/execution/engine/__tests__/common/journal-wiring.test.ts +84 -0
  157. package/src/execution/engine/__tests__/common/kill-chain.test.ts +34 -7
  158. package/src/execution/engine/__tests__/common/persona-router.test.ts +4 -5
  159. package/src/execution/engine/__tests__/common/pool-manager.test.ts +211 -51
  160. package/src/execution/engine/__tests__/common/session-view-service-zcode-dbpath.test.ts +149 -0
  161. package/src/execution/engine/__tests__/common/session-view-service.test.ts +499 -0
  162. package/src/execution/engine/__tests__/conformance/contract.abort.test.ts +56 -99
  163. package/src/execution/engine/__tests__/conformance/contract.agent-events.test.ts +88 -15
  164. package/src/execution/engine/__tests__/conformance/engine-conformance.live.test.ts +33 -7
  165. package/src/execution/engine/__tests__/conformance/golden-replay.pi.test.ts +1 -1
  166. package/src/execution/engine/__tests__/conformance/golden-replay.zcode.test.ts +75 -54
  167. package/src/execution/engine/__tests__/conformance/zcode-appserver-harness.ts +128 -0
  168. package/src/execution/engine/__tests__/engine-discovery.test.ts +15 -3
  169. package/src/execution/engine/__tests__/model-prompt.test.ts +15 -3
  170. package/src/execution/engine/__tests__/registry.test.ts +94 -3
  171. package/src/execution/engine/__tests__/routing.test.ts +115 -6
  172. package/src/execution/engine/common/capability-gate.ts +92 -0
  173. package/src/execution/engine/common/journal-wiring.ts +97 -0
  174. package/src/execution/engine/common/kill-chain.ts +42 -10
  175. package/src/execution/engine/common/nesting-guard.ts +66 -0
  176. package/src/execution/engine/common/persona-router.ts +18 -8
  177. package/src/execution/engine/common/pool-manager.ts +332 -78
  178. package/src/execution/engine/common/session-view-service.ts +506 -0
  179. package/src/execution/engine/common/session-view-types.ts +125 -0
  180. package/src/execution/engine/engine-discovery.ts +12 -16
  181. package/src/execution/engine/engines/pi/__tests__/pi-engine.test.ts +174 -28
  182. package/src/execution/engine/engines/pi/__tests__/spawn-opts-direct.test.ts +257 -0
  183. package/src/execution/{argv-mirror.ts → engine/engines/pi/argv-mirror.ts} +43 -21
  184. package/src/execution/{get-state-handshake.ts → engine/engines/pi/get-state-handshake.ts} +86 -11
  185. package/src/execution/{output-collector.ts → engine/engines/pi/output-collector.ts} +108 -19
  186. package/src/execution/engine/engines/pi/pi-engine.ts +434 -38
  187. package/src/execution/{pi-invocation.ts → engine/engines/pi/pi-invocation.ts} +2 -2
  188. package/src/execution/engine/engines/pi/reader.ts +11 -0
  189. package/src/execution/engine/engines/pi/registration.ts +4 -2
  190. package/src/execution/engine/engines/pi/session-runner.ts +2840 -0
  191. package/src/execution/{spawn-event-adapter.ts → engine/engines/pi/spawn-event-adapter.ts} +75 -34
  192. package/src/execution/{stdin-writer.ts → engine/engines/pi/stdin-writer.ts} +10 -9
  193. package/src/execution/{temp-prompt.ts → engine/engines/pi/temp-prompt.ts} +2 -2
  194. package/src/execution/{turn-limiter.ts → engine/engines/pi/turn-limiter.ts} +1 -1
  195. package/src/execution/engine/engines/zcode/__tests__/__fixtures__/fake-appserver.mjs +301 -0
  196. package/src/execution/engine/engines/zcode/__tests__/__fixtures__/zcode-golden-appserver.json +36 -0
  197. package/src/execution/engine/engines/zcode/__tests__/appserver-launcher.test.ts +321 -0
  198. package/src/execution/engine/engines/zcode/__tests__/connection.test.ts +473 -0
  199. package/src/execution/engine/engines/zcode/__tests__/parser.test.ts +7 -210
  200. package/src/execution/engine/engines/zcode/__tests__/preparer.test.ts +6 -110
  201. package/src/execution/engine/engines/zcode/__tests__/session-channel-dispose-harvest.test.ts +247 -0
  202. package/src/execution/engine/engines/zcode/__tests__/session-channel-turn-timers.test.ts +451 -0
  203. package/src/execution/engine/engines/zcode/__tests__/session-channel.test.ts +792 -0
  204. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-appserver.test.ts +782 -0
  205. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-degrade.test.ts +168 -0
  206. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-dispose.test.ts +210 -0
  207. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-retry.test.ts +353 -0
  208. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-status.test.ts +282 -0
  209. package/src/execution/engine/engines/zcode/__tests__/zcode-engine-timeout.test.ts +372 -0
  210. package/src/execution/engine/engines/zcode/__tests__/zcode-engine.live.test.ts +65 -47
  211. package/src/execution/engine/engines/zcode/appserver-launcher.ts +167 -0
  212. package/src/execution/engine/engines/zcode/connection.ts +598 -0
  213. package/src/execution/engine/engines/zcode/constants.ts +147 -14
  214. package/src/execution/engine/engines/zcode/golden-sample.ts +42 -34
  215. package/src/execution/engine/engines/zcode/parser.ts +12 -346
  216. package/src/execution/engine/engines/zcode/preparer.ts +22 -150
  217. package/src/execution/engine/engines/zcode/session-channel.ts +968 -0
  218. package/src/execution/engine/engines/zcode/zcode-engine.ts +1023 -250
  219. package/src/execution/engine/host-task-spec.ts +32 -36
  220. package/src/execution/engine/model-validation.ts +177 -0
  221. package/src/execution/engine/port.ts +65 -7
  222. package/src/execution/engine/registry.ts +53 -0
  223. package/src/execution/engine/routing.ts +75 -1
  224. package/src/execution/engine/types.ts +30 -103
  225. package/src/execution/execution-record.ts +222 -144
  226. package/src/execution/finalize-record.ts +181 -85
  227. package/src/execution/idle-gc.ts +28 -0
  228. package/src/execution/lifecycle-manager.ts +27 -3
  229. package/src/execution/lifecycle-predicates.ts +1 -1
  230. package/src/execution/manifest-store.ts +53 -62
  231. package/src/execution/notifier.ts +10 -10
  232. package/src/execution/notify-host.ts +212 -0
  233. package/src/execution/notify-ledger.ts +117 -16
  234. package/src/execution/record-entry.ts +8 -2
  235. package/src/execution/record-store.ts +148 -88
  236. package/src/execution/round-settlement.ts +93 -0
  237. package/src/execution/session-file-gc.ts +96 -62
  238. package/src/execution/session-pending.ts +213 -62
  239. package/src/execution/session-reconstructor.ts +256 -143
  240. package/src/execution/sessions-index.ts +127 -102
  241. package/src/execution/settled-watchdog.ts +311 -0
  242. package/src/execution/subagent-actions-core.ts +686 -0
  243. package/src/execution/subagent-service.ts +1106 -907
  244. package/src/execution/subprocess-agent-runner.ts +144 -97
  245. package/src/execution/types.ts +9 -0
  246. package/src/execution/ui-request-handler-factory.ts +126 -75
  247. package/src/execution/ui-request-queue.ts +50 -19
  248. package/src/execution/worktree-git-ops.ts +397 -0
  249. package/src/execution/worktree-manager.ts +72 -10
  250. package/src/execution/worktree-registry.ts +6 -12
  251. package/src/index.ts +542 -9
  252. package/src/orchestration/__tests__/__fixtures__/worker-template.snapshot.txt +42 -3
  253. package/src/orchestration/__tests__/agent-call-catch-fallback.test.ts +3 -5
  254. package/src/orchestration/__tests__/agent-call-stream.test.ts +2 -2
  255. package/src/orchestration/__tests__/args-meta.test.ts +358 -0
  256. package/src/orchestration/__tests__/args-validator.test.ts +14 -0
  257. package/src/orchestration/__tests__/error-recovery-rebuild-failure.test.ts +312 -0
  258. package/src/orchestration/__tests__/error-recovery-terminal-hardening.test.ts +384 -0
  259. package/src/orchestration/__tests__/execute-agent-call.test.ts +151 -11
  260. package/src/orchestration/__tests__/file-run-store-prune.test.ts +168 -0
  261. package/src/orchestration/__tests__/file-run-store-throttle.test.ts +168 -0
  262. package/src/orchestration/__tests__/file-run-store.test.ts +390 -0
  263. package/src/orchestration/__tests__/helpers/flush-microtasks.ts +13 -0
  264. package/src/orchestration/__tests__/launcher-nested-workflow.test.ts +34 -0
  265. package/src/orchestration/__tests__/lifecycle-abort-broadcast-signal.test.ts +357 -0
  266. package/src/orchestration/__tests__/lifecycle-recover-crashed.test.ts +289 -0
  267. package/src/orchestration/__tests__/lifecycle-runid-injection.test.ts +3 -3
  268. package/src/orchestration/__tests__/lifecycle.test.ts +84 -5
  269. package/src/orchestration/__tests__/non-cloneable-return-e2e.test.ts +1 -1
  270. package/src/orchestration/__tests__/run-snapshot.test.ts +356 -0
  271. package/src/orchestration/__tests__/script-generate.test.ts +314 -0
  272. package/src/orchestration/__tests__/script-lint.test.ts +17 -0
  273. package/src/orchestration/__tests__/test-mocks.ts +2 -0
  274. package/src/orchestration/__tests__/worker-exit-without-result.test.ts +7 -6
  275. package/src/orchestration/__tests__/worker-message-pump-finalize-run.test.ts +229 -0
  276. package/src/orchestration/__tests__/{error-recovery-handlers.test.ts → worker-message-pump-handlers.test.ts} +28 -27
  277. package/src/orchestration/__tests__/{error-recovery-postmessage-defense.test.ts → worker-message-pump-postmessage-defense.test.ts} +8 -8
  278. package/src/orchestration/__tests__/{error-recovery-serialize-failed-result.test.ts → worker-message-pump-serialize-failed-result.test.ts} +2 -2
  279. package/src/orchestration/__tests__/{error-recovery-workflow-call.test.ts → worker-message-pump-workflow-call.test.ts} +1 -1
  280. package/src/orchestration/__tests__/worker-pending-timeout-abort.test.ts +275 -0
  281. package/src/orchestration/__tests__/worker-script-builder-runtime.test.ts +78 -1
  282. package/src/orchestration/__tests__/worker-script-builder.test.ts +1 -1
  283. package/src/orchestration/__tests__/workflow-files.test.ts +186 -0
  284. package/src/orchestration/__tests__/workflow-nesting-e2e.test.ts +1 -1
  285. package/src/orchestration/__tests__/workflow-run-summary.test.ts +119 -0
  286. package/src/orchestration/__tests__/workflow-script-registry-impl.test.ts +124 -0
  287. package/src/orchestration/agent-opts-resolver.ts +8 -8
  288. package/src/orchestration/args-meta.ts +198 -0
  289. package/src/orchestration/args-validator.ts +53 -31
  290. package/src/orchestration/execute-agent-call.ts +25 -79
  291. package/src/orchestration/file-run-store.ts +327 -0
  292. package/src/orchestration/launcher.ts +160 -104
  293. package/src/orchestration/lifecycle.ts +371 -97
  294. package/src/orchestration/models/agent-call.ts +7 -7
  295. package/src/orchestration/models/budget.ts +5 -5
  296. package/src/orchestration/models/ports.ts +4 -4
  297. package/src/orchestration/models/run-runtime.ts +15 -15
  298. package/src/orchestration/models/trace.ts +9 -9
  299. package/src/orchestration/models/types.ts +111 -22
  300. package/src/orchestration/models/workflow-run.ts +28 -28
  301. package/src/orchestration/models/workflow-script.ts +4 -4
  302. package/src/orchestration/run-snapshot.ts +266 -0
  303. package/src/orchestration/script-generate.ts +154 -0
  304. package/src/orchestration/script-lint.ts +123 -90
  305. package/src/orchestration/worker-handle.ts +10 -10
  306. package/src/orchestration/worker-host.ts +10 -10
  307. package/src/orchestration/{error-recovery.ts → worker-message-pump.ts} +498 -221
  308. package/src/orchestration/worker-script-builder.ts +401 -346
  309. package/src/orchestration/workflow-files.ts +37 -11
  310. package/src/orchestration/workflow-run-summary.ts +69 -0
  311. package/src/orchestration/workflow-script-registry-impl.ts +31 -9
  312. package/src/shared/__tests__/agent-ref.test.ts +209 -2
  313. package/src/shared/__tests__/atomic-write.test.ts +267 -0
  314. package/src/shared/__tests__/bounded-serialize.test.ts +236 -0
  315. package/src/shared/__tests__/injection-render.test.ts +518 -0
  316. package/src/shared/__tests__/meta-parser.test.ts +151 -0
  317. package/src/shared/__tests__/resource-discovery-host-roots.test.ts +474 -0
  318. package/src/shared/__tests__/resource-discovery.test.ts +261 -217
  319. package/src/shared/agent-ref.ts +143 -2
  320. package/src/shared/atomic-write.ts +323 -0
  321. package/src/shared/bounded-serialize.ts +154 -0
  322. package/src/shared/injection-render.ts +279 -0
  323. package/src/shared/meta-parser.ts +182 -68
  324. package/src/shared/model-ref.ts +15 -2
  325. package/src/shared/resource-discovery.ts +97 -204
  326. package/src/shared/resource-meta.ts +14 -0
  327. package/src/shared/schema-jsonify.ts +1 -1
  328. package/src/shared/xml-injection.ts +9 -9
  329. package/workflows/README.md +9 -9
  330. package/workflows/chain.js +4 -2
  331. package/workflows/map-reduce.js +5 -3
  332. package/workflows/parallel.js +5 -3
  333. package/workflows/review-fix-loop-utils.cjs +165 -92
  334. package/workflows/review-fix-loop-utils.d.cts +287 -0
  335. package/workflows/review-fix-loop.js +18 -7
  336. package/workflows/scatter-gather.js +4 -2
  337. package/dist/chunk-3VOERJPJ.js +0 -22
  338. package/src/execution/__tests__/execute-options-mapper.test.ts +0 -200
  339. package/src/execution/engine/engines/pi/__tests__/task-spec-mapper.test.ts +0 -164
  340. package/src/execution/engine/engines/pi/task-spec-mapper.ts +0 -100
  341. package/src/execution/engine/engines/zcode/__tests__/__fixtures__/zcode-golden-spawn.json +0 -39
  342. package/src/execution/engine/engines/zcode/__tests__/launcher.test.ts +0 -150
  343. package/src/execution/engine/engines/zcode/__tests__/zcode-engine.test.ts +0 -580
  344. package/src/execution/engine/engines/zcode/launcher.ts +0 -161
  345. package/src/execution/execute-options-mapper.ts +0 -115
  346. package/src/execution/session-runner.ts +0 -1789
  347. package/src/shared/__tests__/resource-discovery-manifest-cache.test.ts +0 -288
@@ -274,39 +274,16 @@ interface PendingToolCall {
274
274
  }
275
275
 
276
276
  // ============================================================
277
- // 公开函数
277
+ // 全量重建内部 helper(按处理阶段拆分:读文件 → 扫身份 → 重建 turns → 组装)
278
278
  // ============================================================
279
279
 
280
280
  /**
281
- * session.jsonl 重建完整 SubagentRecord 数据。
282
- *
283
- * ╔══════════════════════════════════════════════════════════════════╗
284
- * ║ 1. readFileSync(sessionFile) + 逐行 JSON.parse(跳 header) ║
285
- * ║ (损坏行静默跳过;失败 → undefined) ║
286
- * ║ 2. 扫 custom entry(customType:"subagent-identity")→ 身份 ║
287
- * ║ 缺 identity → undefined(无法构造 record) ║
288
- * ║ 3. 顺序遍历 message entries: ║
289
- * ║ - role:"assistant" → 开新 Turn ║
290
- * ║ text/thinking 累积;usage → usageDelta ║
291
- * ║ toolCall block → 待匹配队列;stopReason error → lastError ║
292
- * ║ - role:"toolResult" → 配对 toolCallId ║
293
- * ║ 产 InternalToolCall(done/failed)推进请求 Turn ║
294
- * ║ 4. 闭合所有 turn;算 turnCount/totalTokens/result/eventLog ║
295
- * ╚══════════════════════════════════════════════════════════════════╝
296
- *
297
- * 返回 undefined:文件缺失/空/损坏/缺 identity entry/无 assistant message。
298
- * 不抛——消费方(collectRecords)降级跳过该 record。
299
- *
300
- * status 由最后一条 assistant message 的 stopReason 推导(error/aborted → failed,
301
- * 其余 → done)。cancelled 由 tombstone override(record-store 层),本函数不感知。
302
- *
303
- * [perf] 本函数是重路径(全文读 + 全 entry 解析)。列表扫描用 readIdentityHeader
304
- * (只读头部 identity),详情才走本函数(RecordStore.getFullRecord 懒加载)。
281
+ * 读文件 + 逐行 JSON.parse(session.jsonl = newline-delimited JSON)。
282
+ * 第 1 行是 session header(type:"session",跳过);后续每行一个 entry。
283
+ * 损坏行静默跳过(与 SDK parseSessionEntries 行为一致)。
284
+ * @returns 文件缺失/读失败 undefined;否则 entry 数组(可能为空)。
305
285
  */
306
- export function reconstructFromFile(sessionFile: string): ReconstructedRecord | undefined {
307
- // 读文件 + 逐行 JSON.parse(session.jsonl = newline-delimited JSON)。
308
- // 第 1 行是 session header(跳过);后续每行一个 entry。
309
- // 损坏行静默跳过(与 SDK parseSessionEntries 行为一致)。
286
+ function readJsonlEntries(sessionFile: string): JsonlEntry[] | undefined {
310
287
  let raw: string;
311
288
  try {
312
289
  raw = fs.readFileSync(sessionFile, "utf-8");
@@ -338,10 +315,18 @@ export function reconstructFromFile(sessionFile: string): ReconstructedRecord |
338
315
  void _e; // 损坏行跳过(不阻断后续行)。
339
316
  }
340
317
  }
318
+ return entries;
319
+ }
341
320
 
342
- if (entries.length === 0) return undefined;
321
+ /** 身份/模型扫描产出(identity custom entry + 途经的 model/thinking_level change)。 */
322
+ interface IdentityScan {
323
+ identity: SubagentIdentityData | undefined;
324
+ model: string;
325
+ thinkingLevel: string | undefined;
326
+ }
343
327
 
344
- // ── 扫身份 custom entry(必须存在,否则无法构造 record)──
328
+ /** identity custom entry(必须存在,否则无法构造 record)+ 途经 model/thinking_level。 */
329
+ function scanIdentityAndModel(entries: JsonlEntry[]): IdentityScan {
345
330
  let identity: SubagentIdentityData | undefined;
346
331
  let model = "";
347
332
  let thinkingLevel: string | undefined;
@@ -357,14 +342,95 @@ export function reconstructFromFile(sessionFile: string): ReconstructedRecord |
357
342
  if (typeof entry.thinkingLevel === "string") thinkingLevel = entry.thinkingLevel;
358
343
  }
359
344
  }
360
- if (!identity) return undefined; // 缺身份 无法构造 record。
345
+ return { identity, model, thinkingLevel };
346
+ }
347
+
348
+ /** message entries 重建产出(turns + 跨 entry 累积状态)。 */
349
+ interface RebuiltTurns {
350
+ turns: Turn[];
351
+ lastError: string | undefined;
352
+ totalTokens: number;
353
+ /** 最后一条 entry 的时间戳(ms),推导 endedAt(避免重建 record 耗时随墙钟无限增长)。 */
354
+ lastEntryTsMs: number | undefined;
355
+ }
356
+
357
+ /**
358
+ * assistant message → 填充调用方已创建的空 Turn:text/thinking 累积;toolCall block 进
359
+ * 待匹配队列;usage → usageDelta(token 总量增量返回给调用方累加)。
360
+ *
361
+ * stopReason 语义(与 updateFromEvent 一致):error/aborted → 设 lastError;
362
+ * stop(正常结束)→ 清 lastError(镜像 turn_end 的清除语义,即前序 turn 的瞬态
363
+ * error 在后续成功 turn 后恢复,不误判 success=false);其余 stopReason → 保持
364
+ * prevLastError 原值。 [v4 B-1] status 恒 closed 后 lastStopReason 不再参与推导,死变量已删。
365
+ *
366
+ * content 非数组 → 跳过 usage/stopReason 处理(镜像原实现的 continue):turn 仍存在
367
+ * (由调用方 push),lastError 透传 prevLastError、token 增量为 0。
368
+ */
369
+ function applyAssistantMessage(
370
+ msg: JsonlAssistantMessage,
371
+ turn: Turn,
372
+ pending: PendingToolCall[],
373
+ prevLastError: string | undefined,
374
+ ): { lastError: string | undefined; totalTokensDelta: number } {
375
+ if (!Array.isArray(msg.content)) {
376
+ return { lastError: prevLastError, totalTokensDelta: 0 };
377
+ }
378
+ for (const block of msg.content) {
379
+ if (block.type === "text") {
380
+ turn.text += block.text;
381
+ } else if (block.type === "thinking") {
382
+ turn.thinking += block.thinking;
383
+ } else if (block.type === "toolCall") {
384
+ pending.push({
385
+ toolCallId: block.id,
386
+ toolName: block.name,
387
+ args: block.arguments,
388
+ turn,
389
+ startedTs: msg.timestamp,
390
+ });
391
+ }
392
+ }
393
+
394
+ let totalTokensDelta = 0;
395
+ if (msg.usage) {
396
+ const u = toAgentUsage(msg.usage);
397
+ turn.usageDelta = addUsage(turn.usageDelta, u);
398
+ totalTokensDelta = u.input + u.output + u.cacheRead + u.cacheWrite;
399
+ }
400
+
401
+ let lastError = prevLastError;
402
+ if (msg.stopReason === "error" || msg.stopReason === "aborted") {
403
+ lastError = msg.errorMessage ?? msg.stopReason;
404
+ } else if (msg.stopReason === "stop") {
405
+ lastError = undefined;
406
+ }
407
+ return { lastError, totalTokensDelta };
408
+ }
361
409
 
362
- // ── 重建 turns[] ──
410
+ /** toolResult message 按 toolCallId 配对回填 InternalToolCall;未配对(孤儿)→ 丢弃。 */
411
+ function applyToolResultMessage(msg: JsonlToolResultMessage, pending: PendingToolCall[]): void {
412
+ const idx = pending.findIndex((p) => p.toolCallId === msg.toolCallId);
413
+ if (idx >= 0) {
414
+ const p = pending[idx];
415
+ pending.splice(idx, 1);
416
+ const tc: InternalToolCall = {
417
+ toolName: p.toolName,
418
+ args: p.args,
419
+ result: { content: msg.content, details: msg.details },
420
+ isError: msg.isError ?? false,
421
+ _status: msg.isError ? "failed" : "done",
422
+ startedTs: p.startedTs,
423
+ };
424
+ p.turn.toolCalls.push(tc);
425
+ }
426
+ }
427
+
428
+ /** 顺序遍历 entries 重建 turns[](assistant 开 turn / toolResult 配对回填;user 跳过)。 */
429
+ function rebuildTurns(entries: JsonlEntry[]): RebuiltTurns {
363
430
  const turns: Turn[] = [];
364
431
  const pending: PendingToolCall[] = [];
365
432
  let lastError: string | undefined;
366
433
  let totalTokens = 0;
367
- /** 最后一条 entry 的时间戳(ms),推导 endedAt(避免重建 record 耗时随墙钟无限增长)。 */
368
434
  let lastEntryTsMs: number | undefined;
369
435
 
370
436
  for (const entry of entries) {
@@ -383,81 +449,38 @@ export function reconstructFromFile(sessionFile: string): ReconstructedRecord |
383
449
  if (msg.role === "assistant") {
384
450
  const turn = emptyTurn();
385
451
  turns.push(turn);
386
-
387
- if (!Array.isArray(msg.content)) continue;
388
- for (const block of msg.content) {
389
- if (block.type === "text") {
390
- turn.text += block.text;
391
- } else if (block.type === "thinking") {
392
- turn.thinking += block.thinking;
393
- } else if (block.type === "toolCall") {
394
- pending.push({
395
- toolCallId: block.id,
396
- toolName: block.name,
397
- args: block.arguments,
398
- turn,
399
- startedTs: msg.timestamp,
400
- });
401
- }
402
- }
403
-
404
- if (msg.usage) {
405
- const u = toAgentUsage(msg.usage);
406
- turn.usageDelta = addUsage(turn.usageDelta, u);
407
- totalTokens += u.input + u.output + u.cacheRead + u.cacheWrite;
408
- }
409
-
410
- // stopReason 驱动 lastError(与 updateFromEvent 一致):
411
- // error/aborted → 设 lastError;stop(正常结束)→ 清 lastError(镜像 turn_end 的清除语义,
412
- // 即前序 turn 的瞬态 error 在后续成功 turn 后恢复,不误判 success=false)。
413
- // [v4 B-1] status 恒 closed 后 lastStopReason 不再参与推导,死变量已删。
414
- if (msg.stopReason === "error" || msg.stopReason === "aborted") {
415
- lastError = msg.errorMessage ?? msg.stopReason;
416
- } else if (msg.stopReason === "stop") {
417
- lastError = undefined;
418
- }
452
+ const applied = applyAssistantMessage(msg, turn, pending, lastError);
453
+ totalTokens += applied.totalTokensDelta;
454
+ lastError = applied.lastError;
419
455
  } else if (msg.role === "toolResult") {
420
- const idx = pending.findIndex((p) => p.toolCallId === msg.toolCallId);
421
- if (idx >= 0) {
422
- const p = pending[idx];
423
- pending.splice(idx, 1);
424
- const tc: InternalToolCall = {
425
- toolName: p.toolName,
426
- args: p.args,
427
- result: { content: msg.content, details: msg.details },
428
- isError: msg.isError ?? false,
429
- _status: msg.isError ? "failed" : "done",
430
- startedTs: p.startedTs,
431
- };
432
- p.turn.toolCalls.push(tc);
433
- }
434
- // 未配对(孤儿 toolResult)→ 丢弃。
456
+ applyToolResultMessage(msg, pending);
435
457
  }
436
458
  // role:"user" → 跳过(task 来自 identity custom entry)。
437
459
  }
460
+ return { turns, lastError, totalTokens, lastEntryTsMs };
461
+ }
438
462
 
439
- if (turns.length === 0) return undefined; // assistant message → 空壳,降级。
440
-
441
- // 闭合所有 turn(重建的是历史,全是已完成 turn)。
442
- for (const turn of turns) {
443
- turn.closed = true;
444
- }
445
-
446
- const turnCount = turns.length;
447
- const resultText = turns
448
- .map((t) => t.text)
449
- .filter((t) => t.length > 0)
450
- .join("\n\n");
451
-
452
- // eventLog 从 turns[] 派生(与活态 record 的 getEventLog 同形,消费方无感知差异)。
453
- const eventLog = deriveEventLog(turns, lastError, identity.startedAt);
454
-
463
+ /** 组装 ReconstructedRecord(终态投影:status closed/gc + 身份字段归一化 + 派生数据)。 */
464
+ function buildReconstructedRecord(
465
+ sessionFile: string,
466
+ identity: SubagentIdentityData,
467
+ rebuilt: RebuiltTurns,
468
+ eventLog: AgentEventLogEntry[],
469
+ model: string,
470
+ thinkingLevel: string | undefined,
471
+ ): ReconstructedRecord {
455
472
  // 终态 status:最后一条 assistant message 的 stopReason 推导(与 finalizeRecord 的判定一致)。
456
473
  // SP-1:done/failed 合并为 closed,cancelled 由 tombstone override(record-store 层),本函数不感知。
457
474
  const status: ExecutionStatus = "closed";
458
475
  // closedReason 统 gc(通用完成/失败)。error/aborted 的区分由 error 字段保留。
459
476
  const closedReason: import("./types.ts").ClosedReason = "gc";
460
477
 
478
+ const turnCount = rebuilt.turns.length;
479
+ const resultText = rebuilt.turns
480
+ .map((t) => t.text)
481
+ .filter((t) => t.length > 0)
482
+ .join("\n\n");
483
+
461
484
  // rootSessionId 归一化:新文件读 rootSessionId,旧文件 fallback parentSessionId。
462
485
  const rootSessionId = identity.rootSessionId ?? identity.parentSessionId;
463
486
  // slug 兜底:旧 identity entry 无 slug 字段 → 空串(与 SubagentRecord.slug: string 契约一致)。
@@ -472,19 +495,74 @@ export function reconstructFromFile(sessionFile: string): ReconstructedRecord |
472
495
  sessionFile,
473
496
  status,
474
497
  closedReason,
475
- turns,
498
+ turns: rebuilt.turns,
476
499
  turnCount,
477
- totalTokens,
478
- lastError,
500
+ totalTokens: rebuilt.totalTokens,
501
+ lastError: rebuilt.lastError,
479
502
  model,
480
503
  thinkingLevel,
481
- endedAt: lastEntryTsMs,
504
+ endedAt: rebuilt.lastEntryTsMs,
482
505
  result: resultText.length > 0 ? resultText : undefined,
483
- error: lastError,
506
+ error: rebuilt.lastError,
484
507
  eventLog,
485
508
  };
486
509
  }
487
510
 
511
+ // ============================================================
512
+ // 公开函数
513
+ // ============================================================
514
+
515
+ /**
516
+ * 从 session.jsonl 重建完整 SubagentRecord 数据。
517
+ *
518
+ * ╔══════════════════════════════════════════════════════════════════╗
519
+ * ║ 1. readFileSync(sessionFile) + 逐行 JSON.parse(跳 header) ║
520
+ * ║ (损坏行静默跳过;失败 → undefined) ║
521
+ * ║ 2. 扫 custom entry(customType:"subagent-identity")→ 身份 ║
522
+ * ║ 缺 identity → undefined(无法构造 record) ║
523
+ * ║ 3. 顺序遍历 message entries: ║
524
+ * ║ - role:"assistant" → 开新 Turn ║
525
+ * ║ text/thinking 累积;usage → usageDelta ║
526
+ * ║ toolCall block → 待匹配队列;stopReason error → lastError ║
527
+ * ║ - role:"toolResult" → 配对 toolCallId ║
528
+ * ║ 产 InternalToolCall(done/failed)推进请求 Turn ║
529
+ * ║ 4. 闭合所有 turn;算 turnCount/totalTokens/result/eventLog ║
530
+ * ╚══════════════════════════════════════════════════════════════════╝
531
+ *
532
+ * 返回 undefined:文件缺失/空/损坏/缺 identity entry/无 assistant message。
533
+ * 不抛——消费方(collectRecords)降级跳过该 record。
534
+ *
535
+ * status 由最后一条 assistant message 的 stopReason 推导(error/aborted → failed,
536
+ * 其余 → done)。cancelled 由 tombstone override(record-store 层),本函数不感知。
537
+ *
538
+ * [perf] 本函数是重路径(全文读 + 全 entry 解析)。列表扫描用 readIdentityHeader
539
+ * (只读头部 identity),详情才走本函数(RecordStore.getFullRecord 懒加载)。
540
+ */
541
+ export function reconstructFromFile(sessionFile: string): ReconstructedRecord | undefined {
542
+ // 1. 读文件 + 逐行 JSON.parse(readJsonlEntries:损坏行静默跳过;文件缺失 → undefined)。
543
+ const entries = readJsonlEntries(sessionFile);
544
+ if (!entries || entries.length === 0) return undefined;
545
+
546
+ // 2. 扫身份 custom entry(scanIdentityAndModel:identity 缺失 → 无法构造 record)。
547
+ const { identity, model, thinkingLevel } = scanIdentityAndModel(entries);
548
+ if (!identity) return undefined; // 缺身份 → 无法构造 record。
549
+
550
+ // 3. 重建 turns[](rebuildTurns:assistant 开 turn / toolResult 配对回填)。
551
+ const rebuilt = rebuildTurns(entries);
552
+ if (rebuilt.turns.length === 0) return undefined; // 无 assistant message → 空壳,降级。
553
+
554
+ // 4. 闭合所有 turn(重建的是历史,全是已完成 turn)。
555
+ for (const turn of rebuilt.turns) {
556
+ turn.closed = true;
557
+ }
558
+
559
+ // eventLog 从 turns[] 派生(与活态 record 的 getEventLog 同形,消费方无感知差异)。
560
+ // 必须在闭合 turn 之后派生(deriveEventLog 读 turn.closed)。
561
+ const eventLog = deriveEventLog(rebuilt.turns, rebuilt.lastError, identity.startedAt);
562
+
563
+ return buildReconstructedRecord(sessionFile, identity, rebuilt, eventLog, model, thinkingLevel);
564
+ }
565
+
488
566
  // ============================================================
489
567
  // 轻量头部读取(列表扫描用)
490
568
  // ============================================================
@@ -615,48 +693,62 @@ export function readIdentityTail(sessionFile: string): IdentityHeaderRecon | und
615
693
  return undefined;
616
694
  }
617
695
 
618
- /** 从文本片段解析 identity(头部/全文两入口共享)。解析到 identity 即停(返回);
619
- * 找不到返回 undefined。model/thinking_level 仅在 identity 之前的途经 entry
620
- * best-effort 提取,详情场景由全量重建补齐。 */
621
- function parseIdentityFromText(text: string, sessionFile: string): IdentityHeaderRecon | undefined {
622
- let identity: SubagentIdentityData | undefined;
623
- let model = "";
624
- let thinkingLevel: string | undefined;
625
- for (const line of text.split("\n")) {
626
- const s = line.trim();
627
- if (!s) continue;
628
- // 预筛([S-4] 同款值匹配):只有含三种目标 entry 值串的行才值得 JSON.parse——
629
- // head 64KB 内大 toolResult 行(数十 KB/行)占多数,全量 parse 是冷扫描 CPU 大头。
630
- // 值字符串在任意序列化格式下连续出现,不耦合 pi 的空格习惯。
631
- if (
632
- !s.includes(IDENTITY_CUSTOM_TYPE) &&
633
- !s.includes('"model_change"') &&
634
- !s.includes('"thinking_level_change"')
635
- ) {
636
- continue;
637
- }
638
- let entry: JsonlEntry;
639
- try {
640
- entry = JSON.parse(s) as JsonlEntry;
641
- } catch {
642
- continue; // 损坏行/截断行(头部读取边界)跳过
696
+ // ============================================================
697
+ // 轻量 identity 扫描内部 helper(parseIdentityFromText 按阶段分发)
698
+ // ============================================================
699
+
700
+ /**
701
+ * 预筛([S-4] 同款值匹配):只有含三种目标 entry 值串的行才值得 JSON.parse——
702
+ * head 64KB 内大 toolResult 行(数十 KB/行)占多数,全量 parse 是冷扫描 CPU 大头。
703
+ * 值字符串在任意序列化格式下连续出现,不耦合 pi 的空格习惯。
704
+ */
705
+ function lineMayCarryScannableEntry(s: string): boolean {
706
+ return (
707
+ s.includes(IDENTITY_CUSTOM_TYPE) ||
708
+ s.includes('"model_change"') ||
709
+ s.includes('"thinking_level_change"')
710
+ );
711
+ }
712
+
713
+ /** 轻量扫描的可变累积态(identity + 途经 model/thinkingLevel)。 */
714
+ interface LightIdentityScan {
715
+ identity: SubagentIdentityData | undefined;
716
+ model: string;
717
+ thinkingLevel: string | undefined;
718
+ }
719
+
720
+ /**
721
+ * 单条 entry 并入扫描态。identity 命中(custom + customType 匹配 + data 合法)返回
722
+ * true 供调用方 break(找到即停,后续行不再解析);其余恒 false。三个目标 type 互斥,
723
+ * 与原 if/else-if 链语义一致;custom 但 data 非法 → 不并入、不中断扫描。
724
+ */
725
+ function absorbScannedEntry(state: LightIdentityScan, entry: JsonlEntry): boolean {
726
+ if (entry.type === "custom" && entry.customType === IDENTITY_CUSTOM_TYPE) {
727
+ if (isIdentityData(entry.data)) {
728
+ state.identity = entry.data;
729
+ return true;
643
730
  }
644
- if (entry.type === "custom" && entry.customType === IDENTITY_CUSTOM_TYPE) {
645
- if (isIdentityData(entry.data)) {
646
- identity = entry.data;
647
- break; // 找到即停(后续行不再解析)
648
- }
649
- } else if (entry.type === "model_change") {
650
- if (typeof entry.provider === "string" && typeof entry.modelId === "string") {
651
- model = `${entry.provider}/${entry.modelId}`;
652
- }
653
- } else if (entry.type === "thinking_level_change") {
654
- if (typeof entry.thinkingLevel === "string") thinkingLevel = entry.thinkingLevel;
731
+ return false;
732
+ }
733
+ if (entry.type === "model_change") {
734
+ // model_change: {provider, modelId} → "provider/modelId"(与 record.model 同形)。
735
+ if (typeof entry.provider === "string" && typeof entry.modelId === "string") {
736
+ state.model = `${entry.provider}/${entry.modelId}`;
655
737
  }
738
+ return false;
739
+ }
740
+ if (entry.type === "thinking_level_change") {
741
+ if (typeof entry.thinkingLevel === "string") state.thinkingLevel = entry.thinkingLevel;
656
742
  }
657
- if (!identity) return undefined;
743
+ return false;
744
+ }
658
745
 
659
- // 归一化与全量 recon 同源:rootSessionId fallback 旧字段、slug 兜底空串。
746
+ /** 扫描态 → IdentityHeaderRecon(归一化与全量 recon 同源:rootSessionId fallback 旧字段、slug 兜底空串)。 */
747
+ function toIdentityRecon(
748
+ state: LightIdentityScan,
749
+ identity: SubagentIdentityData,
750
+ sessionFile: string,
751
+ ): IdentityHeaderRecon {
660
752
  const rootSessionId = identity.rootSessionId ?? identity.parentSessionId;
661
753
  return {
662
754
  id: identity.id,
@@ -671,8 +763,29 @@ function parseIdentityFromText(text: string, sessionFile: string): IdentityHeade
671
763
  forkDepth: identity.forkDepth,
672
764
  chatMode: identity.chatMode,
673
765
  worktree: identity.worktree,
674
- model,
675
- thinkingLevel,
766
+ model: state.model,
767
+ thinkingLevel: state.thinkingLevel,
676
768
  sessionFile,
677
769
  };
678
770
  }
771
+
772
+ /** 从文本片段解析 identity(头部/全文两入口共享)。解析到 identity 即停(返回);
773
+ * 找不到返回 undefined。model/thinking_level 仅在 identity 之前的途经 entry 中
774
+ * best-effort 提取,详情场景由全量重建补齐。 */
775
+ function parseIdentityFromText(text: string, sessionFile: string): IdentityHeaderRecon | undefined {
776
+ const state: LightIdentityScan = { identity: undefined, model: "", thinkingLevel: undefined };
777
+ for (const line of text.split("\n")) {
778
+ const s = line.trim();
779
+ if (!s) continue;
780
+ if (!lineMayCarryScannableEntry(s)) continue;
781
+ let entry: JsonlEntry;
782
+ try {
783
+ entry = JSON.parse(s) as JsonlEntry;
784
+ } catch {
785
+ continue; // 损坏行/截断行(头部读取边界)跳过
786
+ }
787
+ if (absorbScannedEntry(state, entry)) break; // 找到即停(后续行不再解析)
788
+ }
789
+ if (!state.identity) return undefined;
790
+ return toIdentityRecon(state, state.identity, sessionFile);
791
+ }