@duckmind/dm-windows-x64 0.61.4 → 0.61.9
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/dm.exe +0 -0
- package/extensions/.dm-extensions.json +211 -67
- package/extensions/dm-subagents/agents/claude-code-writer.md +15 -0
- package/extensions/dm-subagents/agents/claude-code.md +15 -0
- package/extensions/dm-subagents/agents/codex-exec-writer.md +15 -0
- package/extensions/dm-subagents/agents/codex-exec.md +15 -0
- package/extensions/dm-subagents/agents/cursor-agent-writer.md +14 -0
- package/extensions/dm-subagents/agents/cursor-agent.md +14 -0
- package/extensions/dm-subagents/agents/delegate.md +3 -2
- package/extensions/dm-subagents/agents/oracle.md +10 -5
- package/extensions/dm-subagents/agents/researcher.md +2 -2
- package/extensions/dm-subagents/agents/reviewer.md +17 -7
- package/extensions/dm-subagents/agents/scout.md +5 -5
- package/extensions/dm-subagents/agents/worker.md +6 -2
- package/extensions/dm-subagents/async-retention-discovery-worker.mjs +167 -0
- package/extensions/dm-subagents/index.js +4 -0
- package/extensions/dm-subagents/inspector-runner.mjs +10 -0
- package/extensions/dm-subagents/install.mjs +3 -2
- package/extensions/dm-subagents/package.json +2 -2
- package/extensions/dm-subagents/prompts/council.md +60 -0
- package/extensions/dm-subagents/prompts/parallel-review.md +5 -1
- package/extensions/dm-subagents/prompts/review-loop.md +13 -7
- package/extensions/dm-subagents/skills/council-mode/SKILL.md +59 -0
- package/extensions/dm-subagents/skills/council-mode/references/pass-contracts.md +150 -0
- package/extensions/dm-subagents/skills/dm-subagents/SKILL.md +96 -911
- package/extensions/dm-subagents/skills/dm-subagents/references/constraints-and-recipes.md +70 -0
- package/extensions/dm-subagents/skills/dm-subagents/references/execution-controls.md +539 -0
- package/extensions/dm-subagents/skills/dm-subagents/references/management-authoring-rpc.md +161 -0
- package/extensions/dm-subagents/skills/dm-subagents/references/multi-lane-orchestration.md +51 -0
- package/extensions/dm-subagents/skills/dm-subagents/references/prompting-and-roles.md +295 -0
- package/extensions/dm-subagents/skills/dm-subagents/references/review-and-validation.md +73 -0
- package/extensions/dm-subagents/src/agents/agent-management.js +716 -484
- package/extensions/dm-subagents/src/agents/agent-refinements.js +563 -0
- package/extensions/dm-subagents/src/agents/agent-serializer.js +70 -5
- package/extensions/dm-subagents/src/agents/agents.js +1447 -299
- package/extensions/dm-subagents/src/agents/builtin-names.js +15 -0
- package/extensions/dm-subagents/src/agents/chain-serializer.js +12 -7
- package/extensions/dm-subagents/src/agents/frontmatter.js +64 -14
- package/extensions/dm-subagents/src/agents/identity.js +1 -1
- package/extensions/dm-subagents/src/agents/proactive-skills.js +14 -11
- package/extensions/dm-subagents/src/agents/runtime-agent-events.js +49 -0
- package/extensions/dm-subagents/src/agents/runtime-agent-registry.js +412 -0
- package/extensions/dm-subagents/src/agents/skills.js +52 -35
- package/extensions/dm-subagents/src/api/agents.js +6 -0
- package/extensions/dm-subagents/src/api/background-work.js +151 -0
- package/extensions/dm-subagents/src/api/capability-ceiling.js +12 -0
- package/extensions/dm-subagents/src/api/control-channel.js +3 -0
- package/extensions/dm-subagents/src/api/delegation.js +5 -0
- package/extensions/dm-subagents/src/api/dm-args.js +3 -0
- package/extensions/dm-subagents/src/api/external-job-provider.js +137 -0
- package/extensions/dm-subagents/src/api/external-runs.js +233 -0
- package/extensions/dm-subagents/src/api/intercom-bridge.js +3 -0
- package/extensions/dm-subagents/src/api/preflight.js +322 -0
- package/extensions/dm-subagents/src/api/project-panes.js +11 -0
- package/extensions/dm-subagents/src/api/shared-types.js +4 -0
- package/extensions/dm-subagents/src/extension/config.js +175 -0
- package/extensions/dm-subagents/src/extension/control-notices.js +4 -43
- package/extensions/dm-subagents/src/extension/doctor.js +71 -17
- package/extensions/dm-subagents/src/extension/fanout-child.js +49 -32
- package/extensions/dm-subagents/src/extension/index.js +711 -265
- package/extensions/dm-subagents/src/extension/public-execution.js +114 -0
- package/extensions/dm-subagents/src/extension/rpc.js +427 -22
- package/extensions/dm-subagents/src/extension/schemas.js +158 -65
- package/extensions/dm-subagents/src/extension/steering-notices.js +23 -0
- package/extensions/dm-subagents/src/extension/subagent-guide.js +31 -0
- package/extensions/dm-subagents/src/extension/tool-description.js +92 -74
- package/extensions/dm-subagents/src/extension/tool-result.js +7 -0
- package/extensions/dm-subagents/src/inspectors/herdr/actions.js +218 -0
- package/extensions/dm-subagents/src/inspectors/herdr/client.js +123 -0
- package/extensions/dm-subagents/src/inspectors/herdr/focus.js +47 -0
- package/extensions/dm-subagents/src/inspectors/herdr/inspector-runner.js +160 -0
- package/extensions/dm-subagents/src/inspectors/herdr/project-panes.js +618 -0
- package/extensions/dm-subagents/src/inspectors/herdr/session-roots-codec.js +21 -0
- package/extensions/dm-subagents/src/inspectors/herdr/shell-command.js +15 -0
- package/extensions/dm-subagents/src/integrations/herdr-status.js +377 -0
- package/extensions/dm-subagents/src/intercom/intercom-bridge.js +17 -13
- package/extensions/dm-subagents/src/intercom/native-supervisor-channel.js +371 -79
- package/extensions/dm-subagents/src/intercom/result-intercom.js +47 -7
- package/extensions/dm-subagents/src/missions/actions.js +394 -0
- package/extensions/dm-subagents/src/missions/goal-driver.js +149 -0
- package/extensions/dm-subagents/src/missions/lifecycle.js +331 -0
- package/extensions/dm-subagents/src/missions/store.js +548 -0
- package/extensions/dm-subagents/src/missions/types.js +9 -0
- package/extensions/dm-subagents/src/missions/workflow-state.js +245 -0
- package/extensions/dm-subagents/src/policy/authority.js +37 -0
- package/extensions/dm-subagents/src/profiles/profiles.js +36 -18
- package/extensions/dm-subagents/src/runs/background/active-async-capacity.js +427 -0
- package/extensions/dm-subagents/src/runs/background/active-run-index.js +122 -0
- package/extensions/dm-subagents/src/runs/background/async-execution.js +925 -137
- package/extensions/dm-subagents/src/runs/background/async-job-tracker.js +515 -148
- package/extensions/dm-subagents/src/runs/background/async-resume.js +378 -51
- package/extensions/dm-subagents/src/runs/background/async-retention.js +828 -0
- package/extensions/dm-subagents/src/runs/background/async-status-snapshot.js +31 -0
- package/extensions/dm-subagents/src/runs/background/async-status.js +259 -22
- package/extensions/dm-subagents/src/runs/background/auto-drain.js +46 -0
- package/extensions/dm-subagents/src/runs/background/chain-append.js +50 -15
- package/extensions/dm-subagents/src/runs/background/chain-root-attachment.js +67 -12
- package/extensions/dm-subagents/src/runs/background/completion-batcher.js +5 -1
- package/extensions/dm-subagents/src/runs/background/completion-dedupe.js +3 -11
- package/extensions/dm-subagents/src/runs/background/completion-replay.js +245 -0
- package/extensions/dm-subagents/src/runs/background/control-channel.js +423 -36
- package/extensions/dm-subagents/src/runs/background/fleet-view.js +132 -59
- package/extensions/dm-subagents/src/runs/background/index-segment.js +38 -0
- package/extensions/dm-subagents/src/runs/background/inspect-rpc.js +373 -0
- package/extensions/dm-subagents/src/runs/background/notify.js +357 -57
- package/extensions/dm-subagents/src/runs/background/owned-process-tree.js +86 -0
- package/extensions/dm-subagents/src/runs/background/process-terminal.js +269 -0
- package/extensions/dm-subagents/src/runs/background/result-delivery-ownership.js +34 -0
- package/extensions/dm-subagents/src/runs/background/result-files.js +469 -0
- package/extensions/dm-subagents/src/runs/background/result-watcher.js +540 -75
- package/extensions/dm-subagents/src/runs/background/resume-guidance.js +44 -0
- package/extensions/dm-subagents/src/runs/background/retained-children.js +119 -0
- package/extensions/dm-subagents/src/runs/background/run-id-query.js +5 -0
- package/extensions/dm-subagents/src/runs/background/run-id-resolver.js +93 -9
- package/extensions/dm-subagents/src/runs/background/run-status.js +303 -32
- package/extensions/dm-subagents/src/runs/background/scheduled-runs.js +784 -376
- package/extensions/dm-subagents/src/runs/background/stale-run-reconciler.js +75 -34
- package/extensions/dm-subagents/src/runs/background/steering.js +221 -0
- package/extensions/dm-subagents/src/runs/background/subagent-runner.js +3106 -844
- package/extensions/dm-subagents/src/runs/background/subagent-wait.js +529 -0
- package/extensions/dm-subagents/src/runs/background/terminal-run-index.js +106 -0
- package/extensions/dm-subagents/src/runs/background/top-level-async.js +1 -1
- package/extensions/dm-subagents/src/runs/background/wait-completions.js +155 -0
- package/extensions/dm-subagents/src/runs/background/wait-config.js +46 -0
- package/extensions/dm-subagents/src/runs/background/wait-subscriptions.js +278 -0
- package/extensions/dm-subagents/src/runs/background/wait-tool.js +47 -0
- package/extensions/dm-subagents/src/runs/foreground/async-dismiss-action.js +81 -0
- package/extensions/dm-subagents/src/runs/foreground/async-steering-action.js +245 -0
- package/extensions/dm-subagents/src/runs/foreground/async-stop-action.js +74 -0
- package/extensions/dm-subagents/src/runs/foreground/execution.js +1401 -342
- package/extensions/dm-subagents/src/runs/foreground/foreground-control.js +133 -0
- package/extensions/dm-subagents/src/runs/foreground/foreground-history.js +148 -0
- package/extensions/dm-subagents/src/runs/foreground/prompt-audit.js +139 -0
- package/extensions/dm-subagents/src/runs/foreground/subagent-executor.js +4278 -1441
- package/extensions/dm-subagents/src/runs/foreground/workflow-detach-reconcile.js +278 -0
- package/extensions/dm-subagents/src/runs/foreground/workflow-foreground-steering.js +155 -0
- package/extensions/dm-subagents/src/runs/shared/abort-recovery.js +97 -0
- package/extensions/dm-subagents/src/runs/shared/acceptance.js +597 -148
- package/extensions/dm-subagents/src/runs/shared/agent-contract.js +35 -0
- package/extensions/dm-subagents/src/runs/shared/async-status-projection.js +472 -0
- package/extensions/dm-subagents/src/runs/shared/background-process-options.js +6 -0
- package/extensions/dm-subagents/src/runs/shared/capability-ceiling.js +175 -0
- package/extensions/dm-subagents/src/runs/shared/child-identity.js +32 -0
- package/extensions/dm-subagents/src/runs/shared/child-launch-plan.js +65 -0
- package/extensions/dm-subagents/src/runs/shared/child-protocol.js +447 -0
- package/extensions/dm-subagents/src/runs/shared/claude-code-adapter.js +120 -0
- package/extensions/dm-subagents/src/runs/shared/codex-exec-adapter.js +129 -0
- package/extensions/dm-subagents/src/runs/shared/completion-evidence.js +40 -0
- package/extensions/dm-subagents/src/runs/shared/completion-guard.js +140 -83
- package/extensions/dm-subagents/src/runs/shared/context-mode.js +38 -0
- package/extensions/dm-subagents/src/runs/shared/cursor-agent-adapter.js +101 -0
- package/extensions/dm-subagents/src/runs/shared/dm-args.js +445 -72
- package/extensions/dm-subagents/src/runs/shared/dm-spawn.js +27 -16
- package/extensions/dm-subagents/src/runs/shared/dynamic-fanout.js +19 -6
- package/extensions/dm-subagents/src/runs/shared/extension-bindings.js +81 -0
- package/extensions/dm-subagents/src/runs/shared/external-cli-contract.js +134 -0
- package/extensions/dm-subagents/src/runs/shared/external-cli-preflight.js +98 -0
- package/extensions/dm-subagents/src/runs/shared/external-cli-runner.js +419 -0
- package/extensions/dm-subagents/src/runs/shared/external-job-bridge.js +404 -0
- package/extensions/dm-subagents/src/runs/shared/external-job-runner.js +334 -0
- package/extensions/dm-subagents/src/runs/shared/fast-mode-extension.js +8 -0
- package/extensions/dm-subagents/src/runs/shared/host-step-status.js +228 -0
- package/extensions/dm-subagents/src/runs/shared/lane-metadata.js +104 -0
- package/extensions/dm-subagents/src/runs/shared/launch-cwd.js +17 -0
- package/extensions/dm-subagents/src/runs/shared/llm-intent-arbiter.js +190 -0
- package/extensions/dm-subagents/src/runs/shared/long-running-guard.js +48 -3
- package/extensions/dm-subagents/src/runs/shared/mcp-config-sources.js +387 -0
- package/extensions/dm-subagents/src/runs/shared/mcp-direct-tool-allowlist.js +212 -137
- package/extensions/dm-subagents/src/runs/shared/mcp-direct-tool-grant.js +131 -0
- package/extensions/dm-subagents/src/runs/shared/model-exclusions.js +207 -0
- package/extensions/dm-subagents/src/runs/shared/model-fallback.js +225 -55
- package/extensions/dm-subagents/src/runs/shared/model-scope.js +85 -28
- package/extensions/dm-subagents/src/runs/shared/mutation-evidence.js +182 -0
- package/extensions/dm-subagents/src/runs/shared/nested-events.js +264 -102
- package/extensions/dm-subagents/src/runs/shared/nested-render.js +15 -5
- package/extensions/dm-subagents/src/runs/shared/orca-progress-tabs.js +505 -0
- package/extensions/dm-subagents/src/runs/shared/parallel-handoff.js +653 -0
- package/extensions/dm-subagents/src/runs/shared/parallel-utils.js +29 -12
- package/extensions/dm-subagents/src/runs/shared/permissions.js +108 -0
- package/extensions/dm-subagents/src/runs/shared/process-signal.js +13 -0
- package/extensions/dm-subagents/src/runs/shared/run-fanout-budget.js +257 -0
- package/extensions/dm-subagents/src/runs/shared/run-history.js +133 -13
- package/extensions/dm-subagents/src/runs/shared/runtime-acknowledged-extensions.js +62 -0
- package/extensions/dm-subagents/src/runs/shared/session-lease.js +225 -0
- package/extensions/dm-subagents/src/runs/shared/single-output.js +129 -27
- package/extensions/dm-subagents/src/runs/shared/spawn-budget.js +95 -0
- package/extensions/dm-subagents/src/runs/shared/structured-output.js +129 -10
- package/extensions/dm-subagents/src/runs/shared/subagent-control.js +66 -11
- package/extensions/dm-subagents/src/runs/shared/subagent-prompt-runtime.js +548 -70
- package/extensions/dm-subagents/src/runs/shared/subagent-startup-retry.js +50 -0
- package/extensions/dm-subagents/src/runs/shared/task-intent.js +130 -0
- package/extensions/dm-subagents/src/runs/shared/tool-availability.js +59 -0
- package/extensions/dm-subagents/src/runs/shared/tool-budget.js +7 -5
- package/extensions/dm-subagents/src/runs/shared/tool-timeout.js +64 -0
- package/extensions/dm-subagents/src/runs/shared/usage-budget.js +74 -0
- package/extensions/dm-subagents/src/runs/shared/workflow-graph.js +22 -0
- package/extensions/dm-subagents/src/runs/shared/worktree-cleanup-plan.js +721 -0
- package/extensions/dm-subagents/src/runs/shared/worktree.js +168 -19
- package/extensions/dm-subagents/src/shared/accessible-dir.js +35 -0
- package/extensions/dm-subagents/src/shared/agent-stream-options.js +3 -0
- package/extensions/dm-subagents/src/shared/artifacts.js +170 -11
- package/extensions/dm-subagents/src/shared/atomic-json.js +36 -38
- package/extensions/dm-subagents/src/shared/capacity-resilient-json.js +77 -0
- package/extensions/dm-subagents/src/shared/child-session-name.js +15 -0
- package/extensions/dm-subagents/src/shared/child-transcript.js +57 -2
- package/extensions/dm-subagents/src/shared/completion-owner.js +7 -0
- package/extensions/dm-subagents/src/shared/display-text.js +142 -0
- package/extensions/dm-subagents/src/shared/extension-context.js +17 -0
- package/extensions/dm-subagents/src/shared/file-coalescer.js +9 -0
- package/extensions/dm-subagents/src/shared/file-system-retry.js +56 -0
- package/extensions/dm-subagents/src/shared/fork-context.js +96 -33
- package/extensions/dm-subagents/src/shared/formatters.js +21 -7
- package/extensions/dm-subagents/src/shared/launch-contract.js +94 -0
- package/extensions/dm-subagents/src/shared/model-info.js +10 -5
- package/extensions/dm-subagents/src/shared/node-executable.js +19 -0
- package/extensions/dm-subagents/src/shared/prompt-resources.js +10 -0
- package/extensions/dm-subagents/src/shared/pruned-fork.js +427 -0
- package/extensions/dm-subagents/src/shared/session-file-trust.js +19 -0
- package/extensions/dm-subagents/src/shared/session-tokens.js +14 -3
- package/extensions/dm-subagents/src/shared/settings.js +39 -47
- package/extensions/dm-subagents/src/shared/shortcuts.js +16 -0
- package/extensions/dm-subagents/src/shared/status-format.js +9 -2
- package/extensions/dm-subagents/src/shared/thinking-ceiling.js +41 -0
- package/extensions/dm-subagents/src/shared/types.js +47 -7
- package/extensions/dm-subagents/src/shared/utf8.js +12 -0
- package/extensions/dm-subagents/src/shared/utils.js +151 -131
- package/extensions/dm-subagents/src/shared/watch-strategy.js +3 -0
- package/extensions/dm-subagents/src/shared/workflow-child-permit.js +84 -0
- package/extensions/dm-subagents/src/slash/delegation-adapters.js +274 -0
- package/extensions/dm-subagents/src/slash/delegation-json.js +113 -0
- package/extensions/dm-subagents/src/slash/delegation-request.js +152 -0
- package/extensions/dm-subagents/src/slash/prompt-template-bridge.js +294 -243
- package/extensions/dm-subagents/src/slash/prompt-workflows.js +35 -73
- package/extensions/dm-subagents/src/slash/selector.js +101 -0
- package/extensions/dm-subagents/src/slash/slash-bridge.js +17 -1
- package/extensions/dm-subagents/src/slash/slash-commands.js +722 -732
- package/extensions/dm-subagents/src/slash/slash-live-state.js +37 -19
- package/extensions/dm-subagents/src/slash/subagents-admin.js +410 -0
- package/extensions/dm-subagents/src/tui/fleet-status.js +824 -0
- package/extensions/dm-subagents/src/tui/fleet-transcript.js +479 -0
- package/extensions/dm-subagents/src/tui/fleet.js +1326 -0
- package/extensions/dm-subagents/src/tui/render-helpers.js +22 -0
- package/extensions/dm-subagents/src/tui/render.js +1511 -261
- package/extensions/dm-subagents/src/watchdog/change-signature.js +220 -0
- package/extensions/dm-subagents/src/watchdog/child-status.js +151 -0
- package/extensions/dm-subagents/src/watchdog/emission-guard.js +90 -0
- package/extensions/dm-subagents/src/watchdog/lsp-diagnostics.js +484 -0
- package/extensions/dm-subagents/src/watchdog/model-selection.js +154 -0
- package/extensions/dm-subagents/src/watchdog/permission-arbiter.js +138 -0
- package/extensions/dm-subagents/src/watchdog/register-child.js +112 -0
- package/extensions/dm-subagents/src/watchdog/register-main.js +419 -0
- package/extensions/dm-subagents/src/watchdog/render.js +54 -0
- package/extensions/dm-subagents/src/watchdog/review.js +251 -0
- package/extensions/dm-subagents/src/watchdog/runtime.js +803 -0
- package/extensions/dm-subagents/src/watchdog/scope.js +56 -0
- package/extensions/dm-subagents/src/watchdog/settings.js +515 -0
- package/extensions/dm-subagents/src/watchdog/tool-actions.js +151 -0
- package/extensions/dm-subagents/src/watchdog/turn-delta.js +169 -0
- package/extensions/dm-subagents/src/watchdog/types.js +29 -0
- package/extensions/dm-subagents/src/watchdog/warning-format.js +58 -0
- package/extensions/dm-subagents/src/workflows/chat-progress.js +116 -0
- package/extensions/dm-subagents/src/workflows/host-command.js +227 -0
- package/extensions/dm-subagents/src/workflows/scripted-workflow.js +2011 -0
- package/extensions/dm-subagents/src/workflows/workflow-child-summary.js +116 -0
- package/extensions/dm-subagents/src/workflows/workflow-preflight.js +243 -0
- package/extensions/dm-subagents/src/workflows/workflow-receipt.js +387 -0
- package/extensions/dm-subagents/src/workflows/workflow-settlement.js +189 -0
- package/package.json +4 -3
- package/extensions/dm-fff/package.json +0 -21
- package/extensions/dm-fff/src/index.js +0 -691
- package/extensions/dm-fff/src/query.js +0 -60
- package/extensions/dm-subagents/agents/context-builder.md +0 -46
- package/extensions/dm-subagents/agents/planner.md +0 -55
- package/extensions/dm-subagents/prompts/parallel-context-build.md +0 -55
- package/extensions/dm-subagents/prompts/parallel-handoff-plan.md +0 -61
- package/extensions/dm-subagents/src/runs/background/wait.js +0 -206
- package/extensions/dm-subagents/src/runs/foreground/chain-clarify.js +0 -1013
- package/extensions/dm-subagents/src/runs/foreground/chain-execution.js +0 -981
- package/extensions/dm-subagents/src/runs/shared/turn-budget.js +0 -50
|
@@ -10,8 +10,9 @@ import {
|
|
|
10
10
|
SUBAGENT_RUN_ID_ENV,
|
|
11
11
|
SUBAGENT_SUPERVISOR_CHANNEL_DIR_ENV
|
|
12
12
|
} from "../runs/shared/dm-args.js";
|
|
13
|
-
import { POLL_INTERVAL_MS, TEMP_ROOT_DIR } from "../shared/types.js";
|
|
13
|
+
import { INTERCOM_DETACH_REQUEST_EVENT, POLL_INTERVAL_MS, TEMP_ROOT_DIR } from "../shared/types.js";
|
|
14
14
|
import { writeAtomicJson } from "../shared/atomic-json.js";
|
|
15
|
+
import { shouldUseNativeFsWatch } from "../shared/watch-strategy.js";
|
|
15
16
|
const SUPERVISOR_CHANNEL_ROOT = path.join(TEMP_ROOT_DIR, "supervisor-channels");
|
|
16
17
|
const REQUESTS_DIR = "requests";
|
|
17
18
|
const REPLIES_DIR = "replies";
|
|
@@ -19,6 +20,9 @@ export const NATIVE_SUPERVISOR_TOOL_NAME = "subagent_supervisor";
|
|
|
19
20
|
const MAX_MESSAGE_BYTES = 64 * 1024;
|
|
20
21
|
const DEFAULT_ASK_TIMEOUT_MS = 10 * 60 * 1000;
|
|
21
22
|
const CHANNEL_POLL_MS = Math.min(POLL_INTERVAL_MS, 500);
|
|
23
|
+
const CHANNEL_SAFETY_POLL_MS = 5000;
|
|
24
|
+
const STALE_EMPTY_CHANNEL_AGE_MS = 60 * 1000;
|
|
25
|
+
const STALE_EMPTY_CHANNEL_CLEANUP_INTERVAL_MS = 60 * 1000;
|
|
22
26
|
const ContactSupervisorParamsSchema = Type.Object({
|
|
23
27
|
reason: Type.String({ enum: ["need_decision", "interview_request", "progress_update"] }),
|
|
24
28
|
message: Type.Optional(Type.String()),
|
|
@@ -131,9 +135,8 @@ function delay(ms, signal) {
|
|
|
131
135
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
132
136
|
});
|
|
133
137
|
}
|
|
134
|
-
async function waitForReply(channelDir, requestId, signal) {
|
|
138
|
+
async function waitForReply(channelDir, requestId, deadline, signal) {
|
|
135
139
|
const file = replyPath(channelDir, requestId);
|
|
136
|
-
const deadline = Date.now() + askTimeoutMs();
|
|
137
140
|
while (Date.now() <= deadline) {
|
|
138
141
|
if (signal?.aborted)
|
|
139
142
|
throw new Error("Supervisor request cancelled.");
|
|
@@ -157,11 +160,15 @@ async function sendSupervisorRequest(params, signal) {
|
|
|
157
160
|
ensureSupervisorChannelDir(metadata.channelDir);
|
|
158
161
|
const requestId = randomUUID();
|
|
159
162
|
const expectsReply = params.reason !== "progress_update";
|
|
163
|
+
const createdAt = Date.now();
|
|
164
|
+
const replyDeadline = createdAt + askTimeoutMs();
|
|
165
|
+
const expiresAt = expectsReply ? replyDeadline : undefined;
|
|
160
166
|
const message = formatChildMessage({ ...metadata, reason: params.reason, message: params.message, interview: params.interview });
|
|
161
167
|
const request = {
|
|
162
168
|
type: "subagent.supervisor.request",
|
|
163
169
|
id: requestId,
|
|
164
|
-
createdAt
|
|
170
|
+
createdAt,
|
|
171
|
+
...expiresAt !== undefined ? { expiresAt } : {},
|
|
165
172
|
reason: params.reason,
|
|
166
173
|
message,
|
|
167
174
|
expectsReply,
|
|
@@ -183,65 +190,46 @@ async function sendSupervisorRequest(params, signal) {
|
|
|
183
190
|
details: { delivered: true, requestId, reason: params.reason }
|
|
184
191
|
};
|
|
185
192
|
}
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
193
|
+
try {
|
|
194
|
+
const reply = await waitForReply(metadata.channelDir, requestId, replyDeadline, signal);
|
|
195
|
+
const details = { requestId, reason: params.reason };
|
|
196
|
+
if (params.reason === "interview_request") {
|
|
197
|
+
const structured = parseStructuredReply(reply.message);
|
|
198
|
+
if (structured.error)
|
|
199
|
+
details.structuredReplyParseError = structured.error;
|
|
200
|
+
else
|
|
201
|
+
details.structuredReply = structured.value;
|
|
202
|
+
}
|
|
203
|
+
return {
|
|
204
|
+
content: [{ type: "text", text: `**Reply from supervisor:**
|
|
197
205
|
${reply.message}` }],
|
|
198
|
-
|
|
199
|
-
|
|
206
|
+
details
|
|
207
|
+
};
|
|
208
|
+
} catch (error) {
|
|
209
|
+
removeRequestFile(requestPath(metadata.channelDir, requestId));
|
|
210
|
+
throw error;
|
|
211
|
+
}
|
|
200
212
|
}
|
|
201
|
-
function hasTool(
|
|
213
|
+
function hasTool(dm, name) {
|
|
202
214
|
try {
|
|
203
|
-
return
|
|
215
|
+
return dm.getAllTools?.().some((tool) => tool.name === name) === true;
|
|
204
216
|
} catch {
|
|
205
217
|
return false;
|
|
206
218
|
}
|
|
207
219
|
}
|
|
208
|
-
export function registerNativeSupervisorClient(
|
|
209
|
-
if (!readChildMetadata())
|
|
220
|
+
export function registerNativeSupervisorClient(dm) {
|
|
221
|
+
if (!readChildMetadata() || hasTool(dm, "contact_supervisor"))
|
|
210
222
|
return;
|
|
211
|
-
const
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
};
|
|
222
|
-
pi.registerTool(tool);
|
|
223
|
-
}
|
|
224
|
-
if (includeIntercomFallback && !hasTool(pi, "intercom")) {
|
|
225
|
-
const tool = {
|
|
226
|
-
name: "intercom",
|
|
227
|
-
label: "Intercom",
|
|
228
|
-
description: "Native supervisor-channel intercom fallback for subagents. Prefer contact_supervisor when available.",
|
|
229
|
-
parameters: IntercomParamsSchema,
|
|
230
|
-
async execute(_id, params, signal) {
|
|
231
|
-
const action = params.action;
|
|
232
|
-
if (action === "status")
|
|
233
|
-
return { content: [{ type: "text", text: "Native supervisor channel is active." }], details: { active: true } };
|
|
234
|
-
if (action === "list")
|
|
235
|
-
return { content: [{ type: "text", text: "Supervisor session available through contact_supervisor." }], details: { sessions: [] } };
|
|
236
|
-
if (action === "send")
|
|
237
|
-
return sendSupervisorRequest({ reason: "progress_update", message: params.message ?? "" }, signal);
|
|
238
|
-
if (action === "ask")
|
|
239
|
-
return sendSupervisorRequest({ reason: "need_decision", message: params.message ?? "" }, signal);
|
|
240
|
-
throw new Error("Native child intercom supports status, list, send, and ask. Use parent intercom reply from the supervisor session.");
|
|
241
|
-
}
|
|
242
|
-
};
|
|
243
|
-
pi.registerTool(tool);
|
|
244
|
-
}
|
|
223
|
+
const tool = {
|
|
224
|
+
name: "contact_supervisor",
|
|
225
|
+
label: "Contact Supervisor",
|
|
226
|
+
description: "Contact the parent/supervisor session for a blocking decision, structured interview, or progress update.",
|
|
227
|
+
parameters: ContactSupervisorParamsSchema,
|
|
228
|
+
execute(_id, params, signal) {
|
|
229
|
+
return sendSupervisorRequest(params, signal);
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
dm.registerTool(tool);
|
|
245
233
|
}
|
|
246
234
|
function parseRequestFile(file, channelDir) {
|
|
247
235
|
try {
|
|
@@ -289,6 +277,75 @@ function listRequestFiles() {
|
|
|
289
277
|
}
|
|
290
278
|
return files;
|
|
291
279
|
}
|
|
280
|
+
function readDirectoryEntries(dir) {
|
|
281
|
+
try {
|
|
282
|
+
return fs.readdirSync(dir, { withFileTypes: true });
|
|
283
|
+
} catch (error) {
|
|
284
|
+
if (error.code === "ENOENT")
|
|
285
|
+
return [];
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
function directoryMtimeMs(dir) {
|
|
290
|
+
try {
|
|
291
|
+
return fs.statSync(dir).mtimeMs;
|
|
292
|
+
} catch {
|
|
293
|
+
return 0;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
function removeEmptyDirectory(dir) {
|
|
297
|
+
try {
|
|
298
|
+
fs.rmdirSync(dir);
|
|
299
|
+
return true;
|
|
300
|
+
} catch (error) {
|
|
301
|
+
const code = error.code;
|
|
302
|
+
if (code === "ENOENT")
|
|
303
|
+
return true;
|
|
304
|
+
if (code === "ENOTEMPTY" || code === "EEXIST" || code === "EPERM" || code === "EBUSY")
|
|
305
|
+
return false;
|
|
306
|
+
throw error;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
function removeStaleEmptySupervisorChannel(channelDir, nowMs) {
|
|
310
|
+
const requestsDir = path.join(channelDir, REQUESTS_DIR);
|
|
311
|
+
const repliesDir = path.join(channelDir, REPLIES_DIR);
|
|
312
|
+
const newestKnownMtimeMs = Math.max(directoryMtimeMs(channelDir), directoryMtimeMs(requestsDir), directoryMtimeMs(repliesDir));
|
|
313
|
+
if (nowMs - newestKnownMtimeMs < STALE_EMPTY_CHANNEL_AGE_MS)
|
|
314
|
+
return false;
|
|
315
|
+
const requestEntries = readDirectoryEntries(requestsDir);
|
|
316
|
+
if (!requestEntries || requestEntries.length > 0)
|
|
317
|
+
return false;
|
|
318
|
+
const replyEntries = readDirectoryEntries(repliesDir);
|
|
319
|
+
if (!replyEntries || replyEntries.length > 0)
|
|
320
|
+
return false;
|
|
321
|
+
if (!removeEmptyDirectory(requestsDir))
|
|
322
|
+
return false;
|
|
323
|
+
if (!removeEmptyDirectory(repliesDir))
|
|
324
|
+
return false;
|
|
325
|
+
if (!removeEmptyDirectory(channelDir))
|
|
326
|
+
return false;
|
|
327
|
+
return true;
|
|
328
|
+
}
|
|
329
|
+
function cleanupStaleEmptySupervisorChannels(nowMs = Date.now()) {
|
|
330
|
+
let channelEntries;
|
|
331
|
+
try {
|
|
332
|
+
channelEntries = fs.readdirSync(SUPERVISOR_CHANNEL_ROOT, { withFileTypes: true });
|
|
333
|
+
} catch (error) {
|
|
334
|
+
if (error.code === "ENOENT")
|
|
335
|
+
return 0;
|
|
336
|
+
throw error;
|
|
337
|
+
}
|
|
338
|
+
let removed = 0;
|
|
339
|
+
for (const entry of channelEntries) {
|
|
340
|
+
if (!entry.isDirectory())
|
|
341
|
+
continue;
|
|
342
|
+
try {
|
|
343
|
+
if (removeStaleEmptySupervisorChannel(path.join(SUPERVISOR_CHANNEL_ROOT, entry.name), nowMs))
|
|
344
|
+
removed++;
|
|
345
|
+
} catch {}
|
|
346
|
+
}
|
|
347
|
+
return removed;
|
|
348
|
+
}
|
|
292
349
|
function currentContextSessionId(state, ctx) {
|
|
293
350
|
try {
|
|
294
351
|
const sessionId = ctx.sessionManager.getSessionId();
|
|
@@ -301,6 +358,89 @@ function requestMatchesContext(request, state, ctx) {
|
|
|
301
358
|
const currentSessionId = currentContextSessionId(state, ctx);
|
|
302
359
|
return Boolean(currentSessionId && request.orchestratorSessionId === currentSessionId);
|
|
303
360
|
}
|
|
361
|
+
function rememberedForegroundChild(request, state) {
|
|
362
|
+
const run = state.foregroundRuns?.get(request.runId);
|
|
363
|
+
const child = run?.children.find((candidate) => candidate.index === request.childIndex && candidate.agent === request.agent) ?? run?.children[request.childIndex];
|
|
364
|
+
return run && child ? { run, child } : undefined;
|
|
365
|
+
}
|
|
366
|
+
function markForegroundSupervisorAttention(request, state) {
|
|
367
|
+
const remembered = rememberedForegroundChild(request, state);
|
|
368
|
+
if (!remembered || remembered.child.status !== "detached")
|
|
369
|
+
return;
|
|
370
|
+
const updatedAt = Date.now();
|
|
371
|
+
remembered.run.updatedAt = updatedAt;
|
|
372
|
+
remembered.child.activityState = "needs_attention";
|
|
373
|
+
remembered.child.lastActivityAt = request.createdAt;
|
|
374
|
+
remembered.child.currentTool = "contact_supervisor";
|
|
375
|
+
remembered.child.currentToolStartedAt = request.createdAt;
|
|
376
|
+
remembered.child.updatedAt = updatedAt;
|
|
377
|
+
}
|
|
378
|
+
function clearForegroundSupervisorAttention(request, pending, state) {
|
|
379
|
+
if ([...pending.values()].some((candidate) => candidate.expectsReply && candidate.runId === request.runId && candidate.agent === request.agent && candidate.childIndex === request.childIndex))
|
|
380
|
+
return;
|
|
381
|
+
const remembered = rememberedForegroundChild(request, state);
|
|
382
|
+
if (!remembered || remembered.child.status !== "detached")
|
|
383
|
+
return;
|
|
384
|
+
const updatedAt = Date.now();
|
|
385
|
+
remembered.run.updatedAt = updatedAt;
|
|
386
|
+
remembered.child.activityState = undefined;
|
|
387
|
+
remembered.child.lastActivityAt = updatedAt;
|
|
388
|
+
remembered.child.currentTool = undefined;
|
|
389
|
+
remembered.child.currentToolStartedAt = undefined;
|
|
390
|
+
remembered.child.updatedAt = updatedAt;
|
|
391
|
+
}
|
|
392
|
+
function removeRequestFile(file) {
|
|
393
|
+
try {
|
|
394
|
+
fs.rmSync(file, { force: true });
|
|
395
|
+
} catch {}
|
|
396
|
+
}
|
|
397
|
+
function requestExpiresAt(request, now) {
|
|
398
|
+
const expiresAt = request.expiresAt;
|
|
399
|
+
if (typeof expiresAt === "number" && Number.isFinite(expiresAt))
|
|
400
|
+
return expiresAt;
|
|
401
|
+
return Number.isFinite(request.createdAt) ? request.createdAt + askTimeoutMs() : now;
|
|
402
|
+
}
|
|
403
|
+
function requestRunInactive(request, state) {
|
|
404
|
+
if (state.foregroundControls.has(request.runId))
|
|
405
|
+
return false;
|
|
406
|
+
const foreground = rememberedForegroundChild(request, state);
|
|
407
|
+
if (foreground)
|
|
408
|
+
return foreground.child.status !== "detached";
|
|
409
|
+
const asyncJob = state.asyncJobs.get(request.runId);
|
|
410
|
+
if (!asyncJob)
|
|
411
|
+
return false;
|
|
412
|
+
if (asyncJob.status === "complete" || asyncJob.status === "failed" || asyncJob.status === "paused")
|
|
413
|
+
return true;
|
|
414
|
+
const stepStatus = asyncJob.steps?.[request.childIndex]?.status;
|
|
415
|
+
return stepStatus === "complete" || stepStatus === "completed" || stepStatus === "failed" || stepStatus === "paused";
|
|
416
|
+
}
|
|
417
|
+
function requestLifecycle(request, state, ctx, now) {
|
|
418
|
+
if (ctx && !requestMatchesContext(request, state, ctx))
|
|
419
|
+
return "wrong-session";
|
|
420
|
+
if (!fs.existsSync(request.requestFile))
|
|
421
|
+
return "missing";
|
|
422
|
+
if (request.expectsReply && fs.existsSync(replyPath(request.channelDir, request.id)))
|
|
423
|
+
return "resolved";
|
|
424
|
+
if (request.expectsReply && now > requestExpiresAt(request, now))
|
|
425
|
+
return "expired";
|
|
426
|
+
if (request.expectsReply && requestRunInactive(request, state))
|
|
427
|
+
return "inactive";
|
|
428
|
+
return "pending";
|
|
429
|
+
}
|
|
430
|
+
function cleanupRequestLifecycle(request, lifecycle) {
|
|
431
|
+
if (lifecycle === "resolved" || lifecycle === "expired" || lifecycle === "inactive")
|
|
432
|
+
removeRequestFile(request.requestFile);
|
|
433
|
+
}
|
|
434
|
+
function refreshPendingRequests(pending, state, ctx) {
|
|
435
|
+
const now = Date.now();
|
|
436
|
+
for (const request of pending.values()) {
|
|
437
|
+
const lifecycle = requestLifecycle(request, state, ctx, now);
|
|
438
|
+
if (lifecycle === "pending")
|
|
439
|
+
continue;
|
|
440
|
+
pending.delete(request.id);
|
|
441
|
+
cleanupRequestLifecycle(request, lifecycle);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
304
444
|
function formatPendingLine(request) {
|
|
305
445
|
const replyHint = request.expectsReply ? ` Reply: ${NATIVE_SUPERVISOR_TOOL_NAME}({ action: "reply", replyTo: "${request.id}", message: "..." })` : "";
|
|
306
446
|
return `- ${request.id}: ${request.agent} [${request.runId}#${request.childIndex}] ${request.reason}.${replyHint}`;
|
|
@@ -323,9 +463,7 @@ function writeReply(request, message) {
|
|
|
323
463
|
message: message.trim()
|
|
324
464
|
};
|
|
325
465
|
writeAtomicJson(replyPath(request.channelDir, request.id), reply);
|
|
326
|
-
|
|
327
|
-
fs.rmSync(request.requestFile, { force: true });
|
|
328
|
-
} catch {}
|
|
466
|
+
removeRequestFile(request.requestFile);
|
|
329
467
|
}
|
|
330
468
|
function resolvePendingRequest(pending, params) {
|
|
331
469
|
if (params.replyTo) {
|
|
@@ -359,13 +497,14 @@ function publicPendingRequests(pending) {
|
|
|
359
497
|
expectsReply: request.expectsReply
|
|
360
498
|
}));
|
|
361
499
|
}
|
|
362
|
-
function
|
|
500
|
+
function buildParentSupervisorTool(pending, state) {
|
|
363
501
|
return {
|
|
364
|
-
name,
|
|
365
|
-
label:
|
|
366
|
-
description:
|
|
502
|
+
name: NATIVE_SUPERVISOR_TOOL_NAME,
|
|
503
|
+
label: "Subagent Supervisor",
|
|
504
|
+
description: "Native dm-subagents supervisor channel. Use reply/pending/status to answer child subagent requests without overriding dm-intercom.",
|
|
367
505
|
parameters: IntercomParamsSchema,
|
|
368
506
|
async execute(_id, params) {
|
|
507
|
+
refreshPendingRequests(pending, state, state.lastUiContext ?? undefined);
|
|
369
508
|
const input = params;
|
|
370
509
|
if (input.action === "status") {
|
|
371
510
|
return { content: [{ type: "text", text: `Native supervisor channel active. Pending replies: ${pending.size}.` }], details: { active: true, pending: pending.size, root: SUPERVISOR_CHANNEL_ROOT } };
|
|
@@ -379,44 +518,77 @@ function buildParentIntercomTool(pending, name = "intercom") {
|
|
|
379
518
|
const request = resolvePendingRequest(pending, input);
|
|
380
519
|
writeReply(request, input.message ?? "");
|
|
381
520
|
pending.delete(request.id);
|
|
521
|
+
clearForegroundSupervisorAttention(request, pending, state);
|
|
382
522
|
return { content: [{ type: "text", text: `Replied to supervisor request ${request.id}.` }], details: { replyTo: request.id, runId: request.runId, agent: request.agent } };
|
|
383
523
|
}
|
|
384
524
|
if (input.action === "send" || input.action === "ask") {
|
|
385
|
-
throw new Error("
|
|
525
|
+
throw new Error("The native subagent supervisor handles replies only. Child agents initiate asks with contact_supervisor.");
|
|
386
526
|
}
|
|
387
|
-
throw new Error(`Unsupported
|
|
527
|
+
throw new Error(`Unsupported supervisor action: ${input.action}`);
|
|
388
528
|
}
|
|
389
529
|
};
|
|
390
530
|
}
|
|
391
|
-
export function createNativeSupervisorChannel(
|
|
531
|
+
export function createNativeSupervisorChannel(dm, state, deps = {}) {
|
|
532
|
+
const watch = deps.watch ?? fs.watch;
|
|
533
|
+
const timers = deps.timers ?? globalThis;
|
|
392
534
|
const pending = new Map;
|
|
393
535
|
const seenFiles = new Set;
|
|
536
|
+
const requestWatchers = new Map;
|
|
537
|
+
let rootWatcher;
|
|
394
538
|
let poller;
|
|
539
|
+
let safetyPoller;
|
|
540
|
+
let deferredWatcherRefresh;
|
|
541
|
+
let started = false;
|
|
542
|
+
let lastStaleCleanupAt = 0;
|
|
543
|
+
const platform = deps.platform ?? process.platform;
|
|
544
|
+
const useNativeWatcher = () => shouldUseNativeFsWatch("supervisor-channel", platform) && platform !== "win32";
|
|
545
|
+
const hasTransportDemand = () => {
|
|
546
|
+
if (pending.size > 0)
|
|
547
|
+
return true;
|
|
548
|
+
if (state.foregroundControls.size > 0)
|
|
549
|
+
return true;
|
|
550
|
+
return [...state.asyncJobs.values()].some((job) => job.status === "queued" || job.status === "running");
|
|
551
|
+
};
|
|
395
552
|
const registerParentTools = () => {
|
|
396
|
-
if (!hasTool(
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
553
|
+
if (!hasTool(dm, NATIVE_SUPERVISOR_TOOL_NAME))
|
|
554
|
+
dm.registerTool(buildParentSupervisorTool(pending, state));
|
|
555
|
+
};
|
|
556
|
+
const cleanupStaleChannelsIfDue = () => {
|
|
557
|
+
const nowMs = Date.now();
|
|
558
|
+
if (nowMs - lastStaleCleanupAt < STALE_EMPTY_CHANNEL_CLEANUP_INTERVAL_MS)
|
|
559
|
+
return;
|
|
560
|
+
lastStaleCleanupAt = nowMs;
|
|
561
|
+
try {
|
|
562
|
+
cleanupStaleEmptySupervisorChannels(nowMs);
|
|
563
|
+
} catch {}
|
|
400
564
|
};
|
|
401
565
|
const poll = () => {
|
|
566
|
+
cleanupStaleChannelsIfDue();
|
|
402
567
|
const ctx = state.lastUiContext;
|
|
403
568
|
if (!ctx)
|
|
404
569
|
return;
|
|
570
|
+
refreshPendingRequests(pending, state, ctx);
|
|
571
|
+
const now = Date.now();
|
|
405
572
|
for (const { channelDir, file } of listRequestFiles()) {
|
|
406
573
|
if (seenFiles.has(file))
|
|
407
574
|
continue;
|
|
408
575
|
const request = parseRequestFile(file, channelDir);
|
|
409
576
|
if (!request || !requestMatchesContext(request, state, ctx))
|
|
410
577
|
continue;
|
|
578
|
+
const lifecycle = requestLifecycle(request, state, undefined, now);
|
|
579
|
+
if (lifecycle !== "pending") {
|
|
580
|
+
seenFiles.add(file);
|
|
581
|
+
cleanupRequestLifecycle(request, lifecycle);
|
|
582
|
+
continue;
|
|
583
|
+
}
|
|
411
584
|
seenFiles.add(file);
|
|
412
|
-
if (request.expectsReply)
|
|
585
|
+
if (request.expectsReply) {
|
|
413
586
|
pending.set(request.id, request);
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
} catch {}
|
|
587
|
+
markForegroundSupervisorAttention(request, state);
|
|
588
|
+
} else {
|
|
589
|
+
removeRequestFile(request.requestFile);
|
|
418
590
|
}
|
|
419
|
-
|
|
591
|
+
dm.sendMessage({
|
|
420
592
|
customType: "subagent_supervisor_request",
|
|
421
593
|
content: requestVisibleText(request),
|
|
422
594
|
display: true,
|
|
@@ -428,22 +600,142 @@ export function createNativeSupervisorChannel(pi, state) {
|
|
|
428
600
|
agent: request.agent,
|
|
429
601
|
childIndex: request.childIndex
|
|
430
602
|
}
|
|
603
|
+
}, { triggerTurn: true });
|
|
604
|
+
if (request.expectsReply) {
|
|
605
|
+
dm.events?.emit(INTERCOM_DETACH_REQUEST_EVENT, {
|
|
606
|
+
requestId: request.id,
|
|
607
|
+
runId: request.runId,
|
|
608
|
+
agent: request.agent,
|
|
609
|
+
childIndex: request.childIndex
|
|
610
|
+
});
|
|
611
|
+
if (pending.has(request.id))
|
|
612
|
+
markForegroundSupervisorAttention(request, state);
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
};
|
|
616
|
+
const startPolling = () => {
|
|
617
|
+
if (poller)
|
|
618
|
+
return;
|
|
619
|
+
poller = timers.setInterval(() => {
|
|
620
|
+
poll();
|
|
621
|
+
if (!useNativeWatcher() && platform === "darwin" && !hasTransportDemand()) {
|
|
622
|
+
if (poller)
|
|
623
|
+
timers.clearInterval(poller);
|
|
624
|
+
poller = undefined;
|
|
625
|
+
}
|
|
626
|
+
}, CHANNEL_POLL_MS);
|
|
627
|
+
poller.unref?.();
|
|
628
|
+
};
|
|
629
|
+
const startSafetyPolling = () => {
|
|
630
|
+
if (safetyPoller)
|
|
631
|
+
return;
|
|
632
|
+
safetyPoller = timers.setInterval(() => {
|
|
633
|
+
watchExistingRequestDirs();
|
|
634
|
+
poll();
|
|
635
|
+
}, CHANNEL_SAFETY_POLL_MS);
|
|
636
|
+
safetyPoller.unref?.();
|
|
637
|
+
};
|
|
638
|
+
const watchRequestDir = (requestsDir) => {
|
|
639
|
+
if (requestWatchers.has(requestsDir))
|
|
640
|
+
return;
|
|
641
|
+
try {
|
|
642
|
+
const watcher = watch(requestsDir, () => poll());
|
|
643
|
+
watcher.on("error", () => {
|
|
644
|
+
try {
|
|
645
|
+
watcher.close();
|
|
646
|
+
} catch {}
|
|
647
|
+
requestWatchers.delete(requestsDir);
|
|
648
|
+
startPolling();
|
|
431
649
|
});
|
|
650
|
+
watcher.unref?.();
|
|
651
|
+
requestWatchers.set(requestsDir, watcher);
|
|
652
|
+
} catch (error) {
|
|
653
|
+
if (error.code !== "ENOENT")
|
|
654
|
+
startPolling();
|
|
432
655
|
}
|
|
433
656
|
};
|
|
657
|
+
const watchExistingRequestDirs = () => {
|
|
658
|
+
let channelEntries;
|
|
659
|
+
try {
|
|
660
|
+
channelEntries = fs.readdirSync(SUPERVISOR_CHANNEL_ROOT, { withFileTypes: true });
|
|
661
|
+
} catch (error) {
|
|
662
|
+
if (error.code === "ENOENT")
|
|
663
|
+
return;
|
|
664
|
+
startPolling();
|
|
665
|
+
return;
|
|
666
|
+
}
|
|
667
|
+
for (const entry of channelEntries) {
|
|
668
|
+
if (entry.isDirectory())
|
|
669
|
+
watchRequestDir(path.join(SUPERVISOR_CHANNEL_ROOT, entry.name, REQUESTS_DIR));
|
|
670
|
+
}
|
|
671
|
+
};
|
|
672
|
+
const scheduleWatcherRefresh = () => {
|
|
673
|
+
if (deferredWatcherRefresh)
|
|
674
|
+
return;
|
|
675
|
+
deferredWatcherRefresh = timers.setImmediate(() => {
|
|
676
|
+
deferredWatcherRefresh = undefined;
|
|
677
|
+
if (!started)
|
|
678
|
+
return;
|
|
679
|
+
watchExistingRequestDirs();
|
|
680
|
+
poll();
|
|
681
|
+
});
|
|
682
|
+
deferredWatcherRefresh.unref?.();
|
|
683
|
+
};
|
|
434
684
|
return {
|
|
685
|
+
activateTransport: () => {
|
|
686
|
+
if (!started)
|
|
687
|
+
return;
|
|
688
|
+
poll();
|
|
689
|
+
if (!useNativeWatcher() && hasTransportDemand())
|
|
690
|
+
startPolling();
|
|
691
|
+
},
|
|
435
692
|
start: () => {
|
|
436
|
-
if (
|
|
693
|
+
if (started)
|
|
437
694
|
return;
|
|
695
|
+
started = true;
|
|
438
696
|
registerParentTools();
|
|
439
697
|
poll();
|
|
440
|
-
|
|
441
|
-
|
|
698
|
+
try {
|
|
699
|
+
fs.mkdirSync(SUPERVISOR_CHANNEL_ROOT, { recursive: true });
|
|
700
|
+
if (!useNativeWatcher()) {
|
|
701
|
+
if (platform === "win32")
|
|
702
|
+
startPolling();
|
|
703
|
+
return;
|
|
704
|
+
}
|
|
705
|
+
watchExistingRequestDirs();
|
|
706
|
+
rootWatcher = watch(SUPERVISOR_CHANNEL_ROOT, () => {
|
|
707
|
+
watchExistingRequestDirs();
|
|
708
|
+
poll();
|
|
709
|
+
scheduleWatcherRefresh();
|
|
710
|
+
});
|
|
711
|
+
rootWatcher.on("error", startPolling);
|
|
712
|
+
startSafetyPolling();
|
|
713
|
+
scheduleWatcherRefresh();
|
|
714
|
+
} catch {
|
|
715
|
+
startPolling();
|
|
716
|
+
}
|
|
442
717
|
},
|
|
443
718
|
dispose: () => {
|
|
719
|
+
started = false;
|
|
720
|
+
try {
|
|
721
|
+
rootWatcher?.close();
|
|
722
|
+
} catch {}
|
|
723
|
+
rootWatcher = undefined;
|
|
724
|
+
for (const watcher of requestWatchers.values()) {
|
|
725
|
+
try {
|
|
726
|
+
watcher.close();
|
|
727
|
+
} catch {}
|
|
728
|
+
}
|
|
729
|
+
requestWatchers.clear();
|
|
444
730
|
if (poller)
|
|
445
|
-
clearInterval(poller);
|
|
731
|
+
timers.clearInterval(poller);
|
|
446
732
|
poller = undefined;
|
|
733
|
+
if (safetyPoller)
|
|
734
|
+
timers.clearInterval(safetyPoller);
|
|
735
|
+
safetyPoller = undefined;
|
|
736
|
+
if (deferredWatcherRefresh)
|
|
737
|
+
timers.clearImmediate(deferredWatcherRefresh);
|
|
738
|
+
deferredWatcherRefresh = undefined;
|
|
447
739
|
pending.clear();
|
|
448
740
|
seenFiles.clear();
|
|
449
741
|
},
|