@ashx-j/lunr 0.2.19 → 0.2.21
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-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/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-35WNVGMR.js → agent-session-services-C743TYQE.js} +6 -5
- package/dist/node-runtime/{builtin-extensions-322XDDEM.js → builtin-extensions-JCOPAAB5.js} +3 -2
- package/dist/node-runtime/{chunk-XATUM2HK.js → chunk-25I2BHAA.js} +1 -1
- package/dist/node-runtime/{chunk-TXHKBRHZ.js → chunk-2BUAYZ7K.js} +136 -53
- package/dist/node-runtime/chunk-5ZH3ZFIZ.js +308 -0
- package/dist/node-runtime/{chunk-J26TSGDL.js → chunk-6N22HULO.js} +8 -5
- package/dist/node-runtime/chunk-A3KMVBZV.js +60 -0
- package/dist/node-runtime/{chunk-4FX25LWP.js → chunk-AWVD5IEY.js} +20 -421
- package/dist/node-runtime/{chunk-ZRCBN365.js → chunk-GB2MGFLI.js} +12 -12
- package/dist/node-runtime/chunk-LISUTZS3.js +19 -0
- package/dist/node-runtime/{chunk-PNJSG3IZ.js → chunk-LTYWTR3V.js} +1 -369
- package/dist/node-runtime/{chunk-TFBIJTM3.js → chunk-PDNXVXMD.js} +13 -13
- package/dist/node-runtime/{chunk-MCUNIRD5.js → chunk-SY2TFMLO.js} +532 -261
- package/dist/node-runtime/{chunk-HQCKFM2O.js → chunk-VGYZ3APQ.js} +3 -0
- package/dist/node-runtime/{chunk-4DJ6HEGH.js → chunk-VZR3NCM7.js} +3 -3
- package/dist/node-runtime/chunk-W3SILANP.js +24 -0
- package/dist/node-runtime/{chunk-CBGB57XT.js → chunk-WLLDXJRT.js} +10 -0
- package/dist/node-runtime/{chunk-ATGA2WLC.js → chunk-XI77KVKA.js} +399 -36
- package/dist/node-runtime/{chunk-4CSFRBCN.js → chunk-Y5KOEMBH.js} +1 -1
- package/dist/node-runtime/{chunk-AROOY4BB.js → chunk-YMEAYRBE.js} +1 -1
- package/dist/node-runtime/{command-DWUM5X3U.js → command-P4NYCJ2M.js} +1 -1
- package/dist/node-runtime/{customize-XEXL2DGQ.js → customize-LF5VST47.js} +1 -1
- package/dist/node-runtime/{gateway-UZXMFGWY.js → gateway-BM6NLOH4.js} +2 -2
- package/dist/node-runtime/index.js +16 -13
- package/dist/node-runtime/{interactive-mode-QT5IKGQ5.js → interactive-mode-EVVBA64D.js} +11 -8
- package/dist/node-runtime/{lunr-cron-QPBTKBGI.js → lunr-cron-4VHP4E4B.js} +2 -2
- package/dist/node-runtime/main.js +14 -12
- package/dist/node-runtime/{package-manager-cli-7RKSZGEN.js → package-manager-cli-N37546V5.js} +5 -4
- package/dist/node-runtime/{pi-intercom-EEMBGQID.js → pi-intercom-NV2LW6X7.js} +108 -87
- package/dist/node-runtime/{pi-subagents-7YJ3I4VE.js → pi-subagents-6MUIFNDM.js} +1262 -599
- package/dist/node-runtime/rpc-entry.js +14 -12
- package/dist/node-runtime/{runtime-bridges-3RKBDLNA.js → runtime-bridges-2VQTLPOZ.js} +3 -5
- package/dist/node-runtime/{settings-manager-GHPTUN7R.js → settings-manager-CUGAZWAB.js} +2 -1
- package/dist/node-runtime/{subagent-executor-5Q5A4HJ2.js → subagent-executor-MH4A7CCF.js} +181 -294
- package/dist/node-runtime/{update-cli-L3JIBH2U.js → update-cli-XTZMZGOL.js} +2 -1
- 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/package.json +4 -4
- 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-3NMWLTPV.js +0 -64
|
@@ -0,0 +1,541 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import * as fs from "node:fs";
|
|
3
|
+
import * as path from "node:path";
|
|
4
|
+
import { TEMP_ROOT_DIR } from "../shared/types.js";
|
|
5
|
+
export const QUESTIONS_DIR = "questions";
|
|
6
|
+
export const SUPERVISOR_CHANNEL_ROOT = path.join(TEMP_ROOT_DIR, "supervisor-channels");
|
|
7
|
+
export const SUBAGENT_SUPERVISOR_ANSWER_TYPE = "subagent_supervisor_answer";
|
|
8
|
+
export const SUBAGENT_QUESTION_EVENT = "subagent:supervisor-question";
|
|
9
|
+
const MAX_MESSAGE_BYTES = 64 * 1024;
|
|
10
|
+
const DEFAULT_ASK_TIMEOUT_MS = 10 * 60 * 1000;
|
|
11
|
+
const activeQuestionWaits = new Set();
|
|
12
|
+
function askTimeoutMs() {
|
|
13
|
+
const parsed = Number(process.env.PI_INTERCOM_ASK_TIMEOUT_MS);
|
|
14
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_ASK_TIMEOUT_MS;
|
|
15
|
+
}
|
|
16
|
+
function safeSegment(value) {
|
|
17
|
+
return value.trim().replace(/[^A-Za-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "") || "unknown";
|
|
18
|
+
}
|
|
19
|
+
export function resolveSupervisorChannelDir(runId, agent, childIndex) {
|
|
20
|
+
return path.join(SUPERVISOR_CHANNEL_ROOT, `${safeSegment(runId)}-${safeSegment(agent)}-${childIndex}`);
|
|
21
|
+
}
|
|
22
|
+
export function questionsDir(channelDir) {
|
|
23
|
+
return path.join(channelDir, QUESTIONS_DIR);
|
|
24
|
+
}
|
|
25
|
+
function questionFile(channelDir, questionId) {
|
|
26
|
+
return path.join(questionsDir(channelDir), `${safeSegment(questionId)}.json`);
|
|
27
|
+
}
|
|
28
|
+
function deliveredFile(channelDir, questionId) {
|
|
29
|
+
return path.join(questionsDir(channelDir), `${safeSegment(questionId)}.delivered.json`);
|
|
30
|
+
}
|
|
31
|
+
function terminalFile(channelDir, questionId) {
|
|
32
|
+
return path.join(questionsDir(channelDir), `${safeSegment(questionId)}.terminal.json`);
|
|
33
|
+
}
|
|
34
|
+
function notifiedFile(channelDir, questionId) {
|
|
35
|
+
return path.join(questionsDir(channelDir), `${safeSegment(questionId)}.notified.json`);
|
|
36
|
+
}
|
|
37
|
+
function lateFile(channelDir, questionId) {
|
|
38
|
+
return path.join(questionsDir(channelDir), `${safeSegment(questionId)}.late.json`);
|
|
39
|
+
}
|
|
40
|
+
function writeExclusiveJson(filePath, payload) {
|
|
41
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true, mode: 0o700 });
|
|
42
|
+
const temporary = `${filePath}.${randomUUID()}.tmp`;
|
|
43
|
+
try {
|
|
44
|
+
fs.writeFileSync(temporary, JSON.stringify(payload), { encoding: "utf-8", flag: "wx", mode: 0o600 });
|
|
45
|
+
// Publish a complete record without overwriting a competing terminal outcome.
|
|
46
|
+
fs.linkSync(temporary, filePath);
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
if (error.code === "EEXIST")
|
|
51
|
+
return false;
|
|
52
|
+
throw error;
|
|
53
|
+
}
|
|
54
|
+
finally {
|
|
55
|
+
fs.rmSync(temporary, { force: true });
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function readJsonFile(filePath) {
|
|
59
|
+
return JSON.parse(fs.readFileSync(filePath, "utf-8"));
|
|
60
|
+
}
|
|
61
|
+
function tryReadJson(filePath) {
|
|
62
|
+
try {
|
|
63
|
+
return readJsonFile(filePath);
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
if (error.code === "ENOENT")
|
|
67
|
+
return undefined;
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function parseIncarnation(raw) {
|
|
72
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
73
|
+
return undefined;
|
|
74
|
+
const input = raw;
|
|
75
|
+
const pid = input.pid;
|
|
76
|
+
const readyAt = input.readyAt;
|
|
77
|
+
if (!Number.isInteger(pid) || pid === undefined || pid <= 0)
|
|
78
|
+
return undefined;
|
|
79
|
+
if (typeof readyAt !== "number" || !Number.isFinite(readyAt) || readyAt <= 0)
|
|
80
|
+
return undefined;
|
|
81
|
+
return { pid, readyAt };
|
|
82
|
+
}
|
|
83
|
+
function parseQuestionRecord(raw) {
|
|
84
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
85
|
+
return undefined;
|
|
86
|
+
const input = raw;
|
|
87
|
+
if (input.type !== "subagent.supervisor.question")
|
|
88
|
+
return undefined;
|
|
89
|
+
if (typeof input.id !== "string" || !input.id.trim())
|
|
90
|
+
return undefined;
|
|
91
|
+
if (typeof input.createdAt !== "number" || !Number.isFinite(input.createdAt))
|
|
92
|
+
return undefined;
|
|
93
|
+
if (typeof input.expiresAt !== "number" || !Number.isFinite(input.expiresAt))
|
|
94
|
+
return undefined;
|
|
95
|
+
if (typeof input.reason !== "string" || !input.reason.trim())
|
|
96
|
+
return undefined;
|
|
97
|
+
if (typeof input.message !== "string" || !input.message.trim())
|
|
98
|
+
return undefined;
|
|
99
|
+
if (typeof input.runId !== "string" || !input.runId.trim())
|
|
100
|
+
return undefined;
|
|
101
|
+
const childIndex = input.childIndex;
|
|
102
|
+
if (!Number.isInteger(childIndex) || childIndex === undefined || childIndex < 0)
|
|
103
|
+
return undefined;
|
|
104
|
+
if (typeof input.childId !== "string" || !input.childId.trim())
|
|
105
|
+
return undefined;
|
|
106
|
+
if (typeof input.parentSessionId !== "string" || !input.parentSessionId.trim())
|
|
107
|
+
return undefined;
|
|
108
|
+
const parentGeneration = input.parentGeneration;
|
|
109
|
+
if (!Number.isInteger(parentGeneration) || parentGeneration === undefined || parentGeneration < 0)
|
|
110
|
+
return undefined;
|
|
111
|
+
const incarnation = parseIncarnation(input.childIncarnation);
|
|
112
|
+
return {
|
|
113
|
+
type: "subagent.supervisor.question",
|
|
114
|
+
id: input.id.trim(),
|
|
115
|
+
createdAt: input.createdAt,
|
|
116
|
+
expiresAt: input.expiresAt,
|
|
117
|
+
reason: input.reason.trim(),
|
|
118
|
+
message: input.message.trim(),
|
|
119
|
+
runId: input.runId.trim(),
|
|
120
|
+
childIndex,
|
|
121
|
+
childId: input.childId.trim(),
|
|
122
|
+
parentSessionId: input.parentSessionId.trim(),
|
|
123
|
+
parentGeneration,
|
|
124
|
+
...(incarnation ? { childIncarnation: incarnation } : {}),
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
function parseDeliveredRecord(raw) {
|
|
128
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
129
|
+
return undefined;
|
|
130
|
+
const input = raw;
|
|
131
|
+
if (input.type !== "subagent.supervisor.delivered" || typeof input.id !== "string" || !input.id.trim())
|
|
132
|
+
return undefined;
|
|
133
|
+
if (typeof input.at !== "number" || !Number.isFinite(input.at))
|
|
134
|
+
return undefined;
|
|
135
|
+
const incarnation = parseIncarnation(input);
|
|
136
|
+
if (!incarnation)
|
|
137
|
+
return undefined;
|
|
138
|
+
return { type: "subagent.supervisor.delivered", id: input.id.trim(), at: input.at, pid: incarnation.pid, readyAt: incarnation.readyAt };
|
|
139
|
+
}
|
|
140
|
+
function parseTerminalRecord(raw) {
|
|
141
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
142
|
+
return undefined;
|
|
143
|
+
const input = raw;
|
|
144
|
+
if (input.type !== "subagent.supervisor.terminal" || typeof input.id !== "string" || !input.id.trim())
|
|
145
|
+
return undefined;
|
|
146
|
+
if (typeof input.at !== "number" || !Number.isFinite(input.at))
|
|
147
|
+
return undefined;
|
|
148
|
+
if (input.state === "answered") {
|
|
149
|
+
if (typeof input.message !== "string" || !input.message.trim())
|
|
150
|
+
return undefined;
|
|
151
|
+
return { type: "subagent.supervisor.terminal", id: input.id.trim(), state: "answered", at: input.at, message: input.message };
|
|
152
|
+
}
|
|
153
|
+
if (input.state === "expired") {
|
|
154
|
+
return { type: "subagent.supervisor.terminal", id: input.id.trim(), state: "expired", at: input.at };
|
|
155
|
+
}
|
|
156
|
+
if (input.state === "cancelled") {
|
|
157
|
+
if (typeof input.reason !== "string" || !input.reason.trim())
|
|
158
|
+
return undefined;
|
|
159
|
+
return { type: "subagent.supervisor.terminal", id: input.id.trim(), state: "cancelled", at: input.at, reason: input.reason.trim() };
|
|
160
|
+
}
|
|
161
|
+
return undefined;
|
|
162
|
+
}
|
|
163
|
+
function parseNotifiedRecord(raw) {
|
|
164
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
165
|
+
return undefined;
|
|
166
|
+
const input = raw;
|
|
167
|
+
if (input.type !== "subagent.supervisor.notified" || typeof input.id !== "string" || !input.id.trim())
|
|
168
|
+
return undefined;
|
|
169
|
+
if (typeof input.at !== "number" || !Number.isFinite(input.at))
|
|
170
|
+
return undefined;
|
|
171
|
+
return { type: "subagent.supervisor.notified", id: input.id.trim(), at: input.at };
|
|
172
|
+
}
|
|
173
|
+
function parseLateRecord(raw) {
|
|
174
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
175
|
+
return undefined;
|
|
176
|
+
const input = raw;
|
|
177
|
+
if (input.type !== "subagent.supervisor.late-answer" || typeof input.id !== "string" || !input.id.trim())
|
|
178
|
+
return undefined;
|
|
179
|
+
if (typeof input.at !== "number" || !Number.isFinite(input.at) || typeof input.message !== "string")
|
|
180
|
+
return undefined;
|
|
181
|
+
return { type: "subagent.supervisor.late-answer", id: input.id.trim(), at: input.at, message: input.message };
|
|
182
|
+
}
|
|
183
|
+
function composeQuestion(record, channelDir) {
|
|
184
|
+
const delivered = parseDeliveredRecord(tryReadJson(deliveredFile(channelDir, record.id)));
|
|
185
|
+
const terminal = parseTerminalRecord(tryReadJson(terminalFile(channelDir, record.id)));
|
|
186
|
+
const notified = parseNotifiedRecord(tryReadJson(notifiedFile(channelDir, record.id)));
|
|
187
|
+
const late = parseLateRecord(tryReadJson(lateFile(channelDir, record.id)));
|
|
188
|
+
return {
|
|
189
|
+
...record,
|
|
190
|
+
...(delivered ? { deliveredAt: delivered.at, childIncarnation: record.childIncarnation ?? { pid: delivered.pid, readyAt: delivered.readyAt } } : {}),
|
|
191
|
+
...(terminal?.state === "answered" ? { answeredAt: terminal.at, answer: terminal.message } : {}),
|
|
192
|
+
...(terminal?.state === "expired" ? { expiredAt: terminal.at } : {}),
|
|
193
|
+
...(terminal?.state === "cancelled" ? { cancelledAt: terminal.at, cancelReason: terminal.reason } : {}),
|
|
194
|
+
...(notified ? { notifiedAt: notified.at } : {}),
|
|
195
|
+
...(late ? { lateAnswerAt: late.at, ...(terminal?.state === "answered" ? {} : { answer: late.message }) } : {}),
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
function assertMessageSize(value, label) {
|
|
199
|
+
if (Buffer.byteLength(value, "utf-8") > MAX_MESSAGE_BYTES)
|
|
200
|
+
throw new Error(`${label} is too large.`);
|
|
201
|
+
}
|
|
202
|
+
export function ensureQuestionsDir(channelDir) {
|
|
203
|
+
fs.mkdirSync(questionsDir(channelDir), { recursive: true, mode: 0o700 });
|
|
204
|
+
}
|
|
205
|
+
export function supervisorQuestionPublicState(question) {
|
|
206
|
+
if (question.answeredAt)
|
|
207
|
+
return "answered";
|
|
208
|
+
if (question.expiredAt)
|
|
209
|
+
return "expired";
|
|
210
|
+
if (question.cancelledAt)
|
|
211
|
+
return "cancelled";
|
|
212
|
+
return "pending";
|
|
213
|
+
}
|
|
214
|
+
export function supervisorQuestionIsTerminal(question) {
|
|
215
|
+
return supervisorQuestionPublicState(question) !== "pending";
|
|
216
|
+
}
|
|
217
|
+
export function readSupervisorQuestion(channelDir, questionId) {
|
|
218
|
+
const record = parseQuestionRecord(tryReadJson(questionFile(channelDir, questionId)));
|
|
219
|
+
if (!record || record.id !== questionId)
|
|
220
|
+
return undefined;
|
|
221
|
+
return composeQuestion(record, channelDir);
|
|
222
|
+
}
|
|
223
|
+
export function listSupervisorQuestions(channelDir) {
|
|
224
|
+
const dir = questionsDir(channelDir);
|
|
225
|
+
let entries;
|
|
226
|
+
try {
|
|
227
|
+
entries = fs.readdirSync(dir).filter((name) => name.endsWith(".json") && !name.endsWith(".delivered.json") && !name.endsWith(".terminal.json") && !name.endsWith(".notified.json") && !name.endsWith(".late.json"));
|
|
228
|
+
}
|
|
229
|
+
catch (error) {
|
|
230
|
+
if (error.code === "ENOENT")
|
|
231
|
+
return [];
|
|
232
|
+
throw error;
|
|
233
|
+
}
|
|
234
|
+
const questions = [];
|
|
235
|
+
for (const entry of entries.sort()) {
|
|
236
|
+
const record = parseQuestionRecord(tryReadJson(path.join(dir, entry)));
|
|
237
|
+
if (record)
|
|
238
|
+
questions.push(composeQuestion(record, channelDir));
|
|
239
|
+
}
|
|
240
|
+
return questions;
|
|
241
|
+
}
|
|
242
|
+
function writeTerminal(channelDir, record) {
|
|
243
|
+
return writeExclusiveJson(terminalFile(channelDir, record.id), record);
|
|
244
|
+
}
|
|
245
|
+
function readTerminal(channelDir, questionId) {
|
|
246
|
+
return parseTerminalRecord(tryReadJson(terminalFile(channelDir, questionId)));
|
|
247
|
+
}
|
|
248
|
+
export function createSupervisorQuestion(input) {
|
|
249
|
+
const reason = input.reason.trim();
|
|
250
|
+
const message = input.message.trim();
|
|
251
|
+
if (!reason)
|
|
252
|
+
throw new Error("reason is required and must name the concrete decision the child's answer will change.");
|
|
253
|
+
if (!message)
|
|
254
|
+
throw new Error("message is required for supervisor questions.");
|
|
255
|
+
assertMessageSize(reason, "reason");
|
|
256
|
+
assertMessageSize(message, "message");
|
|
257
|
+
const createdAt = input.now ?? Date.now();
|
|
258
|
+
const timeoutMs = input.timeoutMs && input.timeoutMs > 0 ? input.timeoutMs : askTimeoutMs();
|
|
259
|
+
const record = {
|
|
260
|
+
type: "subagent.supervisor.question",
|
|
261
|
+
id: input.id ?? randomUUID(),
|
|
262
|
+
createdAt,
|
|
263
|
+
expiresAt: createdAt + timeoutMs,
|
|
264
|
+
reason,
|
|
265
|
+
message,
|
|
266
|
+
runId: input.runId,
|
|
267
|
+
childIndex: input.childIndex,
|
|
268
|
+
childId: input.childId,
|
|
269
|
+
parentSessionId: input.parentSessionId,
|
|
270
|
+
parentGeneration: input.parentGeneration,
|
|
271
|
+
...(input.childIncarnation ? { childIncarnation: input.childIncarnation } : {}),
|
|
272
|
+
};
|
|
273
|
+
assertMessageSize(JSON.stringify(record), "Supervisor question");
|
|
274
|
+
ensureQuestionsDir(input.channelDir);
|
|
275
|
+
if (!writeExclusiveJson(questionFile(input.channelDir, record.id), record)) {
|
|
276
|
+
throw new Error(`Supervisor question '${record.id}' already exists.`);
|
|
277
|
+
}
|
|
278
|
+
return composeQuestion(record, input.channelDir);
|
|
279
|
+
}
|
|
280
|
+
export function outstandingQuestionsForChild(channelDir, childIndex, childId) {
|
|
281
|
+
refreshSupervisorQuestionLifecycle(channelDir);
|
|
282
|
+
return listSupervisorQuestions(channelDir).filter((question) => {
|
|
283
|
+
if (supervisorQuestionIsTerminal(question))
|
|
284
|
+
return false;
|
|
285
|
+
if (question.childIndex !== childIndex)
|
|
286
|
+
return false;
|
|
287
|
+
if (childId && question.childId !== childId)
|
|
288
|
+
return false;
|
|
289
|
+
return true;
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
export function hasBlockingSupervisorRequest(channelDir, runId, childIndex) {
|
|
293
|
+
const directory = path.join(channelDir, "requests");
|
|
294
|
+
if (!fs.existsSync(directory))
|
|
295
|
+
return false;
|
|
296
|
+
for (const name of fs.readdirSync(directory)) {
|
|
297
|
+
if (!name.endsWith(".json"))
|
|
298
|
+
continue;
|
|
299
|
+
const raw = tryReadJson(path.join(directory, name));
|
|
300
|
+
if (!raw || typeof raw !== "object")
|
|
301
|
+
continue;
|
|
302
|
+
const request = raw;
|
|
303
|
+
if (request.type !== "subagent.supervisor.request" || request.expectsReply !== true)
|
|
304
|
+
continue;
|
|
305
|
+
if (request.runId !== runId || request.childIndex !== childIndex || typeof request.id !== "string")
|
|
306
|
+
continue;
|
|
307
|
+
if (typeof request.expiresAt === "number" && request.expiresAt <= Date.now())
|
|
308
|
+
continue;
|
|
309
|
+
if (!fs.existsSync(path.join(channelDir, "replies", `${safeSegment(request.id)}.json`)))
|
|
310
|
+
return true;
|
|
311
|
+
}
|
|
312
|
+
return false;
|
|
313
|
+
}
|
|
314
|
+
export function hasOutstandingQuestionForChild(channelDir, childIndex, childId) {
|
|
315
|
+
return outstandingQuestionsForChild(channelDir, childIndex, childId).length > 0;
|
|
316
|
+
}
|
|
317
|
+
export function incarnationMatches(expected, actual) {
|
|
318
|
+
if (!expected)
|
|
319
|
+
return true;
|
|
320
|
+
return expected.pid === actual.pid && expected.readyAt === actual.readyAt;
|
|
321
|
+
}
|
|
322
|
+
function assertOwner(question, owner) {
|
|
323
|
+
if (owner.runId !== question.runId || owner.childIndex !== question.childIndex || owner.childId !== question.childId) {
|
|
324
|
+
throw new Error(`Supervisor question '${question.id}' is not owned by this child.`);
|
|
325
|
+
}
|
|
326
|
+
if (!incarnationMatches(question.childIncarnation, { pid: owner.pid, readyAt: owner.readyAt })) {
|
|
327
|
+
throw new Error(`Supervisor question '${question.id}' was bound to a different child incarnation.`);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
function ownerMatchesDelivered(channelDir, questionId, owner) {
|
|
331
|
+
const delivered = parseDeliveredRecord(tryReadJson(deliveredFile(channelDir, questionId)));
|
|
332
|
+
if (!delivered)
|
|
333
|
+
return true;
|
|
334
|
+
return delivered.pid === owner.pid && delivered.readyAt === owner.readyAt;
|
|
335
|
+
}
|
|
336
|
+
export function markSupervisorQuestionDelivered(channelDir, questionId, owner, now = Date.now()) {
|
|
337
|
+
const current = readSupervisorQuestion(channelDir, questionId);
|
|
338
|
+
if (!current || supervisorQuestionIsTerminal(current))
|
|
339
|
+
return current;
|
|
340
|
+
assertOwner(current, owner);
|
|
341
|
+
writeExclusiveJson(deliveredFile(channelDir, questionId), {
|
|
342
|
+
type: "subagent.supervisor.delivered",
|
|
343
|
+
id: questionId,
|
|
344
|
+
at: now,
|
|
345
|
+
pid: owner.pid,
|
|
346
|
+
readyAt: owner.readyAt,
|
|
347
|
+
});
|
|
348
|
+
return readSupervisorQuestion(channelDir, questionId);
|
|
349
|
+
}
|
|
350
|
+
function rejectLateOrDuplicate(channelDir, questionId, answer, now, terminal) {
|
|
351
|
+
writeExclusiveJson(lateFile(channelDir, questionId), {
|
|
352
|
+
type: "subagent.supervisor.late-answer",
|
|
353
|
+
id: questionId,
|
|
354
|
+
at: now,
|
|
355
|
+
message: answer,
|
|
356
|
+
});
|
|
357
|
+
if (terminal.state === "answered")
|
|
358
|
+
throw new Error(`Supervisor question '${questionId}' was already answered.`);
|
|
359
|
+
throw new Error(`Supervisor question '${questionId}' is ${terminal.state} and no longer accepts an answer.`);
|
|
360
|
+
}
|
|
361
|
+
export function answerSupervisorQuestion(channelDir, questionId, answer, owner, now = Date.now()) {
|
|
362
|
+
const trimmed = answer.trim();
|
|
363
|
+
if (!trimmed)
|
|
364
|
+
throw new Error("message is required for supervisor question replies.");
|
|
365
|
+
assertMessageSize(trimmed, "answer");
|
|
366
|
+
const current = readSupervisorQuestion(channelDir, questionId);
|
|
367
|
+
if (!current)
|
|
368
|
+
throw new Error(`No supervisor question found for replyTo '${questionId}'.`);
|
|
369
|
+
assertOwner(current, owner);
|
|
370
|
+
if (!ownerMatchesDelivered(channelDir, questionId, owner)) {
|
|
371
|
+
throw new Error(`Supervisor question '${questionId}' was bound to a different child incarnation.`);
|
|
372
|
+
}
|
|
373
|
+
if (now > current.expiresAt) {
|
|
374
|
+
writeTerminal(channelDir, { type: "subagent.supervisor.terminal", id: questionId, state: "expired", at: now });
|
|
375
|
+
const terminal = readTerminal(channelDir, questionId);
|
|
376
|
+
if (terminal && terminal.state !== "answered") {
|
|
377
|
+
rejectLateOrDuplicate(channelDir, questionId, trimmed, now, terminal);
|
|
378
|
+
}
|
|
379
|
+
if (terminal?.state === "answered")
|
|
380
|
+
throw new Error(`Supervisor question '${questionId}' was already answered.`);
|
|
381
|
+
}
|
|
382
|
+
const existing = readTerminal(channelDir, questionId);
|
|
383
|
+
if (existing)
|
|
384
|
+
rejectLateOrDuplicate(channelDir, questionId, trimmed, now, existing);
|
|
385
|
+
if (!writeTerminal(channelDir, { type: "subagent.supervisor.terminal", id: questionId, state: "answered", at: now, message: trimmed })) {
|
|
386
|
+
const terminal = readTerminal(channelDir, questionId);
|
|
387
|
+
if (terminal)
|
|
388
|
+
rejectLateOrDuplicate(channelDir, questionId, trimmed, now, terminal);
|
|
389
|
+
throw new Error(`Supervisor question '${questionId}' is no longer pending.`);
|
|
390
|
+
}
|
|
391
|
+
const answered = readSupervisorQuestion(channelDir, questionId);
|
|
392
|
+
if (!answered)
|
|
393
|
+
throw new Error(`Supervisor question '${questionId}' is no longer pending.`);
|
|
394
|
+
return answered;
|
|
395
|
+
}
|
|
396
|
+
export function expireSupervisorQuestion(channelDir, questionId, now = Date.now()) {
|
|
397
|
+
const current = readSupervisorQuestion(channelDir, questionId);
|
|
398
|
+
if (!current || supervisorQuestionIsTerminal(current) || now <= current.expiresAt)
|
|
399
|
+
return current && supervisorQuestionIsTerminal(current) ? current : undefined;
|
|
400
|
+
if (!writeTerminal(channelDir, { type: "subagent.supervisor.terminal", id: questionId, state: "expired", at: now }))
|
|
401
|
+
return readSupervisorQuestion(channelDir, questionId);
|
|
402
|
+
return readSupervisorQuestion(channelDir, questionId);
|
|
403
|
+
}
|
|
404
|
+
export function cancelSupervisorQuestion(channelDir, questionId, reason, now = Date.now()) {
|
|
405
|
+
const current = readSupervisorQuestion(channelDir, questionId);
|
|
406
|
+
if (!current || supervisorQuestionIsTerminal(current))
|
|
407
|
+
return current;
|
|
408
|
+
if (!writeTerminal(channelDir, { type: "subagent.supervisor.terminal", id: questionId, state: "cancelled", at: now, reason: reason.trim() || "cancelled" })) {
|
|
409
|
+
return readSupervisorQuestion(channelDir, questionId);
|
|
410
|
+
}
|
|
411
|
+
return readSupervisorQuestion(channelDir, questionId);
|
|
412
|
+
}
|
|
413
|
+
export function refreshSupervisorQuestionLifecycle(channelDir, now = Date.now()) {
|
|
414
|
+
const changed = [];
|
|
415
|
+
for (const question of listSupervisorQuestions(channelDir)) {
|
|
416
|
+
if (supervisorQuestionIsTerminal(question))
|
|
417
|
+
continue;
|
|
418
|
+
if (now > question.expiresAt) {
|
|
419
|
+
const expired = expireSupervisorQuestion(channelDir, question.id, now);
|
|
420
|
+
if (expired && expired.expiredAt)
|
|
421
|
+
changed.push(expired);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
return changed;
|
|
425
|
+
}
|
|
426
|
+
export function formatParentQuestionForChild(question) {
|
|
427
|
+
return [
|
|
428
|
+
`Parent question (${question.id})`,
|
|
429
|
+
`Decision needed: ${question.reason}`,
|
|
430
|
+
"",
|
|
431
|
+
question.message,
|
|
432
|
+
"",
|
|
433
|
+
`Reply with: contact_supervisor({ action: "reply", replyTo: "${question.id}", message: "..." })`,
|
|
434
|
+
"Answer from current findings and uncertainty. Do not silently start extra investigation. Continue the assigned task after replying.",
|
|
435
|
+
].join("\n");
|
|
436
|
+
}
|
|
437
|
+
export function formatSupervisorQuestionAnswer(question) {
|
|
438
|
+
const state = supervisorQuestionPublicState(question);
|
|
439
|
+
const header = state === "answered"
|
|
440
|
+
? `Subagent answer (${question.id})`
|
|
441
|
+
: `Subagent question ${state} (${question.id})`;
|
|
442
|
+
const lines = [
|
|
443
|
+
header,
|
|
444
|
+
`Run: ${question.runId}`,
|
|
445
|
+
`Child: ${question.childId} [#${question.childIndex}]`,
|
|
446
|
+
`Decision: ${question.reason}`,
|
|
447
|
+
];
|
|
448
|
+
if (state === "answered" && question.answer?.trim()) {
|
|
449
|
+
lines.push("", question.answer.trim());
|
|
450
|
+
}
|
|
451
|
+
else if (question.cancelReason) {
|
|
452
|
+
lines.push("", question.cancelReason);
|
|
453
|
+
}
|
|
454
|
+
return lines.join("\n");
|
|
455
|
+
}
|
|
456
|
+
export function registerQuestionWait(questionIds) {
|
|
457
|
+
const ids = [...questionIds];
|
|
458
|
+
for (const id of ids)
|
|
459
|
+
activeQuestionWaits.add(id);
|
|
460
|
+
return () => {
|
|
461
|
+
for (const id of ids)
|
|
462
|
+
activeQuestionWaits.delete(id);
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
export function isQuestionWaitActive(questionId) {
|
|
466
|
+
return activeQuestionWaits.has(questionId);
|
|
467
|
+
}
|
|
468
|
+
export function claimQuestionNotification(channelDir, questionId, now = Date.now()) {
|
|
469
|
+
return writeExclusiveJson(notifiedFile(channelDir, questionId), {
|
|
470
|
+
type: "subagent.supervisor.notified",
|
|
471
|
+
id: questionId,
|
|
472
|
+
at: now,
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
export function markSupervisorQuestionNotified(channelDir, questionId, now = Date.now()) {
|
|
476
|
+
claimQuestionNotification(channelDir, questionId, now);
|
|
477
|
+
return readSupervisorQuestion(channelDir, questionId);
|
|
478
|
+
}
|
|
479
|
+
export function resetSupervisorQuestionTestState() {
|
|
480
|
+
activeQuestionWaits.clear();
|
|
481
|
+
}
|
|
482
|
+
export function listSupervisorChannelDirs() {
|
|
483
|
+
let entries;
|
|
484
|
+
try {
|
|
485
|
+
entries = fs.readdirSync(SUPERVISOR_CHANNEL_ROOT, { withFileTypes: true });
|
|
486
|
+
}
|
|
487
|
+
catch (error) {
|
|
488
|
+
if (error.code === "ENOENT")
|
|
489
|
+
return [];
|
|
490
|
+
throw error;
|
|
491
|
+
}
|
|
492
|
+
return entries.filter((entry) => entry.isDirectory()).map((entry) => path.join(SUPERVISOR_CHANNEL_ROOT, entry.name));
|
|
493
|
+
}
|
|
494
|
+
export function findSupervisorQuestion(questionId) {
|
|
495
|
+
const id = questionId.trim();
|
|
496
|
+
if (!id)
|
|
497
|
+
return undefined;
|
|
498
|
+
for (const channelDir of listSupervisorChannelDirs()) {
|
|
499
|
+
const question = readSupervisorQuestion(channelDir, id);
|
|
500
|
+
if (question)
|
|
501
|
+
return { channelDir, question };
|
|
502
|
+
}
|
|
503
|
+
return undefined;
|
|
504
|
+
}
|
|
505
|
+
export function cancelPendingSupervisorQuestionsForOwner(input) {
|
|
506
|
+
if (!input.parentSessionId?.trim())
|
|
507
|
+
return [];
|
|
508
|
+
const now = input.now ?? Date.now();
|
|
509
|
+
const cancelled = [];
|
|
510
|
+
for (const channelDir of listSupervisorChannelDirs()) {
|
|
511
|
+
for (const question of listSupervisorQuestions(channelDir)) {
|
|
512
|
+
if (supervisorQuestionIsTerminal(question))
|
|
513
|
+
continue;
|
|
514
|
+
if (question.parentSessionId !== input.parentSessionId)
|
|
515
|
+
continue;
|
|
516
|
+
if (input.parentGeneration !== undefined && question.parentGeneration !== input.parentGeneration)
|
|
517
|
+
continue;
|
|
518
|
+
if (input.runId && question.runId !== input.runId)
|
|
519
|
+
continue;
|
|
520
|
+
const next = cancelSupervisorQuestion(channelDir, question.id, input.reason, now);
|
|
521
|
+
if (next?.cancelledAt)
|
|
522
|
+
cancelled.push(next);
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
return cancelled;
|
|
526
|
+
}
|
|
527
|
+
export function pendingSupervisorQuestionsForDelivery(channelDir, owner, now = Date.now()) {
|
|
528
|
+
refreshSupervisorQuestionLifecycle(channelDir, now);
|
|
529
|
+
return listSupervisorQuestions(channelDir).filter((question) => {
|
|
530
|
+
if (supervisorQuestionIsTerminal(question))
|
|
531
|
+
return false;
|
|
532
|
+
if (question.deliveredAt)
|
|
533
|
+
return false;
|
|
534
|
+
if (question.runId !== owner.runId || question.childIndex !== owner.childIndex || question.childId !== owner.childId)
|
|
535
|
+
return false;
|
|
536
|
+
if (!incarnationMatches(question.childIncarnation, { pid: owner.pid, readyAt: owner.readyAt }))
|
|
537
|
+
return false;
|
|
538
|
+
return now <= question.expiresAt;
|
|
539
|
+
});
|
|
540
|
+
}
|
|
541
|
+
//# sourceMappingURL=supervisor-questions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"supervisor-questions.js","sourceRoot":"","sources":["../../../../../src/builtin-extensions/pi-subagents/src/intercom/supervisor-questions.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport { TEMP_ROOT_DIR } from \"../shared/types.ts\";\n\nexport const QUESTIONS_DIR = \"questions\";\nexport const SUPERVISOR_CHANNEL_ROOT = path.join(TEMP_ROOT_DIR, \"supervisor-channels\");\nexport const SUBAGENT_SUPERVISOR_ANSWER_TYPE = \"subagent_supervisor_answer\";\nexport const SUBAGENT_QUESTION_EVENT = \"subagent:supervisor-question\";\n\nexport type SupervisorQuestionPublicState = \"pending\" | \"answered\" | \"expired\" | \"cancelled\";\n\nexport interface SupervisorChildIncarnation {\n\tpid: number;\n\treadyAt: number;\n}\n\nexport interface SupervisorQuestion {\n\ttype: \"subagent.supervisor.question\";\n\tid: string;\n\tcreatedAt: number;\n\texpiresAt: number;\n\treason: string;\n\tmessage: string;\n\trunId: string;\n\tchildIndex: number;\n\tchildId: string;\n\tparentSessionId: string;\n\tparentGeneration: number;\n\tchildIncarnation?: SupervisorChildIncarnation;\n\tdeliveredAt?: number;\n\tansweredAt?: number;\n\texpiredAt?: number;\n\tcancelledAt?: number;\n\tcancelReason?: string;\n\tnotifiedAt?: number;\n\tlateAnswerAt?: number;\n\tanswer?: string;\n}\n\nexport interface SupervisorQuestionOwner {\n\trunId: string;\n\tchildIndex: number;\n\tchildId: string;\n\tpid: number;\n\treadyAt: number;\n}\n\ninterface QuestionRecord {\n\ttype: \"subagent.supervisor.question\";\n\tid: string;\n\tcreatedAt: number;\n\texpiresAt: number;\n\treason: string;\n\tmessage: string;\n\trunId: string;\n\tchildIndex: number;\n\tchildId: string;\n\tparentSessionId: string;\n\tparentGeneration: number;\n\tchildIncarnation?: SupervisorChildIncarnation;\n}\n\ninterface DeliveredRecord {\n\ttype: \"subagent.supervisor.delivered\";\n\tid: string;\n\tat: number;\n\tpid: number;\n\treadyAt: number;\n}\n\ntype TerminalRecord =\n\t| { type: \"subagent.supervisor.terminal\"; id: string; state: \"answered\"; at: number; message: string }\n\t| { type: \"subagent.supervisor.terminal\"; id: string; state: \"expired\"; at: number }\n\t| { type: \"subagent.supervisor.terminal\"; id: string; state: \"cancelled\"; at: number; reason: string };\n\ninterface NotifiedRecord {\n\ttype: \"subagent.supervisor.notified\";\n\tid: string;\n\tat: number;\n}\n\ninterface LateAnswerRecord {\n\ttype: \"subagent.supervisor.late-answer\";\n\tid: string;\n\tat: number;\n\tmessage: string;\n}\n\nconst MAX_MESSAGE_BYTES = 64 * 1024;\nconst DEFAULT_ASK_TIMEOUT_MS = 10 * 60 * 1000;\nconst activeQuestionWaits = new Set<string>();\n\nfunction askTimeoutMs(): number {\n\tconst parsed = Number(process.env.PI_INTERCOM_ASK_TIMEOUT_MS);\n\treturn Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_ASK_TIMEOUT_MS;\n}\n\nfunction safeSegment(value: string): string {\n\treturn value.trim().replace(/[^A-Za-z0-9._-]+/g, \"-\").replace(/^-+|-+$/g, \"\") || \"unknown\";\n}\n\nexport function resolveSupervisorChannelDir(runId: string, agent: string, childIndex: number): string {\n\treturn path.join(SUPERVISOR_CHANNEL_ROOT, `${safeSegment(runId)}-${safeSegment(agent)}-${childIndex}`);\n}\n\nexport function questionsDir(channelDir: string): string {\n\treturn path.join(channelDir, QUESTIONS_DIR);\n}\n\nfunction questionFile(channelDir: string, questionId: string): string {\n\treturn path.join(questionsDir(channelDir), `${safeSegment(questionId)}.json`);\n}\n\nfunction deliveredFile(channelDir: string, questionId: string): string {\n\treturn path.join(questionsDir(channelDir), `${safeSegment(questionId)}.delivered.json`);\n}\n\nfunction terminalFile(channelDir: string, questionId: string): string {\n\treturn path.join(questionsDir(channelDir), `${safeSegment(questionId)}.terminal.json`);\n}\n\nfunction notifiedFile(channelDir: string, questionId: string): string {\n\treturn path.join(questionsDir(channelDir), `${safeSegment(questionId)}.notified.json`);\n}\n\nfunction lateFile(channelDir: string, questionId: string): string {\n\treturn path.join(questionsDir(channelDir), `${safeSegment(questionId)}.late.json`);\n}\n\nfunction writeExclusiveJson(filePath: string, payload: object): boolean {\n\tfs.mkdirSync(path.dirname(filePath), { recursive: true, mode: 0o700 });\n\tconst temporary = `${filePath}.${randomUUID()}.tmp`;\n\ttry {\n\t\tfs.writeFileSync(temporary, JSON.stringify(payload), { encoding: \"utf-8\", flag: \"wx\", mode: 0o600 });\n\t\t// Publish a complete record without overwriting a competing terminal outcome.\n\t\tfs.linkSync(temporary, filePath);\n\t\treturn true;\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code === \"EEXIST\") return false;\n\t\tthrow error;\n\t} finally {\n\t\tfs.rmSync(temporary, { force: true });\n\t}\n}\n\nfunction readJsonFile(filePath: string): unknown {\n\treturn JSON.parse(fs.readFileSync(filePath, \"utf-8\"));\n}\n\nfunction tryReadJson(filePath: string): unknown | undefined {\n\ttry {\n\t\treturn readJsonFile(filePath);\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return undefined;\n\t\treturn undefined;\n\t}\n}\n\nfunction parseIncarnation(raw: unknown): SupervisorChildIncarnation | undefined {\n\tif (!raw || typeof raw !== \"object\" || Array.isArray(raw)) return undefined;\n\tconst input = raw as Partial<SupervisorChildIncarnation>;\n\tconst pid = input.pid;\n\tconst readyAt = input.readyAt;\n\tif (!Number.isInteger(pid) || pid === undefined || pid <= 0) return undefined;\n\tif (typeof readyAt !== \"number\" || !Number.isFinite(readyAt) || readyAt <= 0) return undefined;\n\treturn { pid, readyAt };\n}\n\nfunction parseQuestionRecord(raw: unknown): QuestionRecord | undefined {\n\tif (!raw || typeof raw !== \"object\" || Array.isArray(raw)) return undefined;\n\tconst input = raw as Partial<QuestionRecord>;\n\tif (input.type !== \"subagent.supervisor.question\") return undefined;\n\tif (typeof input.id !== \"string\" || !input.id.trim()) return undefined;\n\tif (typeof input.createdAt !== \"number\" || !Number.isFinite(input.createdAt)) return undefined;\n\tif (typeof input.expiresAt !== \"number\" || !Number.isFinite(input.expiresAt)) return undefined;\n\tif (typeof input.reason !== \"string\" || !input.reason.trim()) return undefined;\n\tif (typeof input.message !== \"string\" || !input.message.trim()) return undefined;\n\tif (typeof input.runId !== \"string\" || !input.runId.trim()) return undefined;\n\tconst childIndex = input.childIndex;\n\tif (!Number.isInteger(childIndex) || childIndex === undefined || childIndex < 0) return undefined;\n\tif (typeof input.childId !== \"string\" || !input.childId.trim()) return undefined;\n\tif (typeof input.parentSessionId !== \"string\" || !input.parentSessionId.trim()) return undefined;\n\tconst parentGeneration = input.parentGeneration;\n\tif (!Number.isInteger(parentGeneration) || parentGeneration === undefined || parentGeneration < 0) return undefined;\n\tconst incarnation = parseIncarnation(input.childIncarnation);\n\treturn {\n\t\ttype: \"subagent.supervisor.question\",\n\t\tid: input.id.trim(),\n\t\tcreatedAt: input.createdAt,\n\t\texpiresAt: input.expiresAt,\n\t\treason: input.reason.trim(),\n\t\tmessage: input.message.trim(),\n\t\trunId: input.runId.trim(),\n\t\tchildIndex,\n\t\tchildId: input.childId.trim(),\n\t\tparentSessionId: input.parentSessionId.trim(),\n\t\tparentGeneration,\n\t\t...(incarnation ? { childIncarnation: incarnation } : {}),\n\t};\n}\n\nfunction parseDeliveredRecord(raw: unknown): DeliveredRecord | undefined {\n\tif (!raw || typeof raw !== \"object\" || Array.isArray(raw)) return undefined;\n\tconst input = raw as Partial<DeliveredRecord>;\n\tif (input.type !== \"subagent.supervisor.delivered\" || typeof input.id !== \"string\" || !input.id.trim()) return undefined;\n\tif (typeof input.at !== \"number\" || !Number.isFinite(input.at)) return undefined;\n\tconst incarnation = parseIncarnation(input);\n\tif (!incarnation) return undefined;\n\treturn { type: \"subagent.supervisor.delivered\", id: input.id.trim(), at: input.at, pid: incarnation.pid, readyAt: incarnation.readyAt };\n}\n\nfunction parseTerminalRecord(raw: unknown): TerminalRecord | undefined {\n\tif (!raw || typeof raw !== \"object\" || Array.isArray(raw)) return undefined;\n\tconst input = raw as Partial<TerminalRecord> & { message?: unknown; reason?: unknown };\n\tif (input.type !== \"subagent.supervisor.terminal\" || typeof input.id !== \"string\" || !input.id.trim()) return undefined;\n\tif (typeof input.at !== \"number\" || !Number.isFinite(input.at)) return undefined;\n\tif (input.state === \"answered\") {\n\t\tif (typeof input.message !== \"string\" || !input.message.trim()) return undefined;\n\t\treturn { type: \"subagent.supervisor.terminal\", id: input.id.trim(), state: \"answered\", at: input.at, message: input.message };\n\t}\n\tif (input.state === \"expired\") {\n\t\treturn { type: \"subagent.supervisor.terminal\", id: input.id.trim(), state: \"expired\", at: input.at };\n\t}\n\tif (input.state === \"cancelled\") {\n\t\tif (typeof input.reason !== \"string\" || !input.reason.trim()) return undefined;\n\t\treturn { type: \"subagent.supervisor.terminal\", id: input.id.trim(), state: \"cancelled\", at: input.at, reason: input.reason.trim() };\n\t}\n\treturn undefined;\n}\n\nfunction parseNotifiedRecord(raw: unknown): NotifiedRecord | undefined {\n\tif (!raw || typeof raw !== \"object\" || Array.isArray(raw)) return undefined;\n\tconst input = raw as Partial<NotifiedRecord>;\n\tif (input.type !== \"subagent.supervisor.notified\" || typeof input.id !== \"string\" || !input.id.trim()) return undefined;\n\tif (typeof input.at !== \"number\" || !Number.isFinite(input.at)) return undefined;\n\treturn { type: \"subagent.supervisor.notified\", id: input.id.trim(), at: input.at };\n}\n\nfunction parseLateRecord(raw: unknown): LateAnswerRecord | undefined {\n\tif (!raw || typeof raw !== \"object\" || Array.isArray(raw)) return undefined;\n\tconst input = raw as Partial<LateAnswerRecord>;\n\tif (input.type !== \"subagent.supervisor.late-answer\" || typeof input.id !== \"string\" || !input.id.trim()) return undefined;\n\tif (typeof input.at !== \"number\" || !Number.isFinite(input.at) || typeof input.message !== \"string\") return undefined;\n\treturn { type: \"subagent.supervisor.late-answer\", id: input.id.trim(), at: input.at, message: input.message };\n}\n\nfunction composeQuestion(record: QuestionRecord, channelDir: string): SupervisorQuestion {\n\tconst delivered = parseDeliveredRecord(tryReadJson(deliveredFile(channelDir, record.id)));\n\tconst terminal = parseTerminalRecord(tryReadJson(terminalFile(channelDir, record.id)));\n\tconst notified = parseNotifiedRecord(tryReadJson(notifiedFile(channelDir, record.id)));\n\tconst late = parseLateRecord(tryReadJson(lateFile(channelDir, record.id)));\n\treturn {\n\t\t...record,\n\t\t...(delivered ? { deliveredAt: delivered.at, childIncarnation: record.childIncarnation ?? { pid: delivered.pid, readyAt: delivered.readyAt } } : {}),\n\t\t...(terminal?.state === \"answered\" ? { answeredAt: terminal.at, answer: terminal.message } : {}),\n\t\t...(terminal?.state === \"expired\" ? { expiredAt: terminal.at } : {}),\n\t\t...(terminal?.state === \"cancelled\" ? { cancelledAt: terminal.at, cancelReason: terminal.reason } : {}),\n\t\t...(notified ? { notifiedAt: notified.at } : {}),\n\t\t...(late ? { lateAnswerAt: late.at, ...(terminal?.state === \"answered\" ? {} : { answer: late.message }) } : {}),\n\t};\n}\n\nfunction assertMessageSize(value: string, label: string): void {\n\tif (Buffer.byteLength(value, \"utf-8\") > MAX_MESSAGE_BYTES) throw new Error(`${label} is too large.`);\n}\n\nexport function ensureQuestionsDir(channelDir: string): void {\n\tfs.mkdirSync(questionsDir(channelDir), { recursive: true, mode: 0o700 });\n}\n\nexport function supervisorQuestionPublicState(question: SupervisorQuestion): SupervisorQuestionPublicState {\n\tif (question.answeredAt) return \"answered\";\n\tif (question.expiredAt) return \"expired\";\n\tif (question.cancelledAt) return \"cancelled\";\n\treturn \"pending\";\n}\n\nexport function supervisorQuestionIsTerminal(question: SupervisorQuestion): boolean {\n\treturn supervisorQuestionPublicState(question) !== \"pending\";\n}\n\nexport function readSupervisorQuestion(channelDir: string, questionId: string): SupervisorQuestion | undefined {\n\tconst record = parseQuestionRecord(tryReadJson(questionFile(channelDir, questionId)));\n\tif (!record || record.id !== questionId) return undefined;\n\treturn composeQuestion(record, channelDir);\n}\n\nexport function listSupervisorQuestions(channelDir: string): SupervisorQuestion[] {\n\tconst dir = questionsDir(channelDir);\n\tlet entries: string[];\n\ttry {\n\t\tentries = fs.readdirSync(dir).filter((name) => name.endsWith(\".json\") && !name.endsWith(\".delivered.json\") && !name.endsWith(\".terminal.json\") && !name.endsWith(\".notified.json\") && !name.endsWith(\".late.json\"));\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return [];\n\t\tthrow error;\n\t}\n\tconst questions: SupervisorQuestion[] = [];\n\tfor (const entry of entries.sort()) {\n\t\tconst record = parseQuestionRecord(tryReadJson(path.join(dir, entry)));\n\t\tif (record) questions.push(composeQuestion(record, channelDir));\n\t}\n\treturn questions;\n}\n\nfunction writeTerminal(channelDir: string, record: TerminalRecord): boolean {\n\treturn writeExclusiveJson(terminalFile(channelDir, record.id), record);\n}\n\nfunction readTerminal(channelDir: string, questionId: string): TerminalRecord | undefined {\n\treturn parseTerminalRecord(tryReadJson(terminalFile(channelDir, questionId)));\n}\n\nexport function createSupervisorQuestion(input: {\n\tchannelDir: string;\n\treason: string;\n\tmessage: string;\n\trunId: string;\n\tchildIndex: number;\n\tchildId: string;\n\tparentSessionId: string;\n\tparentGeneration: number;\n\tchildIncarnation?: SupervisorChildIncarnation;\n\tnow?: number;\n\ttimeoutMs?: number;\n\tid?: string;\n}): SupervisorQuestion {\n\tconst reason = input.reason.trim();\n\tconst message = input.message.trim();\n\tif (!reason) throw new Error(\"reason is required and must name the concrete decision the child's answer will change.\");\n\tif (!message) throw new Error(\"message is required for supervisor questions.\");\n\tassertMessageSize(reason, \"reason\");\n\tassertMessageSize(message, \"message\");\n\tconst createdAt = input.now ?? Date.now();\n\tconst timeoutMs = input.timeoutMs && input.timeoutMs > 0 ? input.timeoutMs : askTimeoutMs();\n\tconst record: QuestionRecord = {\n\t\ttype: \"subagent.supervisor.question\",\n\t\tid: input.id ?? randomUUID(),\n\t\tcreatedAt,\n\t\texpiresAt: createdAt + timeoutMs,\n\t\treason,\n\t\tmessage,\n\t\trunId: input.runId,\n\t\tchildIndex: input.childIndex,\n\t\tchildId: input.childId,\n\t\tparentSessionId: input.parentSessionId,\n\t\tparentGeneration: input.parentGeneration,\n\t\t...(input.childIncarnation ? { childIncarnation: input.childIncarnation } : {}),\n\t};\n\tassertMessageSize(JSON.stringify(record), \"Supervisor question\");\n\tensureQuestionsDir(input.channelDir);\n\tif (!writeExclusiveJson(questionFile(input.channelDir, record.id), record)) {\n\t\tthrow new Error(`Supervisor question '${record.id}' already exists.`);\n\t}\n\treturn composeQuestion(record, input.channelDir);\n}\n\nexport function outstandingQuestionsForChild(channelDir: string, childIndex: number, childId?: string): SupervisorQuestion[] {\n\trefreshSupervisorQuestionLifecycle(channelDir);\n\treturn listSupervisorQuestions(channelDir).filter((question) => {\n\t\tif (supervisorQuestionIsTerminal(question)) return false;\n\t\tif (question.childIndex !== childIndex) return false;\n\t\tif (childId && question.childId !== childId) return false;\n\t\treturn true;\n\t});\n}\n\nexport function hasBlockingSupervisorRequest(channelDir: string, runId: string, childIndex: number): boolean {\n\tconst directory = path.join(channelDir, \"requests\");\n\tif (!fs.existsSync(directory)) return false;\n\tfor (const name of fs.readdirSync(directory)) {\n\t\tif (!name.endsWith(\".json\")) continue;\n\t\tconst raw = tryReadJson(path.join(directory, name));\n\t\tif (!raw || typeof raw !== \"object\") continue;\n\t\tconst request = raw as { type?: unknown; id?: unknown; expectsReply?: unknown; runId?: unknown; childIndex?: unknown; expiresAt?: unknown };\n\t\tif (request.type !== \"subagent.supervisor.request\" || request.expectsReply !== true) continue;\n\t\tif (request.runId !== runId || request.childIndex !== childIndex || typeof request.id !== \"string\") continue;\n\t\tif (typeof request.expiresAt === \"number\" && request.expiresAt <= Date.now()) continue;\n\t\tif (!fs.existsSync(path.join(channelDir, \"replies\", `${safeSegment(request.id)}.json`))) return true;\n\t}\n\treturn false;\n}\n\nexport function hasOutstandingQuestionForChild(channelDir: string, childIndex: number, childId?: string): boolean {\n\treturn outstandingQuestionsForChild(channelDir, childIndex, childId).length > 0;\n}\n\nexport function incarnationMatches(expected: SupervisorChildIncarnation | undefined, actual: SupervisorChildIncarnation): boolean {\n\tif (!expected) return true;\n\treturn expected.pid === actual.pid && expected.readyAt === actual.readyAt;\n}\n\nfunction assertOwner(question: SupervisorQuestion, owner: SupervisorQuestionOwner): void {\n\tif (owner.runId !== question.runId || owner.childIndex !== question.childIndex || owner.childId !== question.childId) {\n\t\tthrow new Error(`Supervisor question '${question.id}' is not owned by this child.`);\n\t}\n\tif (!incarnationMatches(question.childIncarnation, { pid: owner.pid, readyAt: owner.readyAt })) {\n\t\tthrow new Error(`Supervisor question '${question.id}' was bound to a different child incarnation.`);\n\t}\n}\n\nfunction ownerMatchesDelivered(channelDir: string, questionId: string, owner: SupervisorQuestionOwner): boolean {\n\tconst delivered = parseDeliveredRecord(tryReadJson(deliveredFile(channelDir, questionId)));\n\tif (!delivered) return true;\n\treturn delivered.pid === owner.pid && delivered.readyAt === owner.readyAt;\n}\n\nexport function markSupervisorQuestionDelivered(\n\tchannelDir: string,\n\tquestionId: string,\n\towner: SupervisorQuestionOwner,\n\tnow = Date.now(),\n): SupervisorQuestion | undefined {\n\tconst current = readSupervisorQuestion(channelDir, questionId);\n\tif (!current || supervisorQuestionIsTerminal(current)) return current;\n\tassertOwner(current, owner);\n\twriteExclusiveJson(deliveredFile(channelDir, questionId), {\n\t\ttype: \"subagent.supervisor.delivered\",\n\t\tid: questionId,\n\t\tat: now,\n\t\tpid: owner.pid,\n\t\treadyAt: owner.readyAt,\n\t} satisfies DeliveredRecord);\n\treturn readSupervisorQuestion(channelDir, questionId);\n}\n\nfunction rejectLateOrDuplicate(channelDir: string, questionId: string, answer: string, now: number, terminal: TerminalRecord): never {\n\twriteExclusiveJson(lateFile(channelDir, questionId), {\n\t\ttype: \"subagent.supervisor.late-answer\",\n\t\tid: questionId,\n\t\tat: now,\n\t\tmessage: answer,\n\t} satisfies LateAnswerRecord);\n\tif (terminal.state === \"answered\") throw new Error(`Supervisor question '${questionId}' was already answered.`);\n\tthrow new Error(`Supervisor question '${questionId}' is ${terminal.state} and no longer accepts an answer.`);\n}\n\nexport function answerSupervisorQuestion(\n\tchannelDir: string,\n\tquestionId: string,\n\tanswer: string,\n\towner: SupervisorQuestionOwner,\n\tnow = Date.now(),\n): SupervisorQuestion {\n\tconst trimmed = answer.trim();\n\tif (!trimmed) throw new Error(\"message is required for supervisor question replies.\");\n\tassertMessageSize(trimmed, \"answer\");\n\tconst current = readSupervisorQuestion(channelDir, questionId);\n\tif (!current) throw new Error(`No supervisor question found for replyTo '${questionId}'.`);\n\tassertOwner(current, owner);\n\tif (!ownerMatchesDelivered(channelDir, questionId, owner)) {\n\t\tthrow new Error(`Supervisor question '${questionId}' was bound to a different child incarnation.`);\n\t}\n\tif (now > current.expiresAt) {\n\t\twriteTerminal(channelDir, { type: \"subagent.supervisor.terminal\", id: questionId, state: \"expired\", at: now });\n\t\tconst terminal = readTerminal(channelDir, questionId);\n\t\tif (terminal && terminal.state !== \"answered\") {\n\t\t\trejectLateOrDuplicate(channelDir, questionId, trimmed, now, terminal);\n\t\t}\n\t\tif (terminal?.state === \"answered\") throw new Error(`Supervisor question '${questionId}' was already answered.`);\n\t}\n\tconst existing = readTerminal(channelDir, questionId);\n\tif (existing) rejectLateOrDuplicate(channelDir, questionId, trimmed, now, existing);\n\tif (!writeTerminal(channelDir, { type: \"subagent.supervisor.terminal\", id: questionId, state: \"answered\", at: now, message: trimmed })) {\n\t\tconst terminal = readTerminal(channelDir, questionId);\n\t\tif (terminal) rejectLateOrDuplicate(channelDir, questionId, trimmed, now, terminal);\n\t\tthrow new Error(`Supervisor question '${questionId}' is no longer pending.`);\n\t}\n\tconst answered = readSupervisorQuestion(channelDir, questionId);\n\tif (!answered) throw new Error(`Supervisor question '${questionId}' is no longer pending.`);\n\treturn answered;\n}\n\nexport function expireSupervisorQuestion(channelDir: string, questionId: string, now = Date.now()): SupervisorQuestion | undefined {\n\tconst current = readSupervisorQuestion(channelDir, questionId);\n\tif (!current || supervisorQuestionIsTerminal(current) || now <= current.expiresAt) return current && supervisorQuestionIsTerminal(current) ? current : undefined;\n\tif (!writeTerminal(channelDir, { type: \"subagent.supervisor.terminal\", id: questionId, state: \"expired\", at: now })) return readSupervisorQuestion(channelDir, questionId);\n\treturn readSupervisorQuestion(channelDir, questionId);\n}\n\nexport function cancelSupervisorQuestion(\n\tchannelDir: string,\n\tquestionId: string,\n\treason: string,\n\tnow = Date.now(),\n): SupervisorQuestion | undefined {\n\tconst current = readSupervisorQuestion(channelDir, questionId);\n\tif (!current || supervisorQuestionIsTerminal(current)) return current;\n\tif (!writeTerminal(channelDir, { type: \"subagent.supervisor.terminal\", id: questionId, state: \"cancelled\", at: now, reason: reason.trim() || \"cancelled\" })) {\n\t\treturn readSupervisorQuestion(channelDir, questionId);\n\t}\n\treturn readSupervisorQuestion(channelDir, questionId);\n}\n\nexport function refreshSupervisorQuestionLifecycle(channelDir: string, now = Date.now()): SupervisorQuestion[] {\n\tconst changed: SupervisorQuestion[] = [];\n\tfor (const question of listSupervisorQuestions(channelDir)) {\n\t\tif (supervisorQuestionIsTerminal(question)) continue;\n\t\tif (now > question.expiresAt) {\n\t\t\tconst expired = expireSupervisorQuestion(channelDir, question.id, now);\n\t\t\tif (expired && expired.expiredAt) changed.push(expired);\n\t\t}\n\t}\n\treturn changed;\n}\n\nexport function formatParentQuestionForChild(question: SupervisorQuestion): string {\n\treturn [\n\t\t`Parent question (${question.id})`,\n\t\t`Decision needed: ${question.reason}`,\n\t\t\"\",\n\t\tquestion.message,\n\t\t\"\",\n\t\t`Reply with: contact_supervisor({ action: \"reply\", replyTo: \"${question.id}\", message: \"...\" })`,\n\t\t\"Answer from current findings and uncertainty. Do not silently start extra investigation. Continue the assigned task after replying.\",\n\t].join(\"\\n\");\n}\n\nexport function formatSupervisorQuestionAnswer(question: SupervisorQuestion): string {\n\tconst state = supervisorQuestionPublicState(question);\n\tconst header = state === \"answered\"\n\t\t? `Subagent answer (${question.id})`\n\t\t: `Subagent question ${state} (${question.id})`;\n\tconst lines = [\n\t\theader,\n\t\t`Run: ${question.runId}`,\n\t\t`Child: ${question.childId} [#${question.childIndex}]`,\n\t\t`Decision: ${question.reason}`,\n\t];\n\tif (state === \"answered\" && question.answer?.trim()) {\n\t\tlines.push(\"\", question.answer.trim());\n\t} else if (question.cancelReason) {\n\t\tlines.push(\"\", question.cancelReason);\n\t}\n\treturn lines.join(\"\\n\");\n}\n\nexport function registerQuestionWait(questionIds: Iterable<string>): () => void {\n\tconst ids = [...questionIds];\n\tfor (const id of ids) activeQuestionWaits.add(id);\n\treturn () => {\n\t\tfor (const id of ids) activeQuestionWaits.delete(id);\n\t};\n}\n\nexport function isQuestionWaitActive(questionId: string): boolean {\n\treturn activeQuestionWaits.has(questionId);\n}\n\nexport function claimQuestionNotification(channelDir: string, questionId: string, now = Date.now()): boolean {\n\treturn writeExclusiveJson(notifiedFile(channelDir, questionId), {\n\t\ttype: \"subagent.supervisor.notified\",\n\t\tid: questionId,\n\t\tat: now,\n\t} satisfies NotifiedRecord);\n}\n\nexport function markSupervisorQuestionNotified(channelDir: string, questionId: string, now = Date.now()): SupervisorQuestion | undefined {\n\tclaimQuestionNotification(channelDir, questionId, now);\n\treturn readSupervisorQuestion(channelDir, questionId);\n}\n\nexport function resetSupervisorQuestionTestState(): void {\n\tactiveQuestionWaits.clear();\n}\n\nexport function listSupervisorChannelDirs(): string[] {\n\tlet entries: fs.Dirent[];\n\ttry {\n\t\tentries = fs.readdirSync(SUPERVISOR_CHANNEL_ROOT, { withFileTypes: true });\n\t} catch (error) {\n\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return [];\n\t\tthrow error;\n\t}\n\treturn entries.filter((entry) => entry.isDirectory()).map((entry) => path.join(SUPERVISOR_CHANNEL_ROOT, entry.name));\n}\n\nexport function findSupervisorQuestion(questionId: string): { channelDir: string; question: SupervisorQuestion } | undefined {\n\tconst id = questionId.trim();\n\tif (!id) return undefined;\n\tfor (const channelDir of listSupervisorChannelDirs()) {\n\t\tconst question = readSupervisorQuestion(channelDir, id);\n\t\tif (question) return { channelDir, question };\n\t}\n\treturn undefined;\n}\n\nexport function cancelPendingSupervisorQuestionsForOwner(input: {\n\tparentSessionId: string;\n\tparentGeneration?: number;\n\trunId?: string;\n\treason: string;\n\tnow?: number;\n}): SupervisorQuestion[] {\n\tif (!input.parentSessionId?.trim()) return [];\n\tconst now = input.now ?? Date.now();\n\tconst cancelled: SupervisorQuestion[] = [];\n\tfor (const channelDir of listSupervisorChannelDirs()) {\n\t\tfor (const question of listSupervisorQuestions(channelDir)) {\n\t\t\tif (supervisorQuestionIsTerminal(question)) continue;\n\t\t\tif (question.parentSessionId !== input.parentSessionId) continue;\n\t\t\tif (input.parentGeneration !== undefined && question.parentGeneration !== input.parentGeneration) continue;\n\t\t\tif (input.runId && question.runId !== input.runId) continue;\n\t\t\tconst next = cancelSupervisorQuestion(channelDir, question.id, input.reason, now);\n\t\t\tif (next?.cancelledAt) cancelled.push(next);\n\t\t}\n\t}\n\treturn cancelled;\n}\n\nexport function pendingSupervisorQuestionsForDelivery(channelDir: string, owner: SupervisorQuestionOwner, now = Date.now()): SupervisorQuestion[] {\n\trefreshSupervisorQuestionLifecycle(channelDir, now);\n\treturn listSupervisorQuestions(channelDir).filter((question) => {\n\t\tif (supervisorQuestionIsTerminal(question)) return false;\n\t\tif (question.deliveredAt) return false;\n\t\tif (question.runId !== owner.runId || question.childIndex !== owner.childIndex || question.childId !== owner.childId) return false;\n\t\tif (!incarnationMatches(question.childIncarnation, { pid: owner.pid, readyAt: owner.readyAt })) return false;\n\t\treturn now <= question.expiresAt;\n\t});\n}\n"]}
|