@ashx-j/lunr-dev 0.2.19-dev.10.1 → 0.2.21-dev.12.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.
- package/CHANGELOG.md +36 -1
- package/README.md +2 -2
- package/dist/builtin-extensions/index.d.ts.map +1 -1
- package/dist/builtin-extensions/index.js +0 -2
- package/dist/builtin-extensions/index.js.map +1 -1
- package/dist/builtin-extensions/lunr-computer-use.d.ts.map +1 -1
- package/dist/builtin-extensions/lunr-computer-use.js +15 -14
- package/dist/builtin-extensions/lunr-computer-use.js.map +1 -1
- package/dist/builtin-extensions/lunr-todos.d.ts +6 -5
- package/dist/builtin-extensions/lunr-todos.d.ts.map +1 -1
- package/dist/builtin-extensions/lunr-todos.js +9 -7
- package/dist/builtin-extensions/lunr-todos.js.map +1 -1
- package/dist/builtin-extensions/pi-intercom/broker/spawn.d.ts +6 -4
- package/dist/builtin-extensions/pi-intercom/broker/spawn.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-intercom/broker/spawn.js +114 -61
- package/dist/builtin-extensions/pi-intercom/broker/spawn.js.map +1 -1
- package/dist/builtin-extensions/pi-intercom/index.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-intercom/index.js +360 -351
- package/dist/builtin-extensions/pi-intercom/index.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/fanout-child.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/fanout-child.js +2 -2
- package/dist/builtin-extensions/pi-subagents/src/extension/fanout-child.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/index.d.ts +8 -6
- package/dist/builtin-extensions/pi-subagents/src/extension/index.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/index.js +128 -57
- package/dist/builtin-extensions/pi-subagents/src/extension/index.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/schemas.d.ts +18 -8
- package/dist/builtin-extensions/pi-subagents/src/extension/schemas.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/schemas.js +38 -13
- package/dist/builtin-extensions/pi-subagents/src/extension/schemas.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.d.ts +4 -3
- package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.js +24 -14
- package/dist/builtin-extensions/pi-subagents/src/extension/tool-description.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/intercom/native-supervisor-channel.d.ts +8 -1
- package/dist/builtin-extensions/pi-subagents/src/intercom/native-supervisor-channel.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/intercom/native-supervisor-channel.js +247 -18
- package/dist/builtin-extensions/pi-subagents/src/intercom/native-supervisor-channel.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/intercom/result-intercom.d.ts +1 -0
- package/dist/builtin-extensions/pi-subagents/src/intercom/result-intercom.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/intercom/result-intercom.js +1 -1
- package/dist/builtin-extensions/pi-subagents/src/intercom/result-intercom.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-ask.d.ts +29 -0
- package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-ask.d.ts.map +1 -0
- package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-ask.js +179 -0
- package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-ask.js.map +1 -0
- package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-questions.d.ts +89 -0
- package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-questions.d.ts.map +1 -0
- package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-questions.js +541 -0
- package/dist/builtin-extensions/pi-subagents/src/intercom/supervisor-questions.js.map +1 -0
- package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.d.ts +11 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.js +38 -12
- package/dist/builtin-extensions/pi-subagents/src/runs/background/async-execution.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/async-job-tracker.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/async-job-tracker.js +3 -2
- package/dist/builtin-extensions/pi-subagents/src/runs/background/async-job-tracker.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/async-resume.d.ts +2 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/async-resume.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/async-resume.js +35 -8
- package/dist/builtin-extensions/pi-subagents/src/runs/background/async-resume.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/notify.d.ts +7 -3
- package/dist/builtin-extensions/pi-subagents/src/runs/background/notify.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/notify.js +26 -4
- package/dist/builtin-extensions/pi-subagents/src/runs/background/notify.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/result-watcher.d.ts +1 -0
- package/dist/builtin-extensions/pi-subagents/src/runs/background/result-watcher.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/result-watcher.js +55 -38
- package/dist/builtin-extensions/pi-subagents/src/runs/background/result-watcher.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.d.ts +100 -0
- package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.js +46 -31
- package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-runner.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-wait.d.ts +3 -6
- package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-wait.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-wait.js +64 -5
- package/dist/builtin-extensions/pi-subagents/src/runs/background/subagent-wait.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/top-level-async.d.ts +15 -2
- package/dist/builtin-extensions/pi-subagents/src/runs/background/top-level-async.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/top-level-async.js +14 -4
- package/dist/builtin-extensions/pi-subagents/src/runs/background/top-level-async.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/wait-tool.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/wait-tool.js +2 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/wait-tool.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.js +21 -8
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/chain-execution.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.js +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.d.ts +0 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.js +71 -25
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/acceptance.d.ts +2 -0
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/acceptance.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/acceptance.js +75 -18
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/acceptance.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/completion-guard.d.ts +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/completion-guard.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/completion-guard.js +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/completion-guard.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.d.ts +13 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.js +67 -11
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/model-fallback.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.d.ts +1 -0
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/parallel-utils.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/pi-args.d.ts +3 -0
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/pi-args.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/pi-args.js +7 -2
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/pi-args.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.js +13 -3
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/task-intent.d.ts +2 -2
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/task-intent.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/task-intent.js +5 -10
- package/dist/builtin-extensions/pi-subagents/src/runs/shared/task-intent.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/shared/async-guidance.d.ts +2 -0
- package/dist/builtin-extensions/pi-subagents/src/shared/async-guidance.d.ts.map +1 -0
- package/dist/builtin-extensions/pi-subagents/src/shared/async-guidance.js +3 -0
- package/dist/builtin-extensions/pi-subagents/src/shared/async-guidance.js.map +1 -0
- package/dist/builtin-extensions/pi-subagents/src/shared/child-spec.d.ts +3 -0
- package/dist/builtin-extensions/pi-subagents/src/shared/child-spec.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/shared/child-spec.js +68 -11
- package/dist/builtin-extensions/pi-subagents/src/shared/child-spec.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/shared/formatters.d.ts +12 -1
- package/dist/builtin-extensions/pi-subagents/src/shared/formatters.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/shared/formatters.js +21 -2
- package/dist/builtin-extensions/pi-subagents/src/shared/formatters.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/shared/types.d.ts +21 -4
- package/dist/builtin-extensions/pi-subagents/src/shared/types.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/shared/types.js +1 -1
- package/dist/builtin-extensions/pi-subagents/src/shared/types.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/slash/delegation-adapters.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/slash/delegation-adapters.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.d.ts +7 -0
- package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.js +11 -7
- package/dist/builtin-extensions/pi-subagents/src/slash/prompt-workflows.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.d.ts +6 -0
- package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.js +46 -29
- package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts +46 -4
- package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/tui/render.js +407 -450
- package/dist/builtin-extensions/pi-subagents/src/tui/render.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/watchdog/register-main.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/watchdog/register-main.js +1 -1
- package/dist/builtin-extensions/pi-subagents/src/watchdog/register-main.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/watchdog/tool-actions.d.ts +2 -13
- package/dist/builtin-extensions/pi-subagents/src/watchdog/tool-actions.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/watchdog/tool-actions.js +5 -91
- package/dist/builtin-extensions/pi-subagents/src/watchdog/tool-actions.js.map +1 -1
- package/dist/core/computer-use/image.d.ts +26 -0
- package/dist/core/computer-use/image.d.ts.map +1 -0
- package/dist/core/computer-use/image.js +64 -0
- package/dist/core/computer-use/image.js.map +1 -0
- package/dist/core/computer-use/policy.d.ts.map +1 -1
- package/dist/core/computer-use/policy.js +2 -6
- package/dist/core/computer-use/policy.js.map +1 -1
- package/dist/core/computer-use/schemas.d.ts +13 -10
- package/dist/core/computer-use/schemas.d.ts.map +1 -1
- package/dist/core/computer-use/schemas.js +26 -35
- package/dist/core/computer-use/schemas.js.map +1 -1
- package/dist/core/computer-use/workflow.d.ts +16 -8
- package/dist/core/computer-use/workflow.d.ts.map +1 -1
- package/dist/core/computer-use/workflow.js +271 -260
- package/dist/core/computer-use/workflow.js.map +1 -1
- package/dist/core/customize.d.ts +2 -0
- package/dist/core/customize.d.ts.map +1 -1
- package/dist/core/customize.js +3 -0
- package/dist/core/customize.js.map +1 -1
- package/dist/core/permissions.d.ts +1 -0
- package/dist/core/permissions.d.ts.map +1 -1
- package/dist/core/permissions.js +8 -4
- package/dist/core/permissions.js.map +1 -1
- package/dist/core/plan-mode.d.ts.map +1 -1
- package/dist/core/plan-mode.js +0 -5
- package/dist/core/plan-mode.js.map +1 -1
- package/dist/core/runtime-bridges.d.ts.map +1 -1
- package/dist/core/runtime-bridges.js +0 -2
- package/dist/core/runtime-bridges.js.map +1 -1
- package/dist/core/settings-manager.d.ts +4 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +11 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/subagent-cancellation.d.ts +21 -0
- package/dist/core/subagent-cancellation.d.ts.map +1 -0
- package/dist/core/subagent-cancellation.js +53 -0
- package/dist/core/subagent-cancellation.js.map +1 -0
- package/dist/core/subagent-spinner-setting.d.ts +6 -0
- package/dist/core/subagent-spinner-setting.d.ts.map +1 -0
- package/dist/core/subagent-spinner-setting.js +12 -0
- package/dist/core/subagent-spinner-setting.js.map +1 -0
- package/dist/core/subagent-spinner.d.ts +4 -0
- package/dist/core/subagent-spinner.d.ts.map +1 -0
- package/dist/core/subagent-spinner.js +6 -0
- package/dist/core/subagent-spinner.js.map +1 -0
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +12 -18
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +4 -0
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +73 -1
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +12 -0
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/extension-widget-order.d.ts +8 -0
- package/dist/modes/interactive/extension-widget-order.d.ts.map +1 -0
- package/dist/modes/interactive/extension-widget-order.js +37 -0
- package/dist/modes/interactive/extension-widget-order.js.map +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +44 -22
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/node-runtime/{agent-session-services-RSGP5GDN.js → agent-session-services-QANFGM2V.js} +14 -13
- package/dist/node-runtime/{builtin-extensions-7STLFW3A.js → builtin-extensions-SRCYQPZ6.js} +4 -3
- package/dist/node-runtime/{chunk-5OLJGVCB.js → chunk-3ONQTOMR.js} +2 -2
- package/dist/node-runtime/chunk-5ZH3ZFIZ.js +308 -0
- package/dist/node-runtime/{chunk-4SJWFTUP.js → chunk-7NBZ5P7I.js} +1 -1
- package/dist/node-runtime/chunk-A3KMVBZV.js +60 -0
- package/dist/node-runtime/{chunk-FLYMHKCS.js → chunk-BJ6H7DPI.js} +25 -25
- package/dist/node-runtime/{chunk-T5GM5BFH.js → chunk-BYQ2MOFI.js} +6 -6
- package/dist/node-runtime/{chunk-W7S2REEG.js → chunk-CZUBYPFP.js} +157 -74
- package/dist/node-runtime/{chunk-ZRDIMBEQ.js → chunk-D466UAID.js} +9 -6
- package/dist/node-runtime/{chunk-K72NVGUB.js → chunk-GT5F3OKM.js} +1 -1
- package/dist/node-runtime/chunk-H2BI7G7T.js +73 -0
- package/dist/node-runtime/{chunk-ISQDQIZN.js → chunk-HXJS2PJM.js} +2 -2
- package/dist/node-runtime/chunk-LISUTZS3.js +19 -0
- package/dist/node-runtime/{chunk-BKAZ6BKX.js → chunk-LOYUC2ID.js} +7 -7
- package/dist/node-runtime/{chunk-OTT6JMPU.js → chunk-LTYWTR3V.js} +1 -369
- package/dist/node-runtime/{chunk-5Q45AVQG.js → chunk-MW2XJZIK.js} +1 -1
- package/dist/node-runtime/{chunk-MUMMMTW4.js → chunk-N3PNL74S.js} +536 -265
- package/dist/node-runtime/{chunk-HQCKFM2O.js → chunk-VGYZ3APQ.js} +3 -0
- package/dist/node-runtime/{chunk-5NWQCSKR.js → chunk-VQ4UBWSA.js} +11 -1
- package/dist/node-runtime/{chunk-6SPPH4FY.js → chunk-VTGEKB7R.js} +4 -4
- package/dist/node-runtime/chunk-W3SILANP.js +24 -0
- package/dist/node-runtime/{chunk-J7QGQD45.js → chunk-WJVFOIB5.js} +1 -1
- package/dist/node-runtime/{chunk-JT6YCS5B.js → chunk-XAUQOKYK.js} +408 -45
- package/dist/node-runtime/{chunk-LCACDWHJ.js → chunk-XSRCAQK2.js} +13 -13
- package/dist/node-runtime/{chunk-TAP7QTUT.js → chunk-ZOIIMEN6.js} +24 -425
- package/dist/node-runtime/{chunk-MGSB2C3M.js → chunk-ZVSORYRM.js} +1 -1
- package/dist/node-runtime/{command-6UXQ6XZN.js → command-ZURZJDXF.js} +1 -1
- package/dist/node-runtime/{commands-LGR5VT5X.js → commands-BZGSLIP7.js} +3 -3
- package/dist/node-runtime/{customize-XEXL2DGQ.js → customize-LF5VST47.js} +1 -1
- package/dist/node-runtime/{direct-tool-executor-TDJS7TBD.js → direct-tool-executor-BSZDHIYR.js} +4 -4
- package/dist/node-runtime/{extract-IUCVZCWC.js → extract-XLQSJN4V.js} +2 -2
- package/dist/node-runtime/{gateway-3OLC4GQN.js → gateway-FWHRIBK5.js} +9 -9
- package/dist/node-runtime/{gemini-search-NCIDF7NE.js → gemini-search-U7SUMPQA.js} +1 -1
- package/dist/node-runtime/{gemini-url-context-OKIN7AIP.js → gemini-url-context-PXWCBQHK.js} +2 -2
- package/dist/node-runtime/index.js +34 -31
- package/dist/node-runtime/{init-EKE277AG.js → init-DVJUAOUO.js} +3 -3
- package/dist/node-runtime/{interactive-mode-S5M26CQ7.js → interactive-mode-BBASNWHN.js} +18 -15
- package/dist/node-runtime/lunr-computer-use-TJNDAMWM.js +135 -0
- package/dist/node-runtime/{lunr-cron-KKBOGAEF.js → lunr-cron-J64I72C6.js} +5 -5
- package/dist/node-runtime/main.js +22 -20
- package/dist/node-runtime/{package-manager-cli-C4EJOO5Q.js → package-manager-cli-VMYX4Y2S.js} +8 -7
- package/dist/node-runtime/{pi-intercom-EEMBGQID.js → pi-intercom-NV2LW6X7.js} +108 -87
- package/dist/node-runtime/{pi-mcp-adapter-DPTJGAAL.js → pi-mcp-adapter-JLB5YL2F.js} +6 -6
- package/dist/node-runtime/{pi-subagents-VKCLYIBY.js → pi-subagents-WEHV3W7H.js} +1267 -604
- package/dist/node-runtime/{pi-web-access-BV6DSZOP.js → pi-web-access-FN5YC5T6.js} +5 -5
- package/dist/node-runtime/{proxy-modes-R64LU6WZ.js → proxy-modes-OR7ISBXK.js} +7 -7
- package/dist/node-runtime/rpc-entry.js +22 -20
- package/dist/node-runtime/{runtime-bridges-UJ5WJJLN.js → runtime-bridges-2VQTLPOZ.js} +3 -5
- package/dist/node-runtime/{settings-manager-K6IPIQTI.js → settings-manager-3CCU326G.js} +3 -2
- package/dist/node-runtime/{subagent-executor-EFLTO32A.js → subagent-executor-CXKXQDHH.js} +186 -299
- package/dist/node-runtime/{update-cli-I6OVDRPL.js → update-cli-NM7B4CKL.js} +3 -2
- package/dist/node-runtime/{video-extract-ETA5RA7U.js → video-extract-OYT5WKS5.js} +2 -2
- package/dist/node-runtime/workflow-C26QCUTW.js +468 -0
- package/dist/node-runtime/{youtube-extract-SRVGNN26.js → youtube-extract-TQYKGFGS.js} +2 -2
- package/docs/computer-use.md +233 -268
- package/docs/features.md +22 -4
- package/docs/keybindings.md +3 -1
- package/docs/settings.md +3 -2
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/install-lock/package-lock.json +24 -24
- package/install-lock/package.json +2 -2
- package/npm-shrinkwrap.json +21 -21
- package/package.json +7 -7
- package/dist/builtin-extensions/lunr-settings-tools.d.ts +0 -4
- package/dist/builtin-extensions/lunr-settings-tools.d.ts.map +0 -1
- package/dist/builtin-extensions/lunr-settings-tools.js +0 -120
- package/dist/builtin-extensions/lunr-settings-tools.js.map +0 -1
- package/dist/core/settings-tools-bridge.d.ts +0 -35
- package/dist/core/settings-tools-bridge.d.ts.map +0 -1
- package/dist/core/settings-tools-bridge.js +0 -56
- package/dist/core/settings-tools-bridge.js.map +0 -1
- package/dist/node-runtime/chunk-EH2LJQPM.js +0 -64
- package/dist/node-runtime/image-resize-6ZPBFMWW.js +0 -11
- package/dist/node-runtime/lunr-computer-use-4X3KUNF4.js +0 -206
- package/dist/node-runtime/workflow-SA34S4VX.js +0 -325
- package/dist/node-runtime/{chunk-EHMBW7FA.js → chunk-VSELYKWU.js} +3 -3
- package/dist/node-runtime/{chunk-ZSEZY3II.js → chunk-VTPM5V35.js} +0 -0
- package/dist/node-runtime/{src-GPFAU3N6.js → src-BPQFJR76.js} +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"async-job-tracker.d.ts","sourceRoot":"","sources":["../../../../../../src/builtin-extensions/pi-subagents/src/runs/background/async-job-tracker.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAKtF,OAAO,EAKN,KAAK,aAAa,EAMlB,MAAM,uBAAuB,CAAC;AAO/B,UAAU,sBAAsB;IAC/B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,OAAO,GAAG,CAAC,KAAK,OAAO,CAAC;IAC7D,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACnB;AAgBD,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,EAAE,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,EAAE,OAAO,GAAE,sBAA2B,GAAG;IAC1J,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,aAAa,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC/C,aAAa,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,cAAc,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACxC,SAAS,EAAE,CAAC,GAAG,CAAC,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC5C,iBAAiB,EAAE,CAAC,GAAG,CAAC,EAAE,gBAAgB,KAAK,IAAI,CAAC;CACpD,CAmbA","sourcesContent":["// @ts-nocheck\nimport type { ExtensionAPI, ExtensionContext } from \"@ashx-j/lunr-dev\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { renderWidget, widgetRenderKey } from \"../../tui/render.ts\";\nimport { formatControlNoticeMessage } from \"../shared/subagent-control.ts\";\nimport {\n\ttype AsyncJobState,\n\ttype AsyncStartedEvent,\n\ttype ControlEvent,\n\ttype SteeringNotice,\n\ttype SubagentState,\n\tPOLL_INTERVAL_MS,\n\tRESULTS_DIR,\n\tSUBAGENT_CONTROL_EVENT,\n\tSUBAGENT_CONTROL_INTERCOM_EVENT,\n\tSUBAGENT_STEERING_NOTICE_EVENT,\n} from \"../../shared/types.ts\";\nimport { readStatus } from \"../../shared/utils.ts\";\nimport { normalizeParallelGroups } from \"./parallel-groups.ts\";\nimport { reconcileAsyncRun, reconcileNestedAsyncDescendants } from \"./stale-run-reconciler.ts\";\nimport { hasLiveNestedDescendants, updateAsyncJobNestedProjection } from \"../shared/nested-events.ts\";\nimport { listAsyncRuns, type AsyncRunSummary } from \"./async-status.ts\";\n\ninterface AsyncJobTrackerOptions {\n\tcompletionRetentionMs?: number;\n\tpollIntervalMs?: number;\n\tresultsDir?: string;\n\twidgetEnabled?: boolean;\n\tkill?: (pid: number, signal?: NodeJS.Signals | 0) => boolean;\n\tnow?: () => number;\n}\n\nconst CONTROL_EVENT_READ_CHUNK_BYTES = 64 * 1024;\nconst MAX_CONTROL_EVENT_LINE_BYTES = 1024 * 1024;\nconst CONTROL_EVENT_SCAN_WINDOW_BYTES = 2 * 1024 * 1024;\nconst MAX_RECENT_FLEET_JOBS = 20;\n\nfunction rememberFleetJob(state: SubagentState, job: AsyncJobState): void {\n\tstate.fleetJobs ??= new Map();\n\tstate.fleetJobs.set(job.asyncId, job);\n\tconst terminal = [...state.fleetJobs.values()]\n\t\t.filter((candidate) => candidate.status === \"complete\" || candidate.status === \"failed\" || candidate.status === \"paused\" || candidate.status === \"stopped\")\n\t\t.sort((left, right) => (right.updatedAt ?? right.startedAt ?? 0) - (left.updatedAt ?? left.startedAt ?? 0));\n\tfor (const stale of terminal.slice(MAX_RECENT_FLEET_JOBS)) state.fleetJobs.delete(stale.asyncId);\n}\n\nexport function createAsyncJobTracker(pi: Pick<ExtensionAPI, \"events\">, state: SubagentState, asyncDirRoot: string, options: AsyncJobTrackerOptions = {}): {\n\tensurePoller: () => void;\n\trefreshWidget: (ctx: ExtensionContext) => void;\n\thandleStarted: (data: unknown) => void;\n\thandleComplete: (data: unknown) => void;\n\tresetJobs: (ctx?: ExtensionContext) => void;\n\trestoreActiveJobs: (ctx?: ExtensionContext) => void;\n} {\n\tconst completionRetentionMs = options.completionRetentionMs ?? 10000;\n\tconst pollIntervalMs = options.pollIntervalMs ?? POLL_INTERVAL_MS;\n\tconst resultsDir = options.resultsDir ?? RESULTS_DIR;\n\tconst steeringNoticeSeen = new Map<string, number>();\n\tconst rerenderWidget = (ctx: ExtensionContext, jobs = Array.from(state.asyncJobs.values())) => {\n\t\trenderWidget(ctx, options.widgetEnabled === false ? [] : jobs);\n\t\tctx.ui.requestRender?.();\n\t};\n\tconst refreshWidget = (ctx: ExtensionContext) => rerenderWidget(ctx);\n\tconst restoredControlEventCursor = (asyncDir: string) => {\n\t\ttry {\n\t\t\treturn fs.statSync(path.join(asyncDir, \"events.jsonl\")).size;\n\t\t} catch (error) {\n\t\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return 0;\n\t\t\tthrow error;\n\t\t}\n\t};\n\tconst summaryToJob = (run: AsyncRunSummary): AsyncJobState => {\n\t\tconst groups = normalizeParallelGroups(run.parallelGroups, run.steps.length, run.chainStepCount ?? run.steps.length);\n\t\tconst activeGroup = run.currentStep !== undefined\n\t\t\t? groups.find((group) => run.currentStep! >= group.start && run.currentStep! < group.start + group.count)\n\t\t\t: undefined;\n\t\tconst visibleSteps = activeGroup\n\t\t\t? run.steps.slice(activeGroup.start, activeGroup.start + activeGroup.count).map((step, index) => ({ ...step, index: activeGroup.start + index }))\n\t\t\t: run.steps.map((step, index) => ({ ...step, index }));\n\t\treturn {\n\t\t\tasyncId: run.id,\n\t\t\tasyncDir: run.asyncDir,\n\t\t\tstatus: run.state,\n\t\t\tsessionId: run.sessionId,\n\t\t\tactivityState: run.activityState,\n\t\t\tlastActivityAt: run.lastActivityAt,\n\t\t\tcurrentTool: run.currentTool,\n\t\t\tcurrentToolStartedAt: run.currentToolStartedAt,\n\t\t\tcurrentPath: run.currentPath,\n\t\t\tturnCount: run.turnCount,\n\t\t\ttoolCount: run.toolCount,\n\t\t\tsteering: run.steering,\n\t\t\tmode: run.mode,\n\t\t\tagents: visibleSteps.map((step) => step.agent),\n\t\t\tcurrentStep: run.currentStep,\n\t\t\tchainStepCount: run.chainStepCount,\n\t\t\tparallelGroups: groups,\n\t\t\tsteps: visibleSteps,\n\t\t\tstepsTotal: visibleSteps.length,\n\t\t\trunningSteps: visibleSteps.filter((step) => step.status === \"running\").length,\n\t\t\tcompletedSteps: visibleSteps.filter((step) => step.status === \"complete\" || step.status === \"completed\").length,\n\t\t\thasParallelGroups: groups.length > 0,\n\t\t\tactiveParallelGroup: Boolean(activeGroup),\n\t\t\tstartedAt: run.startedAt,\n\t\t\tupdatedAt: run.lastUpdate ?? run.startedAt,\n\t\t\ttimeoutMs: run.timeoutMs,\n\t\t\tdeadlineAt: run.deadlineAt,\n\t\t\ttimedOut: run.timedOut,\n\t\t\tstopped: run.stopped,\n\t\t\tturnBudget: run.turnBudget,\n\t\t\tturnBudgetExceeded: run.turnBudgetExceeded,\n\t\t\twrapUpRequested: run.wrapUpRequested,\n\t\t\tsessionDir: run.sessionDir,\n\t\t\toutputFile: run.outputFile,\n\t\t\ttotalTokens: run.totalTokens,\n\t\t\tsessionFile: run.sessionFile,\n\t\t\tcontrolEventCursor: restoredControlEventCursor(run.asyncDir),\n\t\t\tnestedChildren: run.nestedChildren,\n\t\t};\n\t};\n\tconst cancelCleanup = (asyncId: string) => {\n\t\tconst existingTimer = state.cleanupTimers.get(asyncId);\n\t\tif (!existingTimer) return;\n\t\tclearTimeout(existingTimer);\n\t\tstate.cleanupTimers.delete(asyncId);\n\t};\n\tconst scheduleCleanup = (asyncId: string) => {\n\t\tcancelCleanup(asyncId);\n\t\tconst timer = setTimeout(() => {\n\t\t\tstate.cleanupTimers.delete(asyncId);\n\t\t\tstate.asyncJobs.delete(asyncId);\n\t\t\tif (state.lastUiContext) {\n\t\t\t\trerenderWidget(state.lastUiContext);\n\t\t\t}\n\t\t}, completionRetentionMs);\n\t\tstate.cleanupTimers.set(asyncId, timer);\n\t};\n\tconst emitNewControlEvents = (job: AsyncJobState) => {\n\t\tconst eventsPath = path.join(job.asyncDir, \"events.jsonl\");\n\t\tlet fd: number;\n\t\ttry {\n\t\t\tfd = fs.openSync(eventsPath, \"r\");\n\t\t} catch (error) {\n\t\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return;\n\t\t\tconsole.error(`Failed to open async control events for '${job.asyncDir}':`, error);\n\t\t\treturn;\n\t\t}\n\t\ttry {\n\t\t\tconst stat = fs.fstatSync(fd);\n\t\t\tconst savedCursor = job.controlEventCursor;\n\t\t\tlet cursor = stat.size < (savedCursor ?? 0) ? 0 : (savedCursor ?? 0);\n\t\t\tconst startedFromTail = savedCursor === undefined && stat.size > CONTROL_EVENT_SCAN_WINDOW_BYTES;\n\t\t\tif (startedFromTail) cursor = stat.size - CONTROL_EVENT_SCAN_WINDOW_BYTES;\n\t\t\tif (stat.size <= cursor) return;\n\t\t\tconst scanEnd = Math.min(stat.size, cursor + CONTROL_EVENT_SCAN_WINDOW_BYTES);\n\t\t\tconst handleLine = (line: string) => {\n\t\t\t\tif (!line.trim()) return;\n\t\t\t\tlet parsed: unknown;\n\t\t\t\ttry {\n\t\t\t\t\tparsed = JSON.parse(line);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconsole.error(`Ignoring malformed async control event in '${eventsPath}':`, error);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (!parsed || typeof parsed !== \"object\") return;\n\t\t\t\tif ((parsed as { type?: unknown }).type === \"subagent.steering.notice\") {\n\t\t\t\t\tconst notice = parsed as Partial<SteeringNotice>;\n\t\t\t\t\tif (typeof notice.requestId !== \"string\" || typeof notice.runId !== \"string\" || (notice.state !== \"failed\" && notice.state !== \"partial\" && notice.state !== \"recovered\") || typeof notice.message !== \"string\") return;\n\t\t\t\t\tif (typeof state.currentSessionId === \"string\" && notice.currentSessionId !== state.currentSessionId) return;\n\t\t\t\t\tconst key = `${notice.runId}:${notice.requestId}:${notice.state}`;\n\t\t\t\t\tif (steeringNoticeSeen.has(key)) return;\n\t\t\t\t\tconst now = Date.now();\n\t\t\t\t\tsteeringNoticeSeen.set(key, now);\n\t\t\t\t\tif (steeringNoticeSeen.size > 200) {\n\t\t\t\t\t\tfor (const [seenKey, seenAt] of steeringNoticeSeen) {\n\t\t\t\t\t\t\tif (now - seenAt > 10 * 60 * 1000 || steeringNoticeSeen.size > 200) steeringNoticeSeen.delete(seenKey);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tpi.events.emit(SUBAGENT_STEERING_NOTICE_EVENT, { ...notice, source: \"async\", asyncDir: job.asyncDir, noticeText: notice.message });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif ((parsed as { type?: unknown }).type !== \"subagent.control\") return;\n\t\t\t\tconst record = parsed as { event?: ControlEvent; channels?: string[]; childIntercomTarget?: string; noticeText?: string; intercom?: { to?: string; message?: string } };\n\t\t\t\tif (!record.event || !Array.isArray(record.channels)) return;\n\t\t\t\tconst payload = {\n\t\t\t\t\tevent: record.event,\n\t\t\t\t\tsource: \"async\" as const,\n\t\t\t\t\tasyncDir: job.asyncDir,\n\t\t\t\t\tchildIntercomTarget: record.childIntercomTarget,\n\t\t\t\t\tnoticeText: record.noticeText ?? formatControlNoticeMessage(record.event, record.childIntercomTarget),\n\t\t\t\t};\n\t\t\t\tif (record.channels.includes(\"event\")) {\n\t\t\t\t\tpi.events.emit(SUBAGENT_CONTROL_EVENT, payload);\n\t\t\t\t}\n\t\t\t\tif (record.event.type !== \"active_long_running\" && record.channels.includes(\"intercom\") && record.intercom?.to && record.intercom.message) {\n\t\t\t\t\tpi.events.emit(SUBAGENT_CONTROL_INTERCOM_EVENT, {\n\t\t\t\t\t\t...payload,\n\t\t\t\t\t\tto: record.intercom.to,\n\t\t\t\t\t\tmessage: record.intercom.message,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t};\n\t\t\tlet readCursor = cursor;\n\t\t\tlet lastCompleteCursor = cursor;\n\t\t\tlet lineParts: Buffer[] = [];\n\t\t\tlet lineBytes = 0;\n\t\t\tlet skippingOversizedLine = startedFromTail;\n\t\t\tconst appendLineSegment = (segment: Buffer) => {\n\t\t\t\tif (segment.length === 0 || skippingOversizedLine) return;\n\t\t\t\tif (lineBytes + segment.length > MAX_CONTROL_EVENT_LINE_BYTES) {\n\t\t\t\t\tlineParts = [];\n\t\t\t\t\tlineBytes = 0;\n\t\t\t\t\tskippingOversizedLine = true;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tlineParts.push(segment);\n\t\t\t\tlineBytes += segment.length;\n\t\t\t};\n\t\t\twhile (readCursor < scanEnd) {\n\t\t\t\tconst toRead = Math.min(CONTROL_EVENT_READ_CHUNK_BYTES, scanEnd - readCursor);\n\t\t\t\tconst buffer = Buffer.alloc(toRead);\n\t\t\t\tconst bytesRead = fs.readSync(fd, buffer, 0, toRead, readCursor);\n\t\t\t\tif (bytesRead <= 0) break;\n\t\t\t\tconst chunk = bytesRead === buffer.length ? buffer : buffer.subarray(0, bytesRead);\n\t\t\t\tlet lineStart = 0;\n\t\t\t\tfor (let index = 0; index < chunk.length; index++) {\n\t\t\t\t\tif (chunk[index] !== 0x0a) continue;\n\t\t\t\t\tappendLineSegment(chunk.subarray(lineStart, index));\n\t\t\t\t\tif (!skippingOversizedLine && lineBytes > 0) {\n\t\t\t\t\t\thandleLine(Buffer.concat(lineParts, lineBytes).toString(\"utf-8\"));\n\t\t\t\t\t}\n\t\t\t\t\tlineParts = [];\n\t\t\t\t\tlineBytes = 0;\n\t\t\t\t\tskippingOversizedLine = false;\n\t\t\t\t\tlastCompleteCursor = readCursor + index + 1;\n\t\t\t\t\tlineStart = index + 1;\n\t\t\t\t}\n\t\t\t\tappendLineSegment(chunk.subarray(lineStart));\n\t\t\t\treadCursor += bytesRead;\n\t\t\t\tif (skippingOversizedLine) job.controlEventCursor = readCursor;\n\t\t\t}\n\t\t\tif (lastCompleteCursor > cursor) job.controlEventCursor = lastCompleteCursor;\n\t\t\telse if (scanEnd < stat.size || startedFromTail) job.controlEventCursor = scanEnd;\n\t\t} catch (error) {\n\t\t\tconsole.error(`Failed to read async control events for '${job.asyncDir}':`, error);\n\t\t} finally {\n\t\t\tfs.closeSync(fd);\n\t\t}\n\t};\n\n\tconst ensurePoller = () => {\n\t\tif (state.poller) return;\n\t\tstate.poller = setInterval(() => {\n\t\t\tif (state.asyncJobs.size === 0) {\n\t\t\t\tif (state.lastUiContext?.hasUI) rerenderWidget(state.lastUiContext, []);\n\t\t\t\tif (state.poller) {\n\t\t\t\t\tclearInterval(state.poller);\n\t\t\t\t\tstate.poller = null;\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlet widgetChanged = false;\n\t\t\tfor (const job of state.asyncJobs.values()) {\n\t\t\t\tconst widgetStateBefore = widgetRenderKey(job);\n\t\t\t\tlet nestedRefreshFailed = false;\n\t\t\t\tconst refreshNestedProjection = () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tupdateAsyncJobNestedProjection(job);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tnestedRefreshFailed = true;\n\t\t\t\t\t\tconsole.error(`Failed to refresh nested async descendants for '${job.asyncDir}':`, error);\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\tconst reconcileNestedDescendants = () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (job.nestedRoute) reconcileNestedAsyncDescendants(job.nestedRoute, { resultsDir, kill: options.kill, now: options.now });\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tnestedRefreshFailed = true;\n\t\t\t\t\t\tconsole.error(`Failed to refresh nested async descendants for '${job.asyncDir}':`, error);\n\t\t\t\t\t}\n\t\t\t\t\trefreshNestedProjection();\n\t\t\t\t};\n\t\t\t\ttry {\n\t\t\t\t\temitNewControlEvents(job);\n\t\t\t\t\treconcileNestedDescendants();\n\t\t\t\t\tconst reconciliation = reconcileAsyncRun(job.asyncDir, {\n\t\t\t\t\t\tresultsDir,\n\t\t\t\t\t\tkill: options.kill,\n\t\t\t\t\t\tnow: options.now,\n\t\t\t\t\t\tstartedRun: {\n\t\t\t\t\t\t\trunId: job.asyncId,\n\t\t\t\t\t\t\tpid: job.pid,\n\t\t\t\t\t\t\tsessionId: job.sessionId,\n\t\t\t\t\t\t\tmode: job.mode,\n\t\t\t\t\t\t\tagents: job.agents,\n\t\t\t\t\t\t\tchainStepCount: job.chainStepCount,\n\t\t\t\t\t\t\tparallelGroups: job.parallelGroups,\n\t\t\t\t\t\t\tstartedAt: job.startedAt,\n\t\t\t\t\t\t\tsessionFile: job.sessionFile,\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t\tconst status = reconciliation.status ?? readStatus(job.asyncDir);\n\t\t\t\t\tif (status) {\n\t\t\t\t\t\tconst previousStatus = job.status;\n\t\t\t\t\t\tjob.status = status.state;\n\t\t\t\t\t\tif (job.status !== \"complete\" && job.status !== \"failed\" && job.status !== \"paused\" && job.status !== \"stopped\") cancelCleanup(job.asyncId);\n\t\t\t\t\t\tjob.sessionId = status.sessionId ?? job.sessionId;\n\t\t\t\t\t\tjob.activityState = status.activityState;\n\t\t\t\t\t\tjob.lastActivityAt = status.lastActivityAt ?? job.lastActivityAt;\n\t\t\t\t\t\tjob.currentTool = status.currentTool;\n\t\t\t\t\t\tjob.currentToolStartedAt = status.currentToolStartedAt;\n\t\t\t\t\t\tjob.currentPath = status.currentPath;\n\t\t\t\t\t\tjob.turnCount = status.turnCount ?? job.turnCount;\n\t\t\t\t\t\tjob.toolCount = status.toolCount ?? job.toolCount;\n\t\t\t\t\t\tjob.steering = status.steering ?? job.steering;\n\t\t\t\t\t\tjob.mode = status.mode;\n\t\t\t\t\t\tjob.currentStep = status.currentStep ?? job.currentStep;\n\t\t\t\t\t\tjob.chainStepCount = status.chainStepCount ?? job.chainStepCount;\n\t\t\t\t\t\tjob.startedAt = status.startedAt ?? job.startedAt;\n\t\t\t\t\t\tif (status.lastUpdate !== undefined) job.updatedAt = status.lastUpdate;\n\t\t\t\t\t\tif (status.steps?.length) {\n\t\t\t\t\t\t\tconst groups = normalizeParallelGroups(status.parallelGroups, status.steps.length, status.chainStepCount ?? status.steps.length);\n\t\t\t\t\t\t\tjob.parallelGroups = groups.length ? groups : job.parallelGroups;\n\t\t\t\t\t\t\tjob.hasParallelGroups = groups.length > 0 || job.hasParallelGroups;\n\t\t\t\t\t\t\tconst activeGroup = status.currentStep !== undefined\n\t\t\t\t\t\t\t\t? groups.find((group) => status.currentStep! >= group.start && status.currentStep! < group.start + group.count)\n\t\t\t\t\t\t\t\t: undefined;\n\t\t\t\t\t\t\tconst visibleSteps = activeGroup\n\t\t\t\t\t\t\t\t? status.steps.slice(activeGroup.start, activeGroup.start + activeGroup.count).map((step, index) => ({ ...step, index: activeGroup.start + index }))\n\t\t\t\t\t\t\t\t: status.steps.map((step, index) => ({ ...step, index }));\n\t\t\t\t\t\t\tjob.activeParallelGroup = Boolean(activeGroup);\n\t\t\t\t\t\t\tjob.agents = visibleSteps.map((step) => step.agent);\n\t\t\t\t\t\t\tjob.steps = visibleSteps;\n\t\t\t\t\t\t\trefreshNestedProjection();\n\t\t\t\t\t\t\tjob.stepsTotal = visibleSteps.length;\n\t\t\t\t\t\t\tjob.runningSteps = visibleSteps.filter((step) => step.status === \"running\").length;\n\t\t\t\t\t\t\tjob.completedSteps = visibleSteps.filter((step) => step.status === \"complete\" || step.status === \"completed\").length;\n\t\t\t\t\t\t\tif (status.state === \"complete\") job.completedSteps = visibleSteps.length;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tjob.sessionDir = status.sessionDir ?? job.sessionDir;\n\t\t\t\t\t\tjob.outputFile = status.outputFile ?? job.outputFile;\n\t\t\t\t\t\tjob.totalTokens = status.totalTokens ?? job.totalTokens;\n\t\t\t\t\t\tjob.timeoutMs = status.timeoutMs ?? job.timeoutMs;\n\t\t\t\t\t\tjob.deadlineAt = status.deadlineAt ?? job.deadlineAt;\n\t\t\t\t\t\tjob.timedOut = status.timedOut ?? job.timedOut;\n\t\t\t\t\t\tjob.stopped = status.stopped ?? job.stopped;\n\t\t\t\t\t\tjob.turnBudget = status.turnBudget ?? job.turnBudget;\n\t\t\t\t\t\tjob.turnBudgetExceeded = status.turnBudgetExceeded ?? job.turnBudgetExceeded;\n\t\t\t\t\t\tjob.wrapUpRequested = status.wrapUpRequested ?? job.wrapUpRequested;\n\t\t\t\t\t\tjob.sessionFile = status.sessionFile ?? job.sessionFile;\n\t\t\t\t\t\tif (job.status === \"complete\" || job.status === \"failed\" || job.status === \"paused\" || job.status === \"stopped\") {\n\t\t\t\t\t\t\trememberFleetJob(state, job);\n\t\t\t\t\t\t\tif (!nestedRefreshFailed && !hasLiveNestedDescendants(job.nestedChildren) && (previousStatus !== job.status || !state.cleanupTimers.has(job.asyncId))) {\n\t\t\t\t\t\t\t\tscheduleCleanup(job.asyncId);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (widgetRenderKey(job) !== widgetStateBefore) widgetChanged = true;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tif (job.status === \"queued\") {\n\t\t\t\t\t\tjob.status = \"running\";\n\t\t\t\t\t\tjob.updatedAt = Date.now();\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (job.status !== \"failed\") {\n\t\t\t\t\t\tconsole.error(`Failed to read async status for '${job.asyncDir}':`, error);\n\t\t\t\t\t\tjob.status = \"failed\";\n\t\t\t\t\t\tjob.updatedAt = Date.now();\n\t\t\t\t\t}\n\t\t\t\t\trememberFleetJob(state, job);\n\t\t\t\t\tif (!hasLiveNestedDescendants(job.nestedChildren) && !state.cleanupTimers.has(job.asyncId)) {\n\t\t\t\t\t\tscheduleCleanup(job.asyncId);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (widgetRenderKey(job) !== widgetStateBefore) widgetChanged = true;\n\t\t\t}\n\n\t\t\tconst timerNeedsPaint = [...state.asyncJobs.values()].some((job) => job.status === \"running\");\n\t\t\tif ((widgetChanged || timerNeedsPaint) && state.lastUiContext?.hasUI) rerenderWidget(state.lastUiContext);\n\t\t}, pollIntervalMs);\n\t\tstate.poller.unref?.();\n\t};\n\n\tconst handleStarted = (data: unknown) => {\n\t\tconst info = data as AsyncStartedEvent;\n\t\tif (!info.id) return;\n\t\tif (typeof state.currentSessionId === \"string\" && info.sessionId !== state.currentSessionId) return;\n\t\tconst now = Date.now();\n\t\tconst asyncDir = info.asyncDir ?? path.join(asyncDirRoot, info.id);\n\t\tconst rawAgents = info.agents?.length ? info.agents : info.chain && info.chain.length > 0 ? info.chain : info.agent ? [info.agent] : undefined;\n\t\tconst validParallelGroups = normalizeParallelGroups(info.parallelGroups, Number.MAX_SAFE_INTEGER, info.chainStepCount ?? Number.MAX_SAFE_INTEGER);\n\t\tconst firstGroup = validParallelGroups.find((group) => group.start === 0);\n\t\tconst firstGroupCount = firstGroup?.count;\n\t\tconst agents = firstGroupCount && firstGroupCount > 0\n\t\t\t? rawAgents?.slice(0, firstGroupCount)\n\t\t\t: rawAgents;\n\t\tstate.asyncJobs.set(info.id, {\n\t\t\tasyncId: info.id,\n\t\t\tasyncDir,\n\t\t\tstatus: \"queued\",\n\t\t\tpid: typeof info.pid === \"number\" ? info.pid : undefined,\n\t\t\t...(typeof info.sessionId === \"string\" ? { sessionId: info.sessionId } : {}),\n\t\t\tmode: info.mode ?? (info.chain ? \"chain\" : \"single\"),\n\t\t\tagents,\n\t\t\tchainStepCount: info.chainStepCount,\n\t\t\tparallelGroups: validParallelGroups,\n\t\t\tnestedRoute: info.nestedRoute,\n\t\t\tstepsTotal: firstGroupCount ?? agents?.length,\n\t\t\thasParallelGroups: validParallelGroups.length > 0,\n\t\t\tactiveParallelGroup: Boolean(firstGroupCount && firstGroupCount > 0),\n\t\t\tstartedAt: now,\n\t\t\tupdatedAt: now,\n\t\t\ttimeoutMs: info.timeoutMs,\n\t\t\tdeadlineAt: info.deadlineAt,\n\t\t\tturnBudget: info.turnBudget,\n\t\t\tcontrolEventCursor: 0,\n\t\t});\n\t\trememberFleetJob(state, state.asyncJobs.get(info.id)!);\n\t\tensurePoller();\n\t\tif (state.lastUiContext) {\n\t\t\trerenderWidget(state.lastUiContext);\n\t\t}\n\t};\n\n\tconst handleComplete = (data: unknown) => {\n\t\tconst result = data as { id?: string; success?: boolean; state?: AsyncJobState[\"status\"]; asyncDir?: string; sessionId?: string; stopped?: boolean };\n\t\tif (typeof state.currentSessionId === \"string\" && result.sessionId !== state.currentSessionId) return;\n\t\tconst asyncId = result.id;\n\t\tif (!asyncId) return;\n\t\tconst job = state.asyncJobs.get(asyncId);\n\t\tlet nestedRefreshFailed = false;\n\t\tif (job) {\n\t\t\tjob.status = result.state ?? (result.success ? \"complete\" : \"failed\");\n\t\t\tjob.stopped = result.stopped ?? job.stopped;\n\t\t\tjob.updatedAt = Date.now();\n\t\t\tif (result.asyncDir) job.asyncDir = result.asyncDir;\n\t\t\ttry {\n\t\t\t\tupdateAsyncJobNestedProjection(job);\n\t\t\t} catch (error) {\n\t\t\t\tnestedRefreshFailed = true;\n\t\t\t\tconsole.error(`Failed to refresh nested async descendants for '${job.asyncDir}':`, error);\n\t\t\t}\n\t\t}\n\t\tif (job) rememberFleetJob(state, job);\n\t\tif (state.lastUiContext) {\n\t\t\trerenderWidget(state.lastUiContext);\n\t\t}\n\t\tif (!nestedRefreshFailed && !hasLiveNestedDescendants(job?.nestedChildren)) scheduleCleanup(asyncId);\n\t};\n\n\tconst resetJobs = (ctx?: ExtensionContext) => {\n\t\tfor (const timer of state.cleanupTimers.values()) {\n\t\t\tclearTimeout(timer);\n\t\t}\n\t\tstate.cleanupTimers.clear();\n\t\tstate.asyncJobs.clear();\n\t\tstate.fleetJobs?.clear();\n\t\tstate.foregroundControls?.clear();\n\t\tstate.lastForegroundControlId = null;\n\t\tstate.resultFileCoalescer.clear();\n\t\tif (ctx?.hasUI) {\n\t\t\tstate.lastUiContext = ctx;\n\t\t\trerenderWidget(ctx, []);\n\t\t}\n\t};\n\n\tconst restoreActiveJobs = (ctx?: ExtensionContext) => {\n\t\tif (ctx?.hasUI) state.lastUiContext = ctx;\n\t\tif (!state.currentSessionId) return;\n\t\tlet runs: AsyncRunSummary[];\n\t\ttry {\n\t\t\truns = listAsyncRuns(asyncDirRoot, { states: [\"queued\", \"running\"], sessionId: state.currentSessionId, resultsDir, kill: options.kill, now: options.now });\n\t\t} catch (error) {\n\t\t\tconsole.error(`Failed to restore active async jobs from '${asyncDirRoot}':`, error);\n\t\t\treturn;\n\t\t}\n\t\tfor (const run of runs) {\n\t\t\tconst job = summaryToJob(run);\n\t\t\tstate.asyncJobs.set(run.id, job);\n\t\t\trememberFleetJob(state, job);\n\t\t}\n\t\tif (runs.length === 0) return;\n\t\tensurePoller();\n\t\tif (state.lastUiContext?.hasUI) rerenderWidget(state.lastUiContext);\n\t};\n\n\treturn { ensurePoller, refreshWidget, handleStarted, handleComplete, resetJobs, restoreActiveJobs };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"async-job-tracker.d.ts","sourceRoot":"","sources":["../../../../../../src/builtin-extensions/pi-subagents/src/runs/background/async-job-tracker.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAKtF,OAAO,EAKN,KAAK,aAAa,EAMlB,MAAM,uBAAuB,CAAC;AAO/B,UAAU,sBAAsB;IAC/B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,OAAO,GAAG,CAAC,KAAK,OAAO,CAAC;IAC7D,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACnB;AAgBD,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,EAAE,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,EAAE,OAAO,GAAE,sBAA2B,GAAG;IAC1J,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,aAAa,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC/C,aAAa,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,cAAc,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACxC,SAAS,EAAE,CAAC,GAAG,CAAC,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC5C,iBAAiB,EAAE,CAAC,GAAG,CAAC,EAAE,gBAAgB,KAAK,IAAI,CAAC;CACpD,CAmbA","sourcesContent":["// @ts-nocheck\nimport type { ExtensionAPI, ExtensionContext } from \"@ashx-j/lunr-dev\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { renderWidget, widgetRenderKey } from \"../../tui/render.ts\";\nimport { formatControlNoticeMessage } from \"../shared/subagent-control.ts\";\nimport {\n\ttype AsyncJobState,\n\ttype AsyncStartedEvent,\n\ttype ControlEvent,\n\ttype SteeringNotice,\n\ttype SubagentState,\n\tPOLL_INTERVAL_MS,\n\tRESULTS_DIR,\n\tSUBAGENT_CONTROL_EVENT,\n\tSUBAGENT_CONTROL_INTERCOM_EVENT,\n\tSUBAGENT_STEERING_NOTICE_EVENT,\n} from \"../../shared/types.ts\";\nimport { readStatus } from \"../../shared/utils.ts\";\nimport { normalizeParallelGroups } from \"./parallel-groups.ts\";\nimport { reconcileAsyncRun, reconcileNestedAsyncDescendants } from \"./stale-run-reconciler.ts\";\nimport { hasLiveNestedDescendants, updateAsyncJobNestedProjection } from \"../shared/nested-events.ts\";\nimport { listAsyncRuns, type AsyncRunSummary } from \"./async-status.ts\";\n\ninterface AsyncJobTrackerOptions {\n\tcompletionRetentionMs?: number;\n\tpollIntervalMs?: number;\n\tresultsDir?: string;\n\twidgetEnabled?: boolean;\n\tkill?: (pid: number, signal?: NodeJS.Signals | 0) => boolean;\n\tnow?: () => number;\n}\n\nconst CONTROL_EVENT_READ_CHUNK_BYTES = 64 * 1024;\nconst MAX_CONTROL_EVENT_LINE_BYTES = 1024 * 1024;\nconst CONTROL_EVENT_SCAN_WINDOW_BYTES = 2 * 1024 * 1024;\nconst MAX_RECENT_FLEET_JOBS = 20;\n\nfunction rememberFleetJob(state: SubagentState, job: AsyncJobState): void {\n\tstate.fleetJobs ??= new Map();\n\tstate.fleetJobs.set(job.asyncId, job);\n\tconst terminal = [...state.fleetJobs.values()]\n\t\t.filter((candidate) => candidate.status === \"complete\" || candidate.status === \"failed\" || candidate.status === \"paused\" || candidate.status === \"stopped\")\n\t\t.sort((left, right) => (right.updatedAt ?? right.startedAt ?? 0) - (left.updatedAt ?? left.startedAt ?? 0));\n\tfor (const stale of terminal.slice(MAX_RECENT_FLEET_JOBS)) state.fleetJobs.delete(stale.asyncId);\n}\n\nexport function createAsyncJobTracker(pi: Pick<ExtensionAPI, \"events\">, state: SubagentState, asyncDirRoot: string, options: AsyncJobTrackerOptions = {}): {\n\tensurePoller: () => void;\n\trefreshWidget: (ctx: ExtensionContext) => void;\n\thandleStarted: (data: unknown) => void;\n\thandleComplete: (data: unknown) => void;\n\tresetJobs: (ctx?: ExtensionContext) => void;\n\trestoreActiveJobs: (ctx?: ExtensionContext) => void;\n} {\n\tconst completionRetentionMs = options.completionRetentionMs ?? 10000;\n\tconst pollIntervalMs = options.pollIntervalMs ?? POLL_INTERVAL_MS;\n\tconst resultsDir = options.resultsDir ?? RESULTS_DIR;\n\tconst steeringNoticeSeen = new Map<string, number>();\n\tconst rerenderWidget = (ctx: ExtensionContext, jobs = Array.from(state.asyncJobs.values())) => {\n\t\trenderWidget(ctx, options.widgetEnabled === false ? [] : jobs);\n\t\tctx.ui.requestRender?.();\n\t};\n\tconst refreshWidget = (ctx: ExtensionContext) => rerenderWidget(ctx);\n\tconst restoredControlEventCursor = (asyncDir: string) => {\n\t\ttry {\n\t\t\treturn fs.statSync(path.join(asyncDir, \"events.jsonl\")).size;\n\t\t} catch (error) {\n\t\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return 0;\n\t\t\tthrow error;\n\t\t}\n\t};\n\tconst summaryToJob = (run: AsyncRunSummary): AsyncJobState => {\n\t\tconst groups = normalizeParallelGroups(run.parallelGroups, run.steps.length, run.chainStepCount ?? run.steps.length);\n\t\tconst activeGroup = run.currentStep !== undefined\n\t\t\t? groups.find((group) => run.currentStep! >= group.start && run.currentStep! < group.start + group.count)\n\t\t\t: undefined;\n\t\tconst visibleSteps = activeGroup\n\t\t\t? run.steps.slice(activeGroup.start, activeGroup.start + activeGroup.count).map((step, index) => ({ ...step, index: activeGroup.start + index }))\n\t\t\t: run.steps.map((step, index) => ({ ...step, index }));\n\t\treturn {\n\t\t\tasyncId: run.id,\n\t\t\tasyncDir: run.asyncDir,\n\t\t\tstatus: run.state,\n\t\t\tsessionId: run.sessionId,\n\t\t\tactivityState: run.activityState,\n\t\t\tlastActivityAt: run.lastActivityAt,\n\t\t\tcurrentTool: run.currentTool,\n\t\t\tcurrentToolStartedAt: run.currentToolStartedAt,\n\t\t\tcurrentPath: run.currentPath,\n\t\t\tturnCount: run.turnCount,\n\t\t\ttoolCount: run.toolCount,\n\t\t\tsteering: run.steering,\n\t\t\tmode: run.mode,\n\t\t\tagents: visibleSteps.map((step) => step.agent),\n\t\t\tcurrentStep: run.currentStep,\n\t\t\tchainStepCount: run.chainStepCount,\n\t\t\tparallelGroups: groups,\n\t\t\tsteps: visibleSteps,\n\t\t\tstepsTotal: visibleSteps.length,\n\t\t\trunningSteps: visibleSteps.filter((step) => step.status === \"running\").length,\n\t\t\tcompletedSteps: visibleSteps.filter((step) => step.status === \"complete\" || step.status === \"completed\").length,\n\t\t\thasParallelGroups: groups.length > 0,\n\t\t\tactiveParallelGroup: Boolean(activeGroup),\n\t\t\tstartedAt: run.startedAt,\n\t\t\tupdatedAt: run.lastUpdate ?? run.startedAt,\n\t\t\ttimeoutMs: run.timeoutMs,\n\t\t\tdeadlineAt: run.deadlineAt,\n\t\t\ttimedOut: run.timedOut,\n\t\t\tstopped: run.stopped,\n\t\t\tturnBudget: run.turnBudget,\n\t\t\tturnBudgetExceeded: run.turnBudgetExceeded,\n\t\t\twrapUpRequested: run.wrapUpRequested,\n\t\t\tsessionDir: run.sessionDir,\n\t\t\toutputFile: run.outputFile,\n\t\t\ttotalTokens: run.totalTokens,\n\t\t\tsessionFile: run.sessionFile,\n\t\t\tcontrolEventCursor: restoredControlEventCursor(run.asyncDir),\n\t\t\tnestedChildren: run.nestedChildren,\n\t\t};\n\t};\n\tconst cancelCleanup = (asyncId: string) => {\n\t\tconst existingTimer = state.cleanupTimers.get(asyncId);\n\t\tif (!existingTimer) return;\n\t\tclearTimeout(existingTimer);\n\t\tstate.cleanupTimers.delete(asyncId);\n\t};\n\tconst scheduleCleanup = (asyncId: string) => {\n\t\tcancelCleanup(asyncId);\n\t\tconst timer = setTimeout(() => {\n\t\t\tstate.cleanupTimers.delete(asyncId);\n\t\t\tstate.asyncJobs.delete(asyncId);\n\t\t\tif (state.lastUiContext) {\n\t\t\t\trerenderWidget(state.lastUiContext);\n\t\t\t}\n\t\t}, completionRetentionMs);\n\t\tstate.cleanupTimers.set(asyncId, timer);\n\t};\n\tconst emitNewControlEvents = (job: AsyncJobState) => {\n\t\tconst eventsPath = path.join(job.asyncDir, \"events.jsonl\");\n\t\tlet fd: number;\n\t\ttry {\n\t\t\tfd = fs.openSync(eventsPath, \"r\");\n\t\t} catch (error) {\n\t\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return;\n\t\t\tconsole.error(`Failed to open async control events for '${job.asyncDir}':`, error);\n\t\t\treturn;\n\t\t}\n\t\ttry {\n\t\t\tconst stat = fs.fstatSync(fd);\n\t\t\tconst savedCursor = job.controlEventCursor;\n\t\t\tlet cursor = stat.size < (savedCursor ?? 0) ? 0 : (savedCursor ?? 0);\n\t\t\tconst startedFromTail = savedCursor === undefined && stat.size > CONTROL_EVENT_SCAN_WINDOW_BYTES;\n\t\t\tif (startedFromTail) cursor = stat.size - CONTROL_EVENT_SCAN_WINDOW_BYTES;\n\t\t\tif (stat.size <= cursor) return;\n\t\t\tconst scanEnd = Math.min(stat.size, cursor + CONTROL_EVENT_SCAN_WINDOW_BYTES);\n\t\t\tconst handleLine = (line: string) => {\n\t\t\t\tif (!line.trim()) return;\n\t\t\t\tlet parsed: unknown;\n\t\t\t\ttry {\n\t\t\t\t\tparsed = JSON.parse(line);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconsole.error(`Ignoring malformed async control event in '${eventsPath}':`, error);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (!parsed || typeof parsed !== \"object\") return;\n\t\t\t\tif ((parsed as { type?: unknown }).type === \"subagent.steering.notice\") {\n\t\t\t\t\tconst notice = parsed as Partial<SteeringNotice>;\n\t\t\t\t\tif (typeof notice.requestId !== \"string\" || typeof notice.runId !== \"string\" || (notice.state !== \"failed\" && notice.state !== \"partial\" && notice.state !== \"recovered\") || typeof notice.message !== \"string\") return;\n\t\t\t\t\tif (typeof state.currentSessionId === \"string\" && notice.currentSessionId !== state.currentSessionId) return;\n\t\t\t\t\tconst key = `${notice.runId}:${notice.requestId}:${notice.state}`;\n\t\t\t\t\tif (steeringNoticeSeen.has(key)) return;\n\t\t\t\t\tconst now = Date.now();\n\t\t\t\t\tsteeringNoticeSeen.set(key, now);\n\t\t\t\t\tif (steeringNoticeSeen.size > 200) {\n\t\t\t\t\t\tfor (const [seenKey, seenAt] of steeringNoticeSeen) {\n\t\t\t\t\t\t\tif (now - seenAt > 10 * 60 * 1000 || steeringNoticeSeen.size > 200) steeringNoticeSeen.delete(seenKey);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tpi.events.emit(SUBAGENT_STEERING_NOTICE_EVENT, { ...notice, source: \"async\", asyncDir: job.asyncDir, noticeText: notice.message });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif ((parsed as { type?: unknown }).type !== \"subagent.control\") return;\n\t\t\t\tconst record = parsed as { event?: ControlEvent; channels?: string[]; childIntercomTarget?: string; noticeText?: string; intercom?: { to?: string; message?: string } };\n\t\t\t\tif (!record.event || !Array.isArray(record.channels)) return;\n\t\t\t\tif (record.event.reason === \"completion_guard\") return;\n\t\t\t\tconst payload = {\n\t\t\t\t\tevent: record.event,\n\t\t\t\t\tsource: \"async\" as const,\n\t\t\t\t\tasyncDir: job.asyncDir,\n\t\t\t\t\tchildIntercomTarget: record.childIntercomTarget,\n\t\t\t\t\tnoticeText: record.noticeText ?? formatControlNoticeMessage(record.event, record.childIntercomTarget),\n\t\t\t\t};\n\t\t\t\tif (record.channels.includes(\"event\")) {\n\t\t\t\t\tpi.events.emit(SUBAGENT_CONTROL_EVENT, payload);\n\t\t\t\t}\n\t\t\t\tif (record.event.type !== \"active_long_running\" && record.channels.includes(\"intercom\") && record.intercom?.to && record.intercom.message) {\n\t\t\t\t\tpi.events.emit(SUBAGENT_CONTROL_INTERCOM_EVENT, {\n\t\t\t\t\t\t...payload,\n\t\t\t\t\t\tto: record.intercom.to,\n\t\t\t\t\t\tmessage: record.intercom.message,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t};\n\t\t\tlet readCursor = cursor;\n\t\t\tlet lastCompleteCursor = cursor;\n\t\t\tlet lineParts: Buffer[] = [];\n\t\t\tlet lineBytes = 0;\n\t\t\tlet skippingOversizedLine = startedFromTail;\n\t\t\tconst appendLineSegment = (segment: Buffer) => {\n\t\t\t\tif (segment.length === 0 || skippingOversizedLine) return;\n\t\t\t\tif (lineBytes + segment.length > MAX_CONTROL_EVENT_LINE_BYTES) {\n\t\t\t\t\tlineParts = [];\n\t\t\t\t\tlineBytes = 0;\n\t\t\t\t\tskippingOversizedLine = true;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tlineParts.push(segment);\n\t\t\t\tlineBytes += segment.length;\n\t\t\t};\n\t\t\twhile (readCursor < scanEnd) {\n\t\t\t\tconst toRead = Math.min(CONTROL_EVENT_READ_CHUNK_BYTES, scanEnd - readCursor);\n\t\t\t\tconst buffer = Buffer.alloc(toRead);\n\t\t\t\tconst bytesRead = fs.readSync(fd, buffer, 0, toRead, readCursor);\n\t\t\t\tif (bytesRead <= 0) break;\n\t\t\t\tconst chunk = bytesRead === buffer.length ? buffer : buffer.subarray(0, bytesRead);\n\t\t\t\tlet lineStart = 0;\n\t\t\t\tfor (let index = 0; index < chunk.length; index++) {\n\t\t\t\t\tif (chunk[index] !== 0x0a) continue;\n\t\t\t\t\tappendLineSegment(chunk.subarray(lineStart, index));\n\t\t\t\t\tif (!skippingOversizedLine && lineBytes > 0) {\n\t\t\t\t\t\thandleLine(Buffer.concat(lineParts, lineBytes).toString(\"utf-8\"));\n\t\t\t\t\t}\n\t\t\t\t\tlineParts = [];\n\t\t\t\t\tlineBytes = 0;\n\t\t\t\t\tskippingOversizedLine = false;\n\t\t\t\t\tlastCompleteCursor = readCursor + index + 1;\n\t\t\t\t\tlineStart = index + 1;\n\t\t\t\t}\n\t\t\t\tappendLineSegment(chunk.subarray(lineStart));\n\t\t\t\treadCursor += bytesRead;\n\t\t\t\tif (skippingOversizedLine) job.controlEventCursor = readCursor;\n\t\t\t}\n\t\t\tif (lastCompleteCursor > cursor) job.controlEventCursor = lastCompleteCursor;\n\t\t\telse if (scanEnd < stat.size || startedFromTail) job.controlEventCursor = scanEnd;\n\t\t} catch (error) {\n\t\t\tconsole.error(`Failed to read async control events for '${job.asyncDir}':`, error);\n\t\t} finally {\n\t\t\tfs.closeSync(fd);\n\t\t}\n\t};\n\n\tconst ensurePoller = () => {\n\t\tif (state.poller) return;\n\t\tstate.poller = setInterval(() => {\n\t\t\tif (state.asyncJobs.size === 0) {\n\t\t\t\tif (state.lastUiContext?.hasUI) rerenderWidget(state.lastUiContext, []);\n\t\t\t\tif (state.poller) {\n\t\t\t\t\tclearInterval(state.poller);\n\t\t\t\t\tstate.poller = null;\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlet widgetChanged = false;\n\t\t\tfor (const job of state.asyncJobs.values()) {\n\t\t\t\tconst widgetStateBefore = widgetRenderKey(job);\n\t\t\t\tlet nestedRefreshFailed = false;\n\t\t\t\tconst refreshNestedProjection = () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tupdateAsyncJobNestedProjection(job);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tnestedRefreshFailed = true;\n\t\t\t\t\t\tconsole.error(`Failed to refresh nested async descendants for '${job.asyncDir}':`, error);\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\tconst reconcileNestedDescendants = () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (job.nestedRoute) reconcileNestedAsyncDescendants(job.nestedRoute, { resultsDir, kill: options.kill, now: options.now });\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tnestedRefreshFailed = true;\n\t\t\t\t\t\tconsole.error(`Failed to refresh nested async descendants for '${job.asyncDir}':`, error);\n\t\t\t\t\t}\n\t\t\t\t\trefreshNestedProjection();\n\t\t\t\t};\n\t\t\t\ttry {\n\t\t\t\t\temitNewControlEvents(job);\n\t\t\t\t\treconcileNestedDescendants();\n\t\t\t\t\tconst reconciliation = reconcileAsyncRun(job.asyncDir, {\n\t\t\t\t\t\tresultsDir,\n\t\t\t\t\t\tkill: options.kill,\n\t\t\t\t\t\tnow: options.now,\n\t\t\t\t\t\tstartedRun: {\n\t\t\t\t\t\t\trunId: job.asyncId,\n\t\t\t\t\t\t\tpid: job.pid,\n\t\t\t\t\t\t\tsessionId: job.sessionId,\n\t\t\t\t\t\t\tmode: job.mode,\n\t\t\t\t\t\t\tagents: job.agents,\n\t\t\t\t\t\t\tchainStepCount: job.chainStepCount,\n\t\t\t\t\t\t\tparallelGroups: job.parallelGroups,\n\t\t\t\t\t\t\tstartedAt: job.startedAt,\n\t\t\t\t\t\t\tsessionFile: job.sessionFile,\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t\tconst status = reconciliation.status ?? readStatus(job.asyncDir);\n\t\t\t\t\tif (status) {\n\t\t\t\t\t\tconst previousStatus = job.status;\n\t\t\t\t\t\tjob.status = status.state;\n\t\t\t\t\t\tif (job.status !== \"complete\" && job.status !== \"failed\" && job.status !== \"paused\" && job.status !== \"stopped\") cancelCleanup(job.asyncId);\n\t\t\t\t\t\tjob.sessionId = status.sessionId ?? job.sessionId;\n\t\t\t\t\t\tjob.activityState = status.activityState;\n\t\t\t\t\t\tjob.lastActivityAt = status.lastActivityAt ?? job.lastActivityAt;\n\t\t\t\t\t\tjob.currentTool = status.currentTool;\n\t\t\t\t\t\tjob.currentToolStartedAt = status.currentToolStartedAt;\n\t\t\t\t\t\tjob.currentPath = status.currentPath;\n\t\t\t\t\t\tjob.turnCount = status.turnCount ?? job.turnCount;\n\t\t\t\t\t\tjob.toolCount = status.toolCount ?? job.toolCount;\n\t\t\t\t\t\tjob.steering = status.steering ?? job.steering;\n\t\t\t\t\t\tjob.mode = status.mode;\n\t\t\t\t\t\tjob.currentStep = status.currentStep ?? job.currentStep;\n\t\t\t\t\t\tjob.chainStepCount = status.chainStepCount ?? job.chainStepCount;\n\t\t\t\t\t\tjob.startedAt = status.startedAt ?? job.startedAt;\n\t\t\t\t\t\tif (status.lastUpdate !== undefined) job.updatedAt = status.lastUpdate;\n\t\t\t\t\t\tif (status.steps?.length) {\n\t\t\t\t\t\t\tconst groups = normalizeParallelGroups(status.parallelGroups, status.steps.length, status.chainStepCount ?? status.steps.length);\n\t\t\t\t\t\t\tjob.parallelGroups = groups.length ? groups : job.parallelGroups;\n\t\t\t\t\t\t\tjob.hasParallelGroups = groups.length > 0 || job.hasParallelGroups;\n\t\t\t\t\t\t\tconst activeGroup = status.currentStep !== undefined\n\t\t\t\t\t\t\t\t? groups.find((group) => status.currentStep! >= group.start && status.currentStep! < group.start + group.count)\n\t\t\t\t\t\t\t\t: undefined;\n\t\t\t\t\t\t\tconst visibleSteps = activeGroup\n\t\t\t\t\t\t\t\t? status.steps.slice(activeGroup.start, activeGroup.start + activeGroup.count).map((step, index) => ({ ...step, index: activeGroup.start + index }))\n\t\t\t\t\t\t\t\t: status.steps.map((step, index) => ({ ...step, index }));\n\t\t\t\t\t\t\tjob.activeParallelGroup = Boolean(activeGroup);\n\t\t\t\t\t\t\tjob.agents = visibleSteps.map((step) => step.agent);\n\t\t\t\t\t\t\tjob.steps = visibleSteps;\n\t\t\t\t\t\t\trefreshNestedProjection();\n\t\t\t\t\t\t\tjob.stepsTotal = visibleSteps.length;\n\t\t\t\t\t\t\tjob.runningSteps = visibleSteps.filter((step) => step.status === \"running\").length;\n\t\t\t\t\t\t\tjob.completedSteps = visibleSteps.filter((step) => step.status === \"complete\" || step.status === \"completed\").length;\n\t\t\t\t\t\t\tif (status.state === \"complete\") job.completedSteps = visibleSteps.length;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tjob.sessionDir = status.sessionDir ?? job.sessionDir;\n\t\t\t\t\t\tjob.outputFile = status.outputFile ?? job.outputFile;\n\t\t\t\t\t\tjob.totalTokens = status.totalTokens ?? job.totalTokens;\n\t\t\t\t\t\tjob.timeoutMs = status.timeoutMs ?? job.timeoutMs;\n\t\t\t\t\t\tjob.deadlineAt = status.deadlineAt ?? job.deadlineAt;\n\t\t\t\t\t\tjob.timedOut = status.timedOut ?? job.timedOut;\n\t\t\t\t\t\tjob.stopped = status.stopped ?? job.stopped;\n\t\t\t\t\t\tjob.turnBudget = status.turnBudget ?? job.turnBudget;\n\t\t\t\t\t\tjob.turnBudgetExceeded = status.turnBudgetExceeded ?? job.turnBudgetExceeded;\n\t\t\t\t\t\tjob.wrapUpRequested = status.wrapUpRequested ?? job.wrapUpRequested;\n\t\t\t\t\t\tjob.sessionFile = status.sessionFile ?? job.sessionFile;\n\t\t\t\t\t\tif (job.status === \"complete\" || job.status === \"failed\" || job.status === \"paused\" || job.status === \"stopped\") {\n\t\t\t\t\t\t\trememberFleetJob(state, job);\n\t\t\t\t\t\t\tif (!nestedRefreshFailed && !hasLiveNestedDescendants(job.nestedChildren) && (previousStatus !== job.status || !state.cleanupTimers.has(job.asyncId))) {\n\t\t\t\t\t\t\t\tscheduleCleanup(job.asyncId);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (widgetRenderKey(job) !== widgetStateBefore) widgetChanged = true;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tif (job.status === \"queued\") {\n\t\t\t\t\t\tjob.status = \"running\";\n\t\t\t\t\t\tjob.updatedAt = Date.now();\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (job.status !== \"failed\") {\n\t\t\t\t\t\tconsole.error(`Failed to read async status for '${job.asyncDir}':`, error);\n\t\t\t\t\t\tjob.status = \"failed\";\n\t\t\t\t\t\tjob.updatedAt = Date.now();\n\t\t\t\t\t}\n\t\t\t\t\trememberFleetJob(state, job);\n\t\t\t\t\tif (!hasLiveNestedDescendants(job.nestedChildren) && !state.cleanupTimers.has(job.asyncId)) {\n\t\t\t\t\t\tscheduleCleanup(job.asyncId);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (widgetRenderKey(job) !== widgetStateBefore) widgetChanged = true;\n\t\t\t}\n\n\t\t\tif (widgetChanged && state.lastUiContext?.hasUI) rerenderWidget(state.lastUiContext);\n\t\t}, pollIntervalMs);\n\t\tstate.poller.unref?.();\n\t};\n\n\tconst handleStarted = (data: unknown) => {\n\t\tconst info = data as AsyncStartedEvent;\n\t\tif (!info.id) return;\n\t\tif (typeof state.currentSessionId === \"string\" && info.sessionId !== state.currentSessionId) return;\n\t\tconst now = Date.now();\n\t\tconst asyncDir = info.asyncDir ?? path.join(asyncDirRoot, info.id);\n\t\tconst rawAgents = info.agents?.length ? info.agents : info.chain && info.chain.length > 0 ? info.chain : info.agent ? [info.agent] : undefined;\n\t\tconst validParallelGroups = normalizeParallelGroups(info.parallelGroups, Number.MAX_SAFE_INTEGER, info.chainStepCount ?? Number.MAX_SAFE_INTEGER);\n\t\tconst firstGroup = validParallelGroups.find((group) => group.start === 0);\n\t\tconst firstGroupCount = firstGroup?.count;\n\t\tconst agents = firstGroupCount && firstGroupCount > 0\n\t\t\t? rawAgents?.slice(0, firstGroupCount)\n\t\t\t: rawAgents;\n\t\tstate.asyncJobs.set(info.id, {\n\t\t\tasyncId: info.id,\n\t\t\tasyncDir,\n\t\t\tstatus: \"queued\",\n\t\t\tpid: typeof info.pid === \"number\" ? info.pid : undefined,\n\t\t\t...(typeof info.sessionId === \"string\" ? { sessionId: info.sessionId } : {}),\n\t\t\tmode: info.mode ?? (info.chain ? \"chain\" : \"single\"),\n\t\t\tagents,\n\t\t\tchainStepCount: info.chainStepCount,\n\t\t\tparallelGroups: validParallelGroups,\n\t\t\tnestedRoute: info.nestedRoute,\n\t\t\tstepsTotal: firstGroupCount ?? agents?.length,\n\t\t\thasParallelGroups: validParallelGroups.length > 0,\n\t\t\tactiveParallelGroup: Boolean(firstGroupCount && firstGroupCount > 0),\n\t\t\tstartedAt: now,\n\t\t\tupdatedAt: now,\n\t\t\ttimeoutMs: info.timeoutMs,\n\t\t\tdeadlineAt: info.deadlineAt,\n\t\t\tturnBudget: info.turnBudget,\n\t\t\tcontrolEventCursor: 0,\n\t\t});\n\t\trememberFleetJob(state, state.asyncJobs.get(info.id)!);\n\t\tensurePoller();\n\t\tif (state.lastUiContext) {\n\t\t\trerenderWidget(state.lastUiContext);\n\t\t}\n\t};\n\n\tconst handleComplete = (data: unknown) => {\n\t\tconst result = data as { id?: string; success?: boolean; state?: AsyncJobState[\"status\"]; asyncDir?: string; sessionId?: string; stopped?: boolean };\n\t\tif (typeof state.currentSessionId === \"string\" && result.sessionId !== state.currentSessionId) return;\n\t\tconst asyncId = result.id;\n\t\tif (!asyncId) return;\n\t\tconst job = state.asyncJobs.get(asyncId);\n\t\tlet nestedRefreshFailed = false;\n\t\tif (job) {\n\t\t\tjob.status = result.state ?? (result.success ? \"complete\" : \"failed\");\n\t\t\tjob.stopped = result.stopped ?? job.stopped;\n\t\t\tjob.updatedAt = Date.now();\n\t\t\tif (result.asyncDir) job.asyncDir = result.asyncDir;\n\t\t\ttry {\n\t\t\t\tupdateAsyncJobNestedProjection(job);\n\t\t\t} catch (error) {\n\t\t\t\tnestedRefreshFailed = true;\n\t\t\t\tconsole.error(`Failed to refresh nested async descendants for '${job.asyncDir}':`, error);\n\t\t\t}\n\t\t}\n\t\tif (job) rememberFleetJob(state, job);\n\t\tif (state.lastUiContext) {\n\t\t\trerenderWidget(state.lastUiContext);\n\t\t}\n\t\tif (!nestedRefreshFailed && !hasLiveNestedDescendants(job?.nestedChildren)) scheduleCleanup(asyncId);\n\t};\n\n\tconst resetJobs = (ctx?: ExtensionContext) => {\n\t\tfor (const timer of state.cleanupTimers.values()) {\n\t\t\tclearTimeout(timer);\n\t\t}\n\t\tstate.cleanupTimers.clear();\n\t\tstate.asyncJobs.clear();\n\t\tstate.fleetJobs?.clear();\n\t\tstate.foregroundControls?.clear();\n\t\tstate.lastForegroundControlId = null;\n\t\tstate.resultFileCoalescer.clear();\n\t\tif (ctx?.hasUI) {\n\t\t\tstate.lastUiContext = ctx;\n\t\t\trerenderWidget(ctx, []);\n\t\t}\n\t};\n\n\tconst restoreActiveJobs = (ctx?: ExtensionContext) => {\n\t\tif (ctx?.hasUI) state.lastUiContext = ctx;\n\t\tif (!state.currentSessionId) return;\n\t\tlet runs: AsyncRunSummary[];\n\t\ttry {\n\t\t\truns = listAsyncRuns(asyncDirRoot, { states: [\"queued\", \"running\"], sessionId: state.currentSessionId, resultsDir, kill: options.kill, now: options.now });\n\t\t} catch (error) {\n\t\t\tconsole.error(`Failed to restore active async jobs from '${asyncDirRoot}':`, error);\n\t\t\treturn;\n\t\t}\n\t\tfor (const run of runs) {\n\t\t\tconst job = summaryToJob(run);\n\t\t\tstate.asyncJobs.set(run.id, job);\n\t\t\trememberFleetJob(state, job);\n\t\t}\n\t\tif (runs.length === 0) return;\n\t\tensurePoller();\n\t\tif (state.lastUiContext?.hasUI) rerenderWidget(state.lastUiContext);\n\t};\n\n\treturn { ensurePoller, refreshWidget, handleStarted, handleComplete, resetJobs, restoreActiveJobs };\n}\n"]}
|
|
@@ -168,6 +168,8 @@ export function createAsyncJobTracker(pi, state, asyncDirRoot, options = {}) {
|
|
|
168
168
|
const record = parsed;
|
|
169
169
|
if (!record.event || !Array.isArray(record.channels))
|
|
170
170
|
return;
|
|
171
|
+
if (record.event.reason === "completion_guard")
|
|
172
|
+
return;
|
|
171
173
|
const payload = {
|
|
172
174
|
event: record.event,
|
|
173
175
|
source: "async",
|
|
@@ -378,8 +380,7 @@ export function createAsyncJobTracker(pi, state, asyncDirRoot, options = {}) {
|
|
|
378
380
|
if (widgetRenderKey(job) !== widgetStateBefore)
|
|
379
381
|
widgetChanged = true;
|
|
380
382
|
}
|
|
381
|
-
|
|
382
|
-
if ((widgetChanged || timerNeedsPaint) && state.lastUiContext?.hasUI)
|
|
383
|
+
if (widgetChanged && state.lastUiContext?.hasUI)
|
|
383
384
|
rerenderWidget(state.lastUiContext);
|
|
384
385
|
}, pollIntervalMs);
|
|
385
386
|
state.poller.unref?.();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"async-job-tracker.js","sourceRoot":"","sources":["../../../../../../src/builtin-extensions/pi-subagents/src/runs/background/async-job-tracker.ts"],"names":[],"mappings":"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","sourcesContent":["// @ts-nocheck\nimport type { ExtensionAPI, ExtensionContext } from \"@ashx-j/lunr-dev\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { renderWidget, widgetRenderKey } from \"../../tui/render.ts\";\nimport { formatControlNoticeMessage } from \"../shared/subagent-control.ts\";\nimport {\n\ttype AsyncJobState,\n\ttype AsyncStartedEvent,\n\ttype ControlEvent,\n\ttype SteeringNotice,\n\ttype SubagentState,\n\tPOLL_INTERVAL_MS,\n\tRESULTS_DIR,\n\tSUBAGENT_CONTROL_EVENT,\n\tSUBAGENT_CONTROL_INTERCOM_EVENT,\n\tSUBAGENT_STEERING_NOTICE_EVENT,\n} from \"../../shared/types.ts\";\nimport { readStatus } from \"../../shared/utils.ts\";\nimport { normalizeParallelGroups } from \"./parallel-groups.ts\";\nimport { reconcileAsyncRun, reconcileNestedAsyncDescendants } from \"./stale-run-reconciler.ts\";\nimport { hasLiveNestedDescendants, updateAsyncJobNestedProjection } from \"../shared/nested-events.ts\";\nimport { listAsyncRuns, type AsyncRunSummary } from \"./async-status.ts\";\n\ninterface AsyncJobTrackerOptions {\n\tcompletionRetentionMs?: number;\n\tpollIntervalMs?: number;\n\tresultsDir?: string;\n\twidgetEnabled?: boolean;\n\tkill?: (pid: number, signal?: NodeJS.Signals | 0) => boolean;\n\tnow?: () => number;\n}\n\nconst CONTROL_EVENT_READ_CHUNK_BYTES = 64 * 1024;\nconst MAX_CONTROL_EVENT_LINE_BYTES = 1024 * 1024;\nconst CONTROL_EVENT_SCAN_WINDOW_BYTES = 2 * 1024 * 1024;\nconst MAX_RECENT_FLEET_JOBS = 20;\n\nfunction rememberFleetJob(state: SubagentState, job: AsyncJobState): void {\n\tstate.fleetJobs ??= new Map();\n\tstate.fleetJobs.set(job.asyncId, job);\n\tconst terminal = [...state.fleetJobs.values()]\n\t\t.filter((candidate) => candidate.status === \"complete\" || candidate.status === \"failed\" || candidate.status === \"paused\" || candidate.status === \"stopped\")\n\t\t.sort((left, right) => (right.updatedAt ?? right.startedAt ?? 0) - (left.updatedAt ?? left.startedAt ?? 0));\n\tfor (const stale of terminal.slice(MAX_RECENT_FLEET_JOBS)) state.fleetJobs.delete(stale.asyncId);\n}\n\nexport function createAsyncJobTracker(pi: Pick<ExtensionAPI, \"events\">, state: SubagentState, asyncDirRoot: string, options: AsyncJobTrackerOptions = {}): {\n\tensurePoller: () => void;\n\trefreshWidget: (ctx: ExtensionContext) => void;\n\thandleStarted: (data: unknown) => void;\n\thandleComplete: (data: unknown) => void;\n\tresetJobs: (ctx?: ExtensionContext) => void;\n\trestoreActiveJobs: (ctx?: ExtensionContext) => void;\n} {\n\tconst completionRetentionMs = options.completionRetentionMs ?? 10000;\n\tconst pollIntervalMs = options.pollIntervalMs ?? POLL_INTERVAL_MS;\n\tconst resultsDir = options.resultsDir ?? RESULTS_DIR;\n\tconst steeringNoticeSeen = new Map<string, number>();\n\tconst rerenderWidget = (ctx: ExtensionContext, jobs = Array.from(state.asyncJobs.values())) => {\n\t\trenderWidget(ctx, options.widgetEnabled === false ? [] : jobs);\n\t\tctx.ui.requestRender?.();\n\t};\n\tconst refreshWidget = (ctx: ExtensionContext) => rerenderWidget(ctx);\n\tconst restoredControlEventCursor = (asyncDir: string) => {\n\t\ttry {\n\t\t\treturn fs.statSync(path.join(asyncDir, \"events.jsonl\")).size;\n\t\t} catch (error) {\n\t\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return 0;\n\t\t\tthrow error;\n\t\t}\n\t};\n\tconst summaryToJob = (run: AsyncRunSummary): AsyncJobState => {\n\t\tconst groups = normalizeParallelGroups(run.parallelGroups, run.steps.length, run.chainStepCount ?? run.steps.length);\n\t\tconst activeGroup = run.currentStep !== undefined\n\t\t\t? groups.find((group) => run.currentStep! >= group.start && run.currentStep! < group.start + group.count)\n\t\t\t: undefined;\n\t\tconst visibleSteps = activeGroup\n\t\t\t? run.steps.slice(activeGroup.start, activeGroup.start + activeGroup.count).map((step, index) => ({ ...step, index: activeGroup.start + index }))\n\t\t\t: run.steps.map((step, index) => ({ ...step, index }));\n\t\treturn {\n\t\t\tasyncId: run.id,\n\t\t\tasyncDir: run.asyncDir,\n\t\t\tstatus: run.state,\n\t\t\tsessionId: run.sessionId,\n\t\t\tactivityState: run.activityState,\n\t\t\tlastActivityAt: run.lastActivityAt,\n\t\t\tcurrentTool: run.currentTool,\n\t\t\tcurrentToolStartedAt: run.currentToolStartedAt,\n\t\t\tcurrentPath: run.currentPath,\n\t\t\tturnCount: run.turnCount,\n\t\t\ttoolCount: run.toolCount,\n\t\t\tsteering: run.steering,\n\t\t\tmode: run.mode,\n\t\t\tagents: visibleSteps.map((step) => step.agent),\n\t\t\tcurrentStep: run.currentStep,\n\t\t\tchainStepCount: run.chainStepCount,\n\t\t\tparallelGroups: groups,\n\t\t\tsteps: visibleSteps,\n\t\t\tstepsTotal: visibleSteps.length,\n\t\t\trunningSteps: visibleSteps.filter((step) => step.status === \"running\").length,\n\t\t\tcompletedSteps: visibleSteps.filter((step) => step.status === \"complete\" || step.status === \"completed\").length,\n\t\t\thasParallelGroups: groups.length > 0,\n\t\t\tactiveParallelGroup: Boolean(activeGroup),\n\t\t\tstartedAt: run.startedAt,\n\t\t\tupdatedAt: run.lastUpdate ?? run.startedAt,\n\t\t\ttimeoutMs: run.timeoutMs,\n\t\t\tdeadlineAt: run.deadlineAt,\n\t\t\ttimedOut: run.timedOut,\n\t\t\tstopped: run.stopped,\n\t\t\tturnBudget: run.turnBudget,\n\t\t\tturnBudgetExceeded: run.turnBudgetExceeded,\n\t\t\twrapUpRequested: run.wrapUpRequested,\n\t\t\tsessionDir: run.sessionDir,\n\t\t\toutputFile: run.outputFile,\n\t\t\ttotalTokens: run.totalTokens,\n\t\t\tsessionFile: run.sessionFile,\n\t\t\tcontrolEventCursor: restoredControlEventCursor(run.asyncDir),\n\t\t\tnestedChildren: run.nestedChildren,\n\t\t};\n\t};\n\tconst cancelCleanup = (asyncId: string) => {\n\t\tconst existingTimer = state.cleanupTimers.get(asyncId);\n\t\tif (!existingTimer) return;\n\t\tclearTimeout(existingTimer);\n\t\tstate.cleanupTimers.delete(asyncId);\n\t};\n\tconst scheduleCleanup = (asyncId: string) => {\n\t\tcancelCleanup(asyncId);\n\t\tconst timer = setTimeout(() => {\n\t\t\tstate.cleanupTimers.delete(asyncId);\n\t\t\tstate.asyncJobs.delete(asyncId);\n\t\t\tif (state.lastUiContext) {\n\t\t\t\trerenderWidget(state.lastUiContext);\n\t\t\t}\n\t\t}, completionRetentionMs);\n\t\tstate.cleanupTimers.set(asyncId, timer);\n\t};\n\tconst emitNewControlEvents = (job: AsyncJobState) => {\n\t\tconst eventsPath = path.join(job.asyncDir, \"events.jsonl\");\n\t\tlet fd: number;\n\t\ttry {\n\t\t\tfd = fs.openSync(eventsPath, \"r\");\n\t\t} catch (error) {\n\t\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return;\n\t\t\tconsole.error(`Failed to open async control events for '${job.asyncDir}':`, error);\n\t\t\treturn;\n\t\t}\n\t\ttry {\n\t\t\tconst stat = fs.fstatSync(fd);\n\t\t\tconst savedCursor = job.controlEventCursor;\n\t\t\tlet cursor = stat.size < (savedCursor ?? 0) ? 0 : (savedCursor ?? 0);\n\t\t\tconst startedFromTail = savedCursor === undefined && stat.size > CONTROL_EVENT_SCAN_WINDOW_BYTES;\n\t\t\tif (startedFromTail) cursor = stat.size - CONTROL_EVENT_SCAN_WINDOW_BYTES;\n\t\t\tif (stat.size <= cursor) return;\n\t\t\tconst scanEnd = Math.min(stat.size, cursor + CONTROL_EVENT_SCAN_WINDOW_BYTES);\n\t\t\tconst handleLine = (line: string) => {\n\t\t\t\tif (!line.trim()) return;\n\t\t\t\tlet parsed: unknown;\n\t\t\t\ttry {\n\t\t\t\t\tparsed = JSON.parse(line);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconsole.error(`Ignoring malformed async control event in '${eventsPath}':`, error);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (!parsed || typeof parsed !== \"object\") return;\n\t\t\t\tif ((parsed as { type?: unknown }).type === \"subagent.steering.notice\") {\n\t\t\t\t\tconst notice = parsed as Partial<SteeringNotice>;\n\t\t\t\t\tif (typeof notice.requestId !== \"string\" || typeof notice.runId !== \"string\" || (notice.state !== \"failed\" && notice.state !== \"partial\" && notice.state !== \"recovered\") || typeof notice.message !== \"string\") return;\n\t\t\t\t\tif (typeof state.currentSessionId === \"string\" && notice.currentSessionId !== state.currentSessionId) return;\n\t\t\t\t\tconst key = `${notice.runId}:${notice.requestId}:${notice.state}`;\n\t\t\t\t\tif (steeringNoticeSeen.has(key)) return;\n\t\t\t\t\tconst now = Date.now();\n\t\t\t\t\tsteeringNoticeSeen.set(key, now);\n\t\t\t\t\tif (steeringNoticeSeen.size > 200) {\n\t\t\t\t\t\tfor (const [seenKey, seenAt] of steeringNoticeSeen) {\n\t\t\t\t\t\t\tif (now - seenAt > 10 * 60 * 1000 || steeringNoticeSeen.size > 200) steeringNoticeSeen.delete(seenKey);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tpi.events.emit(SUBAGENT_STEERING_NOTICE_EVENT, { ...notice, source: \"async\", asyncDir: job.asyncDir, noticeText: notice.message });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif ((parsed as { type?: unknown }).type !== \"subagent.control\") return;\n\t\t\t\tconst record = parsed as { event?: ControlEvent; channels?: string[]; childIntercomTarget?: string; noticeText?: string; intercom?: { to?: string; message?: string } };\n\t\t\t\tif (!record.event || !Array.isArray(record.channels)) return;\n\t\t\t\tconst payload = {\n\t\t\t\t\tevent: record.event,\n\t\t\t\t\tsource: \"async\" as const,\n\t\t\t\t\tasyncDir: job.asyncDir,\n\t\t\t\t\tchildIntercomTarget: record.childIntercomTarget,\n\t\t\t\t\tnoticeText: record.noticeText ?? formatControlNoticeMessage(record.event, record.childIntercomTarget),\n\t\t\t\t};\n\t\t\t\tif (record.channels.includes(\"event\")) {\n\t\t\t\t\tpi.events.emit(SUBAGENT_CONTROL_EVENT, payload);\n\t\t\t\t}\n\t\t\t\tif (record.event.type !== \"active_long_running\" && record.channels.includes(\"intercom\") && record.intercom?.to && record.intercom.message) {\n\t\t\t\t\tpi.events.emit(SUBAGENT_CONTROL_INTERCOM_EVENT, {\n\t\t\t\t\t\t...payload,\n\t\t\t\t\t\tto: record.intercom.to,\n\t\t\t\t\t\tmessage: record.intercom.message,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t};\n\t\t\tlet readCursor = cursor;\n\t\t\tlet lastCompleteCursor = cursor;\n\t\t\tlet lineParts: Buffer[] = [];\n\t\t\tlet lineBytes = 0;\n\t\t\tlet skippingOversizedLine = startedFromTail;\n\t\t\tconst appendLineSegment = (segment: Buffer) => {\n\t\t\t\tif (segment.length === 0 || skippingOversizedLine) return;\n\t\t\t\tif (lineBytes + segment.length > MAX_CONTROL_EVENT_LINE_BYTES) {\n\t\t\t\t\tlineParts = [];\n\t\t\t\t\tlineBytes = 0;\n\t\t\t\t\tskippingOversizedLine = true;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tlineParts.push(segment);\n\t\t\t\tlineBytes += segment.length;\n\t\t\t};\n\t\t\twhile (readCursor < scanEnd) {\n\t\t\t\tconst toRead = Math.min(CONTROL_EVENT_READ_CHUNK_BYTES, scanEnd - readCursor);\n\t\t\t\tconst buffer = Buffer.alloc(toRead);\n\t\t\t\tconst bytesRead = fs.readSync(fd, buffer, 0, toRead, readCursor);\n\t\t\t\tif (bytesRead <= 0) break;\n\t\t\t\tconst chunk = bytesRead === buffer.length ? buffer : buffer.subarray(0, bytesRead);\n\t\t\t\tlet lineStart = 0;\n\t\t\t\tfor (let index = 0; index < chunk.length; index++) {\n\t\t\t\t\tif (chunk[index] !== 0x0a) continue;\n\t\t\t\t\tappendLineSegment(chunk.subarray(lineStart, index));\n\t\t\t\t\tif (!skippingOversizedLine && lineBytes > 0) {\n\t\t\t\t\t\thandleLine(Buffer.concat(lineParts, lineBytes).toString(\"utf-8\"));\n\t\t\t\t\t}\n\t\t\t\t\tlineParts = [];\n\t\t\t\t\tlineBytes = 0;\n\t\t\t\t\tskippingOversizedLine = false;\n\t\t\t\t\tlastCompleteCursor = readCursor + index + 1;\n\t\t\t\t\tlineStart = index + 1;\n\t\t\t\t}\n\t\t\t\tappendLineSegment(chunk.subarray(lineStart));\n\t\t\t\treadCursor += bytesRead;\n\t\t\t\tif (skippingOversizedLine) job.controlEventCursor = readCursor;\n\t\t\t}\n\t\t\tif (lastCompleteCursor > cursor) job.controlEventCursor = lastCompleteCursor;\n\t\t\telse if (scanEnd < stat.size || startedFromTail) job.controlEventCursor = scanEnd;\n\t\t} catch (error) {\n\t\t\tconsole.error(`Failed to read async control events for '${job.asyncDir}':`, error);\n\t\t} finally {\n\t\t\tfs.closeSync(fd);\n\t\t}\n\t};\n\n\tconst ensurePoller = () => {\n\t\tif (state.poller) return;\n\t\tstate.poller = setInterval(() => {\n\t\t\tif (state.asyncJobs.size === 0) {\n\t\t\t\tif (state.lastUiContext?.hasUI) rerenderWidget(state.lastUiContext, []);\n\t\t\t\tif (state.poller) {\n\t\t\t\t\tclearInterval(state.poller);\n\t\t\t\t\tstate.poller = null;\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlet widgetChanged = false;\n\t\t\tfor (const job of state.asyncJobs.values()) {\n\t\t\t\tconst widgetStateBefore = widgetRenderKey(job);\n\t\t\t\tlet nestedRefreshFailed = false;\n\t\t\t\tconst refreshNestedProjection = () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tupdateAsyncJobNestedProjection(job);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tnestedRefreshFailed = true;\n\t\t\t\t\t\tconsole.error(`Failed to refresh nested async descendants for '${job.asyncDir}':`, error);\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\tconst reconcileNestedDescendants = () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (job.nestedRoute) reconcileNestedAsyncDescendants(job.nestedRoute, { resultsDir, kill: options.kill, now: options.now });\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tnestedRefreshFailed = true;\n\t\t\t\t\t\tconsole.error(`Failed to refresh nested async descendants for '${job.asyncDir}':`, error);\n\t\t\t\t\t}\n\t\t\t\t\trefreshNestedProjection();\n\t\t\t\t};\n\t\t\t\ttry {\n\t\t\t\t\temitNewControlEvents(job);\n\t\t\t\t\treconcileNestedDescendants();\n\t\t\t\t\tconst reconciliation = reconcileAsyncRun(job.asyncDir, {\n\t\t\t\t\t\tresultsDir,\n\t\t\t\t\t\tkill: options.kill,\n\t\t\t\t\t\tnow: options.now,\n\t\t\t\t\t\tstartedRun: {\n\t\t\t\t\t\t\trunId: job.asyncId,\n\t\t\t\t\t\t\tpid: job.pid,\n\t\t\t\t\t\t\tsessionId: job.sessionId,\n\t\t\t\t\t\t\tmode: job.mode,\n\t\t\t\t\t\t\tagents: job.agents,\n\t\t\t\t\t\t\tchainStepCount: job.chainStepCount,\n\t\t\t\t\t\t\tparallelGroups: job.parallelGroups,\n\t\t\t\t\t\t\tstartedAt: job.startedAt,\n\t\t\t\t\t\t\tsessionFile: job.sessionFile,\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t\tconst status = reconciliation.status ?? readStatus(job.asyncDir);\n\t\t\t\t\tif (status) {\n\t\t\t\t\t\tconst previousStatus = job.status;\n\t\t\t\t\t\tjob.status = status.state;\n\t\t\t\t\t\tif (job.status !== \"complete\" && job.status !== \"failed\" && job.status !== \"paused\" && job.status !== \"stopped\") cancelCleanup(job.asyncId);\n\t\t\t\t\t\tjob.sessionId = status.sessionId ?? job.sessionId;\n\t\t\t\t\t\tjob.activityState = status.activityState;\n\t\t\t\t\t\tjob.lastActivityAt = status.lastActivityAt ?? job.lastActivityAt;\n\t\t\t\t\t\tjob.currentTool = status.currentTool;\n\t\t\t\t\t\tjob.currentToolStartedAt = status.currentToolStartedAt;\n\t\t\t\t\t\tjob.currentPath = status.currentPath;\n\t\t\t\t\t\tjob.turnCount = status.turnCount ?? job.turnCount;\n\t\t\t\t\t\tjob.toolCount = status.toolCount ?? job.toolCount;\n\t\t\t\t\t\tjob.steering = status.steering ?? job.steering;\n\t\t\t\t\t\tjob.mode = status.mode;\n\t\t\t\t\t\tjob.currentStep = status.currentStep ?? job.currentStep;\n\t\t\t\t\t\tjob.chainStepCount = status.chainStepCount ?? job.chainStepCount;\n\t\t\t\t\t\tjob.startedAt = status.startedAt ?? job.startedAt;\n\t\t\t\t\t\tif (status.lastUpdate !== undefined) job.updatedAt = status.lastUpdate;\n\t\t\t\t\t\tif (status.steps?.length) {\n\t\t\t\t\t\t\tconst groups = normalizeParallelGroups(status.parallelGroups, status.steps.length, status.chainStepCount ?? status.steps.length);\n\t\t\t\t\t\t\tjob.parallelGroups = groups.length ? groups : job.parallelGroups;\n\t\t\t\t\t\t\tjob.hasParallelGroups = groups.length > 0 || job.hasParallelGroups;\n\t\t\t\t\t\t\tconst activeGroup = status.currentStep !== undefined\n\t\t\t\t\t\t\t\t? groups.find((group) => status.currentStep! >= group.start && status.currentStep! < group.start + group.count)\n\t\t\t\t\t\t\t\t: undefined;\n\t\t\t\t\t\t\tconst visibleSteps = activeGroup\n\t\t\t\t\t\t\t\t? status.steps.slice(activeGroup.start, activeGroup.start + activeGroup.count).map((step, index) => ({ ...step, index: activeGroup.start + index }))\n\t\t\t\t\t\t\t\t: status.steps.map((step, index) => ({ ...step, index }));\n\t\t\t\t\t\t\tjob.activeParallelGroup = Boolean(activeGroup);\n\t\t\t\t\t\t\tjob.agents = visibleSteps.map((step) => step.agent);\n\t\t\t\t\t\t\tjob.steps = visibleSteps;\n\t\t\t\t\t\t\trefreshNestedProjection();\n\t\t\t\t\t\t\tjob.stepsTotal = visibleSteps.length;\n\t\t\t\t\t\t\tjob.runningSteps = visibleSteps.filter((step) => step.status === \"running\").length;\n\t\t\t\t\t\t\tjob.completedSteps = visibleSteps.filter((step) => step.status === \"complete\" || step.status === \"completed\").length;\n\t\t\t\t\t\t\tif (status.state === \"complete\") job.completedSteps = visibleSteps.length;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tjob.sessionDir = status.sessionDir ?? job.sessionDir;\n\t\t\t\t\t\tjob.outputFile = status.outputFile ?? job.outputFile;\n\t\t\t\t\t\tjob.totalTokens = status.totalTokens ?? job.totalTokens;\n\t\t\t\t\t\tjob.timeoutMs = status.timeoutMs ?? job.timeoutMs;\n\t\t\t\t\t\tjob.deadlineAt = status.deadlineAt ?? job.deadlineAt;\n\t\t\t\t\t\tjob.timedOut = status.timedOut ?? job.timedOut;\n\t\t\t\t\t\tjob.stopped = status.stopped ?? job.stopped;\n\t\t\t\t\t\tjob.turnBudget = status.turnBudget ?? job.turnBudget;\n\t\t\t\t\t\tjob.turnBudgetExceeded = status.turnBudgetExceeded ?? job.turnBudgetExceeded;\n\t\t\t\t\t\tjob.wrapUpRequested = status.wrapUpRequested ?? job.wrapUpRequested;\n\t\t\t\t\t\tjob.sessionFile = status.sessionFile ?? job.sessionFile;\n\t\t\t\t\t\tif (job.status === \"complete\" || job.status === \"failed\" || job.status === \"paused\" || job.status === \"stopped\") {\n\t\t\t\t\t\t\trememberFleetJob(state, job);\n\t\t\t\t\t\t\tif (!nestedRefreshFailed && !hasLiveNestedDescendants(job.nestedChildren) && (previousStatus !== job.status || !state.cleanupTimers.has(job.asyncId))) {\n\t\t\t\t\t\t\t\tscheduleCleanup(job.asyncId);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (widgetRenderKey(job) !== widgetStateBefore) widgetChanged = true;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tif (job.status === \"queued\") {\n\t\t\t\t\t\tjob.status = \"running\";\n\t\t\t\t\t\tjob.updatedAt = Date.now();\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (job.status !== \"failed\") {\n\t\t\t\t\t\tconsole.error(`Failed to read async status for '${job.asyncDir}':`, error);\n\t\t\t\t\t\tjob.status = \"failed\";\n\t\t\t\t\t\tjob.updatedAt = Date.now();\n\t\t\t\t\t}\n\t\t\t\t\trememberFleetJob(state, job);\n\t\t\t\t\tif (!hasLiveNestedDescendants(job.nestedChildren) && !state.cleanupTimers.has(job.asyncId)) {\n\t\t\t\t\t\tscheduleCleanup(job.asyncId);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (widgetRenderKey(job) !== widgetStateBefore) widgetChanged = true;\n\t\t\t}\n\n\t\t\tconst timerNeedsPaint = [...state.asyncJobs.values()].some((job) => job.status === \"running\");\n\t\t\tif ((widgetChanged || timerNeedsPaint) && state.lastUiContext?.hasUI) rerenderWidget(state.lastUiContext);\n\t\t}, pollIntervalMs);\n\t\tstate.poller.unref?.();\n\t};\n\n\tconst handleStarted = (data: unknown) => {\n\t\tconst info = data as AsyncStartedEvent;\n\t\tif (!info.id) return;\n\t\tif (typeof state.currentSessionId === \"string\" && info.sessionId !== state.currentSessionId) return;\n\t\tconst now = Date.now();\n\t\tconst asyncDir = info.asyncDir ?? path.join(asyncDirRoot, info.id);\n\t\tconst rawAgents = info.agents?.length ? info.agents : info.chain && info.chain.length > 0 ? info.chain : info.agent ? [info.agent] : undefined;\n\t\tconst validParallelGroups = normalizeParallelGroups(info.parallelGroups, Number.MAX_SAFE_INTEGER, info.chainStepCount ?? Number.MAX_SAFE_INTEGER);\n\t\tconst firstGroup = validParallelGroups.find((group) => group.start === 0);\n\t\tconst firstGroupCount = firstGroup?.count;\n\t\tconst agents = firstGroupCount && firstGroupCount > 0\n\t\t\t? rawAgents?.slice(0, firstGroupCount)\n\t\t\t: rawAgents;\n\t\tstate.asyncJobs.set(info.id, {\n\t\t\tasyncId: info.id,\n\t\t\tasyncDir,\n\t\t\tstatus: \"queued\",\n\t\t\tpid: typeof info.pid === \"number\" ? info.pid : undefined,\n\t\t\t...(typeof info.sessionId === \"string\" ? { sessionId: info.sessionId } : {}),\n\t\t\tmode: info.mode ?? (info.chain ? \"chain\" : \"single\"),\n\t\t\tagents,\n\t\t\tchainStepCount: info.chainStepCount,\n\t\t\tparallelGroups: validParallelGroups,\n\t\t\tnestedRoute: info.nestedRoute,\n\t\t\tstepsTotal: firstGroupCount ?? agents?.length,\n\t\t\thasParallelGroups: validParallelGroups.length > 0,\n\t\t\tactiveParallelGroup: Boolean(firstGroupCount && firstGroupCount > 0),\n\t\t\tstartedAt: now,\n\t\t\tupdatedAt: now,\n\t\t\ttimeoutMs: info.timeoutMs,\n\t\t\tdeadlineAt: info.deadlineAt,\n\t\t\tturnBudget: info.turnBudget,\n\t\t\tcontrolEventCursor: 0,\n\t\t});\n\t\trememberFleetJob(state, state.asyncJobs.get(info.id)!);\n\t\tensurePoller();\n\t\tif (state.lastUiContext) {\n\t\t\trerenderWidget(state.lastUiContext);\n\t\t}\n\t};\n\n\tconst handleComplete = (data: unknown) => {\n\t\tconst result = data as { id?: string; success?: boolean; state?: AsyncJobState[\"status\"]; asyncDir?: string; sessionId?: string; stopped?: boolean };\n\t\tif (typeof state.currentSessionId === \"string\" && result.sessionId !== state.currentSessionId) return;\n\t\tconst asyncId = result.id;\n\t\tif (!asyncId) return;\n\t\tconst job = state.asyncJobs.get(asyncId);\n\t\tlet nestedRefreshFailed = false;\n\t\tif (job) {\n\t\t\tjob.status = result.state ?? (result.success ? \"complete\" : \"failed\");\n\t\t\tjob.stopped = result.stopped ?? job.stopped;\n\t\t\tjob.updatedAt = Date.now();\n\t\t\tif (result.asyncDir) job.asyncDir = result.asyncDir;\n\t\t\ttry {\n\t\t\t\tupdateAsyncJobNestedProjection(job);\n\t\t\t} catch (error) {\n\t\t\t\tnestedRefreshFailed = true;\n\t\t\t\tconsole.error(`Failed to refresh nested async descendants for '${job.asyncDir}':`, error);\n\t\t\t}\n\t\t}\n\t\tif (job) rememberFleetJob(state, job);\n\t\tif (state.lastUiContext) {\n\t\t\trerenderWidget(state.lastUiContext);\n\t\t}\n\t\tif (!nestedRefreshFailed && !hasLiveNestedDescendants(job?.nestedChildren)) scheduleCleanup(asyncId);\n\t};\n\n\tconst resetJobs = (ctx?: ExtensionContext) => {\n\t\tfor (const timer of state.cleanupTimers.values()) {\n\t\t\tclearTimeout(timer);\n\t\t}\n\t\tstate.cleanupTimers.clear();\n\t\tstate.asyncJobs.clear();\n\t\tstate.fleetJobs?.clear();\n\t\tstate.foregroundControls?.clear();\n\t\tstate.lastForegroundControlId = null;\n\t\tstate.resultFileCoalescer.clear();\n\t\tif (ctx?.hasUI) {\n\t\t\tstate.lastUiContext = ctx;\n\t\t\trerenderWidget(ctx, []);\n\t\t}\n\t};\n\n\tconst restoreActiveJobs = (ctx?: ExtensionContext) => {\n\t\tif (ctx?.hasUI) state.lastUiContext = ctx;\n\t\tif (!state.currentSessionId) return;\n\t\tlet runs: AsyncRunSummary[];\n\t\ttry {\n\t\t\truns = listAsyncRuns(asyncDirRoot, { states: [\"queued\", \"running\"], sessionId: state.currentSessionId, resultsDir, kill: options.kill, now: options.now });\n\t\t} catch (error) {\n\t\t\tconsole.error(`Failed to restore active async jobs from '${asyncDirRoot}':`, error);\n\t\t\treturn;\n\t\t}\n\t\tfor (const run of runs) {\n\t\t\tconst job = summaryToJob(run);\n\t\t\tstate.asyncJobs.set(run.id, job);\n\t\t\trememberFleetJob(state, job);\n\t\t}\n\t\tif (runs.length === 0) return;\n\t\tensurePoller();\n\t\tif (state.lastUiContext?.hasUI) rerenderWidget(state.lastUiContext);\n\t};\n\n\treturn { ensurePoller, refreshWidget, handleStarted, handleComplete, resetJobs, restoreActiveJobs };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"async-job-tracker.js","sourceRoot":"","sources":["../../../../../../src/builtin-extensions/pi-subagents/src/runs/background/async-job-tracker.ts"],"names":[],"mappings":"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","sourcesContent":["// @ts-nocheck\nimport type { ExtensionAPI, ExtensionContext } from \"@ashx-j/lunr-dev\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { renderWidget, widgetRenderKey } from \"../../tui/render.ts\";\nimport { formatControlNoticeMessage } from \"../shared/subagent-control.ts\";\nimport {\n\ttype AsyncJobState,\n\ttype AsyncStartedEvent,\n\ttype ControlEvent,\n\ttype SteeringNotice,\n\ttype SubagentState,\n\tPOLL_INTERVAL_MS,\n\tRESULTS_DIR,\n\tSUBAGENT_CONTROL_EVENT,\n\tSUBAGENT_CONTROL_INTERCOM_EVENT,\n\tSUBAGENT_STEERING_NOTICE_EVENT,\n} from \"../../shared/types.ts\";\nimport { readStatus } from \"../../shared/utils.ts\";\nimport { normalizeParallelGroups } from \"./parallel-groups.ts\";\nimport { reconcileAsyncRun, reconcileNestedAsyncDescendants } from \"./stale-run-reconciler.ts\";\nimport { hasLiveNestedDescendants, updateAsyncJobNestedProjection } from \"../shared/nested-events.ts\";\nimport { listAsyncRuns, type AsyncRunSummary } from \"./async-status.ts\";\n\ninterface AsyncJobTrackerOptions {\n\tcompletionRetentionMs?: number;\n\tpollIntervalMs?: number;\n\tresultsDir?: string;\n\twidgetEnabled?: boolean;\n\tkill?: (pid: number, signal?: NodeJS.Signals | 0) => boolean;\n\tnow?: () => number;\n}\n\nconst CONTROL_EVENT_READ_CHUNK_BYTES = 64 * 1024;\nconst MAX_CONTROL_EVENT_LINE_BYTES = 1024 * 1024;\nconst CONTROL_EVENT_SCAN_WINDOW_BYTES = 2 * 1024 * 1024;\nconst MAX_RECENT_FLEET_JOBS = 20;\n\nfunction rememberFleetJob(state: SubagentState, job: AsyncJobState): void {\n\tstate.fleetJobs ??= new Map();\n\tstate.fleetJobs.set(job.asyncId, job);\n\tconst terminal = [...state.fleetJobs.values()]\n\t\t.filter((candidate) => candidate.status === \"complete\" || candidate.status === \"failed\" || candidate.status === \"paused\" || candidate.status === \"stopped\")\n\t\t.sort((left, right) => (right.updatedAt ?? right.startedAt ?? 0) - (left.updatedAt ?? left.startedAt ?? 0));\n\tfor (const stale of terminal.slice(MAX_RECENT_FLEET_JOBS)) state.fleetJobs.delete(stale.asyncId);\n}\n\nexport function createAsyncJobTracker(pi: Pick<ExtensionAPI, \"events\">, state: SubagentState, asyncDirRoot: string, options: AsyncJobTrackerOptions = {}): {\n\tensurePoller: () => void;\n\trefreshWidget: (ctx: ExtensionContext) => void;\n\thandleStarted: (data: unknown) => void;\n\thandleComplete: (data: unknown) => void;\n\tresetJobs: (ctx?: ExtensionContext) => void;\n\trestoreActiveJobs: (ctx?: ExtensionContext) => void;\n} {\n\tconst completionRetentionMs = options.completionRetentionMs ?? 10000;\n\tconst pollIntervalMs = options.pollIntervalMs ?? POLL_INTERVAL_MS;\n\tconst resultsDir = options.resultsDir ?? RESULTS_DIR;\n\tconst steeringNoticeSeen = new Map<string, number>();\n\tconst rerenderWidget = (ctx: ExtensionContext, jobs = Array.from(state.asyncJobs.values())) => {\n\t\trenderWidget(ctx, options.widgetEnabled === false ? [] : jobs);\n\t\tctx.ui.requestRender?.();\n\t};\n\tconst refreshWidget = (ctx: ExtensionContext) => rerenderWidget(ctx);\n\tconst restoredControlEventCursor = (asyncDir: string) => {\n\t\ttry {\n\t\t\treturn fs.statSync(path.join(asyncDir, \"events.jsonl\")).size;\n\t\t} catch (error) {\n\t\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return 0;\n\t\t\tthrow error;\n\t\t}\n\t};\n\tconst summaryToJob = (run: AsyncRunSummary): AsyncJobState => {\n\t\tconst groups = normalizeParallelGroups(run.parallelGroups, run.steps.length, run.chainStepCount ?? run.steps.length);\n\t\tconst activeGroup = run.currentStep !== undefined\n\t\t\t? groups.find((group) => run.currentStep! >= group.start && run.currentStep! < group.start + group.count)\n\t\t\t: undefined;\n\t\tconst visibleSteps = activeGroup\n\t\t\t? run.steps.slice(activeGroup.start, activeGroup.start + activeGroup.count).map((step, index) => ({ ...step, index: activeGroup.start + index }))\n\t\t\t: run.steps.map((step, index) => ({ ...step, index }));\n\t\treturn {\n\t\t\tasyncId: run.id,\n\t\t\tasyncDir: run.asyncDir,\n\t\t\tstatus: run.state,\n\t\t\tsessionId: run.sessionId,\n\t\t\tactivityState: run.activityState,\n\t\t\tlastActivityAt: run.lastActivityAt,\n\t\t\tcurrentTool: run.currentTool,\n\t\t\tcurrentToolStartedAt: run.currentToolStartedAt,\n\t\t\tcurrentPath: run.currentPath,\n\t\t\tturnCount: run.turnCount,\n\t\t\ttoolCount: run.toolCount,\n\t\t\tsteering: run.steering,\n\t\t\tmode: run.mode,\n\t\t\tagents: visibleSteps.map((step) => step.agent),\n\t\t\tcurrentStep: run.currentStep,\n\t\t\tchainStepCount: run.chainStepCount,\n\t\t\tparallelGroups: groups,\n\t\t\tsteps: visibleSteps,\n\t\t\tstepsTotal: visibleSteps.length,\n\t\t\trunningSteps: visibleSteps.filter((step) => step.status === \"running\").length,\n\t\t\tcompletedSteps: visibleSteps.filter((step) => step.status === \"complete\" || step.status === \"completed\").length,\n\t\t\thasParallelGroups: groups.length > 0,\n\t\t\tactiveParallelGroup: Boolean(activeGroup),\n\t\t\tstartedAt: run.startedAt,\n\t\t\tupdatedAt: run.lastUpdate ?? run.startedAt,\n\t\t\ttimeoutMs: run.timeoutMs,\n\t\t\tdeadlineAt: run.deadlineAt,\n\t\t\ttimedOut: run.timedOut,\n\t\t\tstopped: run.stopped,\n\t\t\tturnBudget: run.turnBudget,\n\t\t\tturnBudgetExceeded: run.turnBudgetExceeded,\n\t\t\twrapUpRequested: run.wrapUpRequested,\n\t\t\tsessionDir: run.sessionDir,\n\t\t\toutputFile: run.outputFile,\n\t\t\ttotalTokens: run.totalTokens,\n\t\t\tsessionFile: run.sessionFile,\n\t\t\tcontrolEventCursor: restoredControlEventCursor(run.asyncDir),\n\t\t\tnestedChildren: run.nestedChildren,\n\t\t};\n\t};\n\tconst cancelCleanup = (asyncId: string) => {\n\t\tconst existingTimer = state.cleanupTimers.get(asyncId);\n\t\tif (!existingTimer) return;\n\t\tclearTimeout(existingTimer);\n\t\tstate.cleanupTimers.delete(asyncId);\n\t};\n\tconst scheduleCleanup = (asyncId: string) => {\n\t\tcancelCleanup(asyncId);\n\t\tconst timer = setTimeout(() => {\n\t\t\tstate.cleanupTimers.delete(asyncId);\n\t\t\tstate.asyncJobs.delete(asyncId);\n\t\t\tif (state.lastUiContext) {\n\t\t\t\trerenderWidget(state.lastUiContext);\n\t\t\t}\n\t\t}, completionRetentionMs);\n\t\tstate.cleanupTimers.set(asyncId, timer);\n\t};\n\tconst emitNewControlEvents = (job: AsyncJobState) => {\n\t\tconst eventsPath = path.join(job.asyncDir, \"events.jsonl\");\n\t\tlet fd: number;\n\t\ttry {\n\t\t\tfd = fs.openSync(eventsPath, \"r\");\n\t\t} catch (error) {\n\t\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return;\n\t\t\tconsole.error(`Failed to open async control events for '${job.asyncDir}':`, error);\n\t\t\treturn;\n\t\t}\n\t\ttry {\n\t\t\tconst stat = fs.fstatSync(fd);\n\t\t\tconst savedCursor = job.controlEventCursor;\n\t\t\tlet cursor = stat.size < (savedCursor ?? 0) ? 0 : (savedCursor ?? 0);\n\t\t\tconst startedFromTail = savedCursor === undefined && stat.size > CONTROL_EVENT_SCAN_WINDOW_BYTES;\n\t\t\tif (startedFromTail) cursor = stat.size - CONTROL_EVENT_SCAN_WINDOW_BYTES;\n\t\t\tif (stat.size <= cursor) return;\n\t\t\tconst scanEnd = Math.min(stat.size, cursor + CONTROL_EVENT_SCAN_WINDOW_BYTES);\n\t\t\tconst handleLine = (line: string) => {\n\t\t\t\tif (!line.trim()) return;\n\t\t\t\tlet parsed: unknown;\n\t\t\t\ttry {\n\t\t\t\t\tparsed = JSON.parse(line);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tconsole.error(`Ignoring malformed async control event in '${eventsPath}':`, error);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (!parsed || typeof parsed !== \"object\") return;\n\t\t\t\tif ((parsed as { type?: unknown }).type === \"subagent.steering.notice\") {\n\t\t\t\t\tconst notice = parsed as Partial<SteeringNotice>;\n\t\t\t\t\tif (typeof notice.requestId !== \"string\" || typeof notice.runId !== \"string\" || (notice.state !== \"failed\" && notice.state !== \"partial\" && notice.state !== \"recovered\") || typeof notice.message !== \"string\") return;\n\t\t\t\t\tif (typeof state.currentSessionId === \"string\" && notice.currentSessionId !== state.currentSessionId) return;\n\t\t\t\t\tconst key = `${notice.runId}:${notice.requestId}:${notice.state}`;\n\t\t\t\t\tif (steeringNoticeSeen.has(key)) return;\n\t\t\t\t\tconst now = Date.now();\n\t\t\t\t\tsteeringNoticeSeen.set(key, now);\n\t\t\t\t\tif (steeringNoticeSeen.size > 200) {\n\t\t\t\t\t\tfor (const [seenKey, seenAt] of steeringNoticeSeen) {\n\t\t\t\t\t\t\tif (now - seenAt > 10 * 60 * 1000 || steeringNoticeSeen.size > 200) steeringNoticeSeen.delete(seenKey);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tpi.events.emit(SUBAGENT_STEERING_NOTICE_EVENT, { ...notice, source: \"async\", asyncDir: job.asyncDir, noticeText: notice.message });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif ((parsed as { type?: unknown }).type !== \"subagent.control\") return;\n\t\t\t\tconst record = parsed as { event?: ControlEvent; channels?: string[]; childIntercomTarget?: string; noticeText?: string; intercom?: { to?: string; message?: string } };\n\t\t\t\tif (!record.event || !Array.isArray(record.channels)) return;\n\t\t\t\tif (record.event.reason === \"completion_guard\") return;\n\t\t\t\tconst payload = {\n\t\t\t\t\tevent: record.event,\n\t\t\t\t\tsource: \"async\" as const,\n\t\t\t\t\tasyncDir: job.asyncDir,\n\t\t\t\t\tchildIntercomTarget: record.childIntercomTarget,\n\t\t\t\t\tnoticeText: record.noticeText ?? formatControlNoticeMessage(record.event, record.childIntercomTarget),\n\t\t\t\t};\n\t\t\t\tif (record.channels.includes(\"event\")) {\n\t\t\t\t\tpi.events.emit(SUBAGENT_CONTROL_EVENT, payload);\n\t\t\t\t}\n\t\t\t\tif (record.event.type !== \"active_long_running\" && record.channels.includes(\"intercom\") && record.intercom?.to && record.intercom.message) {\n\t\t\t\t\tpi.events.emit(SUBAGENT_CONTROL_INTERCOM_EVENT, {\n\t\t\t\t\t\t...payload,\n\t\t\t\t\t\tto: record.intercom.to,\n\t\t\t\t\t\tmessage: record.intercom.message,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t};\n\t\t\tlet readCursor = cursor;\n\t\t\tlet lastCompleteCursor = cursor;\n\t\t\tlet lineParts: Buffer[] = [];\n\t\t\tlet lineBytes = 0;\n\t\t\tlet skippingOversizedLine = startedFromTail;\n\t\t\tconst appendLineSegment = (segment: Buffer) => {\n\t\t\t\tif (segment.length === 0 || skippingOversizedLine) return;\n\t\t\t\tif (lineBytes + segment.length > MAX_CONTROL_EVENT_LINE_BYTES) {\n\t\t\t\t\tlineParts = [];\n\t\t\t\t\tlineBytes = 0;\n\t\t\t\t\tskippingOversizedLine = true;\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tlineParts.push(segment);\n\t\t\t\tlineBytes += segment.length;\n\t\t\t};\n\t\t\twhile (readCursor < scanEnd) {\n\t\t\t\tconst toRead = Math.min(CONTROL_EVENT_READ_CHUNK_BYTES, scanEnd - readCursor);\n\t\t\t\tconst buffer = Buffer.alloc(toRead);\n\t\t\t\tconst bytesRead = fs.readSync(fd, buffer, 0, toRead, readCursor);\n\t\t\t\tif (bytesRead <= 0) break;\n\t\t\t\tconst chunk = bytesRead === buffer.length ? buffer : buffer.subarray(0, bytesRead);\n\t\t\t\tlet lineStart = 0;\n\t\t\t\tfor (let index = 0; index < chunk.length; index++) {\n\t\t\t\t\tif (chunk[index] !== 0x0a) continue;\n\t\t\t\t\tappendLineSegment(chunk.subarray(lineStart, index));\n\t\t\t\t\tif (!skippingOversizedLine && lineBytes > 0) {\n\t\t\t\t\t\thandleLine(Buffer.concat(lineParts, lineBytes).toString(\"utf-8\"));\n\t\t\t\t\t}\n\t\t\t\t\tlineParts = [];\n\t\t\t\t\tlineBytes = 0;\n\t\t\t\t\tskippingOversizedLine = false;\n\t\t\t\t\tlastCompleteCursor = readCursor + index + 1;\n\t\t\t\t\tlineStart = index + 1;\n\t\t\t\t}\n\t\t\t\tappendLineSegment(chunk.subarray(lineStart));\n\t\t\t\treadCursor += bytesRead;\n\t\t\t\tif (skippingOversizedLine) job.controlEventCursor = readCursor;\n\t\t\t}\n\t\t\tif (lastCompleteCursor > cursor) job.controlEventCursor = lastCompleteCursor;\n\t\t\telse if (scanEnd < stat.size || startedFromTail) job.controlEventCursor = scanEnd;\n\t\t} catch (error) {\n\t\t\tconsole.error(`Failed to read async control events for '${job.asyncDir}':`, error);\n\t\t} finally {\n\t\t\tfs.closeSync(fd);\n\t\t}\n\t};\n\n\tconst ensurePoller = () => {\n\t\tif (state.poller) return;\n\t\tstate.poller = setInterval(() => {\n\t\t\tif (state.asyncJobs.size === 0) {\n\t\t\t\tif (state.lastUiContext?.hasUI) rerenderWidget(state.lastUiContext, []);\n\t\t\t\tif (state.poller) {\n\t\t\t\t\tclearInterval(state.poller);\n\t\t\t\t\tstate.poller = null;\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlet widgetChanged = false;\n\t\t\tfor (const job of state.asyncJobs.values()) {\n\t\t\t\tconst widgetStateBefore = widgetRenderKey(job);\n\t\t\t\tlet nestedRefreshFailed = false;\n\t\t\t\tconst refreshNestedProjection = () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tupdateAsyncJobNestedProjection(job);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tnestedRefreshFailed = true;\n\t\t\t\t\t\tconsole.error(`Failed to refresh nested async descendants for '${job.asyncDir}':`, error);\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\tconst reconcileNestedDescendants = () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (job.nestedRoute) reconcileNestedAsyncDescendants(job.nestedRoute, { resultsDir, kill: options.kill, now: options.now });\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tnestedRefreshFailed = true;\n\t\t\t\t\t\tconsole.error(`Failed to refresh nested async descendants for '${job.asyncDir}':`, error);\n\t\t\t\t\t}\n\t\t\t\t\trefreshNestedProjection();\n\t\t\t\t};\n\t\t\t\ttry {\n\t\t\t\t\temitNewControlEvents(job);\n\t\t\t\t\treconcileNestedDescendants();\n\t\t\t\t\tconst reconciliation = reconcileAsyncRun(job.asyncDir, {\n\t\t\t\t\t\tresultsDir,\n\t\t\t\t\t\tkill: options.kill,\n\t\t\t\t\t\tnow: options.now,\n\t\t\t\t\t\tstartedRun: {\n\t\t\t\t\t\t\trunId: job.asyncId,\n\t\t\t\t\t\t\tpid: job.pid,\n\t\t\t\t\t\t\tsessionId: job.sessionId,\n\t\t\t\t\t\t\tmode: job.mode,\n\t\t\t\t\t\t\tagents: job.agents,\n\t\t\t\t\t\t\tchainStepCount: job.chainStepCount,\n\t\t\t\t\t\t\tparallelGroups: job.parallelGroups,\n\t\t\t\t\t\t\tstartedAt: job.startedAt,\n\t\t\t\t\t\t\tsessionFile: job.sessionFile,\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t\tconst status = reconciliation.status ?? readStatus(job.asyncDir);\n\t\t\t\t\tif (status) {\n\t\t\t\t\t\tconst previousStatus = job.status;\n\t\t\t\t\t\tjob.status = status.state;\n\t\t\t\t\t\tif (job.status !== \"complete\" && job.status !== \"failed\" && job.status !== \"paused\" && job.status !== \"stopped\") cancelCleanup(job.asyncId);\n\t\t\t\t\t\tjob.sessionId = status.sessionId ?? job.sessionId;\n\t\t\t\t\t\tjob.activityState = status.activityState;\n\t\t\t\t\t\tjob.lastActivityAt = status.lastActivityAt ?? job.lastActivityAt;\n\t\t\t\t\t\tjob.currentTool = status.currentTool;\n\t\t\t\t\t\tjob.currentToolStartedAt = status.currentToolStartedAt;\n\t\t\t\t\t\tjob.currentPath = status.currentPath;\n\t\t\t\t\t\tjob.turnCount = status.turnCount ?? job.turnCount;\n\t\t\t\t\t\tjob.toolCount = status.toolCount ?? job.toolCount;\n\t\t\t\t\t\tjob.steering = status.steering ?? job.steering;\n\t\t\t\t\t\tjob.mode = status.mode;\n\t\t\t\t\t\tjob.currentStep = status.currentStep ?? job.currentStep;\n\t\t\t\t\t\tjob.chainStepCount = status.chainStepCount ?? job.chainStepCount;\n\t\t\t\t\t\tjob.startedAt = status.startedAt ?? job.startedAt;\n\t\t\t\t\t\tif (status.lastUpdate !== undefined) job.updatedAt = status.lastUpdate;\n\t\t\t\t\t\tif (status.steps?.length) {\n\t\t\t\t\t\t\tconst groups = normalizeParallelGroups(status.parallelGroups, status.steps.length, status.chainStepCount ?? status.steps.length);\n\t\t\t\t\t\t\tjob.parallelGroups = groups.length ? groups : job.parallelGroups;\n\t\t\t\t\t\t\tjob.hasParallelGroups = groups.length > 0 || job.hasParallelGroups;\n\t\t\t\t\t\t\tconst activeGroup = status.currentStep !== undefined\n\t\t\t\t\t\t\t\t? groups.find((group) => status.currentStep! >= group.start && status.currentStep! < group.start + group.count)\n\t\t\t\t\t\t\t\t: undefined;\n\t\t\t\t\t\t\tconst visibleSteps = activeGroup\n\t\t\t\t\t\t\t\t? status.steps.slice(activeGroup.start, activeGroup.start + activeGroup.count).map((step, index) => ({ ...step, index: activeGroup.start + index }))\n\t\t\t\t\t\t\t\t: status.steps.map((step, index) => ({ ...step, index }));\n\t\t\t\t\t\t\tjob.activeParallelGroup = Boolean(activeGroup);\n\t\t\t\t\t\t\tjob.agents = visibleSteps.map((step) => step.agent);\n\t\t\t\t\t\t\tjob.steps = visibleSteps;\n\t\t\t\t\t\t\trefreshNestedProjection();\n\t\t\t\t\t\t\tjob.stepsTotal = visibleSteps.length;\n\t\t\t\t\t\t\tjob.runningSteps = visibleSteps.filter((step) => step.status === \"running\").length;\n\t\t\t\t\t\t\tjob.completedSteps = visibleSteps.filter((step) => step.status === \"complete\" || step.status === \"completed\").length;\n\t\t\t\t\t\t\tif (status.state === \"complete\") job.completedSteps = visibleSteps.length;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tjob.sessionDir = status.sessionDir ?? job.sessionDir;\n\t\t\t\t\t\tjob.outputFile = status.outputFile ?? job.outputFile;\n\t\t\t\t\t\tjob.totalTokens = status.totalTokens ?? job.totalTokens;\n\t\t\t\t\t\tjob.timeoutMs = status.timeoutMs ?? job.timeoutMs;\n\t\t\t\t\t\tjob.deadlineAt = status.deadlineAt ?? job.deadlineAt;\n\t\t\t\t\t\tjob.timedOut = status.timedOut ?? job.timedOut;\n\t\t\t\t\t\tjob.stopped = status.stopped ?? job.stopped;\n\t\t\t\t\t\tjob.turnBudget = status.turnBudget ?? job.turnBudget;\n\t\t\t\t\t\tjob.turnBudgetExceeded = status.turnBudgetExceeded ?? job.turnBudgetExceeded;\n\t\t\t\t\t\tjob.wrapUpRequested = status.wrapUpRequested ?? job.wrapUpRequested;\n\t\t\t\t\t\tjob.sessionFile = status.sessionFile ?? job.sessionFile;\n\t\t\t\t\t\tif (job.status === \"complete\" || job.status === \"failed\" || job.status === \"paused\" || job.status === \"stopped\") {\n\t\t\t\t\t\t\trememberFleetJob(state, job);\n\t\t\t\t\t\t\tif (!nestedRefreshFailed && !hasLiveNestedDescendants(job.nestedChildren) && (previousStatus !== job.status || !state.cleanupTimers.has(job.asyncId))) {\n\t\t\t\t\t\t\t\tscheduleCleanup(job.asyncId);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (widgetRenderKey(job) !== widgetStateBefore) widgetChanged = true;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tif (job.status === \"queued\") {\n\t\t\t\t\t\tjob.status = \"running\";\n\t\t\t\t\t\tjob.updatedAt = Date.now();\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (job.status !== \"failed\") {\n\t\t\t\t\t\tconsole.error(`Failed to read async status for '${job.asyncDir}':`, error);\n\t\t\t\t\t\tjob.status = \"failed\";\n\t\t\t\t\t\tjob.updatedAt = Date.now();\n\t\t\t\t\t}\n\t\t\t\t\trememberFleetJob(state, job);\n\t\t\t\t\tif (!hasLiveNestedDescendants(job.nestedChildren) && !state.cleanupTimers.has(job.asyncId)) {\n\t\t\t\t\t\tscheduleCleanup(job.asyncId);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (widgetRenderKey(job) !== widgetStateBefore) widgetChanged = true;\n\t\t\t}\n\n\t\t\tif (widgetChanged && state.lastUiContext?.hasUI) rerenderWidget(state.lastUiContext);\n\t\t}, pollIntervalMs);\n\t\tstate.poller.unref?.();\n\t};\n\n\tconst handleStarted = (data: unknown) => {\n\t\tconst info = data as AsyncStartedEvent;\n\t\tif (!info.id) return;\n\t\tif (typeof state.currentSessionId === \"string\" && info.sessionId !== state.currentSessionId) return;\n\t\tconst now = Date.now();\n\t\tconst asyncDir = info.asyncDir ?? path.join(asyncDirRoot, info.id);\n\t\tconst rawAgents = info.agents?.length ? info.agents : info.chain && info.chain.length > 0 ? info.chain : info.agent ? [info.agent] : undefined;\n\t\tconst validParallelGroups = normalizeParallelGroups(info.parallelGroups, Number.MAX_SAFE_INTEGER, info.chainStepCount ?? Number.MAX_SAFE_INTEGER);\n\t\tconst firstGroup = validParallelGroups.find((group) => group.start === 0);\n\t\tconst firstGroupCount = firstGroup?.count;\n\t\tconst agents = firstGroupCount && firstGroupCount > 0\n\t\t\t? rawAgents?.slice(0, firstGroupCount)\n\t\t\t: rawAgents;\n\t\tstate.asyncJobs.set(info.id, {\n\t\t\tasyncId: info.id,\n\t\t\tasyncDir,\n\t\t\tstatus: \"queued\",\n\t\t\tpid: typeof info.pid === \"number\" ? info.pid : undefined,\n\t\t\t...(typeof info.sessionId === \"string\" ? { sessionId: info.sessionId } : {}),\n\t\t\tmode: info.mode ?? (info.chain ? \"chain\" : \"single\"),\n\t\t\tagents,\n\t\t\tchainStepCount: info.chainStepCount,\n\t\t\tparallelGroups: validParallelGroups,\n\t\t\tnestedRoute: info.nestedRoute,\n\t\t\tstepsTotal: firstGroupCount ?? agents?.length,\n\t\t\thasParallelGroups: validParallelGroups.length > 0,\n\t\t\tactiveParallelGroup: Boolean(firstGroupCount && firstGroupCount > 0),\n\t\t\tstartedAt: now,\n\t\t\tupdatedAt: now,\n\t\t\ttimeoutMs: info.timeoutMs,\n\t\t\tdeadlineAt: info.deadlineAt,\n\t\t\tturnBudget: info.turnBudget,\n\t\t\tcontrolEventCursor: 0,\n\t\t});\n\t\trememberFleetJob(state, state.asyncJobs.get(info.id)!);\n\t\tensurePoller();\n\t\tif (state.lastUiContext) {\n\t\t\trerenderWidget(state.lastUiContext);\n\t\t}\n\t};\n\n\tconst handleComplete = (data: unknown) => {\n\t\tconst result = data as { id?: string; success?: boolean; state?: AsyncJobState[\"status\"]; asyncDir?: string; sessionId?: string; stopped?: boolean };\n\t\tif (typeof state.currentSessionId === \"string\" && result.sessionId !== state.currentSessionId) return;\n\t\tconst asyncId = result.id;\n\t\tif (!asyncId) return;\n\t\tconst job = state.asyncJobs.get(asyncId);\n\t\tlet nestedRefreshFailed = false;\n\t\tif (job) {\n\t\t\tjob.status = result.state ?? (result.success ? \"complete\" : \"failed\");\n\t\t\tjob.stopped = result.stopped ?? job.stopped;\n\t\t\tjob.updatedAt = Date.now();\n\t\t\tif (result.asyncDir) job.asyncDir = result.asyncDir;\n\t\t\ttry {\n\t\t\t\tupdateAsyncJobNestedProjection(job);\n\t\t\t} catch (error) {\n\t\t\t\tnestedRefreshFailed = true;\n\t\t\t\tconsole.error(`Failed to refresh nested async descendants for '${job.asyncDir}':`, error);\n\t\t\t}\n\t\t}\n\t\tif (job) rememberFleetJob(state, job);\n\t\tif (state.lastUiContext) {\n\t\t\trerenderWidget(state.lastUiContext);\n\t\t}\n\t\tif (!nestedRefreshFailed && !hasLiveNestedDescendants(job?.nestedChildren)) scheduleCleanup(asyncId);\n\t};\n\n\tconst resetJobs = (ctx?: ExtensionContext) => {\n\t\tfor (const timer of state.cleanupTimers.values()) {\n\t\t\tclearTimeout(timer);\n\t\t}\n\t\tstate.cleanupTimers.clear();\n\t\tstate.asyncJobs.clear();\n\t\tstate.fleetJobs?.clear();\n\t\tstate.foregroundControls?.clear();\n\t\tstate.lastForegroundControlId = null;\n\t\tstate.resultFileCoalescer.clear();\n\t\tif (ctx?.hasUI) {\n\t\t\tstate.lastUiContext = ctx;\n\t\t\trerenderWidget(ctx, []);\n\t\t}\n\t};\n\n\tconst restoreActiveJobs = (ctx?: ExtensionContext) => {\n\t\tif (ctx?.hasUI) state.lastUiContext = ctx;\n\t\tif (!state.currentSessionId) return;\n\t\tlet runs: AsyncRunSummary[];\n\t\ttry {\n\t\t\truns = listAsyncRuns(asyncDirRoot, { states: [\"queued\", \"running\"], sessionId: state.currentSessionId, resultsDir, kill: options.kill, now: options.now });\n\t\t} catch (error) {\n\t\t\tconsole.error(`Failed to restore active async jobs from '${asyncDirRoot}':`, error);\n\t\t\treturn;\n\t\t}\n\t\tfor (const run of runs) {\n\t\t\tconst job = summaryToJob(run);\n\t\t\tstate.asyncJobs.set(run.id, job);\n\t\t\trememberFleetJob(state, job);\n\t\t}\n\t\tif (runs.length === 0) return;\n\t\tensurePoller();\n\t\tif (state.lastUiContext?.hasUI) rerenderWidget(state.lastUiContext);\n\t};\n\n\treturn { ensurePoller, refreshWidget, handleStarted, handleComplete, resetJobs, restoreActiveJobs };\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type AsyncStatus, type SteeringRecoveryDescriptor, type SubagentState } from "../../shared/types.ts";
|
|
1
|
+
import { type AsyncStatus, type ModelSelection, type SteeringRecoveryDescriptor, type SubagentState } from "../../shared/types.ts";
|
|
2
2
|
export declare const ASYNC_RESUME_INTERRUPT_SIGNAL: NodeJS.Signals;
|
|
3
3
|
export interface AsyncResumeParams {
|
|
4
4
|
id?: string;
|
|
@@ -30,6 +30,7 @@ export type AsyncResumeTarget = {
|
|
|
30
30
|
sessionFile?: string;
|
|
31
31
|
model?: string;
|
|
32
32
|
thinking?: string;
|
|
33
|
+
modelSelection?: ModelSelection;
|
|
33
34
|
recoveryDescriptor?: SteeringRecoveryDescriptor;
|
|
34
35
|
};
|
|
35
36
|
type KillFn = (pid: number, signal?: NodeJS.Signals | 0) => boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"async-resume.d.ts","sourceRoot":"","sources":["../../../../../../src/builtin-extensions/pi-subagents/src/runs/background/async-resume.ts"],"names":[],"mappings":"AAGA,OAAO,EAAuG,KAAK,WAAW,EAAE,KAAK,0BAA0B,EAAE,KAAK,aAAa,EAAE,MAAM,uBAAuB,CAAC;AASnN,eAAO,MAAM,6BAA6B,EAAE,MAAM,CAAC,OAA+D,CAAC;AAEnH,MAAM,WAAW,iBAAiB;IACjC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,eAAe;IAC/B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,OAAO,GAAG,CAAC,KAAK,OAAO,CAAC;IAC7D,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IAClC,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC/B,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,CAAC;IACvB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kBAAkB,CAAC,EAAE,0BAA0B,CAAC;CAChD,CAAC;AAEF,KAAK,MAAM,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,OAAO,GAAG,CAAC,KAAK,OAAO,CAAC;AAEpE,wBAAgB,8BAA8B,CAAC,KAAK,EAAE;IACrD,MAAM,EAAE,iBAAiB,GAAG;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,KAAK,CAAC,EAAE,IAAI,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;IACzC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CA4BjE;AAgBD,MAAM,WAAW,gBAAgB;IAChC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;AA8GD,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,gBAAgB,CAAA;CAAE,CAAC,CAqBrJ;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,gBAAgB,CAgC7H;AA+BD,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,0BAA0B,GAAG,SAAS,CA8FhH;AASD,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,iBAAiB,EAAE,IAAI,GAAE,eAAoB,EAAE,OAAO,GAAE,kBAAuB,GAAG,iBAAiB,CAqHnJ;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAaxF","sourcesContent":["// @ts-nocheck\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { ASYNC_DIR, RESULTS_DIR, isSupportedSubagentLifecycleVersion, UNSUPPORTED_SUBAGENT_LIFECYCLE_MESSAGE, type AsyncStatus, type SteeringRecoveryDescriptor, type SubagentState } from \"../../shared/types.ts\";\nimport { validateChildDescription } from \"../../shared/child-spec.ts\";\nimport { resolveSubagentIntercomTarget } from \"../../intercom/intercom-bridge.ts\";\nimport { validateAcceptanceInput } from \"../shared/acceptance.ts\";\nimport { validateToolBudgetConfig } from \"../shared/tool-budget.ts\";\nimport { resolveTurnBudgetConfig } from \"../shared/turn-budget.ts\";\nimport { deliverInterruptRequest } from \"./control-channel.ts\";\nimport { reconcileAsyncRun } from \"./stale-run-reconciler.ts\";\n\nexport const ASYNC_RESUME_INTERRUPT_SIGNAL: NodeJS.Signals = process.platform === \"win32\" ? \"SIGBREAK\" : \"SIGUSR2\";\n\nexport interface AsyncResumeParams {\n\tid?: string;\n\trunId?: string;\n\tdir?: string;\n\tindex?: number;\n}\n\nexport interface AsyncResumeDeps {\n\tasyncDirRoot?: string;\n\tresultsDir?: string;\n\tkill?: (pid: number, signal?: NodeJS.Signals | 0) => boolean;\n\tnow?: () => number;\n}\n\nexport interface AsyncResumeOptions {\n\trequireSessionFile?: boolean;\n}\n\nexport type AsyncResumeTarget = {\n\tkind: \"live\" | \"revive\";\n\trunId: string;\n\tasyncDir?: string;\n\tstate: AsyncStatus[\"state\"];\n\tagent: string;\n\tchildId?: string;\n\tdescription?: string;\n\tpermissions?: \"full\" | \"read-only\";\n\tindex: number;\n\tintercomTarget: string;\n\tcwd?: string;\n\tsessionFile?: string;\n\tmodel?: string;\n\tthinking?: string;\n\trecoveryDescriptor?: SteeringRecoveryDescriptor;\n};\n\ntype KillFn = (pid: number, signal?: NodeJS.Signals | 0) => boolean;\n\nexport function interruptLiveAsyncResumeTarget(input: {\n\ttarget: AsyncResumeTarget & { kind: \"live\" };\n\tstate?: Pick<SubagentState, \"asyncJobs\">;\n\tkill?: KillFn;\n\tnow?: () => number;\n\tresultsDir?: string;\n}): { ok: true; asyncId: string } | { ok: false; message: string } {\n\tconst asyncId = input.target.runId;\n\tif (!input.target.asyncDir) {\n\t\treturn { ok: false, message: `Async run ${asyncId} is live but does not have an async directory to interrupt.` };\n\t}\n\tconst status = reconcileAsyncRun(input.target.asyncDir, { resultsDir: input.resultsDir, kill: input.kill, now: input.now }).status;\n\tif (!status || status.state !== \"running\" || typeof status.pid !== \"number\") {\n\t\treturn { ok: false, message: `Async run ${asyncId} is live but no interrupt-capable runner pid was found.` };\n\t}\n\ttry {\n\t\tdeliverInterruptRequest({\n\t\t\tasyncDir: input.target.asyncDir,\n\t\t\tpid: status.pid,\n\t\t\tkill: input.kill,\n\t\t\tsignal: ASYNC_RESUME_INTERRUPT_SIGNAL,\n\t\t\tnow: input.now,\n\t\t\tsource: \"async-resume\",\n\t\t});\n\t\tconst tracked = input.state?.asyncJobs.get(asyncId);\n\t\tif (tracked) {\n\t\t\ttracked.activityState = undefined;\n\t\t\ttracked.updatedAt = input.now?.() ?? Date.now();\n\t\t}\n\t\treturn { ok: true, asyncId };\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\treturn { ok: false, message: `Failed to interrupt async run ${asyncId}: ${message}` };\n\t}\n}\n\ninterface AsyncResultFile {\n\tid?: string;\n\trunId?: string;\n\tagent?: string;\n\tmode?: string;\n\tstate?: string;\n\tsuccess?: boolean;\n\tcwd?: string;\n\tsessionFile?: string;\n\tmodel?: string;\n\tthinking?: string;\n\tresults?: Array<{ agent?: string; success?: boolean; sessionFile?: string; intercomTarget?: string; model?: string; thinking?: string }>;\n}\n\nexport interface AsyncRunLocation {\n\tasyncDir: string | null;\n\tresultPath: string | null;\n\tresolvedId?: string;\n}\n\nfunction getErrorMessage(error: unknown): string {\n\treturn error instanceof Error ? error.message : String(error);\n}\n\nfunction ensureObject(value: unknown, source: string): Record<string, unknown> {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) {\n\t\tthrow new Error(`Async result file '${source}' must contain a JSON object.`);\n\t}\n\treturn value as Record<string, unknown>;\n}\n\nfunction validateOptionalString(value: Record<string, unknown>, field: string, source: string, displayField = field): string | undefined {\n\tconst fieldValue = value[field];\n\tif (fieldValue === undefined) return undefined;\n\tif (typeof fieldValue !== \"string\") throw new Error(`Invalid async result file '${source}': ${displayField} must be a string.`);\n\treturn fieldValue;\n}\n\nfunction validateResultFile(value: unknown, resultPath: string): AsyncResultFile {\n\tconst data = ensureObject(value, resultPath);\n\tif (!isSupportedSubagentLifecycleVersion(data.lifecycleArtifactVersion)) {\n\t\tthrow new Error(UNSUPPORTED_SUBAGENT_LIFECYCLE_MESSAGE);\n\t}\n\tconst resultsValue = data.results;\n\tlet results: AsyncResultFile[\"results\"];\n\tif (resultsValue !== undefined) {\n\t\tif (!Array.isArray(resultsValue)) throw new Error(`Invalid async result file '${resultPath}': results must be an array.`);\n\t\tresults = resultsValue.map((entry, index) => {\n\t\t\tconst child = ensureObject(entry, `${resultPath} results[${index}]`);\n\t\t\tconst agent = validateOptionalString(child, \"agent\", resultPath, `results[${index}].agent`);\n\t\t\tconst sessionFile = validateOptionalString(child, \"sessionFile\", resultPath, `results[${index}].sessionFile`);\n\t\t\tconst intercomTarget = validateOptionalString(child, \"intercomTarget\", resultPath, `results[${index}].intercomTarget`);\n\t\t\tconst model = validateOptionalString(child, \"model\", resultPath, `results[${index}].model`);\n\t\t\tconst thinking = validateOptionalString(child, \"thinking\", resultPath, `results[${index}].thinking`);\n\t\t\tconst success = child.success;\n\t\t\tif (success !== undefined && typeof success !== \"boolean\") throw new Error(`Invalid async result file '${resultPath}': results[${index}].success must be a boolean.`);\n\t\t\treturn { agent, sessionFile, intercomTarget, model, thinking, ...(typeof success === \"boolean\" ? { success } : {}) };\n\t\t});\n\t}\n\tconst success = data.success;\n\tif (success !== undefined && typeof success !== \"boolean\") throw new Error(`Invalid async result file '${resultPath}': success must be a boolean.`);\n\treturn {\n\t\tid: validateOptionalString(data, \"id\", resultPath),\n\t\trunId: validateOptionalString(data, \"runId\", resultPath),\n\t\tagent: validateOptionalString(data, \"agent\", resultPath),\n\t\tmode: validateOptionalString(data, \"mode\", resultPath),\n\t\tstate: validateOptionalString(data, \"state\", resultPath),\n\t\tcwd: validateOptionalString(data, \"cwd\", resultPath),\n\t\tsessionFile: validateOptionalString(data, \"sessionFile\", resultPath),\n\t\tmodel: validateOptionalString(data, \"model\", resultPath),\n\t\tthinking: validateOptionalString(data, \"thinking\", resultPath),\n\t\t...(typeof success === \"boolean\" ? { success } : {}),\n\t\t...(results ? { results } : {}),\n\t};\n}\n\nfunction readResultFile(resultPath: string): AsyncResultFile {\n\tlet raw: string;\n\ttry {\n\t\traw = fs.readFileSync(resultPath, \"utf-8\");\n\t} catch (error) {\n\t\tthrow new Error(`Failed to read async result file '${resultPath}': ${getErrorMessage(error)}`, {\n\t\t\tcause: error instanceof Error ? error : undefined,\n\t\t});\n\t}\n\ttry {\n\t\treturn validateResultFile(JSON.parse(raw), resultPath);\n\t} catch (error) {\n\t\tif (error instanceof SyntaxError) {\n\t\t\tthrow new Error(`Failed to parse async result file '${resultPath}': ${getErrorMessage(error)}`, {\n\t\t\t\tcause: error,\n\t\t\t});\n\t\t}\n\t\tthrow error;\n\t}\n}\n\nfunction assertRunId(value: string | undefined, field: \"id\" | \"runId\"): string | undefined {\n\tif (value === undefined) return undefined;\n\tif (value.trim() === \"\") throw new Error(`${field} must not be empty.`);\n\tif (path.isAbsolute(value) || /[\\\\/]/.test(value) || value.includes(\"..\")) {\n\t\tthrow new Error(`${field} must be an async run id or prefix, not a path.`);\n\t}\n\treturn value;\n}\n\nfunction assertInsideRoot(root: string, target: string, label: string): void {\n\tconst rootPath = path.resolve(root);\n\tconst targetPath = path.resolve(target);\n\tconst relative = path.relative(rootPath, targetPath);\n\tif (relative === \"\" || (!relative.startsWith(\"..\") && !path.isAbsolute(relative))) return;\n\tthrow new Error(`${label} must be inside ${rootPath}.`);\n}\n\nfunction prefixedRunIds(dir: string, prefix: string, suffix = \"\"): string[] {\n\tif (!fs.existsSync(dir)) return [];\n\treturn fs.readdirSync(dir)\n\t\t.filter((entry) => entry.startsWith(prefix) && (!suffix || entry.endsWith(suffix)))\n\t\t.map((entry) => suffix ? entry.slice(0, -suffix.length) : entry)\n\t\t.sort();\n}\n\nfunction exactResultPath(resultsDir: string, runId: string): string | null {\n\tconst resultPath = path.join(resultsDir, `${runId}.json`);\n\tassertInsideRoot(resultsDir, resultPath, \"Async result file\");\n\treturn fs.existsSync(resultPath) ? resultPath : null;\n}\n\nexport function findAsyncRunPrefixMatches(prefix: string, asyncDirRoot: string, resultsDir: string): Array<{ id: string; location: AsyncRunLocation }> {\n\tconst requestedId = assertRunId(prefix, \"id\");\n\tif (!requestedId) return [];\n\tconst asyncRoot = path.resolve(asyncDirRoot);\n\tconst resultRoot = path.resolve(resultsDir);\n\tconst matchingIds = [...new Set([\n\t\t...prefixedRunIds(asyncRoot, requestedId),\n\t\t...prefixedRunIds(resultRoot, requestedId, \".json\"),\n\t])].sort();\n\treturn matchingIds.map((id) => {\n\t\tconst asyncDir = path.join(asyncRoot, id);\n\t\tassertInsideRoot(asyncRoot, asyncDir, \"Async run directory\");\n\t\treturn {\n\t\t\tid,\n\t\t\tlocation: {\n\t\t\t\tasyncDir: fs.existsSync(asyncDir) ? asyncDir : null,\n\t\t\t\tresultPath: exactResultPath(resultRoot, id),\n\t\t\t\tresolvedId: id,\n\t\t\t},\n\t\t};\n\t});\n}\n\nexport function resolveAsyncRunLocation(params: AsyncResumeParams, asyncDirRoot: string, resultsDir: string): AsyncRunLocation {\n\tconst asyncRoot = path.resolve(asyncDirRoot);\n\tconst resultRoot = path.resolve(resultsDir);\n\tconst requestedId = assertRunId(params.id, \"id\") ?? assertRunId(params.runId, \"runId\");\n\tif (params.dir) {\n\t\tconst asyncDir = path.resolve(params.dir);\n\t\tassertInsideRoot(asyncRoot, asyncDir, \"Async run directory\");\n\t\tconst resolvedId = requestedId ?? path.basename(asyncDir);\n\t\tif (requestedId && requestedId !== path.basename(asyncDir)) {\n\t\t\tthrow new Error(`Async run id '${requestedId}' does not match directory '${path.basename(asyncDir)}'.`);\n\t\t}\n\t\treturn { asyncDir, resultPath: exactResultPath(resultRoot, resolvedId), resolvedId };\n\t}\n\tif (!requestedId) return { asyncDir: null, resultPath: null };\n\n\tconst directAsyncDir = path.join(asyncRoot, requestedId);\n\tassertInsideRoot(asyncRoot, directAsyncDir, \"Async run directory\");\n\tconst directResultPath = exactResultPath(resultRoot, requestedId);\n\tif (fs.existsSync(directAsyncDir) || directResultPath) {\n\t\treturn {\n\t\t\tasyncDir: fs.existsSync(directAsyncDir) ? directAsyncDir : null,\n\t\t\tresultPath: directResultPath,\n\t\t\tresolvedId: requestedId,\n\t\t};\n\t}\n\n\tconst matching = findAsyncRunPrefixMatches(requestedId, asyncRoot, resultRoot);\n\tif (matching.length === 0) return { asyncDir: null, resultPath: null, resolvedId: requestedId };\n\tif (matching.length > 1) {\n\t\tthrow new Error(`Ambiguous async run id prefix '${requestedId}' matched: ${matching.map((match) => match.id).join(\", \")}. Provide a longer id.`);\n\t}\n\treturn matching[0]!.location;\n}\n\nfunction resultState(result: AsyncResultFile): AsyncStatus[\"state\"] {\n\tif (result.state === \"complete\" || result.state === \"failed\" || result.state === \"paused\" || result.state === \"stopped\" || result.state === \"running\" || result.state === \"queued\") {\n\t\treturn result.state;\n\t}\n\treturn result.success ? \"complete\" : \"failed\";\n}\n\nfunction validateStatusForResume(status: AsyncStatus | null, source: string): void {\n\tif (!status) return;\n\tif (typeof status.runId !== \"string\") throw new Error(`Invalid async status '${source}': runId must be a string.`);\n\tif (status.sessionId !== undefined && typeof status.sessionId !== \"string\") throw new Error(`Invalid async status '${source}': sessionId must be a string.`);\n\tif (status.cwd !== undefined && typeof status.cwd !== \"string\") throw new Error(`Invalid async status '${source}': cwd must be a string.`);\n\tif (status.sessionFile !== undefined && typeof status.sessionFile !== \"string\") throw new Error(`Invalid async status '${source}': sessionFile must be a string.`);\n\tif (status.steps !== undefined) {\n\t\tif (!Array.isArray(status.steps)) throw new Error(`Invalid async status '${source}': steps must be an array.`);\n\t\tstatus.steps.forEach((step, index) => {\n\t\t\tif (!step || typeof step !== \"object\" || Array.isArray(step)) throw new Error(`Invalid async status '${source}': steps[${index}] must be an object.`);\n\t\t\tconst stepRecord = step as Record<string, unknown>;\n\t\t\tif (typeof stepRecord.agent !== \"string\") throw new Error(`Invalid async status '${source}': steps[${index}].agent must be a string.`);\n\t\t\tif (stepRecord.childId !== undefined && (typeof stepRecord.childId !== \"string\" || !stepRecord.childId.trim())) throw new Error(`Invalid async status '${source}': steps[${index}].childId must be a non-empty string.`);\n\t\t\tif (stepRecord.description !== undefined) validateChildDescription(stepRecord.description, `Async status '${source}' steps[${index}].description`);\n\t\t\tif (stepRecord.permissions !== undefined && stepRecord.permissions !== \"full\" && stepRecord.permissions !== \"read-only\") throw new Error(`Invalid async status '${source}': steps[${index}].permissions must be full or read-only.`);\n\t\t\tif (stepRecord.sessionFile !== undefined && typeof stepRecord.sessionFile !== \"string\") throw new Error(`Invalid async status '${source}': steps[${index}].sessionFile must be a string.`);\n\t\t\tif (stepRecord.model !== undefined && typeof stepRecord.model !== \"string\") throw new Error(`Invalid async status '${source}': steps[${index}].model must be a string.`);\n\t\t\tif (stepRecord.thinking !== undefined && typeof stepRecord.thinking !== \"string\") throw new Error(`Invalid async status '${source}': steps[${index}].thinking must be a string.`);\n\t\t});\n\t}\n}\n\nexport function readAsyncRecoveryDescriptor(asyncDir: string | undefined): SteeringRecoveryDescriptor | undefined {\n\tif (!asyncDir) return undefined;\n\tconst descriptorPath = path.join(asyncDir, \"recovery-descriptor.json\");\n\tif (!fs.existsSync(descriptorPath)) return undefined;\n\tlet value: unknown;\n\ttry {\n\t\tvalue = JSON.parse(fs.readFileSync(descriptorPath, \"utf-8\"));\n\t} catch (error) {\n\t\tthrow new Error(`Failed to parse async recovery descriptor '${descriptorPath}': ${getErrorMessage(error)}`, { cause: error instanceof Error ? error : undefined });\n\t}\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': expected an object.`);\n\tconst parsed = value as Record<string, unknown>;\n\tconst allowedFields = new Set([\n\t\t\"version\", \"lifecycleArtifactVersion\", \"sourceRunId\", \"childId\", \"description\", \"permissions\", \"agent\", \"sessionFile\", \"cwd\", \"model\", \"thinking\", \"tier\", \"modelSelection\", \"skills\",\n\t\t\"outputPath\", \"outputMode\", \"acceptance\", \"sessionDir\", \"artifactConfig\",\n\t\t\"artifactsDir\", \"maxOutput\", \"controlConfig\", \"absoluteDeadlineAt\", \"initialTurnBudget\", \"initialToolBudget\", \"maxSubagentDepth\", \"share\",\n\t]);\n\tfor (const field of Object.keys(parsed)) {\n\t\tif (!allowedFields.has(field)) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': unknown field '${field}'.`);\n\t}\n\tif (parsed.version !== 4) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': version must be 4.`);\n\tif (!isSupportedSubagentLifecycleVersion(parsed.lifecycleArtifactVersion)) throw new Error(UNSUPPORTED_SUBAGENT_LIFECYCLE_MESSAGE);\n\tconst requiredStrings = [\"sourceRunId\", \"childId\", \"description\", \"agent\", \"cwd\", \"outputMode\"] as const;\n\tfor (const field of requiredStrings) {\n\t\tif (typeof parsed[field] !== \"string\" || !(parsed[field] as string).trim()) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': ${field} must be a non-empty string.`);\n\t}\n\tif (parsed.permissions !== \"full\" && parsed.permissions !== \"read-only\") throw new Error(`Invalid async recovery descriptor '${descriptorPath}': permissions must be full or read-only.`);\n\tif (parsed.tier !== \"light\" && parsed.tier !== \"standard\" && parsed.tier !== \"heavy\") throw new Error(`Invalid async recovery descriptor '${descriptorPath}': tier must be light, standard, or heavy.`);\n\tvalidateChildDescription(parsed.description, `Async recovery descriptor '${descriptorPath}' description`);\n\tif (parsed.outputMode !== \"inline\" && parsed.outputMode !== \"file-only\") throw new Error(`Invalid async recovery descriptor '${descriptorPath}': outputMode is invalid.`);\n\tfor (const field of [\"share\"] as const) {\n\t\tif (typeof parsed[field] !== \"boolean\") throw new Error(`Invalid async recovery descriptor '${descriptorPath}': ${field} must be a boolean.`);\n\t}\n\tif (!Number.isInteger(parsed.maxSubagentDepth) || (parsed.maxSubagentDepth as number) < 0) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': maxSubagentDepth must be a non-negative integer.`);\n\tfor (const field of [\"skills\"] as const) {\n\t\tconst item = parsed[field];\n\t\tif (item !== undefined && (!Array.isArray(item) || item.some((entry) => typeof entry !== \"string\" || !entry.trim()))) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': ${field} must contain non-empty strings.`);\n\t}\n\tfor (const field of [\"sessionFile\", \"model\", \"thinking\", \"outputPath\", \"sessionDir\", \"artifactsDir\"] as const) {\n\t\tif (parsed[field] !== undefined && (typeof parsed[field] !== \"string\" || !(parsed[field] as string).trim())) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': ${field} must be a non-empty string.`);\n\t}\n\tif (parsed.modelSelection !== undefined) {\n\t\tconst selection = parsed.modelSelection as { kind?: unknown; tier?: unknown };\n\t\tif (!selection || typeof selection !== \"object\") throw new Error(`Invalid async recovery descriptor '${descriptorPath}': modelSelection must be an object.`);\n\t\tif (selection.kind !== \"tier\") {\n\t\t\tthrow new Error(`Invalid async recovery descriptor '${descriptorPath}': modelSelection.kind is invalid.`);\n\t\t}\n\t\tif (selection.kind === \"tier\" && selection.tier !== \"light\" && selection.tier !== \"standard\" && selection.tier !== \"heavy\") {\n\t\t\tthrow new Error(`Invalid async recovery descriptor '${descriptorPath}': modelSelection.tier is invalid.`);\n\t\t}\n\t}\n\tif (parsed.absoluteDeadlineAt !== undefined && (!Number.isFinite(parsed.absoluteDeadlineAt) || (parsed.absoluteDeadlineAt as number) <= 0)) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': absoluteDeadlineAt must be a positive timestamp.`);\n\tif (parsed.initialTurnBudget !== undefined) {\n\t\tconst result = resolveTurnBudgetConfig(parsed.initialTurnBudget, \"recoveryDescriptor.initialTurnBudget\");\n\t\tif (result.error) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': ${result.error}`);\n\t}\n\tif (parsed.initialToolBudget !== undefined) {\n\t\tconst result = validateToolBudgetConfig(parsed.initialToolBudget, \"recoveryDescriptor.initialToolBudget\");\n\t\tif (result.error) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': ${result.error}`);\n\t}\n\tif (parsed.maxOutput !== undefined) {\n\t\tif (!parsed.maxOutput || typeof parsed.maxOutput !== \"object\" || Array.isArray(parsed.maxOutput)) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': maxOutput must be an object.`);\n\t\tfor (const field of [\"bytes\", \"lines\"] as const) {\n\t\t\tconst item = (parsed.maxOutput as Record<string, unknown>)[field];\n\t\t\tif (item !== undefined && (!Number.isInteger(item) || (item as number) < 1)) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': maxOutput.${field} must be a positive integer.`);\n\t\t}\n\t}\n\tif (parsed.artifactConfig !== undefined) {\n\t\tif (!parsed.artifactConfig || typeof parsed.artifactConfig !== \"object\" || Array.isArray(parsed.artifactConfig)) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': artifactConfig must be an object.`);\n\t\tconst artifact = parsed.artifactConfig as Record<string, unknown>;\n\t\tfor (const field of [\"enabled\", \"includeInput\", \"includeOutput\", \"includeJsonl\", \"includeMetadata\"] as const) {\n\t\t\tif (typeof artifact[field] !== \"boolean\") throw new Error(`Invalid async recovery descriptor '${descriptorPath}': artifactConfig.${field} must be a boolean.`);\n\t\t}\n\t\tif (artifact.includeTranscript !== undefined && typeof artifact.includeTranscript !== \"boolean\") throw new Error(`Invalid async recovery descriptor '${descriptorPath}': artifactConfig.includeTranscript must be a boolean.`);\n\t\tif (!Number.isInteger(artifact.cleanupDays) || (artifact.cleanupDays as number) < 0) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': artifactConfig.cleanupDays must be a non-negative integer.`);\n\t}\n\tif (parsed.controlConfig !== undefined) {\n\t\tif (!parsed.controlConfig || typeof parsed.controlConfig !== \"object\" || Array.isArray(parsed.controlConfig)) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': controlConfig must be an object.`);\n\t\tconst control = parsed.controlConfig as Record<string, unknown>;\n\t\tif (typeof control.enabled !== \"boolean\") throw new Error(`Invalid async recovery descriptor '${descriptorPath}': controlConfig.enabled must be a boolean.`);\n\t\tfor (const field of [\"needsAttentionAfterMs\", \"activeNoticeAfterMs\", \"failedToolAttemptsBeforeAttention\"] as const) {\n\t\t\tif (!Number.isInteger(control[field]) || (control[field] as number) < 1) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': controlConfig.${field} must be a positive integer.`);\n\t\t}\n\t\tfor (const field of [\"activeNoticeAfterTurns\", \"activeNoticeAfterTokens\"] as const) {\n\t\t\tif (control[field] !== undefined && (!Number.isInteger(control[field]) || (control[field] as number) < 1)) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': controlConfig.${field} must be a positive integer.`);\n\t\t}\n\t\tif (!Array.isArray(control.notifyOn) || control.notifyOn.some((item) => item !== \"active_long_running\" && item !== \"needs_attention\")) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': controlConfig.notifyOn is invalid.`);\n\t\tif (!Array.isArray(control.notifyChannels) || control.notifyChannels.some((item) => item !== \"event\" && item !== \"async\" && item !== \"intercom\")) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': controlConfig.notifyChannels is invalid.`);\n\t}\n\tif (parsed.acceptance !== undefined) {\n\t\tconst errors = validateAcceptanceInput(parsed.acceptance, \"recoveryDescriptor.acceptance\");\n\t\tif (errors.length) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': ${errors.join(\" \")}`);\n\t}\n\treturn parsed as unknown as SteeringRecoveryDescriptor;\n}\n\nfunction validateResumeSessionFile(runId: string, sessionFile: string): string {\n\tif (path.extname(sessionFile) !== \".jsonl\") throw new Error(`Async run '${runId}' session file must be a .jsonl file: ${sessionFile}`);\n\tconst resolved = path.resolve(sessionFile);\n\tif (!fs.existsSync(resolved)) throw new Error(`Async run '${runId}' session file does not exist: ${sessionFile}`);\n\treturn resolved;\n}\n\nexport function resolveAsyncResumeTarget(params: AsyncResumeParams, deps: AsyncResumeDeps = {}, options: AsyncResumeOptions = {}): AsyncResumeTarget {\n\tconst asyncDirRoot = deps.asyncDirRoot ?? ASYNC_DIR;\n\tconst resultsDir = deps.resultsDir ?? RESULTS_DIR;\n\tconst requireSessionFile = options.requireSessionFile ?? true;\n\tconst location = resolveAsyncRunLocation(params, asyncDirRoot, resultsDir);\n\tif (!location.asyncDir && !location.resultPath) {\n\t\tthrow new Error(\"Async run not found. Provide id or dir.\");\n\t}\n\n\tconst reconciliation = location.asyncDir\n\t\t? reconcileAsyncRun(location.asyncDir, { resultsDir, kill: deps.kill, now: deps.now })\n\t\t: undefined;\n\tconst status = reconciliation?.status ?? null;\n\tvalidateStatusForResume(status, location.asyncDir ? path.join(location.asyncDir, \"status.json\") : \"status.json\");\n\tconst recoveryDescriptor = readAsyncRecoveryDescriptor(location.asyncDir);\n\tconst result = location.resultPath ? readResultFile(location.resultPath) : undefined;\n\tconst runId = status?.runId ?? result?.runId ?? result?.id ?? location.resolvedId ?? (location.asyncDir ? path.basename(location.asyncDir) : \"unknown\");\n\tif (recoveryDescriptor && recoveryDescriptor.sourceRunId !== runId) throw new Error(`Async run '${runId}' has a recovery descriptor for a different source run.`);\n\tconst state = status?.state ?? (result ? resultState(result) : undefined);\n\tif (!state) throw new Error(`Status file not found for async run '${runId}'.`);\n\tif (state === \"stopped\") throw new Error(`Async run '${runId}' was stopped and cannot be resumed. Start a new run instead.`);\n\n\tconst statusSteps = status?.steps ?? [];\n\tconst resultSteps = result?.results ?? [];\n\tconst stepCount = statusSteps.length || resultSteps.length || (result?.agent ? 1 : 0);\n\tconst requestedIndex = params.index;\n\tif (requestedIndex !== undefined && !Number.isInteger(requestedIndex)) throw new Error(`Async run '${runId}' index must be an integer.`);\n\tconst terminalStepStatuses = new Set([\"complete\", \"completed\", \"failed\", \"paused\"]);\n\n\tif (state === \"running\") {\n\t\tif (requestedIndex !== undefined) {\n\t\t\tif (requestedIndex < 0 || requestedIndex >= stepCount) throw new Error(`Async run '${runId}' has ${stepCount} children. Index ${requestedIndex} is out of range.`);\n\t\t\tconst selectedStep = statusSteps[requestedIndex];\n\t\t\tif (selectedStep?.status === \"running\") {\n\t\t\t\treturn {\n\t\t\t\t\tkind: \"live\",\n\t\t\t\t\trunId,\n\t\t\t\t\tasyncDir: location.asyncDir ?? undefined,\n\t\t\t\t\tstate,\n\t\t\t\t\tagent: selectedStep.agent,\n\t\t\t\t\tchildId: selectedStep.childId,\n\t\t\t\t\tdescription: selectedStep.description,\n\t\t\t\t\tpermissions: selectedStep.permissions,\n\t\t\t\t\tindex: requestedIndex,\n\t\t\t\t\tintercomTarget: resolveSubagentIntercomTarget(runId, selectedStep.childId ?? selectedStep.agent, requestedIndex),\n\t\t\t\t\tcwd: status?.cwd ?? result?.cwd,\n\t\t\t\t\tsessionFile: selectedStep.sessionFile ?? status?.sessionFile ?? result?.sessionFile,\n\t\t\t\t\tmodel: selectedStep.model,\n\t\t\t\t\tthinking: selectedStep.thinking,\n\t\t\t\t\t...(recoveryDescriptor ? { recoveryDescriptor } : {}),\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (selectedStep?.status === \"pending\") throw new Error(`Async run '${runId}' child ${requestedIndex} is pending and has not started yet. Wait for it to run or complete before resuming.`);\n\t\t\tif (selectedStep && !terminalStepStatuses.has(selectedStep.status)) throw new Error(`Async run '${runId}' child ${requestedIndex} is ${selectedStep.status} and cannot be revived yet.`);\n\t\t} else {\n\t\t\tconst running = statusSteps\n\t\t\t\t.map((step, index) => ({ step, index }))\n\t\t\t\t.filter(({ step }) => step.status === \"running\");\n\t\t\tconst selected = running.length === 1 ? running[0] : undefined;\n\t\t\tif (!selected) {\n\t\t\t\tthrow new Error(`Async run '${runId}' has ${running.length} running children. Provide index to choose one.`);\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tkind: \"live\",\n\t\t\t\trunId,\n\t\t\t\tasyncDir: location.asyncDir ?? undefined,\n\t\t\t\tstate,\n\t\t\t\tagent: selected.step.agent,\n\t\t\t\tchildId: selected.step.childId,\n\t\t\t\tdescription: selected.step.description,\n\t\t\t\tpermissions: selected.step.permissions,\n\t\t\t\tindex: selected.index,\n\t\t\t\tintercomTarget: resolveSubagentIntercomTarget(runId, selected.step.childId ?? selected.step.agent, selected.index),\n\t\t\t\tcwd: status?.cwd ?? result?.cwd,\n\t\t\t\tsessionFile: selected.step.sessionFile ?? status?.sessionFile ?? result?.sessionFile,\n\t\t\t\tmodel: selected.step.model,\n\t\t\t\tthinking: selected.step.thinking,\n\t\t\t\t...(recoveryDescriptor ? { recoveryDescriptor } : {}),\n\t\t\t};\n\t\t}\n\t}\n\n\tif (stepCount > 1 && requestedIndex === undefined) {\n\t\tthrow new Error(`Async run '${runId}' has ${stepCount} children. Provide index to choose one.`);\n\t}\n\tconst index = requestedIndex ?? 0;\n\tif (!Number.isInteger(index)) throw new Error(`Async run '${runId}' index must be an integer.`);\n\tif (index < 0 || index >= stepCount) throw new Error(`Async run '${runId}' has ${stepCount} children. Index ${index} is out of range.`);\n\tconst agent = statusSteps[index]?.agent ?? resultSteps[index]?.agent ?? result?.agent;\n\tif (!agent) throw new Error(`Could not determine child agent for async run '${runId}'.`);\n\tif (recoveryDescriptor && recoveryDescriptor.agent !== agent) throw new Error(`Async run '${runId}' has a recovery descriptor for '${recoveryDescriptor.agent}', not '${agent}'.`);\n\tconst sessionFile = statusSteps[index]?.sessionFile\n\t\t?? resultSteps[index]?.sessionFile\n\t\t?? (stepCount === 1 ? status?.sessionFile ?? result?.sessionFile : undefined);\n\tif (!sessionFile && requireSessionFile) throw new Error(`Async run '${runId}' child ${index} does not have a persisted session file to resume from.`);\n\tconst resolvedSessionFile = sessionFile ? validateResumeSessionFile(runId, sessionFile) : undefined;\n\tconst stepModel = statusSteps[index]?.model ?? resultSteps[index]?.model ?? (stepCount === 1 ? result?.model : undefined);\n\tconst stepThinking = statusSteps[index]?.thinking ?? resultSteps[index]?.thinking ?? (stepCount === 1 ? result?.thinking : undefined);\n\tconst childId = statusSteps[index]?.childId ?? resultSteps[index]?.childId;\n\n\treturn {\n\t\tkind: \"revive\",\n\t\trunId,\n\t\tasyncDir: location.asyncDir ?? undefined,\n\t\tstate,\n\t\tagent,\n\t\tchildId,\n\t\tdescription: statusSteps[index]?.description ?? resultSteps[index]?.description,\n\t\tpermissions: statusSteps[index]?.permissions ?? resultSteps[index]?.permissions,\n\t\tindex,\n\t\tintercomTarget: resolveSubagentIntercomTarget(runId, childId ?? agent, index),\n\t\tcwd: status?.cwd ?? result?.cwd,\n\t\t...(resolvedSessionFile ? { sessionFile: resolvedSessionFile } : {}),\n\t\t...(stepModel ? { model: stepModel } : {}),\n\t\t...(stepThinking ? { thinking: stepThinking } : {}),\n\t\t...(recoveryDescriptor ? { recoveryDescriptor } : {}),\n\t};\n}\n\nexport function buildRevivedAsyncTask(target: AsyncResumeTarget, message: string): string {\n\treturn [\n\t\t\"You are reviving a previous subagent conversation.\",\n\t\t\"\",\n\t\t`Original run: ${target.runId}`,\n\t\t`Original agent: ${target.agent}`,\n\t\ttarget.sessionFile ? `Original session file: ${target.sessionFile}` : undefined,\n\t\t\"\",\n\t\t\"Use the stored session context as background. Answer the orchestrator's follow-up below. Do not assume the original child process is still alive.\",\n\t\t\"\",\n\t\t\"Follow-up:\",\n\t\tmessage,\n\t].filter((line): line is string => line !== undefined).join(\"\\n\");\n}\n"]}
|
|
1
|
+
{"version":3,"file":"async-resume.d.ts","sourceRoot":"","sources":["../../../../../../src/builtin-extensions/pi-subagents/src/runs/background/async-resume.ts"],"names":[],"mappings":"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","sourcesContent":["// @ts-nocheck\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { ASYNC_DIR, RESULTS_DIR, isSupportedSubagentLifecycleVersion, UNSUPPORTED_SUBAGENT_LIFECYCLE_MESSAGE, type AsyncStatus, type ModelSelection, type SteeringRecoveryDescriptor, type SubagentState } from \"../../shared/types.ts\";\nimport { validateChildDescription } from \"../../shared/child-spec.ts\";\nimport { resolveSubagentIntercomTarget } from \"../../intercom/intercom-bridge.ts\";\nimport { validatePersistedAcceptance } from \"../shared/acceptance.ts\";\nimport { validateToolBudgetConfig } from \"../shared/tool-budget.ts\";\nimport { resolveTurnBudgetConfig } from \"../shared/turn-budget.ts\";\nimport { deliverInterruptRequest } from \"./control-channel.ts\";\nimport { reconcileAsyncRun } from \"./stale-run-reconciler.ts\";\n\nexport const ASYNC_RESUME_INTERRUPT_SIGNAL: NodeJS.Signals = process.platform === \"win32\" ? \"SIGBREAK\" : \"SIGUSR2\";\n\nexport interface AsyncResumeParams {\n\tid?: string;\n\trunId?: string;\n\tdir?: string;\n\tindex?: number;\n}\n\nexport interface AsyncResumeDeps {\n\tasyncDirRoot?: string;\n\tresultsDir?: string;\n\tkill?: (pid: number, signal?: NodeJS.Signals | 0) => boolean;\n\tnow?: () => number;\n}\n\nexport interface AsyncResumeOptions {\n\trequireSessionFile?: boolean;\n}\n\nexport type AsyncResumeTarget = {\n\tkind: \"live\" | \"revive\";\n\trunId: string;\n\tasyncDir?: string;\n\tstate: AsyncStatus[\"state\"];\n\tagent: string;\n\tchildId?: string;\n\tdescription?: string;\n\tpermissions?: \"full\" | \"read-only\";\n\tindex: number;\n\tintercomTarget: string;\n\tcwd?: string;\n\tsessionFile?: string;\n\tmodel?: string;\n\tthinking?: string;\n\tmodelSelection?: ModelSelection;\n\trecoveryDescriptor?: SteeringRecoveryDescriptor;\n};\n\ntype KillFn = (pid: number, signal?: NodeJS.Signals | 0) => boolean;\n\nexport function interruptLiveAsyncResumeTarget(input: {\n\ttarget: AsyncResumeTarget & { kind: \"live\" };\n\tstate?: Pick<SubagentState, \"asyncJobs\">;\n\tkill?: KillFn;\n\tnow?: () => number;\n\tresultsDir?: string;\n}): { ok: true; asyncId: string } | { ok: false; message: string } {\n\tconst asyncId = input.target.runId;\n\tif (!input.target.asyncDir) {\n\t\treturn { ok: false, message: `Async run ${asyncId} is live but does not have an async directory to interrupt.` };\n\t}\n\tconst status = reconcileAsyncRun(input.target.asyncDir, { resultsDir: input.resultsDir, kill: input.kill, now: input.now }).status;\n\tif (!status || status.state !== \"running\" || typeof status.pid !== \"number\") {\n\t\treturn { ok: false, message: `Async run ${asyncId} is live but no interrupt-capable runner pid was found.` };\n\t}\n\ttry {\n\t\tdeliverInterruptRequest({\n\t\t\tasyncDir: input.target.asyncDir,\n\t\t\tpid: status.pid,\n\t\t\tkill: input.kill,\n\t\t\tsignal: ASYNC_RESUME_INTERRUPT_SIGNAL,\n\t\t\tnow: input.now,\n\t\t\tsource: \"async-resume\",\n\t\t});\n\t\tconst tracked = input.state?.asyncJobs.get(asyncId);\n\t\tif (tracked) {\n\t\t\ttracked.activityState = undefined;\n\t\t\ttracked.updatedAt = input.now?.() ?? Date.now();\n\t\t}\n\t\treturn { ok: true, asyncId };\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\treturn { ok: false, message: `Failed to interrupt async run ${asyncId}: ${message}` };\n\t}\n}\n\ninterface AsyncResultFile {\n\tid?: string;\n\trunId?: string;\n\tagent?: string;\n\tmode?: string;\n\tstate?: string;\n\tsuccess?: boolean;\n\tcwd?: string;\n\tsessionFile?: string;\n\tmodel?: string;\n\tthinking?: string;\n\tresults?: Array<{ agent?: string; success?: boolean; sessionFile?: string; intercomTarget?: string; model?: string; thinking?: string }>;\n}\n\nexport interface AsyncRunLocation {\n\tasyncDir: string | null;\n\tresultPath: string | null;\n\tresolvedId?: string;\n}\n\nfunction getErrorMessage(error: unknown): string {\n\treturn error instanceof Error ? error.message : String(error);\n}\n\nconst TURN_BUDGET_RUNTIME_KEYS = new Set([\"outcome\", \"turnCount\", \"wrapUpRequestedAtTurn\", \"exceededAtTurn\"]);\n\nfunction persistedTurnBudgetConfig(raw: unknown): unknown {\n\tif (!raw || typeof raw !== \"object\" || Array.isArray(raw)) return raw;\n\tconst config: Record<string, unknown> = {};\n\tfor (const [key, value] of Object.entries(raw as Record<string, unknown>)) {\n\t\tif (TURN_BUDGET_RUNTIME_KEYS.has(key)) continue;\n\t\tconfig[key] = value;\n\t}\n\treturn config;\n}\n\nfunction ensureObject(value: unknown, source: string): Record<string, unknown> {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) {\n\t\tthrow new Error(`Async result file '${source}' must contain a JSON object.`);\n\t}\n\treturn value as Record<string, unknown>;\n}\n\nfunction validateOptionalString(value: Record<string, unknown>, field: string, source: string, displayField = field): string | undefined {\n\tconst fieldValue = value[field];\n\tif (fieldValue === undefined) return undefined;\n\tif (typeof fieldValue !== \"string\") throw new Error(`Invalid async result file '${source}': ${displayField} must be a string.`);\n\treturn fieldValue;\n}\n\nfunction validateResultFile(value: unknown, resultPath: string): AsyncResultFile {\n\tconst data = ensureObject(value, resultPath);\n\tif (!isSupportedSubagentLifecycleVersion(data.lifecycleArtifactVersion)) {\n\t\tthrow new Error(UNSUPPORTED_SUBAGENT_LIFECYCLE_MESSAGE);\n\t}\n\tconst resultsValue = data.results;\n\tlet results: AsyncResultFile[\"results\"];\n\tif (resultsValue !== undefined) {\n\t\tif (!Array.isArray(resultsValue)) throw new Error(`Invalid async result file '${resultPath}': results must be an array.`);\n\t\tresults = resultsValue.map((entry, index) => {\n\t\t\tconst child = ensureObject(entry, `${resultPath} results[${index}]`);\n\t\t\tconst agent = validateOptionalString(child, \"agent\", resultPath, `results[${index}].agent`);\n\t\t\tconst sessionFile = validateOptionalString(child, \"sessionFile\", resultPath, `results[${index}].sessionFile`);\n\t\t\tconst intercomTarget = validateOptionalString(child, \"intercomTarget\", resultPath, `results[${index}].intercomTarget`);\n\t\t\tconst model = validateOptionalString(child, \"model\", resultPath, `results[${index}].model`);\n\t\t\tconst thinking = validateOptionalString(child, \"thinking\", resultPath, `results[${index}].thinking`);\n\t\t\tconst success = child.success;\n\t\t\tif (success !== undefined && typeof success !== \"boolean\") throw new Error(`Invalid async result file '${resultPath}': results[${index}].success must be a boolean.`);\n\t\t\treturn { agent, sessionFile, intercomTarget, model, thinking, ...(typeof success === \"boolean\" ? { success } : {}) };\n\t\t});\n\t}\n\tconst success = data.success;\n\tif (success !== undefined && typeof success !== \"boolean\") throw new Error(`Invalid async result file '${resultPath}': success must be a boolean.`);\n\treturn {\n\t\tid: validateOptionalString(data, \"id\", resultPath),\n\t\trunId: validateOptionalString(data, \"runId\", resultPath),\n\t\tagent: validateOptionalString(data, \"agent\", resultPath),\n\t\tmode: validateOptionalString(data, \"mode\", resultPath),\n\t\tstate: validateOptionalString(data, \"state\", resultPath),\n\t\tcwd: validateOptionalString(data, \"cwd\", resultPath),\n\t\tsessionFile: validateOptionalString(data, \"sessionFile\", resultPath),\n\t\tmodel: validateOptionalString(data, \"model\", resultPath),\n\t\tthinking: validateOptionalString(data, \"thinking\", resultPath),\n\t\t...(typeof success === \"boolean\" ? { success } : {}),\n\t\t...(results ? { results } : {}),\n\t};\n}\n\nfunction readResultFile(resultPath: string): AsyncResultFile {\n\tlet raw: string;\n\ttry {\n\t\traw = fs.readFileSync(resultPath, \"utf-8\");\n\t} catch (error) {\n\t\tthrow new Error(`Failed to read async result file '${resultPath}': ${getErrorMessage(error)}`, {\n\t\t\tcause: error instanceof Error ? error : undefined,\n\t\t});\n\t}\n\ttry {\n\t\treturn validateResultFile(JSON.parse(raw), resultPath);\n\t} catch (error) {\n\t\tif (error instanceof SyntaxError) {\n\t\t\tthrow new Error(`Failed to parse async result file '${resultPath}': ${getErrorMessage(error)}`, {\n\t\t\t\tcause: error,\n\t\t\t});\n\t\t}\n\t\tthrow error;\n\t}\n}\n\nfunction assertRunId(value: string | undefined, field: \"id\" | \"runId\"): string | undefined {\n\tif (value === undefined) return undefined;\n\tif (value.trim() === \"\") throw new Error(`${field} must not be empty.`);\n\tif (path.isAbsolute(value) || /[\\\\/]/.test(value) || value.includes(\"..\")) {\n\t\tthrow new Error(`${field} must be an async run id or prefix, not a path.`);\n\t}\n\treturn value;\n}\n\nfunction assertInsideRoot(root: string, target: string, label: string): void {\n\tconst rootPath = path.resolve(root);\n\tconst targetPath = path.resolve(target);\n\tconst relative = path.relative(rootPath, targetPath);\n\tif (relative === \"\" || (!relative.startsWith(\"..\") && !path.isAbsolute(relative))) return;\n\tthrow new Error(`${label} must be inside ${rootPath}.`);\n}\n\nfunction prefixedRunIds(dir: string, prefix: string, suffix = \"\"): string[] {\n\tif (!fs.existsSync(dir)) return [];\n\treturn fs.readdirSync(dir)\n\t\t.filter((entry) => entry.startsWith(prefix) && (!suffix || entry.endsWith(suffix)))\n\t\t.map((entry) => suffix ? entry.slice(0, -suffix.length) : entry)\n\t\t.sort();\n}\n\nfunction exactResultPath(resultsDir: string, runId: string): string | null {\n\tconst resultPath = path.join(resultsDir, `${runId}.json`);\n\tassertInsideRoot(resultsDir, resultPath, \"Async result file\");\n\treturn fs.existsSync(resultPath) ? resultPath : null;\n}\n\nexport function findAsyncRunPrefixMatches(prefix: string, asyncDirRoot: string, resultsDir: string): Array<{ id: string; location: AsyncRunLocation }> {\n\tconst requestedId = assertRunId(prefix, \"id\");\n\tif (!requestedId) return [];\n\tconst asyncRoot = path.resolve(asyncDirRoot);\n\tconst resultRoot = path.resolve(resultsDir);\n\tconst matchingIds = [...new Set([\n\t\t...prefixedRunIds(asyncRoot, requestedId),\n\t\t...prefixedRunIds(resultRoot, requestedId, \".json\"),\n\t])].sort();\n\treturn matchingIds.map((id) => {\n\t\tconst asyncDir = path.join(asyncRoot, id);\n\t\tassertInsideRoot(asyncRoot, asyncDir, \"Async run directory\");\n\t\treturn {\n\t\t\tid,\n\t\t\tlocation: {\n\t\t\t\tasyncDir: fs.existsSync(asyncDir) ? asyncDir : null,\n\t\t\t\tresultPath: exactResultPath(resultRoot, id),\n\t\t\t\tresolvedId: id,\n\t\t\t},\n\t\t};\n\t});\n}\n\nexport function resolveAsyncRunLocation(params: AsyncResumeParams, asyncDirRoot: string, resultsDir: string): AsyncRunLocation {\n\tconst asyncRoot = path.resolve(asyncDirRoot);\n\tconst resultRoot = path.resolve(resultsDir);\n\tconst requestedId = assertRunId(params.id, \"id\") ?? assertRunId(params.runId, \"runId\");\n\tif (params.dir) {\n\t\tconst asyncDir = path.resolve(params.dir);\n\t\tassertInsideRoot(asyncRoot, asyncDir, \"Async run directory\");\n\t\tconst resolvedId = requestedId ?? path.basename(asyncDir);\n\t\tif (requestedId && requestedId !== path.basename(asyncDir)) {\n\t\t\tthrow new Error(`Async run id '${requestedId}' does not match directory '${path.basename(asyncDir)}'.`);\n\t\t}\n\t\treturn { asyncDir, resultPath: exactResultPath(resultRoot, resolvedId), resolvedId };\n\t}\n\tif (!requestedId) return { asyncDir: null, resultPath: null };\n\n\tconst directAsyncDir = path.join(asyncRoot, requestedId);\n\tassertInsideRoot(asyncRoot, directAsyncDir, \"Async run directory\");\n\tconst directResultPath = exactResultPath(resultRoot, requestedId);\n\tif (fs.existsSync(directAsyncDir) || directResultPath) {\n\t\treturn {\n\t\t\tasyncDir: fs.existsSync(directAsyncDir) ? directAsyncDir : null,\n\t\t\tresultPath: directResultPath,\n\t\t\tresolvedId: requestedId,\n\t\t};\n\t}\n\n\tconst matching = findAsyncRunPrefixMatches(requestedId, asyncRoot, resultRoot);\n\tif (matching.length === 0) return { asyncDir: null, resultPath: null, resolvedId: requestedId };\n\tif (matching.length > 1) {\n\t\tthrow new Error(`Ambiguous async run id prefix '${requestedId}' matched: ${matching.map((match) => match.id).join(\", \")}. Provide a longer id.`);\n\t}\n\treturn matching[0]!.location;\n}\n\nfunction resultState(result: AsyncResultFile): AsyncStatus[\"state\"] {\n\tif (result.state === \"complete\" || result.state === \"failed\" || result.state === \"paused\" || result.state === \"stopped\" || result.state === \"running\" || result.state === \"queued\") {\n\t\treturn result.state;\n\t}\n\treturn result.success ? \"complete\" : \"failed\";\n}\n\nfunction validateStatusForResume(status: AsyncStatus | null, source: string): void {\n\tif (!status) return;\n\tif (typeof status.runId !== \"string\") throw new Error(`Invalid async status '${source}': runId must be a string.`);\n\tif (status.sessionId !== undefined && typeof status.sessionId !== \"string\") throw new Error(`Invalid async status '${source}': sessionId must be a string.`);\n\tif (status.cwd !== undefined && typeof status.cwd !== \"string\") throw new Error(`Invalid async status '${source}': cwd must be a string.`);\n\tif (status.sessionFile !== undefined && typeof status.sessionFile !== \"string\") throw new Error(`Invalid async status '${source}': sessionFile must be a string.`);\n\tif (status.steps !== undefined) {\n\t\tif (!Array.isArray(status.steps)) throw new Error(`Invalid async status '${source}': steps must be an array.`);\n\t\tstatus.steps.forEach((step, index) => {\n\t\t\tif (!step || typeof step !== \"object\" || Array.isArray(step)) throw new Error(`Invalid async status '${source}': steps[${index}] must be an object.`);\n\t\t\tconst stepRecord = step as Record<string, unknown>;\n\t\t\tif (typeof stepRecord.agent !== \"string\") throw new Error(`Invalid async status '${source}': steps[${index}].agent must be a string.`);\n\t\t\tif (stepRecord.childId !== undefined && (typeof stepRecord.childId !== \"string\" || !stepRecord.childId.trim())) throw new Error(`Invalid async status '${source}': steps[${index}].childId must be a non-empty string.`);\n\t\t\tif (stepRecord.description !== undefined) validateChildDescription(stepRecord.description, `Async status '${source}' steps[${index}].description`);\n\t\t\tif (stepRecord.permissions !== undefined && stepRecord.permissions !== \"full\" && stepRecord.permissions !== \"read-only\") throw new Error(`Invalid async status '${source}': steps[${index}].permissions must be full or read-only.`);\n\t\t\tif (stepRecord.sessionFile !== undefined && typeof stepRecord.sessionFile !== \"string\") throw new Error(`Invalid async status '${source}': steps[${index}].sessionFile must be a string.`);\n\t\t\tif (stepRecord.model !== undefined && typeof stepRecord.model !== \"string\") throw new Error(`Invalid async status '${source}': steps[${index}].model must be a string.`);\n\t\t\tif (stepRecord.thinking !== undefined && typeof stepRecord.thinking !== \"string\") throw new Error(`Invalid async status '${source}': steps[${index}].thinking must be a string.`);\n\t\t});\n\t}\n}\n\nexport function readAsyncRecoveryDescriptor(asyncDir: string | undefined): SteeringRecoveryDescriptor | undefined {\n\tif (!asyncDir) return undefined;\n\tconst descriptorPath = path.join(asyncDir, \"recovery-descriptor.json\");\n\tif (!fs.existsSync(descriptorPath)) return undefined;\n\tlet value: unknown;\n\ttry {\n\t\tvalue = JSON.parse(fs.readFileSync(descriptorPath, \"utf-8\"));\n\t} catch (error) {\n\t\tthrow new Error(`Failed to parse async recovery descriptor '${descriptorPath}': ${getErrorMessage(error)}`, { cause: error instanceof Error ? error : undefined });\n\t}\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': expected an object.`);\n\tconst parsed = value as Record<string, unknown>;\n\tconst allowedFields = new Set([\n\t\t\"version\", \"lifecycleArtifactVersion\", \"sourceRunId\", \"childId\", \"description\", \"permissions\", \"agent\", \"sessionFile\", \"cwd\", \"model\", \"thinking\", \"tier\", \"modelSelection\", \"skills\",\n\t\t\"outputPath\", \"outputMode\", \"acceptance\", \"sessionDir\", \"artifactConfig\",\n\t\t\"artifactsDir\", \"maxOutput\", \"controlConfig\", \"absoluteDeadlineAt\", \"initialTurnBudget\", \"initialToolBudget\", \"maxSubagentDepth\", \"share\",\n\t]);\n\tfor (const field of Object.keys(parsed)) {\n\t\tif (!allowedFields.has(field)) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': unknown field '${field}'.`);\n\t}\n\tif (parsed.version !== 4) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': version must be 4.`);\n\tif (!isSupportedSubagentLifecycleVersion(parsed.lifecycleArtifactVersion)) throw new Error(UNSUPPORTED_SUBAGENT_LIFECYCLE_MESSAGE);\n\tconst requiredStrings = [\"sourceRunId\", \"childId\", \"description\", \"agent\", \"cwd\", \"outputMode\"] as const;\n\tfor (const field of requiredStrings) {\n\t\tif (typeof parsed[field] !== \"string\" || !(parsed[field] as string).trim()) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': ${field} must be a non-empty string.`);\n\t}\n\tif (parsed.permissions !== \"full\" && parsed.permissions !== \"read-only\") throw new Error(`Invalid async recovery descriptor '${descriptorPath}': permissions must be full or read-only.`);\n\tif (parsed.tier !== undefined && parsed.tier !== \"light\" && parsed.tier !== \"standard\" && parsed.tier !== \"heavy\") throw new Error(`Invalid async recovery descriptor '${descriptorPath}': tier must be light, standard, or heavy.`);\n\tvalidateChildDescription(parsed.description, `Async recovery descriptor '${descriptorPath}' description`);\n\tif (parsed.outputMode !== \"inline\" && parsed.outputMode !== \"file-only\") throw new Error(`Invalid async recovery descriptor '${descriptorPath}': outputMode is invalid.`);\n\tfor (const field of [\"share\"] as const) {\n\t\tif (typeof parsed[field] !== \"boolean\") throw new Error(`Invalid async recovery descriptor '${descriptorPath}': ${field} must be a boolean.`);\n\t}\n\tif (!Number.isInteger(parsed.maxSubagentDepth) || (parsed.maxSubagentDepth as number) < 0) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': maxSubagentDepth must be a non-negative integer.`);\n\tfor (const field of [\"skills\"] as const) {\n\t\tconst item = parsed[field];\n\t\tif (item !== undefined && (!Array.isArray(item) || item.some((entry) => typeof entry !== \"string\" || !entry.trim()))) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': ${field} must contain non-empty strings.`);\n\t}\n\tfor (const field of [\"sessionFile\", \"model\", \"thinking\", \"outputPath\", \"sessionDir\", \"artifactsDir\"] as const) {\n\t\tif (parsed[field] !== undefined && (typeof parsed[field] !== \"string\" || !(parsed[field] as string).trim())) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': ${field} must be a non-empty string.`);\n\t}\n\tif (parsed.modelSelection !== undefined) {\n\t\tconst selection = parsed.modelSelection as { kind?: unknown; tier?: unknown; model?: unknown };\n\t\tif (!selection || typeof selection !== \"object\") throw new Error(`Invalid async recovery descriptor '${descriptorPath}': modelSelection must be an object.`);\n\t\tif (selection.kind === \"tier\") {\n\t\t\tif (selection.tier !== \"light\" && selection.tier !== \"standard\" && selection.tier !== \"heavy\") {\n\t\t\t\tthrow new Error(`Invalid async recovery descriptor '${descriptorPath}': modelSelection.tier is invalid.`);\n\t\t\t}\n\t\t} else if (selection.kind === \"model\") {\n\t\t\tif (selection.model !== undefined && (typeof selection.model !== \"string\" || !selection.model.trim())) {\n\t\t\t\tthrow new Error(`Invalid async recovery descriptor '${descriptorPath}': modelSelection.model must be a non-empty string.`);\n\t\t\t}\n\t\t} else {\n\t\t\tthrow new Error(`Invalid async recovery descriptor '${descriptorPath}': modelSelection.kind is invalid.`);\n\t\t}\n\t} else if (parsed.tier === undefined) {\n\t\tthrow new Error(`Invalid async recovery descriptor '${descriptorPath}': tier or modelSelection is required.`);\n\t}\n\tif (parsed.absoluteDeadlineAt !== undefined && (!Number.isFinite(parsed.absoluteDeadlineAt) || (parsed.absoluteDeadlineAt as number) <= 0)) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': absoluteDeadlineAt must be a positive timestamp.`);\n\tif (parsed.initialTurnBudget !== undefined) {\n\t\tconst result = resolveTurnBudgetConfig(\n\t\t\tpersistedTurnBudgetConfig(parsed.initialTurnBudget),\n\t\t\t\"recoveryDescriptor.initialTurnBudget\",\n\t\t);\n\t\tif (result.error) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': ${result.error}`);\n\t\tif (result.turnBudget) parsed.initialTurnBudget = result.turnBudget;\n\t}\n\tif (parsed.initialToolBudget !== undefined) {\n\t\tconst result = validateToolBudgetConfig(parsed.initialToolBudget, \"recoveryDescriptor.initialToolBudget\");\n\t\tif (result.error) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': ${result.error}`);\n\t}\n\tif (parsed.maxOutput !== undefined) {\n\t\tif (!parsed.maxOutput || typeof parsed.maxOutput !== \"object\" || Array.isArray(parsed.maxOutput)) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': maxOutput must be an object.`);\n\t\tfor (const field of [\"bytes\", \"lines\"] as const) {\n\t\t\tconst item = (parsed.maxOutput as Record<string, unknown>)[field];\n\t\t\tif (item !== undefined && (!Number.isInteger(item) || (item as number) < 1)) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': maxOutput.${field} must be a positive integer.`);\n\t\t}\n\t}\n\tif (parsed.artifactConfig !== undefined) {\n\t\tif (!parsed.artifactConfig || typeof parsed.artifactConfig !== \"object\" || Array.isArray(parsed.artifactConfig)) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': artifactConfig must be an object.`);\n\t\tconst artifact = parsed.artifactConfig as Record<string, unknown>;\n\t\tfor (const field of [\"enabled\", \"includeInput\", \"includeOutput\", \"includeJsonl\", \"includeMetadata\"] as const) {\n\t\t\tif (typeof artifact[field] !== \"boolean\") throw new Error(`Invalid async recovery descriptor '${descriptorPath}': artifactConfig.${field} must be a boolean.`);\n\t\t}\n\t\tif (artifact.includeTranscript !== undefined && typeof artifact.includeTranscript !== \"boolean\") throw new Error(`Invalid async recovery descriptor '${descriptorPath}': artifactConfig.includeTranscript must be a boolean.`);\n\t\tif (!Number.isInteger(artifact.cleanupDays) || (artifact.cleanupDays as number) < 0) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': artifactConfig.cleanupDays must be a non-negative integer.`);\n\t}\n\tif (parsed.controlConfig !== undefined) {\n\t\tif (!parsed.controlConfig || typeof parsed.controlConfig !== \"object\" || Array.isArray(parsed.controlConfig)) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': controlConfig must be an object.`);\n\t\tconst control = parsed.controlConfig as Record<string, unknown>;\n\t\tif (typeof control.enabled !== \"boolean\") throw new Error(`Invalid async recovery descriptor '${descriptorPath}': controlConfig.enabled must be a boolean.`);\n\t\tfor (const field of [\"needsAttentionAfterMs\", \"activeNoticeAfterMs\", \"failedToolAttemptsBeforeAttention\"] as const) {\n\t\t\tif (!Number.isInteger(control[field]) || (control[field] as number) < 1) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': controlConfig.${field} must be a positive integer.`);\n\t\t}\n\t\tfor (const field of [\"activeNoticeAfterTurns\", \"activeNoticeAfterTokens\"] as const) {\n\t\t\tif (control[field] !== undefined && (!Number.isInteger(control[field]) || (control[field] as number) < 1)) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': controlConfig.${field} must be a positive integer.`);\n\t\t}\n\t\tif (!Array.isArray(control.notifyOn) || control.notifyOn.some((item) => item !== \"active_long_running\" && item !== \"needs_attention\")) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': controlConfig.notifyOn is invalid.`);\n\t\tif (!Array.isArray(control.notifyChannels) || control.notifyChannels.some((item) => item !== \"event\" && item !== \"async\" && item !== \"intercom\")) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': controlConfig.notifyChannels is invalid.`);\n\t}\n\tif (parsed.acceptance !== undefined) {\n\t\tconst errors = validatePersistedAcceptance(parsed.acceptance, \"recoveryDescriptor.acceptance\");\n\t\tif (errors.length) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': ${errors.join(\" \")}`);\n\t}\n\treturn parsed as unknown as SteeringRecoveryDescriptor;\n}\n\nfunction validateResumeSessionFile(runId: string, sessionFile: string): string {\n\tif (path.extname(sessionFile) !== \".jsonl\") throw new Error(`Async run '${runId}' session file must be a .jsonl file: ${sessionFile}`);\n\tconst resolved = path.resolve(sessionFile);\n\tif (!fs.existsSync(resolved)) throw new Error(`Async run '${runId}' session file does not exist: ${sessionFile}`);\n\treturn resolved;\n}\n\nexport function resolveAsyncResumeTarget(params: AsyncResumeParams, deps: AsyncResumeDeps = {}, options: AsyncResumeOptions = {}): AsyncResumeTarget {\n\tconst asyncDirRoot = deps.asyncDirRoot ?? ASYNC_DIR;\n\tconst resultsDir = deps.resultsDir ?? RESULTS_DIR;\n\tconst requireSessionFile = options.requireSessionFile ?? true;\n\tconst location = resolveAsyncRunLocation(params, asyncDirRoot, resultsDir);\n\tif (!location.asyncDir && !location.resultPath) {\n\t\tthrow new Error(\"Async run not found. Provide id or dir.\");\n\t}\n\n\tconst reconciliation = location.asyncDir\n\t\t? reconcileAsyncRun(location.asyncDir, { resultsDir, kill: deps.kill, now: deps.now })\n\t\t: undefined;\n\tconst status = reconciliation?.status ?? null;\n\tvalidateStatusForResume(status, location.asyncDir ? path.join(location.asyncDir, \"status.json\") : \"status.json\");\n\tconst recoveryDescriptor = readAsyncRecoveryDescriptor(location.asyncDir);\n\tconst result = location.resultPath ? readResultFile(location.resultPath) : undefined;\n\tconst runId = status?.runId ?? result?.runId ?? result?.id ?? location.resolvedId ?? (location.asyncDir ? path.basename(location.asyncDir) : \"unknown\");\n\tif (recoveryDescriptor && recoveryDescriptor.sourceRunId !== runId) throw new Error(`Async run '${runId}' has a recovery descriptor for a different source run.`);\n\tconst state = status?.state ?? (result ? resultState(result) : undefined);\n\tif (!state) throw new Error(`Status file not found for async run '${runId}'.`);\n\tif (state === \"stopped\") throw new Error(`Async run '${runId}' was stopped and cannot be resumed. Start a new run instead.`);\n\n\tconst statusSteps = status?.steps ?? [];\n\tconst resultSteps = result?.results ?? [];\n\tconst stepCount = statusSteps.length || resultSteps.length || (result?.agent ? 1 : 0);\n\tconst requestedIndex = params.index;\n\tif (requestedIndex !== undefined && !Number.isInteger(requestedIndex)) throw new Error(`Async run '${runId}' index must be an integer.`);\n\tconst terminalStepStatuses = new Set([\"complete\", \"completed\", \"failed\", \"paused\"]);\n\n\tif (state === \"running\") {\n\t\tif (requestedIndex !== undefined) {\n\t\t\tif (requestedIndex < 0 || requestedIndex >= stepCount) throw new Error(`Async run '${runId}' has ${stepCount} children. Index ${requestedIndex} is out of range.`);\n\t\t\tconst selectedStep = statusSteps[requestedIndex];\n\t\t\tif (selectedStep?.status === \"running\") {\n\t\t\t\treturn {\n\t\t\t\t\tkind: \"live\",\n\t\t\t\t\trunId,\n\t\t\t\t\tasyncDir: location.asyncDir ?? undefined,\n\t\t\t\t\tstate,\n\t\t\t\t\tagent: selectedStep.agent,\n\t\t\t\t\tchildId: selectedStep.childId,\n\t\t\t\t\tdescription: selectedStep.description,\n\t\t\t\t\tpermissions: selectedStep.permissions,\n\t\t\t\t\tindex: requestedIndex,\n\t\t\t\t\tintercomTarget: resolveSubagentIntercomTarget(runId, selectedStep.childId ?? selectedStep.agent, requestedIndex),\n\t\t\t\t\tcwd: status?.cwd ?? result?.cwd,\n\t\t\t\t\tsessionFile: selectedStep.sessionFile ?? status?.sessionFile ?? result?.sessionFile,\n\t\t\t\t\tmodel: selectedStep.model,\n\t\t\t\t\tthinking: selectedStep.thinking,\n\t\t\t\t\tmodelSelection: selectedStep.modelSelection,\n\t\t\t\t\t...(recoveryDescriptor ? { recoveryDescriptor } : {}),\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (selectedStep?.status === \"pending\") throw new Error(`Async run '${runId}' child ${requestedIndex} is pending and has not started yet. Wait for it to run or complete before resuming.`);\n\t\t\tif (selectedStep && !terminalStepStatuses.has(selectedStep.status)) throw new Error(`Async run '${runId}' child ${requestedIndex} is ${selectedStep.status} and cannot be revived yet.`);\n\t\t} else {\n\t\t\tconst running = statusSteps\n\t\t\t\t.map((step, index) => ({ step, index }))\n\t\t\t\t.filter(({ step }) => step.status === \"running\");\n\t\t\tconst selected = running.length === 1 ? running[0] : undefined;\n\t\t\tif (!selected) {\n\t\t\t\tthrow new Error(`Async run '${runId}' has ${running.length} running children. Provide index to choose one.`);\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tkind: \"live\",\n\t\t\t\trunId,\n\t\t\t\tasyncDir: location.asyncDir ?? undefined,\n\t\t\t\tstate,\n\t\t\t\tagent: selected.step.agent,\n\t\t\t\tchildId: selected.step.childId,\n\t\t\t\tdescription: selected.step.description,\n\t\t\t\tpermissions: selected.step.permissions,\n\t\t\t\tindex: selected.index,\n\t\t\t\tintercomTarget: resolveSubagentIntercomTarget(runId, selected.step.childId ?? selected.step.agent, selected.index),\n\t\t\t\tcwd: status?.cwd ?? result?.cwd,\n\t\t\t\tsessionFile: selected.step.sessionFile ?? status?.sessionFile ?? result?.sessionFile,\n\t\t\t\tmodel: selected.step.model,\n\t\t\t\tthinking: selected.step.thinking,\n\t\t\t\tmodelSelection: selected.step.modelSelection,\n\t\t\t\t...(recoveryDescriptor ? { recoveryDescriptor } : {}),\n\t\t\t};\n\t\t}\n\t}\n\n\tif (stepCount > 1 && requestedIndex === undefined) {\n\t\tthrow new Error(`Async run '${runId}' has ${stepCount} children. Provide index to choose one.`);\n\t}\n\tconst index = requestedIndex ?? 0;\n\tif (!Number.isInteger(index)) throw new Error(`Async run '${runId}' index must be an integer.`);\n\tif (index < 0 || index >= stepCount) throw new Error(`Async run '${runId}' has ${stepCount} children. Index ${index} is out of range.`);\n\tconst agent = statusSteps[index]?.agent ?? resultSteps[index]?.agent ?? result?.agent;\n\tif (!agent) throw new Error(`Could not determine child agent for async run '${runId}'.`);\n\tif (recoveryDescriptor && recoveryDescriptor.agent !== agent) throw new Error(`Async run '${runId}' has a recovery descriptor for '${recoveryDescriptor.agent}', not '${agent}'.`);\n\tconst sessionFile = statusSteps[index]?.sessionFile\n\t\t?? resultSteps[index]?.sessionFile\n\t\t?? (stepCount === 1 ? status?.sessionFile ?? result?.sessionFile : undefined);\n\tif (!sessionFile && requireSessionFile) throw new Error(`Async run '${runId}' child ${index} does not have a persisted session file to resume from.`);\n\tconst resolvedSessionFile = sessionFile ? validateResumeSessionFile(runId, sessionFile) : undefined;\n\tconst stepModel = statusSteps[index]?.model ?? resultSteps[index]?.model ?? (stepCount === 1 ? result?.model : undefined);\n\tconst stepThinking = statusSteps[index]?.thinking ?? resultSteps[index]?.thinking ?? (stepCount === 1 ? result?.thinking : undefined);\n\tconst childId = statusSteps[index]?.childId ?? resultSteps[index]?.childId;\n\n\treturn {\n\t\tkind: \"revive\",\n\t\trunId,\n\t\tasyncDir: location.asyncDir ?? undefined,\n\t\tstate,\n\t\tagent,\n\t\tchildId,\n\t\tdescription: statusSteps[index]?.description ?? resultSteps[index]?.description,\n\t\tpermissions: statusSteps[index]?.permissions ?? resultSteps[index]?.permissions,\n\t\tindex,\n\t\tintercomTarget: resolveSubagentIntercomTarget(runId, childId ?? agent, index),\n\t\tcwd: status?.cwd ?? result?.cwd,\n\t\t...(resolvedSessionFile ? { sessionFile: resolvedSessionFile } : {}),\n\t\tmodelSelection: statusSteps[index]?.modelSelection,\n\t\t...(stepModel ? { model: stepModel } : {}),\n\t\t...(stepThinking ? { thinking: stepThinking } : {}),\n\t\t...(recoveryDescriptor ? { recoveryDescriptor } : {}),\n\t};\n}\n\nexport function buildRevivedAsyncTask(target: AsyncResumeTarget, message: string): string {\n\treturn [\n\t\t\"You are reviving a previous subagent conversation.\",\n\t\t\"\",\n\t\t`Original run: ${target.runId}`,\n\t\t`Original agent: ${target.agent}`,\n\t\ttarget.sessionFile ? `Original session file: ${target.sessionFile}` : undefined,\n\t\t\"\",\n\t\t\"Use the stored session context as background. Answer the orchestrator's follow-up below. Do not assume the original child process is still alive.\",\n\t\t\"\",\n\t\t\"Follow-up:\",\n\t\tmessage,\n\t].filter((line): line is string => line !== undefined).join(\"\\n\");\n}\n"]}
|