@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
|
@@ -1,13 +1,36 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
1
2
|
import * as fs from "node:fs";
|
|
2
3
|
import * as path from "node:path";
|
|
3
4
|
import { registerNativeSupervisorClient } from "../../intercom/native-supervisor-channel.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
5
|
+
import { shouldUseNativeFsWatch } from "../../shared/watch-strategy.js";
|
|
6
|
+
import { decodePermissionRules, permissionDecision, PERMISSION_AUDIT_PATH_ENV, PERMISSION_POLICY_ENV } from "./permissions.js";
|
|
7
|
+
import { consumeSteerRequestsFromDir, MAX_STEER_QUEUE_SIZE, steerAckPathFromDir, writeSteerAckAt, writeSteerCapabilityAt, writeSteerRequestToDir } from "../background/control-channel.js";
|
|
8
|
+
import { SUBAGENT_CHILD_AGENT_ENV, SUBAGENT_CHILD_INDEX_ENV, SUBAGENT_FANOUT_CHILD_ENV, SUBAGENT_FORK_CACHE_KEY_ENV, SUBAGENT_INHERIT_GLOBAL_CONTEXT_ENV, SUBAGENT_STEER_ACK_DIR_ENV, SUBAGENT_STEER_CAPABILITY_ENV, SUBAGENT_STEER_INBOX_ENV } from "./dm-args.js";
|
|
9
|
+
import { RUNTIME_EXTENSION_ACK_EVENT, RUNTIME_EXTENSION_ACK_PATH_ENV, isRuntimeAcknowledgedExtensionId, writeRuntimeAcknowledgedExtensions } from "./runtime-acknowledged-extensions.js";
|
|
10
|
+
import { createStructuredOutputToolParameters, STRUCTURED_OUTPUT_ACCEPTANCE_CAPTURE_ENV, STRUCTURED_OUTPUT_CAPTURE_ENV, STRUCTURED_OUTPUT_SCHEMA_ENV, validateStructuredOutputValue } from "./structured-output.js";
|
|
11
|
+
import {
|
|
12
|
+
CHILD_TOOL_DIAGNOSTIC_PATH_ENV,
|
|
13
|
+
formatChildToolDiagnostic,
|
|
14
|
+
MCP_DIRECT_CHILD_TOOLS_ENV,
|
|
15
|
+
REQUIRED_CHILD_TOOLS_ENV,
|
|
16
|
+
writeChildToolDiagnostic
|
|
17
|
+
} from "./tool-availability.js";
|
|
18
|
+
import { TOOL_BUDGET_ENV, TOOL_BUDGET_ZERO_AUTH_ENV, decodeToolBudgetEnv, shouldBlockToolForBudget, toolBudgetBlockedMessage, toolBudgetSoftNudge } from "./tool-budget.js";
|
|
19
|
+
import { resolveCurrentSessionId } from "../../shared/session-identity.js";
|
|
20
|
+
import { getAgentDir, resolveWatchPath } from "../../shared/utils.js";
|
|
21
|
+
import { registerChildWatchdog } from "../../watchdog/register-child.js";
|
|
22
|
+
import { CHILD_WATCHDOG_CONFIG_ENV, decodeChildWatchdogConfig } from "../../watchdog/child-status.js";
|
|
23
|
+
import { requestWatchdogPermission } from "../../watchdog/permission-arbiter.js";
|
|
24
|
+
import { SUBAGENT_WATCHDOG_WARNING_TYPE } from "../../watchdog/types.js";
|
|
25
|
+
import { resolveWaitToolConfig } from "../background/wait-config.js";
|
|
26
|
+
import { registerWaitTool } from "../background/wait-tool.js";
|
|
27
|
+
import { drainOutstandingWork } from "../background/auto-drain.js";
|
|
8
28
|
const SUBAGENT_INHERIT_PROJECT_CONTEXT_ENV = "DM_SUBAGENT_INHERIT_PROJECT_CONTEXT";
|
|
9
29
|
const SUBAGENT_INHERIT_SKILLS_ENV = "DM_SUBAGENT_INHERIT_SKILLS";
|
|
10
30
|
export const SUBAGENT_INTERCOM_SESSION_NAME_ENV = "DM_SUBAGENT_INTERCOM_SESSION_NAME";
|
|
31
|
+
export const SUBAGENT_SESSION_NAME_ENV = "DM_SUBAGENT_SESSION_NAME";
|
|
32
|
+
const STEERING_LEGACY_SETTLE_FALLBACK_MS = 1000;
|
|
33
|
+
const STEERING_SAFETY_POLL_INTERVAL_MS = 5000;
|
|
11
34
|
const STRUCTURED_OUTPUT_INSTRUCTIONS = [
|
|
12
35
|
"This subagent step has a strict structured output contract.",
|
|
13
36
|
"Your final action must be to call the `structured_output` tool with JSON matching the provided schema.",
|
|
@@ -41,7 +64,12 @@ const PARENT_ONLY_CUSTOM_MESSAGE_TYPES = new Set([
|
|
|
41
64
|
"subagent-control-notice"
|
|
42
65
|
]);
|
|
43
66
|
const SUBAGENT_ORCHESTRATION_SKILL_NAME_PATTERN = /<name>\s*dm-subagents\s*<\/name>/;
|
|
44
|
-
const
|
|
67
|
+
const PROJECT_CONTEXT_XML_HEADER = `
|
|
68
|
+
|
|
69
|
+
<project_context>
|
|
70
|
+
|
|
71
|
+
`;
|
|
72
|
+
const PROJECT_CONTEXT_LEGACY_HEADER = `
|
|
45
73
|
|
|
46
74
|
# Project Context
|
|
47
75
|
|
|
@@ -59,6 +87,66 @@ function readBooleanEnv(name) {
|
|
|
59
87
|
return;
|
|
60
88
|
return value !== "0";
|
|
61
89
|
}
|
|
90
|
+
function readRequiredChildTools() {
|
|
91
|
+
const encoded = process.env[REQUIRED_CHILD_TOOLS_ENV]?.trim();
|
|
92
|
+
if (!encoded)
|
|
93
|
+
return;
|
|
94
|
+
const required = JSON.parse(encoded);
|
|
95
|
+
if (!Array.isArray(required) || required.some((name) => typeof name !== "string" || !name)) {
|
|
96
|
+
throw new Error(`Invalid ${REQUIRED_CHILD_TOOLS_ENV} payload.`);
|
|
97
|
+
}
|
|
98
|
+
return required;
|
|
99
|
+
}
|
|
100
|
+
function readMcpDirectChildTools() {
|
|
101
|
+
const encoded = process.env[MCP_DIRECT_CHILD_TOOLS_ENV]?.trim();
|
|
102
|
+
if (!encoded)
|
|
103
|
+
return;
|
|
104
|
+
try {
|
|
105
|
+
const tools = JSON.parse(encoded);
|
|
106
|
+
if (!Array.isArray(tools) || tools.some((name) => typeof name !== "string" || !name))
|
|
107
|
+
return;
|
|
108
|
+
return tools;
|
|
109
|
+
} catch {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
function refreshChildToolDiagnostic(dm) {
|
|
114
|
+
const filePath = process.env[CHILD_TOOL_DIAGNOSTIC_PATH_ENV]?.trim();
|
|
115
|
+
const required = readRequiredChildTools();
|
|
116
|
+
if (!filePath || !required)
|
|
117
|
+
return;
|
|
118
|
+
const available = dm.getAllTools().map((tool) => tool.name);
|
|
119
|
+
return writeChildToolDiagnostic(filePath, required, available, process.env[SUBAGENT_CHILD_AGENT_ENV]?.trim(), readMcpDirectChildTools());
|
|
120
|
+
}
|
|
121
|
+
function registerRuntimeExtensionAcknowledgements(dm) {
|
|
122
|
+
const outputPath = process.env[RUNTIME_EXTENSION_ACK_PATH_ENV]?.trim();
|
|
123
|
+
if (!outputPath)
|
|
124
|
+
return;
|
|
125
|
+
const ids = [];
|
|
126
|
+
let finalized = false;
|
|
127
|
+
const acknowledge = (payload) => {
|
|
128
|
+
if (finalized || !payload || typeof payload !== "object")
|
|
129
|
+
return;
|
|
130
|
+
const id = payload.id;
|
|
131
|
+
if (isRuntimeAcknowledgedExtensionId(id))
|
|
132
|
+
ids.push(id);
|
|
133
|
+
return;
|
|
134
|
+
};
|
|
135
|
+
const finalize = () => {
|
|
136
|
+
if (finalized)
|
|
137
|
+
return;
|
|
138
|
+
finalized = true;
|
|
139
|
+
writeRuntimeAcknowledgedExtensions(outputPath, ids);
|
|
140
|
+
return;
|
|
141
|
+
};
|
|
142
|
+
try {
|
|
143
|
+
const events = dm.events;
|
|
144
|
+
events?.on?.(RUNTIME_EXTENSION_ACK_EVENT, acknowledge);
|
|
145
|
+
const onRuntimeEvent = dm.on;
|
|
146
|
+
onRuntimeEvent("agent_end", finalize);
|
|
147
|
+
onRuntimeEvent("session_shutdown", finalize);
|
|
148
|
+
} catch {}
|
|
149
|
+
}
|
|
62
150
|
function findSectionEnd(prompt, startIndex, nextHeaders) {
|
|
63
151
|
let endIndex = prompt.length;
|
|
64
152
|
for (const header of nextHeaders) {
|
|
@@ -70,11 +158,71 @@ function findSectionEnd(prompt, startIndex, nextHeaders) {
|
|
|
70
158
|
return endIndex;
|
|
71
159
|
}
|
|
72
160
|
export function stripProjectContext(prompt) {
|
|
73
|
-
const
|
|
74
|
-
if (
|
|
161
|
+
const xmlStartIndex = prompt.indexOf(PROJECT_CONTEXT_XML_HEADER);
|
|
162
|
+
if (xmlStartIndex !== -1) {
|
|
163
|
+
const closingTag = "</project_context>";
|
|
164
|
+
const closingIndex = prompt.indexOf(closingTag, xmlStartIndex + PROJECT_CONTEXT_XML_HEADER.length);
|
|
165
|
+
if (closingIndex !== -1) {
|
|
166
|
+
return `${prompt.slice(0, xmlStartIndex)}${prompt.slice(closingIndex + closingTag.length)}`;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
const legacyStartIndex = prompt.indexOf(PROJECT_CONTEXT_LEGACY_HEADER);
|
|
170
|
+
if (legacyStartIndex === -1)
|
|
75
171
|
return prompt;
|
|
76
|
-
const endIndex = findSectionEnd(prompt,
|
|
77
|
-
return `${prompt.slice(0,
|
|
172
|
+
const endIndex = findSectionEnd(prompt, legacyStartIndex + PROJECT_CONTEXT_LEGACY_HEADER.length, [SKILLS_HEADER, DATE_HEADER]);
|
|
173
|
+
return `${prompt.slice(0, legacyStartIndex)}${prompt.slice(endIndex)}`;
|
|
174
|
+
}
|
|
175
|
+
const GLOBAL_CONTEXT_FILE_NAMES = new Set(["agents.md", "agents.override.md", "claude.md"]);
|
|
176
|
+
function canonicalDirectory(dir) {
|
|
177
|
+
try {
|
|
178
|
+
return fs.realpathSync(dir);
|
|
179
|
+
} catch {
|
|
180
|
+
return path.resolve(dir);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
function expandContextPath(filePath) {
|
|
184
|
+
const home = process.env.HOME ?? process.env.USERPROFILE;
|
|
185
|
+
return filePath === "~" ? home ?? filePath : /^~[\\/]/.test(filePath) ? path.join(home ?? "~", filePath.slice(2)) : filePath;
|
|
186
|
+
}
|
|
187
|
+
function isContextFilePath(filePath) {
|
|
188
|
+
return GLOBAL_CONTEXT_FILE_NAMES.has(path.basename(expandContextPath(filePath)).toLowerCase());
|
|
189
|
+
}
|
|
190
|
+
function isGlobalContextFile(filePath) {
|
|
191
|
+
const expanded = expandContextPath(filePath);
|
|
192
|
+
if (!isContextFilePath(filePath))
|
|
193
|
+
return false;
|
|
194
|
+
return canonicalDirectory(path.dirname(expanded)) === canonicalDirectory(getAgentDir());
|
|
195
|
+
}
|
|
196
|
+
function stripGlobalInstructionsFromXmlContext(context) {
|
|
197
|
+
const block = /<project_instructions\s+path=(["'])(.*?)\1\s*>[\s\S]*?<\/project_instructions>\s*/gi;
|
|
198
|
+
return context.replace(block, (match, _quote, filePath) => isGlobalContextFile(filePath) ? "" : match);
|
|
199
|
+
}
|
|
200
|
+
function stripGlobalInstructionsFromLegacyContext(context) {
|
|
201
|
+
const sections = [...context.matchAll(/^## ([^\r\n]+)(?:\r?\n|$)/gm)].filter((match) => isContextFilePath(match[1].trim()));
|
|
202
|
+
let rewritten = "";
|
|
203
|
+
let cursor = 0;
|
|
204
|
+
for (let index = 0;index < sections.length; index++) {
|
|
205
|
+
const section = sections[index];
|
|
206
|
+
const start = section.index;
|
|
207
|
+
const end = sections[index + 1]?.index ?? context.length;
|
|
208
|
+
rewritten += context.slice(cursor, start);
|
|
209
|
+
if (!isGlobalContextFile(section[1].trim()))
|
|
210
|
+
rewritten += context.slice(start, end);
|
|
211
|
+
cursor = end;
|
|
212
|
+
}
|
|
213
|
+
return `${rewritten}${context.slice(cursor)}`;
|
|
214
|
+
}
|
|
215
|
+
export function stripGlobalContext(prompt) {
|
|
216
|
+
const rewrittenXml = prompt.replace(/<project_context>[\s\S]*?<\/project_context>/gi, (context) => {
|
|
217
|
+
const rewritten = stripGlobalInstructionsFromXmlContext(context);
|
|
218
|
+
return /<project_instructions\b/i.test(rewritten) ? rewritten : "";
|
|
219
|
+
});
|
|
220
|
+
const legacyStartIndex = rewrittenXml.indexOf(PROJECT_CONTEXT_LEGACY_HEADER);
|
|
221
|
+
if (legacyStartIndex === -1)
|
|
222
|
+
return rewrittenXml;
|
|
223
|
+
const legacyEndIndex = findSectionEnd(rewrittenXml, legacyStartIndex + PROJECT_CONTEXT_LEGACY_HEADER.length, [SKILLS_HEADER, DATE_HEADER]);
|
|
224
|
+
const legacyContext = rewrittenXml.slice(legacyStartIndex, legacyEndIndex);
|
|
225
|
+
return `${rewrittenXml.slice(0, legacyStartIndex)}${stripGlobalInstructionsFromLegacyContext(legacyContext)}${rewrittenXml.slice(legacyEndIndex)}`;
|
|
78
226
|
}
|
|
79
227
|
export function stripInheritedSkills(prompt) {
|
|
80
228
|
const startIndex = prompt.indexOf(SKILLS_HEADER);
|
|
@@ -100,6 +248,9 @@ export function rewriteSubagentPrompt(prompt, options) {
|
|
|
100
248
|
if (!options.inheritProjectContext) {
|
|
101
249
|
rewritten = stripProjectContext(rewritten);
|
|
102
250
|
}
|
|
251
|
+
if (!options.inheritGlobalContext) {
|
|
252
|
+
rewritten = stripGlobalContext(rewritten);
|
|
253
|
+
}
|
|
103
254
|
if (!options.inheritSkills) {
|
|
104
255
|
rewritten = stripInheritedSkills(rewritten);
|
|
105
256
|
}
|
|
@@ -115,7 +266,11 @@ ${rewritten}`;
|
|
|
115
266
|
}
|
|
116
267
|
function isParentOnlySubagentMessage(message) {
|
|
117
268
|
const m = message;
|
|
118
|
-
|
|
269
|
+
if (m?.role !== "custom" || typeof m.customType !== "string")
|
|
270
|
+
return false;
|
|
271
|
+
if (m.customType === SUBAGENT_WATCHDOG_WARNING_TYPE)
|
|
272
|
+
return true;
|
|
273
|
+
return PARENT_ONLY_CUSTOM_MESSAGE_TYPES.has(m.customType);
|
|
119
274
|
}
|
|
120
275
|
function isSubagentToolResultMessage(message) {
|
|
121
276
|
const m = message;
|
|
@@ -125,6 +280,62 @@ function isSubagentToolCallBlock(block) {
|
|
|
125
280
|
const b = block;
|
|
126
281
|
return b?.type === "toolCall" && b.name === "subagent";
|
|
127
282
|
}
|
|
283
|
+
const PORTABLE_TOOL_ID_PATTERN = /^[a-zA-Z0-9_-]+$/;
|
|
284
|
+
const MAX_PORTABLE_TOOL_ID_LENGTH = 64;
|
|
285
|
+
const COMPOSITE_TOOL_ID_APIS = new Set([
|
|
286
|
+
"azure-openai-responses",
|
|
287
|
+
"cursor-native",
|
|
288
|
+
"openai-completions",
|
|
289
|
+
"openai-responses"
|
|
290
|
+
]);
|
|
291
|
+
const PROMPT_CACHE_KEY_APIS = new Set([
|
|
292
|
+
"azure-openai-responses",
|
|
293
|
+
"openai-codex-responses",
|
|
294
|
+
"openai-completions",
|
|
295
|
+
"openai-responses"
|
|
296
|
+
]);
|
|
297
|
+
export function rewriteForkCacheProviderRequest(event, ctx) {
|
|
298
|
+
const forkCacheKey = process.env[SUBAGENT_FORK_CACHE_KEY_ENV]?.trim();
|
|
299
|
+
if (!forkCacheKey || !PROMPT_CACHE_KEY_APIS.has(ctx?.model?.api ?? ""))
|
|
300
|
+
return;
|
|
301
|
+
if (!event || typeof event !== "object")
|
|
302
|
+
return;
|
|
303
|
+
const payload = event.payload;
|
|
304
|
+
if (!payload || typeof payload !== "object" || Array.isArray(payload))
|
|
305
|
+
return;
|
|
306
|
+
if (typeof payload.prompt_cache_key !== "string")
|
|
307
|
+
return;
|
|
308
|
+
return { ...payload, prompt_cache_key: forkCacheKey };
|
|
309
|
+
}
|
|
310
|
+
function portableToolId(id) {
|
|
311
|
+
if (PORTABLE_TOOL_ID_PATTERN.test(id) && id.length <= MAX_PORTABLE_TOOL_ID_LENGTH)
|
|
312
|
+
return id;
|
|
313
|
+
const encoded = `tool_${Buffer.from(id).toString("base64url") || "empty"}`;
|
|
314
|
+
if (encoded.length <= MAX_PORTABLE_TOOL_ID_LENGTH)
|
|
315
|
+
return encoded;
|
|
316
|
+
return `tool_${createHash("sha256").update(id).digest("base64url")}`;
|
|
317
|
+
}
|
|
318
|
+
function sanitizeToolHistoryMessage(message) {
|
|
319
|
+
const m = message;
|
|
320
|
+
if (m?.role === "toolResult" && typeof m.toolCallId === "string") {
|
|
321
|
+
const toolCallId = portableToolId(m.toolCallId);
|
|
322
|
+
return toolCallId === m.toolCallId ? message : { ...m, toolCallId };
|
|
323
|
+
}
|
|
324
|
+
if (m?.role !== "assistant" || !Array.isArray(m.content))
|
|
325
|
+
return message;
|
|
326
|
+
let changed = false;
|
|
327
|
+
const content = m.content.map((block) => {
|
|
328
|
+
const b = block;
|
|
329
|
+
if (b?.type !== "toolCall" || typeof b.id !== "string")
|
|
330
|
+
return block;
|
|
331
|
+
const id = portableToolId(b.id);
|
|
332
|
+
if (id === b.id)
|
|
333
|
+
return block;
|
|
334
|
+
changed = true;
|
|
335
|
+
return { ...b, id };
|
|
336
|
+
});
|
|
337
|
+
return changed ? { ...m, content } : message;
|
|
338
|
+
}
|
|
128
339
|
function stripAssistantSubagentToolCallBlocks(message) {
|
|
129
340
|
const m = message;
|
|
130
341
|
if (m?.role !== "assistant" || !Array.isArray(m.content))
|
|
@@ -136,8 +347,9 @@ function stripAssistantSubagentToolCallBlocks(message) {
|
|
|
136
347
|
return;
|
|
137
348
|
return { ...m, content: filteredContent };
|
|
138
349
|
}
|
|
139
|
-
export function stripParentOnlySubagentMessages(messages) {
|
|
350
|
+
export function stripParentOnlySubagentMessages(messages, options = {}) {
|
|
140
351
|
const preserveCurrentFanoutToolHistory = process.env[SUBAGENT_FANOUT_CHILD_ENV] === "1";
|
|
352
|
+
const sanitizeToolIds = options.sanitizeToolIds ?? true;
|
|
141
353
|
let changed = false;
|
|
142
354
|
const filtered = [];
|
|
143
355
|
for (const message of messages) {
|
|
@@ -150,15 +362,16 @@ export function stripParentOnlySubagentMessages(messages) {
|
|
|
150
362
|
changed = true;
|
|
151
363
|
continue;
|
|
152
364
|
}
|
|
153
|
-
|
|
365
|
+
const sanitized = sanitizeToolIds ? sanitizeToolHistoryMessage(stripped) : stripped;
|
|
366
|
+
if (stripped !== message || sanitized !== stripped)
|
|
154
367
|
changed = true;
|
|
155
|
-
filtered.push(
|
|
368
|
+
filtered.push(sanitized);
|
|
156
369
|
}
|
|
157
370
|
return changed ? filtered : messages;
|
|
158
371
|
}
|
|
159
372
|
export function formatSteerMessage(request) {
|
|
160
373
|
return [
|
|
161
|
-
"Mid-run steering from the parent orchestrator:",
|
|
374
|
+
request.mode === "follow_up" ? "Queued follow-up from the parent orchestrator:" : "Mid-run steering from the parent orchestrator:",
|
|
162
375
|
"",
|
|
163
376
|
request.message,
|
|
164
377
|
"",
|
|
@@ -166,13 +379,69 @@ export function formatSteerMessage(request) {
|
|
|
166
379
|
].join(`
|
|
167
380
|
`);
|
|
168
381
|
}
|
|
169
|
-
function
|
|
382
|
+
export function registerPermissionGate(dm, requestPermission = requestWatchdogPermission) {
|
|
383
|
+
const rules = decodePermissionRules(process.env[PERMISSION_POLICY_ENV]);
|
|
384
|
+
if (!rules)
|
|
385
|
+
return;
|
|
386
|
+
const onRuntimeEvent = dm.on;
|
|
387
|
+
onRuntimeEvent("tool_call", async (event, ctx) => {
|
|
388
|
+
const toolName = typeof event.toolName === "string" ? event.toolName : "tool";
|
|
389
|
+
const decision = permissionDecision(rules, toolName);
|
|
390
|
+
if (decision === "allow")
|
|
391
|
+
return;
|
|
392
|
+
if (decision === "deny")
|
|
393
|
+
return { block: true, reason: `Blocked by dm-subagents permission rule: '${toolName}' is denied.` };
|
|
394
|
+
const rawWatchdogConfig = process.env[CHILD_WATCHDOG_CONFIG_ENV];
|
|
395
|
+
let timeoutMs = 30000;
|
|
396
|
+
try {
|
|
397
|
+
timeoutMs = decodeChildWatchdogConfig(rawWatchdogConfig)?.agentEndTimeoutMs ?? timeoutMs;
|
|
398
|
+
} catch {}
|
|
399
|
+
if (ctx.signal?.aborted)
|
|
400
|
+
return { block: true, reason: "Blocked by dm-subagents permission rule: Watchdog permission decision was cancelled." };
|
|
401
|
+
let timeout;
|
|
402
|
+
let abort;
|
|
403
|
+
let result;
|
|
404
|
+
try {
|
|
405
|
+
result = await Promise.race([
|
|
406
|
+
requestPermission({
|
|
407
|
+
ctx,
|
|
408
|
+
toolName,
|
|
409
|
+
args: event.input ?? {},
|
|
410
|
+
rawWatchdogConfig,
|
|
411
|
+
auditPath: process.env[PERMISSION_AUDIT_PATH_ENV],
|
|
412
|
+
...ctx.signal ? { signal: ctx.signal } : {}
|
|
413
|
+
}),
|
|
414
|
+
new Promise((resolve) => {
|
|
415
|
+
if (!ctx.signal)
|
|
416
|
+
return;
|
|
417
|
+
abort = () => resolve({ approved: false, reason: "Watchdog permission decision was cancelled.", source: "watchdog" });
|
|
418
|
+
ctx.signal.addEventListener("abort", abort, { once: true });
|
|
419
|
+
}),
|
|
420
|
+
new Promise((_, reject) => {
|
|
421
|
+
timeout = setTimeout(() => reject(new Error(`Watchdog permission decision timed out after ${timeoutMs}ms.`)), timeoutMs);
|
|
422
|
+
})
|
|
423
|
+
]);
|
|
424
|
+
} catch (error) {
|
|
425
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
426
|
+
return { block: true, reason: `Blocked by dm-subagents permission rule: Watchdog permission arbiter failed closed: ${reason}` };
|
|
427
|
+
} finally {
|
|
428
|
+
if (timeout)
|
|
429
|
+
clearTimeout(timeout);
|
|
430
|
+
if (abort)
|
|
431
|
+
ctx.signal?.removeEventListener("abort", abort);
|
|
432
|
+
}
|
|
433
|
+
if (result.approved)
|
|
434
|
+
return;
|
|
435
|
+
return { block: true, reason: `Blocked by dm-subagents permission rule: ${result.reason}` };
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
function registerToolBudget(dm, budget) {
|
|
170
439
|
if (!budget)
|
|
171
440
|
return;
|
|
172
441
|
let toolCount = 0;
|
|
173
442
|
let softNudged = false;
|
|
174
|
-
const sendUserMessage =
|
|
175
|
-
const onRuntimeEvent =
|
|
443
|
+
const sendUserMessage = dm.sendUserMessage;
|
|
444
|
+
const onRuntimeEvent = dm.on;
|
|
176
445
|
onRuntimeEvent("tool_call", (event) => {
|
|
177
446
|
const toolName = typeof event.toolName === "string" ? event.toolName : "tool";
|
|
178
447
|
toolCount++;
|
|
@@ -187,32 +456,78 @@ function registerToolBudget(pi, budget) {
|
|
|
187
456
|
return { block: true, reason: toolBudgetBlockedMessage(budget, toolName, toolCount) };
|
|
188
457
|
});
|
|
189
458
|
}
|
|
190
|
-
function registerSteeringInbox(
|
|
459
|
+
export function registerSteeringInbox(dm, deps = {}) {
|
|
191
460
|
const steerInbox = process.env[SUBAGENT_STEER_INBOX_ENV]?.trim();
|
|
192
461
|
if (!steerInbox)
|
|
193
462
|
return;
|
|
194
|
-
const
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
463
|
+
const capabilityPath = process.env[SUBAGENT_STEER_CAPABILITY_ENV]?.trim();
|
|
464
|
+
const ackDir = process.env[SUBAGENT_STEER_ACK_DIR_ENV]?.trim();
|
|
465
|
+
const sendUserMessage = dm.sendUserMessage;
|
|
466
|
+
const childIndex = Number(process.env[SUBAGENT_CHILD_INDEX_ENV]);
|
|
467
|
+
const pending = new Map;
|
|
468
|
+
const queued = [];
|
|
198
469
|
let disposed = false;
|
|
470
|
+
let agentRunning = false;
|
|
471
|
+
let inTurn = false;
|
|
472
|
+
let awaitingSettlement = false;
|
|
199
473
|
let flushing = false;
|
|
200
474
|
let started = false;
|
|
475
|
+
let canSteer = typeof sendUserMessage === "function";
|
|
201
476
|
let watcher;
|
|
202
477
|
let interval;
|
|
478
|
+
let safetyInterval;
|
|
479
|
+
let settleFallback;
|
|
480
|
+
const legacySettleFallbackMs = deps.legacySettleFallbackMs ?? STEERING_LEGACY_SETTLE_FALLBACK_MS;
|
|
481
|
+
const acknowledge = (request, state, message, deliveryStatus) => {
|
|
482
|
+
if (!ackDir || !Number.isInteger(childIndex) || childIndex < 0)
|
|
483
|
+
return;
|
|
484
|
+
writeSteerAckAt(steerAckPathFromDir(ackDir, request.id), {
|
|
485
|
+
requestId: request.id,
|
|
486
|
+
index: childIndex,
|
|
487
|
+
ts: Date.now(),
|
|
488
|
+
state,
|
|
489
|
+
...deliveryStatus ? { deliveryStatus } : {},
|
|
490
|
+
message
|
|
491
|
+
});
|
|
492
|
+
};
|
|
493
|
+
const publishCapability = () => {
|
|
494
|
+
if (!capabilityPath || !Number.isInteger(childIndex) || childIndex < 0)
|
|
495
|
+
return;
|
|
496
|
+
writeSteerCapabilityAt(capabilityPath, { index: childIndex, pid: process.pid, readyAt: Date.now(), supported: canSteer });
|
|
497
|
+
};
|
|
203
498
|
const flush = () => {
|
|
204
|
-
if (disposed || flushing
|
|
499
|
+
if (disposed || flushing)
|
|
205
500
|
return;
|
|
206
501
|
flushing = true;
|
|
207
502
|
try {
|
|
208
503
|
const requests = consumeSteerRequestsFromDir(steerInbox);
|
|
209
504
|
for (let index = 0;index < requests.length; index++) {
|
|
210
505
|
const request = requests[index];
|
|
506
|
+
if (!canSteer || typeof sendUserMessage !== "function") {
|
|
507
|
+
acknowledge(request, "failed", "Child DM session does not support sendUserMessage steering.");
|
|
508
|
+
continue;
|
|
509
|
+
}
|
|
510
|
+
const requestedMode = request.mode ?? "steer";
|
|
511
|
+
const autoCanUseIdle = requestedMode === "auto" && !agentRunning && !awaitingSettlement;
|
|
512
|
+
const delivery = requestedMode === "follow_up" || requestedMode === "auto" && (inTurn || awaitingSettlement) ? "followUp" : "steer";
|
|
513
|
+
const pendingFollowUps = [...pending.values()].reduce((count, entries) => count + entries.filter((entry) => entry.deliveryStatus === "queued").length, 0);
|
|
514
|
+
if (delivery === "followUp" && queued.length + pendingFollowUps >= MAX_STEER_QUEUE_SIZE) {
|
|
515
|
+
acknowledge(request, "failed", `Follow-up queue is full (${MAX_STEER_QUEUE_SIZE} messages).`);
|
|
516
|
+
continue;
|
|
517
|
+
}
|
|
518
|
+
const formatted = formatSteerMessage(request);
|
|
519
|
+
const entries = pending.get(formatted) ?? [];
|
|
520
|
+
entries.push({ request, deliveryStatus: delivery === "followUp" ? "queued" : "delivered" });
|
|
521
|
+
pending.set(formatted, entries);
|
|
211
522
|
try {
|
|
212
|
-
sendUserMessage(
|
|
213
|
-
} catch {
|
|
214
|
-
|
|
215
|
-
|
|
523
|
+
sendUserMessage(formatted, autoCanUseIdle ? undefined : { deliverAs: delivery });
|
|
524
|
+
} catch (error) {
|
|
525
|
+
entries.pop();
|
|
526
|
+
if (entries.length === 0)
|
|
527
|
+
pending.delete(formatted);
|
|
528
|
+
acknowledge(request, "failed", error instanceof Error ? error.message : String(error));
|
|
529
|
+
for (const retry of requests.slice(index + 1))
|
|
530
|
+
writeSteerRequestToDir(steerInbox, retry);
|
|
216
531
|
break;
|
|
217
532
|
}
|
|
218
533
|
}
|
|
@@ -220,87 +535,238 @@ function registerSteeringInbox(pi) {
|
|
|
220
535
|
flushing = false;
|
|
221
536
|
}
|
|
222
537
|
};
|
|
538
|
+
const onInput = (event) => {
|
|
539
|
+
if (disposed || !event || typeof event !== "object")
|
|
540
|
+
return;
|
|
541
|
+
const input = event;
|
|
542
|
+
if (input.source !== "extension")
|
|
543
|
+
return;
|
|
544
|
+
const text = typeof input.text === "string" ? input.text : typeof input.content === "string" ? input.content : undefined;
|
|
545
|
+
if (!text)
|
|
546
|
+
return;
|
|
547
|
+
const entries = pending.get(text);
|
|
548
|
+
const entry = entries?.shift();
|
|
549
|
+
if (!entry)
|
|
550
|
+
return;
|
|
551
|
+
if (entries?.length === 0)
|
|
552
|
+
pending.delete(text);
|
|
553
|
+
if (entry.deliveryStatus === "queued") {
|
|
554
|
+
queued.push({ request: entry.request, ready: !inTurn });
|
|
555
|
+
acknowledge(entry.request, "queued", "DM queued the correlated follow-up input.", "queued");
|
|
556
|
+
} else {
|
|
557
|
+
acknowledge(entry.request, "delivered", "DM accepted the correlated steering input.", "delivered");
|
|
558
|
+
}
|
|
559
|
+
return;
|
|
560
|
+
};
|
|
223
561
|
const start = () => {
|
|
224
562
|
if (started || disposed)
|
|
225
563
|
return;
|
|
226
564
|
try {
|
|
227
565
|
fs.mkdirSync(steerInbox, { recursive: true });
|
|
566
|
+
publishCapability();
|
|
228
567
|
} catch {
|
|
229
568
|
return;
|
|
230
569
|
}
|
|
231
570
|
started = true;
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
571
|
+
const startPolling = () => {
|
|
572
|
+
if (interval || disposed)
|
|
573
|
+
return;
|
|
574
|
+
interval = (deps.timers?.setInterval ?? setInterval)(flush, 250);
|
|
575
|
+
interval.unref?.();
|
|
576
|
+
};
|
|
577
|
+
const startSafetyPolling = () => {
|
|
578
|
+
if (safetyInterval || disposed)
|
|
579
|
+
return;
|
|
580
|
+
safetyInterval = (deps.timers?.setInterval ?? setInterval)(flush, deps.safetyPollIntervalMs ?? STEERING_SAFETY_POLL_INTERVAL_MS);
|
|
581
|
+
safetyInterval.unref?.();
|
|
582
|
+
};
|
|
583
|
+
if (!shouldUseNativeFsWatch("child-steering-inbox", deps.platform)) {
|
|
584
|
+
startPolling();
|
|
585
|
+
} else {
|
|
586
|
+
try {
|
|
587
|
+
watcher = (deps.watch ?? fs.watch)(resolveWatchPath(steerInbox, deps.nativeRealpath), () => flush());
|
|
588
|
+
watcher.on("error", startPolling);
|
|
589
|
+
startSafetyPolling();
|
|
590
|
+
} catch {
|
|
591
|
+
watcher = undefined;
|
|
592
|
+
startPolling();
|
|
593
|
+
}
|
|
237
594
|
}
|
|
238
|
-
interval = setInterval(flush, 250);
|
|
239
|
-
interval.unref?.();
|
|
240
595
|
};
|
|
241
596
|
const activate = () => {
|
|
242
597
|
start();
|
|
243
|
-
canSteer = true;
|
|
244
598
|
flush();
|
|
245
599
|
return;
|
|
246
600
|
};
|
|
247
|
-
const
|
|
601
|
+
const clearSettleFallback = () => {
|
|
602
|
+
if (!settleFallback)
|
|
603
|
+
return;
|
|
604
|
+
clearTimeout(settleFallback);
|
|
605
|
+
settleFallback = undefined;
|
|
606
|
+
};
|
|
607
|
+
const markSettled = () => {
|
|
608
|
+
clearSettleFallback();
|
|
609
|
+
agentRunning = false;
|
|
610
|
+
inTurn = false;
|
|
611
|
+
awaitingSettlement = false;
|
|
612
|
+
return activate();
|
|
613
|
+
};
|
|
614
|
+
const armLegacySettleFallback = () => {
|
|
615
|
+
clearSettleFallback();
|
|
616
|
+
settleFallback = setTimeout(() => {
|
|
617
|
+
settleFallback = undefined;
|
|
618
|
+
if (disposed || !awaitingSettlement)
|
|
619
|
+
return;
|
|
620
|
+
agentRunning = false;
|
|
621
|
+
inTurn = false;
|
|
622
|
+
awaitingSettlement = false;
|
|
623
|
+
activate();
|
|
624
|
+
}, legacySettleFallbackMs);
|
|
625
|
+
settleFallback.unref?.();
|
|
626
|
+
};
|
|
627
|
+
const onRuntimeEvent = dm.on;
|
|
628
|
+
onRuntimeEvent("input", onInput);
|
|
248
629
|
onRuntimeEvent("session_start", () => start());
|
|
249
|
-
|
|
630
|
+
onRuntimeEvent("agent_start", () => {
|
|
631
|
+
clearSettleFallback();
|
|
632
|
+
agentRunning = true;
|
|
633
|
+
awaitingSettlement = false;
|
|
634
|
+
return activate();
|
|
635
|
+
});
|
|
636
|
+
onRuntimeEvent("agent_end", (event) => {
|
|
637
|
+
inTurn = false;
|
|
638
|
+
if (event?.willRetry === true) {
|
|
639
|
+
clearSettleFallback();
|
|
640
|
+
agentRunning = true;
|
|
641
|
+
awaitingSettlement = true;
|
|
642
|
+
return activate();
|
|
643
|
+
}
|
|
644
|
+
agentRunning = true;
|
|
645
|
+
awaitingSettlement = true;
|
|
646
|
+
armLegacySettleFallback();
|
|
647
|
+
return activate();
|
|
648
|
+
});
|
|
649
|
+
onRuntimeEvent("agent_settled", markSettled);
|
|
650
|
+
onRuntimeEvent("session_compact", () => {
|
|
651
|
+
const unresolved = [...pending.values()].flat();
|
|
652
|
+
pending.clear();
|
|
653
|
+
for (const entry of unresolved) {
|
|
654
|
+
try {
|
|
655
|
+
writeSteerRequestToDir(steerInbox, { ...entry.request, mode: "follow_up" });
|
|
656
|
+
} catch (error) {
|
|
657
|
+
acknowledge(entry.request, "failed", `Could not retry steering after compaction: ${error instanceof Error ? error.message : String(error)}`);
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
return activate();
|
|
661
|
+
});
|
|
662
|
+
onRuntimeEvent("turn_start", () => {
|
|
663
|
+
clearSettleFallback();
|
|
664
|
+
agentRunning = true;
|
|
665
|
+
awaitingSettlement = false;
|
|
666
|
+
inTurn = true;
|
|
667
|
+
const next = queued.findIndex((entry) => entry.ready);
|
|
668
|
+
if (next >= 0) {
|
|
669
|
+
const [entry] = queued.splice(next, 1);
|
|
670
|
+
if (entry)
|
|
671
|
+
acknowledge(entry.request, "delivered", "DM delivered the queued follow-up at a turn boundary.", "delivered");
|
|
672
|
+
}
|
|
673
|
+
return activate();
|
|
674
|
+
});
|
|
675
|
+
onRuntimeEvent("turn_end", () => {
|
|
676
|
+
inTurn = false;
|
|
677
|
+
for (const entry of queued)
|
|
678
|
+
entry.ready = true;
|
|
679
|
+
return activate();
|
|
680
|
+
});
|
|
681
|
+
for (const eventName of ["message_start", "message_update", "message_end", "tool_execution_start", "tool_execution_end"]) {
|
|
250
682
|
onRuntimeEvent(eventName, activate);
|
|
251
683
|
}
|
|
252
684
|
onRuntimeEvent("session_shutdown", () => {
|
|
685
|
+
for (const entry of queued)
|
|
686
|
+
acknowledge(entry.request, "failed", "Run ended before queued follow-up delivery.", "queued");
|
|
687
|
+
for (const entries of pending.values()) {
|
|
688
|
+
for (const entry of entries)
|
|
689
|
+
acknowledge(entry.request, "failed", "Run ended before DM confirmed steering input delivery.");
|
|
690
|
+
}
|
|
253
691
|
disposed = true;
|
|
692
|
+
clearSettleFallback();
|
|
254
693
|
try {
|
|
255
694
|
watcher?.close();
|
|
256
695
|
} catch {}
|
|
257
696
|
if (interval)
|
|
258
|
-
clearInterval(interval);
|
|
697
|
+
(deps.timers?.clearInterval ?? clearInterval)(interval);
|
|
698
|
+
if (safetyInterval)
|
|
699
|
+
(deps.timers?.clearInterval ?? clearInterval)(safetyInterval);
|
|
259
700
|
});
|
|
260
701
|
}
|
|
261
|
-
export default function registerSubagentPromptRuntime(
|
|
262
|
-
|
|
263
|
-
|
|
702
|
+
export default function registerSubagentPromptRuntime(dm) {
|
|
703
|
+
registerRuntimeExtensionAcknowledgements(dm);
|
|
704
|
+
registerSteeringInbox(dm);
|
|
705
|
+
registerPermissionGate(dm);
|
|
706
|
+
registerToolBudget(dm, decodeToolBudgetEnv(process.env[TOOL_BUDGET_ENV], { allowZero: process.env[TOOL_BUDGET_ZERO_AUTH_ENV] === "1" }));
|
|
707
|
+
registerChildWatchdog(dm);
|
|
708
|
+
const waitToolConfig = resolveWaitToolConfig();
|
|
709
|
+
const waitState = {
|
|
710
|
+
baseCwd: "",
|
|
711
|
+
currentSessionId: null,
|
|
712
|
+
asyncJobs: new Map,
|
|
713
|
+
foregroundControls: new Map,
|
|
714
|
+
lastForegroundControlId: null,
|
|
715
|
+
cleanupTimers: new Map,
|
|
716
|
+
lastUiContext: null,
|
|
717
|
+
poller: null,
|
|
718
|
+
completionSeen: new Map,
|
|
719
|
+
watcher: null,
|
|
720
|
+
watcherRestartTimer: null,
|
|
721
|
+
resultFileCoalescer: { schedule: () => false, clear: () => {} }
|
|
722
|
+
};
|
|
723
|
+
if (typeof dm.registerTool === "function")
|
|
724
|
+
registerWaitTool(dm, waitState, waitToolConfig.enabled, undefined, waitToolConfig.defaultTimeoutMs);
|
|
264
725
|
let nativeSupervisorClientRegistered = false;
|
|
265
|
-
let nativeSupervisorFallbackRegistered = false;
|
|
266
726
|
const registerNativeSupervisorClientOnce = () => {
|
|
267
727
|
if (nativeSupervisorClientRegistered)
|
|
268
728
|
return;
|
|
269
729
|
nativeSupervisorClientRegistered = true;
|
|
270
|
-
registerNativeSupervisorClient(
|
|
730
|
+
registerNativeSupervisorClient(dm);
|
|
271
731
|
};
|
|
272
|
-
const
|
|
732
|
+
const onRuntimeEvent = dm.on;
|
|
733
|
+
onRuntimeEvent("session_start", (_event, ctx) => {
|
|
734
|
+
const sessionManager = ctx?.sessionManager;
|
|
735
|
+
waitState.currentSessionId = sessionManager ? resolveCurrentSessionId(sessionManager) : null;
|
|
273
736
|
registerNativeSupervisorClientOnce();
|
|
274
|
-
|
|
737
|
+
});
|
|
738
|
+
onRuntimeEvent("agent_start", () => {
|
|
739
|
+
const diagnostic = refreshChildToolDiagnostic(dm);
|
|
740
|
+
if (diagnostic)
|
|
741
|
+
throw new Error(formatChildToolDiagnostic(diagnostic));
|
|
742
|
+
});
|
|
743
|
+
onRuntimeEvent("agent_end", async (_event, ctx) => {
|
|
744
|
+
if (ctx?.hasUI === true)
|
|
275
745
|
return;
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
};
|
|
279
|
-
const onRuntimeEvent = pi.on;
|
|
280
|
-
onRuntimeEvent("session_start", registerNativeSupervisorClientOnce);
|
|
746
|
+
await drainOutstandingWork({ state: waitState, events: dm.events });
|
|
747
|
+
});
|
|
281
748
|
const structuredOutputPath = process.env[STRUCTURED_OUTPUT_CAPTURE_ENV];
|
|
749
|
+
const structuredAcceptanceReportPath = process.env[STRUCTURED_OUTPUT_ACCEPTANCE_CAPTURE_ENV];
|
|
282
750
|
const structuredSchemaPath = process.env[STRUCTURED_OUTPUT_SCHEMA_ENV];
|
|
283
751
|
if (structuredOutputPath && structuredSchemaPath) {
|
|
284
752
|
const schema = JSON.parse(fs.readFileSync(structuredSchemaPath, "utf-8"));
|
|
285
|
-
const parameters = {
|
|
286
|
-
|
|
287
|
-
properties: { value: schema },
|
|
288
|
-
required: ["value"],
|
|
289
|
-
additionalProperties: false
|
|
290
|
-
};
|
|
291
|
-
const registerTool = pi.registerTool;
|
|
753
|
+
const parameters = createStructuredOutputToolParameters(schema, { acceptanceReport: Boolean(structuredAcceptanceReportPath) });
|
|
754
|
+
const registerTool = dm.registerTool;
|
|
292
755
|
registerTool({
|
|
293
756
|
name: "structured_output",
|
|
294
757
|
label: "Structured Output",
|
|
295
758
|
description: "Submit the required final structured output for this subagent step. This terminates the step.",
|
|
296
759
|
parameters,
|
|
297
760
|
async execute(_id, params) {
|
|
298
|
-
const validation = validateStructuredOutputValue(schema, params.value);
|
|
761
|
+
const validation = await validateStructuredOutputValue(schema, params.value);
|
|
299
762
|
if (validation.status === "invalid") {
|
|
300
763
|
throw new Error(`Structured output validation failed: ${validation.message}`);
|
|
301
764
|
}
|
|
302
765
|
fs.mkdirSync(path.dirname(structuredOutputPath), { recursive: true });
|
|
303
766
|
fs.writeFileSync(structuredOutputPath, JSON.stringify(params.value), { mode: 384 });
|
|
767
|
+
if (structuredAcceptanceReportPath && params.acceptanceReport !== undefined) {
|
|
768
|
+
fs.writeFileSync(structuredAcceptanceReportPath, JSON.stringify(params.acceptanceReport), { mode: 384 });
|
|
769
|
+
}
|
|
304
770
|
return {
|
|
305
771
|
content: [{ type: "text", text: "Structured output captured." }],
|
|
306
772
|
details: { path: structuredOutputPath },
|
|
@@ -309,28 +775,40 @@ export default function registerSubagentPromptRuntime(pi) {
|
|
|
309
775
|
}
|
|
310
776
|
});
|
|
311
777
|
}
|
|
312
|
-
onRuntimeEvent("
|
|
313
|
-
|
|
778
|
+
onRuntimeEvent("before_provider_request", (event, ctx) => rewriteForkCacheProviderRequest(event, ctx));
|
|
779
|
+
onRuntimeEvent("context", (event, ctx) => {
|
|
780
|
+
if (!event || typeof event !== "object" || !("messages" in event) || !Array.isArray(event.messages))
|
|
781
|
+
return;
|
|
782
|
+
const messages = stripParentOnlySubagentMessages(event.messages, {
|
|
783
|
+
sanitizeToolIds: !COMPOSITE_TOOL_ID_APIS.has(ctx?.model?.api ?? "")
|
|
784
|
+
});
|
|
314
785
|
if (messages === event.messages)
|
|
315
786
|
return;
|
|
316
787
|
return { messages };
|
|
317
788
|
});
|
|
318
789
|
onRuntimeEvent("before_agent_start", async (event) => {
|
|
319
|
-
|
|
790
|
+
if (!event || typeof event !== "object" || !("systemPrompt" in event) || typeof event.systemPrompt !== "string")
|
|
791
|
+
return;
|
|
792
|
+
registerNativeSupervisorClientOnce();
|
|
320
793
|
const intercomSessionName = process.env[SUBAGENT_INTERCOM_SESSION_NAME_ENV]?.trim();
|
|
321
|
-
|
|
322
|
-
|
|
794
|
+
const displaySessionName = process.env[SUBAGENT_SESSION_NAME_ENV]?.trim();
|
|
795
|
+
const childSessionName = intercomSessionName || displaySessionName;
|
|
796
|
+
if (childSessionName && typeof dm.setSessionName === "function") {
|
|
797
|
+
dm.setSessionName(childSessionName);
|
|
323
798
|
}
|
|
324
799
|
const inheritProjectContext = readBooleanEnv(SUBAGENT_INHERIT_PROJECT_CONTEXT_ENV);
|
|
800
|
+
const inheritGlobalContext = readBooleanEnv(SUBAGENT_INHERIT_GLOBAL_CONTEXT_ENV);
|
|
325
801
|
const inheritSkills = readBooleanEnv(SUBAGENT_INHERIT_SKILLS_ENV);
|
|
326
802
|
const fanoutChild = readBooleanEnv(SUBAGENT_FANOUT_CHILD_ENV);
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
803
|
+
let rewritten = event.systemPrompt;
|
|
804
|
+
if (inheritProjectContext !== undefined || inheritGlobalContext !== undefined || inheritSkills !== undefined || fanoutChild !== undefined) {
|
|
805
|
+
rewritten = rewriteSubagentPrompt(event.systemPrompt, {
|
|
806
|
+
inheritProjectContext: inheritProjectContext ?? true,
|
|
807
|
+
inheritGlobalContext: inheritGlobalContext ?? true,
|
|
808
|
+
inheritSkills: inheritSkills ?? true,
|
|
809
|
+
fanoutChild: fanoutChild === true
|
|
810
|
+
});
|
|
811
|
+
}
|
|
334
812
|
if (rewritten === event.systemPrompt)
|
|
335
813
|
return;
|
|
336
814
|
return { systemPrompt: rewritten };
|