@duckmind/dm-windows-x64 0.60.6 → 0.60.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 +70 -123
- package/extensions/dm-9router-ext/src/index.js +410 -5
- package/extensions/dm-caveman/extensions/caveman.js +283 -12
- package/extensions/dm-cliproxy/index.js +182 -2
- package/extensions/dm-cliproxy/scripts/check-config-migration.js +66 -8
- package/extensions/dm-cliproxy/src/apply.js +228 -1
- package/extensions/dm-cliproxy/src/cache.js +42 -1
- package/extensions/dm-cliproxy/src/commands.js +50 -2
- package/extensions/dm-cliproxy/src/compat.js +81 -1
- package/extensions/dm-cliproxy/src/config.js +192 -2
- package/extensions/dm-cliproxy/src/conflicts.js +46 -1
- package/extensions/dm-cliproxy/src/fetch-models.js +190 -1
- package/extensions/dm-cliproxy/src/fetch-usage.js +41 -1
- package/extensions/dm-cliproxy/src/log.js +23 -1
- package/extensions/dm-cliproxy/src/status-quota.js +77 -1
- package/extensions/dm-cliproxy/src/ui-frame.js +50 -1
- package/extensions/dm-cliproxy/src/ui-hub/hub.js +199 -2
- package/extensions/dm-cliproxy/src/ui-hub/index.js +26 -2
- package/extensions/dm-cliproxy/src/ui-hub/shell.js +46 -1
- package/extensions/dm-cliproxy/src/ui-hub/view-diagnostics.js +69 -1
- package/extensions/dm-cliproxy/src/ui-hub/view-models.js +379 -1
- package/extensions/dm-cliproxy/src/ui-hub/view-usage.js +106 -1
- package/extensions/dm-cliproxy/src/ui-picker/catalog.js +41 -1
- package/extensions/dm-cliproxy/src/ui-picker/mutate.js +115 -1
- package/extensions/dm-cliproxy/src/ui-picker/prompt-confirm.js +35 -1
- package/extensions/dm-cliproxy/src/ui-picker/prompt-name.js +62 -1
- package/extensions/dm-cliproxy/src/ui-picker/providers.js +45 -1
- package/extensions/dm-cliproxy/src/ui-picker/render-text.js +34 -1
- package/extensions/dm-cliproxy/src/ui-picker/rows.js +57 -1
- package/extensions/dm-cliproxy/src/ui-setup.js +260 -2
- package/extensions/dm-cliproxy/src/ui-usage.js +151 -1
- package/extensions/dm-cliproxy/src/usage-shared-cache.js +97 -1
- package/extensions/dm-context/src/context.js +144 -1
- package/extensions/dm-context/src/index.js +339 -7
- package/extensions/dm-context/src/utils.js +9 -1
- package/extensions/dm-cua/bin/browser-cua.mjs +73 -8
- package/extensions/dm-cua/index.js +75 -6
- package/extensions/dm-cua/src/browser-cua-lib.mjs +490 -6
- package/extensions/dm-cua/src/browser-install.mjs +331 -2
- package/extensions/dm-fff/src/index.js +688 -12
- package/extensions/dm-fff/src/query.js +60 -1
- package/extensions/dm-goal/src/goal.js +894 -23
- package/extensions/dm-image2/index.js +103 -9
- package/extensions/dm-image2/src/image-lib.mjs +1275 -8
- package/extensions/dm-subagents/install.mjs +62 -8
- package/extensions/dm-subagents/src/agents/agent-management.js +1190 -36
- package/extensions/dm-subagents/src/agents/agent-memory.js +216 -6
- package/extensions/dm-subagents/src/agents/agent-scope.js +5 -1
- package/extensions/dm-subagents/src/agents/agent-selection.js +20 -1
- package/extensions/dm-subagents/src/agents/agent-serializer.js +120 -5
- package/extensions/dm-subagents/src/agents/agents.js +1139 -11
- package/extensions/dm-subagents/src/agents/chain-serializer.js +299 -11
- package/extensions/dm-subagents/src/agents/frontmatter.js +65 -6
- package/extensions/dm-subagents/src/agents/identity.js +29 -1
- package/extensions/dm-subagents/src/agents/proactive-skills.js +141 -1
- package/extensions/dm-subagents/src/agents/skills.js +614 -6
- package/extensions/dm-subagents/src/extension/config.js +35 -2
- package/extensions/dm-subagents/src/extension/control-notices.js +69 -4
- package/extensions/dm-subagents/src/extension/doctor.js +172 -15
- package/extensions/dm-subagents/src/extension/fanout-child.js +158 -231
- package/extensions/dm-subagents/src/extension/index.js +521 -359
- package/extensions/dm-subagents/src/extension/rpc.js +266 -7
- package/extensions/dm-subagents/src/extension/schemas.js +275 -1
- package/extensions/dm-subagents/src/extension/tool-description.js +111 -6
- package/extensions/dm-subagents/src/intercom/intercom-bridge.js +126 -4
- package/extensions/dm-subagents/src/intercom/native-supervisor-channel.js +452 -5
- package/extensions/dm-subagents/src/intercom/result-intercom.js +319 -3
- package/extensions/dm-subagents/src/profiles/profiles.js +458 -3
- package/extensions/dm-subagents/src/runs/background/async-execution.js +834 -40
- package/extensions/dm-subagents/src/runs/background/async-job-tracker.js +435 -14
- package/extensions/dm-subagents/src/runs/background/async-resume.js +334 -8
- package/extensions/dm-subagents/src/runs/background/async-status.js +313 -12
- package/extensions/dm-subagents/src/runs/background/chain-append.js +245 -2
- package/extensions/dm-subagents/src/runs/background/chain-root-attachment.js +136 -1
- package/extensions/dm-subagents/src/runs/background/completion-batcher.js +94 -1
- package/extensions/dm-subagents/src/runs/background/completion-dedupe.js +54 -1
- package/extensions/dm-subagents/src/runs/background/control-channel.js +190 -1
- package/extensions/dm-subagents/src/runs/background/fleet-view.js +483 -17
- package/extensions/dm-subagents/src/runs/background/notify.js +129 -3
- package/extensions/dm-subagents/src/runs/background/parallel-groups.js +34 -1
- package/extensions/dm-subagents/src/runs/background/result-watcher.js +236 -6
- package/extensions/dm-subagents/src/runs/background/run-id-resolver.js +76 -4
- package/extensions/dm-subagents/src/runs/background/run-status.js +427 -23
- package/extensions/dm-subagents/src/runs/background/scheduled-runs.js +487 -4
- package/extensions/dm-subagents/src/runs/background/stale-run-reconciler.js +306 -9
- package/extensions/dm-subagents/src/runs/background/subagent-runner.js +2849 -73
- package/extensions/dm-subagents/src/runs/background/top-level-async.js +5 -1
- package/extensions/dm-subagents/src/runs/background/wait.js +206 -11
- package/extensions/dm-subagents/src/runs/foreground/chain-clarify.js +1013 -12
- package/extensions/dm-subagents/src/runs/foreground/chain-execution.js +980 -101
- package/extensions/dm-subagents/src/runs/foreground/execution.js +1165 -45
- package/extensions/dm-subagents/src/runs/foreground/subagent-executor.js +3157 -222
- package/extensions/dm-subagents/src/runs/shared/acceptance.js +835 -3
- package/extensions/dm-subagents/src/runs/shared/chain-outputs.js +104 -1
- package/extensions/dm-subagents/src/runs/shared/completion-guard.js +116 -3
- package/extensions/dm-subagents/src/runs/shared/dm-args.js +208 -1
- package/extensions/dm-subagents/src/runs/shared/dm-spawn.js +90 -1
- package/extensions/dm-subagents/src/runs/shared/dynamic-fanout.js +282 -1
- package/extensions/dm-subagents/src/runs/shared/long-running-guard.js +148 -1
- package/extensions/dm-subagents/src/runs/shared/mcp-direct-tool-allowlist.js +305 -1
- package/extensions/dm-subagents/src/runs/shared/model-fallback.js +194 -1
- package/extensions/dm-subagents/src/runs/shared/model-scope.js +65 -1
- package/extensions/dm-subagents/src/runs/shared/nested-events.js +851 -8
- package/extensions/dm-subagents/src/runs/shared/nested-path.js +41 -1
- package/extensions/dm-subagents/src/runs/shared/nested-render.js +105 -1
- package/extensions/dm-subagents/src/runs/shared/parallel-utils.js +81 -4
- package/extensions/dm-subagents/src/runs/shared/run-history.js +51 -4
- package/extensions/dm-subagents/src/runs/shared/single-output.js +149 -8
- package/extensions/dm-subagents/src/runs/shared/structured-output.js +58 -1
- package/extensions/dm-subagents/src/runs/shared/subagent-control.js +166 -5
- package/extensions/dm-subagents/src/runs/shared/subagent-prompt-runtime.js +329 -13
- package/extensions/dm-subagents/src/runs/shared/tool-budget.js +73 -1
- package/extensions/dm-subagents/src/runs/shared/turn-budget.js +47 -4
- package/extensions/dm-subagents/src/runs/shared/workflow-graph.js +196 -1
- package/extensions/dm-subagents/src/runs/shared/worktree.js +435 -3
- package/extensions/dm-subagents/src/shared/artifacts.js +92 -2
- package/extensions/dm-subagents/src/shared/atomic-json.js +55 -1
- package/extensions/dm-subagents/src/shared/child-transcript.js +167 -5
- package/extensions/dm-subagents/src/shared/file-coalescer.js +25 -1
- package/extensions/dm-subagents/src/shared/fork-context.js +147 -4
- package/extensions/dm-subagents/src/shared/formatters.js +98 -7
- package/extensions/dm-subagents/src/shared/jsonl-writer.js +56 -2
- package/extensions/dm-subagents/src/shared/model-info.js +62 -1
- package/extensions/dm-subagents/src/shared/post-exit-stdio-guard.js +68 -1
- package/extensions/dm-subagents/src/shared/session-identity.js +6 -1
- package/extensions/dm-subagents/src/shared/session-tokens.js +39 -2
- package/extensions/dm-subagents/src/shared/settings.js +198 -11
- package/extensions/dm-subagents/src/shared/status-format.js +53 -1
- package/extensions/dm-subagents/src/shared/types.js +184 -6
- package/extensions/dm-subagents/src/shared/utils.js +462 -2
- package/extensions/dm-subagents/src/slash/prompt-template-bridge.js +288 -1
- package/extensions/dm-subagents/src/slash/prompt-workflows.js +297 -7
- package/extensions/dm-subagents/src/slash/slash-bridge.js +118 -1
- package/extensions/dm-subagents/src/slash/slash-commands.js +1287 -31
- package/extensions/dm-subagents/src/slash/slash-live-state.js +240 -4
- package/extensions/dm-subagents/src/tui/render-helpers.js +64 -1
- package/extensions/dm-subagents/src/tui/render.js +1542 -4
- package/extensions/dm-usage/index.js +1294 -9
- package/extensions/greedysearch-dm/bin/cdp-greedy.mjs +40 -9
- package/extensions/greedysearch-dm/bin/cdp-headless.mjs +5 -2
- package/extensions/greedysearch-dm/bin/cdp-visible.mjs +5 -2
- package/extensions/greedysearch-dm/bin/cdp.mjs +896 -30
- package/extensions/greedysearch-dm/bin/gschrome.mjs +30 -2
- package/extensions/greedysearch-dm/bin/kill-visible.mjs +7 -2
- package/extensions/greedysearch-dm/bin/launch-visible.mjs +13 -2
- package/extensions/greedysearch-dm/bin/launch.mjs +282 -10
- package/extensions/greedysearch-dm/bin/mcp.mjs +386 -361
- package/extensions/greedysearch-dm/bin/search.mjs +620 -540
- package/extensions/greedysearch-dm/bin/visible.mjs +22 -2
- package/extensions/greedysearch-dm/extractors/bing-copilot.mjs +329 -579
- package/extensions/greedysearch-dm/extractors/chatgpt.mjs +301 -583
- package/extensions/greedysearch-dm/extractors/common.mjs +408 -32
- package/extensions/greedysearch-dm/extractors/consensus.mjs +376 -365
- package/extensions/greedysearch-dm/extractors/consent.mjs +303 -14
- package/extensions/greedysearch-dm/extractors/gemini.mjs +228 -592
- package/extensions/greedysearch-dm/extractors/google-ai.mjs +78 -499
- package/extensions/greedysearch-dm/extractors/logically.mjs +270 -347
- package/extensions/greedysearch-dm/extractors/perplexity.mjs +243 -581
- package/extensions/greedysearch-dm/extractors/selectors.mjs +32 -1
- package/extensions/greedysearch-dm/extractors/semantic-scholar.mjs +130 -317
- package/extensions/greedysearch-dm/index.js +123 -23
- package/extensions/greedysearch-dm/src/fetcher.mjs +576 -2
- package/extensions/greedysearch-dm/src/formatters/results.js +95 -10
- package/extensions/greedysearch-dm/src/formatters/sources.js +57 -1
- package/extensions/greedysearch-dm/src/formatters/synthesis.js +49 -1
- package/extensions/greedysearch-dm/src/github.mjs +222 -7
- package/extensions/greedysearch-dm/src/reddit.mjs +145 -14
- package/extensions/greedysearch-dm/src/search/browser-lifecycle.mjs +340 -9
- package/extensions/greedysearch-dm/src/search/challenge-detect.mjs +112 -4
- package/extensions/greedysearch-dm/src/search/chrome.mjs +486 -285
- package/extensions/greedysearch-dm/src/search/constants.mjs +109 -8
- package/extensions/greedysearch-dm/src/search/defaults.mjs +10 -1
- package/extensions/greedysearch-dm/src/search/engines.mjs +79 -9
- package/extensions/greedysearch-dm/src/search/fetch-source.mjs +441 -349
- package/extensions/greedysearch-dm/src/search/file-sources.mjs +29 -7
- package/extensions/greedysearch-dm/src/search/minimize.mjs +86 -1
- package/extensions/greedysearch-dm/src/search/output.mjs +51 -5
- package/extensions/greedysearch-dm/src/search/paths.mjs +48 -1
- package/extensions/greedysearch-dm/src/search/pdf.mjs +63 -2
- package/extensions/greedysearch-dm/src/search/port-pid.mjs +69 -1
- package/extensions/greedysearch-dm/src/search/progress.mjs +109 -2
- package/extensions/greedysearch-dm/src/search/query.mjs +21 -1
- package/extensions/greedysearch-dm/src/search/recovery.mjs +49 -1
- package/extensions/greedysearch-dm/src/search/research.mjs +2227 -458
- package/extensions/greedysearch-dm/src/search/scale-aware.mjs +61 -11
- package/extensions/greedysearch-dm/src/search/simple-research.mjs +396 -805
- package/extensions/greedysearch-dm/src/search/sources.mjs +412 -1
- package/extensions/greedysearch-dm/src/search/synthesis-runner.mjs +127 -12
- package/extensions/greedysearch-dm/src/search/synthesis.mjs +202 -12
- package/extensions/greedysearch-dm/src/tools/greedy-search-handler.js +209 -23
- package/extensions/greedysearch-dm/src/tools/shared.js +226 -10
- package/extensions/greedysearch-dm/src/utils/content.mjs +35 -4
- package/extensions/greedysearch-dm/src/utils/helpers.js +22 -1
- package/extensions/greedysearch-dm/src/utils/node-runtime.mjs +10 -1
- package/extensions/greedysearch-dm/src/utils/system-cmds.mjs +61 -1
- package/package.json +1 -1
|
@@ -1,46 +1,840 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import * as fs from "node:fs";
|
|
3
|
+
import * as path from "node:path";
|
|
4
|
+
import { createRequire } from "node:module";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
import { applyThinkingSuffix, resolveRuntimeExtensionPath } from "../shared/dm-args.js";
|
|
7
|
+
import { injectOutputPathSystemPrompt, injectSingleOutputInstruction, normalizeSingleOutputOverride, resolveSingleOutputPath, validateFileOnlyOutputMode } from "../shared/single-output.js";
|
|
8
|
+
import { buildChainInstructions, isDynamicParallelStep, isParallelStep, resolveStepBehavior, suppressProgressForReadOnlyTask, writeInitialProgressFile } from "../../shared/settings.js";
|
|
9
|
+
import { resolvePiPackageRoot } from "../shared/dm-spawn.js";
|
|
10
|
+
import { buildSkillInjection, normalizeSkillInput, resolveSkillsWithFallback } from "../../agents/skills.js";
|
|
11
|
+
import { buildAgentMemoryInjection } from "../../agents/agent-memory.js";
|
|
12
|
+
import { PI_CODING_AGENT_PACKAGE_ROOT_ENV, resolveChildCwd } from "../../shared/utils.js";
|
|
13
|
+
import { buildModelCandidates, resolveSubagentModelOverride } from "../shared/model-fallback.js";
|
|
14
|
+
import { resolveEffectiveThinking } from "../../shared/model-info.js";
|
|
15
|
+
import { resolveExpectedWorktreeAgentCwd } from "../shared/worktree.js";
|
|
16
|
+
import { buildWorkflowGraphSnapshot } from "../shared/workflow-graph.js";
|
|
17
|
+
import { ChainOutputValidationError, validateChainOutputBindings } from "../shared/chain-outputs.js";
|
|
18
|
+
import { createStructuredOutputRuntime } from "../shared/structured-output.js";
|
|
19
|
+
import { resolveEffectiveAcceptance } from "../shared/acceptance.js";
|
|
20
|
+
import {
|
|
21
|
+
ASYNC_DIR,
|
|
22
|
+
RESULTS_DIR,
|
|
23
|
+
SUBAGENT_ASYNC_STARTED_EVENT,
|
|
24
|
+
SUBAGENT_LIFECYCLE_ARTIFACT_VERSION,
|
|
25
|
+
TEMP_ROOT_DIR,
|
|
26
|
+
getAsyncConfigPath,
|
|
27
|
+
resolveChildMaxSubagentDepth
|
|
28
|
+
} from "../../shared/types.js";
|
|
29
|
+
import { nestedResultsPath, resolveInheritedNestedRouteFromEnv, resolveNestedParentAddressFromEnv, writeNestedEvent } from "../shared/nested-events.js";
|
|
30
|
+
import { initialTurnBudgetState } from "../shared/turn-budget.js";
|
|
31
|
+
import { validateToolBudgetConfig } from "../shared/tool-budget.js";
|
|
32
|
+
const require = createRequire(import.meta.url);
|
|
33
|
+
const piPackageRoot = resolvePiPackageRoot();
|
|
34
|
+
function resolveJitiCliFromPackageJson(packageJsonPath) {
|
|
35
|
+
if (!fs.existsSync(packageJsonPath))
|
|
36
|
+
return;
|
|
37
|
+
const packageRoot = path.dirname(packageJsonPath);
|
|
38
|
+
const pkg = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8"));
|
|
39
|
+
const binField = pkg.bin;
|
|
40
|
+
const binPath = typeof binField === "string" ? binField : binField?.jiti ?? Object.values(binField ?? {})[0];
|
|
41
|
+
const candidates = [binPath, "lib/jiti-cli.mjs"].filter((candidate) => Boolean(candidate));
|
|
42
|
+
for (const candidate of candidates) {
|
|
43
|
+
const cliPath = path.resolve(packageRoot, candidate);
|
|
44
|
+
if (fs.existsSync(cliPath))
|
|
45
|
+
return cliPath;
|
|
46
|
+
}
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
function resolveJitiCliPath() {
|
|
50
|
+
const candidates = [
|
|
51
|
+
() => require.resolve("jiti/package.json"),
|
|
52
|
+
() => piPackageRoot ? createRequire(path.join(piPackageRoot, "package.json")).resolve("jiti/package.json") : undefined,
|
|
53
|
+
() => {
|
|
54
|
+
if (!process.argv[1])
|
|
55
|
+
return;
|
|
56
|
+
const piEntry = fs.realpathSync(process.argv[1]);
|
|
57
|
+
return createRequire(piEntry).resolve("jiti/package.json");
|
|
58
|
+
},
|
|
59
|
+
() => piPackageRoot ? path.join(piPackageRoot, "node_modules", "jiti", "package.json") : undefined
|
|
60
|
+
];
|
|
61
|
+
for (const candidate of candidates) {
|
|
62
|
+
try {
|
|
63
|
+
const packageJsonPath = candidate();
|
|
64
|
+
if (!packageJsonPath)
|
|
65
|
+
continue;
|
|
66
|
+
const cliPath = resolveJitiCliFromPackageJson(packageJsonPath);
|
|
67
|
+
if (cliPath)
|
|
68
|
+
return cliPath;
|
|
69
|
+
} catch {}
|
|
70
|
+
}
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const jitiCliPath = resolveJitiCliPath();
|
|
74
|
+
export function formatAsyncStartedMessage(headline) {
|
|
75
|
+
return [
|
|
76
|
+
headline,
|
|
77
|
+
"",
|
|
78
|
+
"The async run is detached. Do not run sleep timers or polling loops just to wait for it.",
|
|
79
|
+
"If you have independent work, continue that work. When you have nothing left to do until the async result arrives, call wait() — it blocks until the run finishes and delivers the completion here. Only if you are certain you will get another turn (an interactive session where the user will prompt you again) can you instead stop and let DM wake you; inside a skill that must run to completion, or in a non-interactive run, there is no next turn, so use wait().",
|
|
80
|
+
'Use subagent({ action: "status", id: "..." }) when you need a one-shot status/result or to inspect a blocked/stale run. To block until completion, prefer wait(). Do not poll in a loop just to wait.'
|
|
81
|
+
].join(`
|
|
82
|
+
`);
|
|
83
|
+
}
|
|
84
|
+
export function isAsyncAvailable() {
|
|
85
|
+
return jitiCliPath !== undefined;
|
|
86
|
+
}
|
|
87
|
+
function isNodeExecutableName(execPath) {
|
|
88
|
+
const basename = path.basename(execPath).toLowerCase();
|
|
89
|
+
return basename === "node" || basename === "node.exe" || basename === "nodejs" || basename === "nodejs.exe";
|
|
90
|
+
}
|
|
91
|
+
function canUseCurrentNodeExecutable(execPath) {
|
|
92
|
+
try {
|
|
93
|
+
fs.accessSync(execPath, process.platform === "win32" ? fs.constants.F_OK : fs.constants.X_OK);
|
|
94
|
+
return true;
|
|
95
|
+
} catch {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function resolveAsyncRunnerNodeCommand() {
|
|
100
|
+
if (isNodeExecutableName(process.execPath) && canUseCurrentNodeExecutable(process.execPath)) {
|
|
101
|
+
return process.execPath;
|
|
102
|
+
}
|
|
103
|
+
return process.platform === "win32" ? "node.exe" : "node";
|
|
104
|
+
}
|
|
105
|
+
export function resolveAsyncRunnerLogPaths(cfg) {
|
|
106
|
+
const asyncDir = typeof cfg.asyncDir === "string" ? cfg.asyncDir : undefined;
|
|
107
|
+
if (!asyncDir)
|
|
108
|
+
return;
|
|
109
|
+
return {
|
|
110
|
+
stdoutPath: path.join(asyncDir, "runner.stdout.log"),
|
|
111
|
+
stderrPath: path.join(asyncDir, "runner.stderr.log")
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
function closeFd(fd) {
|
|
115
|
+
if (fd === undefined)
|
|
116
|
+
return;
|
|
117
|
+
try {
|
|
118
|
+
fs.closeSync(fd);
|
|
119
|
+
} catch {}
|
|
120
|
+
}
|
|
121
|
+
export function resolveAsyncRunnerPath(moduleUrl = import.meta.url) {
|
|
122
|
+
const modulePath = fileURLToPath(moduleUrl);
|
|
123
|
+
const runnerStem = path.basename(modulePath).startsWith("async-execution.") ? "subagent-runner" : path.join("..", "runs", "background", "subagent-runner");
|
|
124
|
+
return resolveRuntimeExtensionPath(moduleUrl, runnerStem);
|
|
125
|
+
}
|
|
126
|
+
function spawnRunner(cfg, suffix, cwd) {
|
|
127
|
+
if (!jitiCliPath) {
|
|
128
|
+
return { error: "upstream jiti for TypeScript execution could not be found; ensure package dependencies are installed" };
|
|
129
|
+
}
|
|
130
|
+
try {
|
|
131
|
+
const cwdStats = fs.statSync(cwd);
|
|
132
|
+
if (!cwdStats.isDirectory()) {
|
|
133
|
+
return { error: `cwd is not a directory: ${cwd}` };
|
|
134
|
+
}
|
|
135
|
+
} catch {
|
|
136
|
+
return { error: `cwd does not exist: ${cwd}` };
|
|
137
|
+
}
|
|
138
|
+
fs.mkdirSync(TEMP_ROOT_DIR, { recursive: true });
|
|
139
|
+
const cfgPath = getAsyncConfigPath(suffix);
|
|
140
|
+
fs.writeFileSync(cfgPath, JSON.stringify(cfg));
|
|
141
|
+
const runner = resolveAsyncRunnerPath();
|
|
142
|
+
const nodeCommand = resolveAsyncRunnerNodeCommand();
|
|
143
|
+
const logPaths = resolveAsyncRunnerLogPaths(cfg);
|
|
144
|
+
let stdoutFd;
|
|
145
|
+
let stderrFd;
|
|
146
|
+
try {
|
|
147
|
+
if (logPaths) {
|
|
148
|
+
fs.mkdirSync(path.dirname(logPaths.stdoutPath), { recursive: true });
|
|
149
|
+
stdoutFd = fs.openSync(logPaths.stdoutPath, "a");
|
|
150
|
+
stderrFd = fs.openSync(logPaths.stderrPath, "a");
|
|
151
|
+
}
|
|
152
|
+
const proc = spawn(nodeCommand, [jitiCliPath, runner, cfgPath], {
|
|
153
|
+
cwd,
|
|
154
|
+
detached: true,
|
|
155
|
+
stdio: ["ignore", stdoutFd ?? "ignore", stderrFd ?? "ignore"],
|
|
156
|
+
windowsHide: true,
|
|
157
|
+
env: {
|
|
158
|
+
...process.env,
|
|
159
|
+
...piPackageRoot ? { [PI_CODING_AGENT_PACKAGE_ROOT_ENV]: piPackageRoot } : {}
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
closeFd(stdoutFd);
|
|
163
|
+
closeFd(stderrFd);
|
|
164
|
+
proc.on("error", (error) => {
|
|
165
|
+
console.error(`[dm-subagents] async spawn failed: ${error.message}`);
|
|
166
|
+
});
|
|
167
|
+
if (typeof proc.pid !== "number") {
|
|
168
|
+
return { error: `async runner did not produce a pid for cwd: ${cwd}` };
|
|
169
|
+
}
|
|
170
|
+
proc.unref();
|
|
171
|
+
return { pid: proc.pid };
|
|
172
|
+
} catch (error) {
|
|
173
|
+
closeFd(stdoutFd);
|
|
174
|
+
closeFd(stderrFd);
|
|
175
|
+
return { error: error instanceof Error ? error.message : String(error) };
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
function formatAsyncStartError(mode, message) {
|
|
179
|
+
return {
|
|
180
|
+
content: [{ type: "text", text: message }],
|
|
181
|
+
isError: true,
|
|
182
|
+
details: { mode, results: [] }
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
const UNAVAILABLE_SUBAGENT_SKILL_ERROR = "Skills not found: dm-subagents";
|
|
7
186
|
|
|
8
|
-
|
|
9
|
-
|
|
187
|
+
class UnavailableSubagentSkillError extends Error {
|
|
188
|
+
}
|
|
10
189
|
|
|
11
|
-
|
|
190
|
+
class AsyncStartValidationError extends Error {
|
|
191
|
+
}
|
|
192
|
+
export function buildAsyncRunnerSteps(id, params) {
|
|
193
|
+
const {
|
|
194
|
+
chain,
|
|
195
|
+
agents,
|
|
196
|
+
ctx,
|
|
197
|
+
cwd,
|
|
198
|
+
sessionFilesByFlatIndex,
|
|
199
|
+
thinkingOverridesByFlatIndex,
|
|
200
|
+
maxSubagentDepth,
|
|
201
|
+
worktreeBaseDir,
|
|
202
|
+
asyncDir
|
|
203
|
+
} = params;
|
|
204
|
+
const outputBaseDir = params.outputBaseDir;
|
|
205
|
+
const resultMode = params.resultMode ?? "chain";
|
|
206
|
+
const chainSkills = params.chainSkills ?? [];
|
|
207
|
+
const availableModels = params.availableModels;
|
|
208
|
+
const runnerCwd = resolveChildCwd(ctx.cwd, cwd);
|
|
209
|
+
const progressDir = params.progressDir ?? runnerCwd;
|
|
210
|
+
const graphChain = params.attachRoot ? [{
|
|
211
|
+
agent: params.attachRoot.agent,
|
|
212
|
+
task: `Attach async root ${params.attachRoot.runId}`,
|
|
213
|
+
label: params.attachRoot.label ?? `Attached root ${params.attachRoot.runId}`,
|
|
214
|
+
...params.attachRoot.outputName ? { as: params.attachRoot.outputName } : {}
|
|
215
|
+
}, ...chain] : chain;
|
|
216
|
+
const firstStep = chain[0];
|
|
217
|
+
const originalTask = params.task ?? (firstStep ? isParallelStep(firstStep) ? firstStep.parallel[0]?.task : isDynamicParallelStep(firstStep) ? firstStep.parallel.task : firstStep.task : undefined);
|
|
218
|
+
try {
|
|
219
|
+
if (params.validateOutputBindings !== false) {
|
|
220
|
+
validateChainOutputBindings(chain, { maxItems: params.dynamicFanoutMaxItems });
|
|
221
|
+
}
|
|
222
|
+
} catch (error) {
|
|
223
|
+
if (error instanceof ChainOutputValidationError)
|
|
224
|
+
return { error: error.message };
|
|
225
|
+
throw error;
|
|
226
|
+
}
|
|
227
|
+
const workflowGraph = buildWorkflowGraphSnapshot({ runId: id, mode: resultMode, steps: graphChain });
|
|
228
|
+
for (const s of chain) {
|
|
229
|
+
const stepAgents = isParallelStep(s) ? s.parallel.map((t) => t.agent) : isDynamicParallelStep(s) ? [s.parallel.agent] : [s.agent];
|
|
230
|
+
for (const agentName of stepAgents) {
|
|
231
|
+
if (!agents.find((x) => x.name === agentName)) {
|
|
232
|
+
return { error: `Unknown agent: ${agentName}` };
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
let progressInstructionCreated = false;
|
|
237
|
+
const buildStepOverrides = (s) => {
|
|
238
|
+
const stepSkillInput = normalizeSkillInput(s.skill);
|
|
239
|
+
return {
|
|
240
|
+
...s.output !== undefined ? { output: s.output } : {},
|
|
241
|
+
...s.outputMode !== undefined ? { outputMode: s.outputMode } : {},
|
|
242
|
+
...s.reads !== undefined ? { reads: s.reads } : {},
|
|
243
|
+
...s.progress !== undefined ? { progress: s.progress } : {},
|
|
244
|
+
...stepSkillInput !== undefined ? { skills: stepSkillInput } : {},
|
|
245
|
+
...s.model ? { model: s.model } : {}
|
|
246
|
+
};
|
|
247
|
+
};
|
|
248
|
+
const buildSeqStep = (s, sessionFile, behaviorCwd, progressPrecreated = false, resolvedBehavior, flatIndex) => {
|
|
249
|
+
const a = agents.find((x) => x.name === s.agent);
|
|
250
|
+
const toolBudgetInput = s.toolBudget ?? params.toolBudget ?? a.toolBudget ?? params.configToolBudget;
|
|
251
|
+
const resolvedToolBudget = validateToolBudgetConfig(toolBudgetInput, s.toolBudget ? "toolBudget" : a.toolBudget ? "agent.toolBudget" : "config.toolBudget");
|
|
252
|
+
if (resolvedToolBudget.error)
|
|
253
|
+
throw new AsyncStartValidationError(resolvedToolBudget.error);
|
|
254
|
+
const stepCwd = resolveChildCwd(runnerCwd, s.cwd);
|
|
255
|
+
const instructionCwd = behaviorCwd ?? stepCwd;
|
|
256
|
+
const behavior = suppressProgressForReadOnlyTask(resolvedBehavior ?? resolveStepBehavior(a, buildStepOverrides(s), chainSkills), s.task, originalTask);
|
|
257
|
+
const skillNames = behavior.skills === false ? [] : behavior.skills;
|
|
258
|
+
const { resolved: resolvedSkills, missing: missingSkills } = resolveSkillsWithFallback(skillNames, stepCwd, ctx.cwd);
|
|
259
|
+
if (missingSkills.includes("dm-subagents"))
|
|
260
|
+
throw new UnavailableSubagentSkillError(UNAVAILABLE_SUBAGENT_SKILL_ERROR);
|
|
261
|
+
let systemPrompt = a.systemPrompt?.trim() ?? "";
|
|
262
|
+
if (resolvedSkills.length > 0) {
|
|
263
|
+
const injection = buildSkillInjection(resolvedSkills);
|
|
264
|
+
systemPrompt = systemPrompt ? `${systemPrompt}
|
|
12
265
|
|
|
13
|
-
|
|
266
|
+
${injection}` : injection;
|
|
267
|
+
}
|
|
268
|
+
const memoryInjection = buildAgentMemoryInjection(a, stepCwd);
|
|
269
|
+
if (memoryInjection) {
|
|
270
|
+
systemPrompt = systemPrompt ? `${systemPrompt}
|
|
14
271
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
272
|
+
${memoryInjection}` : memoryInjection;
|
|
273
|
+
}
|
|
274
|
+
const readInstructions = buildChainInstructions({ ...behavior, output: false, progress: false }, instructionCwd, false);
|
|
275
|
+
const isFirstProgressAgent = behavior.progress && !progressPrecreated && !progressInstructionCreated;
|
|
276
|
+
if (behavior.progress)
|
|
277
|
+
progressInstructionCreated = true;
|
|
278
|
+
const progressInstructions = buildChainInstructions({ ...behavior, output: false, reads: false }, progressDir, isFirstProgressAgent);
|
|
279
|
+
const outputPath = resolveSingleOutputPath(behavior.output, ctx.cwd, instructionCwd, outputBaseDir);
|
|
280
|
+
systemPrompt = injectOutputPathSystemPrompt(systemPrompt, outputPath);
|
|
281
|
+
const validationError = validateFileOnlyOutputMode(behavior.outputMode, outputPath, `Async step (${s.agent})`);
|
|
282
|
+
if (validationError)
|
|
283
|
+
throw new AsyncStartValidationError(validationError);
|
|
284
|
+
let taskTemplate = s.task ?? "{previous}";
|
|
285
|
+
taskTemplate = taskTemplate.replace(/\{task\}/g, originalTask ?? "");
|
|
286
|
+
taskTemplate = taskTemplate.replace(/\{chain_dir\}/g, runnerCwd);
|
|
287
|
+
const task = injectSingleOutputInstruction(`${readInstructions.prefix}${taskTemplate}${progressInstructions.suffix}`, outputPath);
|
|
288
|
+
const requestedModel = behavior.model ?? a.model;
|
|
289
|
+
const primaryModel = resolveSubagentModelOverride(requestedModel, ctx.currentModel, availableModels, ctx.currentModelProvider, { scope: ctx.modelScope, source: behavior.model ? "explicit" : "inherited" });
|
|
290
|
+
const thinkingOverride = flatIndex === undefined ? undefined : thinkingOverridesByFlatIndex?.[flatIndex];
|
|
291
|
+
const effectiveThinking = thinkingOverride ?? a.thinking;
|
|
292
|
+
const model = applyThinkingSuffix(primaryModel, effectiveThinking, thinkingOverride !== undefined);
|
|
293
|
+
return {
|
|
294
|
+
parentSessionId: ctx.parentSessionId ?? ctx.currentSessionId,
|
|
295
|
+
agent: s.agent,
|
|
296
|
+
task,
|
|
297
|
+
phase: s.phase,
|
|
298
|
+
label: s.label,
|
|
299
|
+
outputName: s.as,
|
|
300
|
+
structured: Boolean(s.outputSchema),
|
|
301
|
+
cwd: stepCwd,
|
|
302
|
+
model,
|
|
303
|
+
thinking: resolveEffectiveThinking(model, effectiveThinking),
|
|
304
|
+
modelCandidates: buildModelCandidates(primaryModel, a.fallbackModels, availableModels, ctx.currentModelProvider, { scope: ctx.modelScope }).map((candidate) => applyThinkingSuffix(candidate, effectiveThinking, thinkingOverride !== undefined)),
|
|
305
|
+
tools: a.tools,
|
|
306
|
+
extensions: a.extensions,
|
|
307
|
+
subagentOnlyExtensions: a.subagentOnlyExtensions,
|
|
308
|
+
mcpDirectTools: a.mcpDirectTools,
|
|
309
|
+
completionGuard: a.completionGuard,
|
|
310
|
+
systemPrompt,
|
|
311
|
+
systemPromptMode: a.systemPromptMode,
|
|
312
|
+
inheritProjectContext: a.inheritProjectContext,
|
|
313
|
+
inheritSkills: a.inheritSkills,
|
|
314
|
+
skills: resolvedSkills.map((r) => r.name),
|
|
315
|
+
outputPath,
|
|
316
|
+
outputMode: behavior.outputMode,
|
|
317
|
+
sessionFile,
|
|
318
|
+
maxSubagentDepth: resolveChildMaxSubagentDepth(maxSubagentDepth, a.maxSubagentDepth),
|
|
319
|
+
effectiveAcceptance: resolveEffectiveAcceptance({
|
|
320
|
+
explicit: s.acceptance,
|
|
321
|
+
agentName: s.agent,
|
|
322
|
+
task: s.task,
|
|
323
|
+
mode: resultMode,
|
|
324
|
+
async: true,
|
|
325
|
+
dynamic: false
|
|
326
|
+
}),
|
|
327
|
+
...s.outputSchema ? { structuredOutputSchema: s.outputSchema } : {},
|
|
328
|
+
...s.outputSchema ? { structuredOutput: createStructuredOutputRuntime(s.outputSchema, path.join(asyncDir, "structured-output")) } : {},
|
|
329
|
+
...resolvedToolBudget.budget ? { toolBudget: resolvedToolBudget.budget } : {}
|
|
330
|
+
};
|
|
331
|
+
};
|
|
332
|
+
let flatStepIndex = 0;
|
|
333
|
+
const nextFlatStep = () => {
|
|
334
|
+
const index = flatStepIndex;
|
|
335
|
+
const sessionFile = sessionFilesByFlatIndex?.[flatStepIndex];
|
|
336
|
+
const thinkingOverride = thinkingOverridesByFlatIndex?.[flatStepIndex];
|
|
337
|
+
flatStepIndex++;
|
|
338
|
+
return {
|
|
339
|
+
index,
|
|
340
|
+
...sessionFile ? { sessionFile } : {},
|
|
341
|
+
...thinkingOverride ? { thinkingOverride } : {}
|
|
342
|
+
};
|
|
343
|
+
};
|
|
344
|
+
try {
|
|
345
|
+
const builtSteps = chain.map((s, stepIndex) => {
|
|
346
|
+
if (isParallelStep(s)) {
|
|
347
|
+
const parallelBehaviors = s.parallel.map((task) => {
|
|
348
|
+
const agent = agents.find((candidate) => candidate.name === task.agent);
|
|
349
|
+
return suppressProgressForReadOnlyTask(resolveStepBehavior(agent, buildStepOverrides(task), chainSkills), task.task, originalTask);
|
|
350
|
+
});
|
|
351
|
+
const progressPrecreated = parallelBehaviors.some((behavior) => behavior.progress);
|
|
352
|
+
if (progressPrecreated) {
|
|
353
|
+
if (!s.worktree || params.progressDir)
|
|
354
|
+
writeInitialProgressFile(progressDir);
|
|
355
|
+
progressInstructionCreated = true;
|
|
356
|
+
}
|
|
357
|
+
return {
|
|
358
|
+
parallel: s.parallel.map((t, taskIndex) => {
|
|
359
|
+
let behaviorCwd;
|
|
360
|
+
if (s.worktree) {
|
|
361
|
+
try {
|
|
362
|
+
behaviorCwd = resolveExpectedWorktreeAgentCwd(runnerCwd, `${id}-s${stepIndex}`, taskIndex, worktreeBaseDir);
|
|
363
|
+
} catch {
|
|
364
|
+
behaviorCwd = undefined;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
const staticStep = nextFlatStep();
|
|
368
|
+
return buildSeqStep(t, staticStep.sessionFile, behaviorCwd, progressPrecreated, parallelBehaviors[taskIndex], staticStep.index);
|
|
369
|
+
}),
|
|
370
|
+
concurrency: s.concurrency,
|
|
371
|
+
failFast: s.failFast,
|
|
372
|
+
worktree: s.worktree
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
if (isDynamicParallelStep(s)) {
|
|
376
|
+
const agent = agents.find((candidate) => candidate.name === s.parallel.agent);
|
|
377
|
+
const behavior = suppressProgressForReadOnlyTask(resolveStepBehavior(agent, buildStepOverrides(s.parallel), chainSkills), s.parallel.task, originalTask);
|
|
378
|
+
const progressPrecreated = behavior.progress;
|
|
379
|
+
if (progressPrecreated) {
|
|
380
|
+
writeInitialProgressFile(progressDir);
|
|
381
|
+
progressInstructionCreated = true;
|
|
382
|
+
}
|
|
383
|
+
const maxItems = s.expand.maxItems ?? params.dynamicFanoutMaxItems ?? 0;
|
|
384
|
+
const dynamicFlatSteps = Array.from({ length: maxItems }, () => nextFlatStep());
|
|
385
|
+
return {
|
|
386
|
+
expand: s.expand,
|
|
387
|
+
parallel: buildSeqStep(s.parallel, undefined, undefined, progressPrecreated, behavior),
|
|
388
|
+
collect: s.collect,
|
|
389
|
+
concurrency: s.concurrency,
|
|
390
|
+
failFast: s.failFast,
|
|
391
|
+
phase: s.phase,
|
|
392
|
+
label: s.label,
|
|
393
|
+
sessionFiles: dynamicFlatSteps.map((step) => step.sessionFile),
|
|
394
|
+
thinkingOverrides: dynamicFlatSteps.map((step) => step.thinkingOverride),
|
|
395
|
+
effectiveAcceptance: resolveEffectiveAcceptance({
|
|
396
|
+
explicit: s.acceptance,
|
|
397
|
+
agentName: s.parallel.agent,
|
|
398
|
+
task: s.parallel.task,
|
|
399
|
+
mode: resultMode,
|
|
400
|
+
async: true,
|
|
401
|
+
dynamicGroup: true
|
|
402
|
+
})
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
const staticStep = nextFlatStep();
|
|
406
|
+
return buildSeqStep(s, staticStep.sessionFile, undefined, false, undefined, staticStep.index);
|
|
407
|
+
});
|
|
408
|
+
const steps = params.attachRoot ? [{
|
|
409
|
+
agent: params.attachRoot.agent,
|
|
410
|
+
task: "",
|
|
411
|
+
label: params.attachRoot.label ?? `Attached root ${params.attachRoot.runId}`,
|
|
412
|
+
outputName: params.attachRoot.outputName,
|
|
413
|
+
importAsyncRoot: {
|
|
414
|
+
runId: params.attachRoot.runId,
|
|
415
|
+
asyncDir: params.attachRoot.asyncDir,
|
|
416
|
+
resultPath: params.attachRoot.resultPath,
|
|
417
|
+
index: params.attachRoot.index
|
|
418
|
+
},
|
|
419
|
+
inheritProjectContext: false,
|
|
420
|
+
inheritSkills: false
|
|
421
|
+
}, ...builtSteps] : builtSteps;
|
|
422
|
+
return { steps, runnerCwd, workflowGraph, eventChain: graphChain, ...originalTask !== undefined ? { originalTask } : {} };
|
|
423
|
+
} catch (error) {
|
|
424
|
+
if (error instanceof UnavailableSubagentSkillError || error instanceof AsyncStartValidationError)
|
|
425
|
+
return { error: error.message };
|
|
426
|
+
throw error;
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
export function executeAsyncChain(id, params) {
|
|
430
|
+
const {
|
|
431
|
+
chain,
|
|
432
|
+
agents,
|
|
433
|
+
ctx,
|
|
434
|
+
cwd,
|
|
435
|
+
maxOutput,
|
|
436
|
+
artifactsDir,
|
|
437
|
+
artifactConfig,
|
|
438
|
+
shareEnabled,
|
|
439
|
+
sessionRoot,
|
|
440
|
+
sessionFilesByFlatIndex,
|
|
441
|
+
thinkingOverridesByFlatIndex,
|
|
442
|
+
maxSubagentDepth,
|
|
443
|
+
worktreeSetupHook,
|
|
444
|
+
worktreeSetupHookTimeoutMs,
|
|
445
|
+
worktreeBaseDir,
|
|
446
|
+
controlConfig,
|
|
447
|
+
controlIntercomTarget,
|
|
448
|
+
childIntercomTarget,
|
|
449
|
+
nestedRoute
|
|
450
|
+
} = params;
|
|
451
|
+
const resultMode = params.resultMode ?? "chain";
|
|
452
|
+
const inheritedNestedRoute = resolveInheritedNestedRouteFromEnv();
|
|
453
|
+
const nestedAddress = inheritedNestedRoute ? resolveNestedParentAddressFromEnv() : undefined;
|
|
454
|
+
const asyncDir = inheritedNestedRoute ? path.join(TEMP_ROOT_DIR, "nested-subagent-runs", inheritedNestedRoute.rootRunId, id) : path.join(ASYNC_DIR, id);
|
|
455
|
+
try {
|
|
456
|
+
fs.mkdirSync(asyncDir, { recursive: true });
|
|
457
|
+
} catch (error) {
|
|
458
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
459
|
+
return {
|
|
460
|
+
content: [{ type: "text", text: `Failed to create async run directory '${asyncDir}': ${message}` }],
|
|
461
|
+
isError: true,
|
|
462
|
+
details: { mode: resultMode, results: [] }
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
const built = buildAsyncRunnerSteps(id, {
|
|
466
|
+
chain,
|
|
467
|
+
task: params.task,
|
|
468
|
+
attachRoot: params.attachRoot,
|
|
469
|
+
resultMode,
|
|
470
|
+
agents,
|
|
471
|
+
ctx,
|
|
472
|
+
availableModels: params.availableModels,
|
|
473
|
+
cwd,
|
|
474
|
+
chainSkills: params.chainSkills,
|
|
475
|
+
sessionFilesByFlatIndex,
|
|
476
|
+
thinkingOverridesByFlatIndex,
|
|
477
|
+
progressDir: params.progressDir ?? (artifactsDir ? path.join(artifactsDir, "progress", id) : resultMode === "parallel" ? path.join(asyncDir, "progress") : undefined),
|
|
478
|
+
outputBaseDir: artifactsDir ? path.join(artifactsDir, "outputs", id) : undefined,
|
|
479
|
+
dynamicFanoutMaxItems: params.dynamicFanoutMaxItems,
|
|
480
|
+
maxSubagentDepth,
|
|
481
|
+
worktreeBaseDir,
|
|
482
|
+
asyncDir,
|
|
483
|
+
toolBudget: params.toolBudget,
|
|
484
|
+
configToolBudget: params.configToolBudget
|
|
485
|
+
});
|
|
486
|
+
if ("error" in built) {
|
|
487
|
+
try {
|
|
488
|
+
fs.rmSync(asyncDir, { recursive: true, force: true });
|
|
489
|
+
} catch {}
|
|
490
|
+
return formatAsyncStartError(resultMode, built.error);
|
|
491
|
+
}
|
|
492
|
+
const { steps, runnerCwd, workflowGraph, eventChain } = built;
|
|
493
|
+
const deadlineAt = params.timeoutMs !== undefined ? Date.now() + params.timeoutMs : undefined;
|
|
494
|
+
const initialTurnBudget = params.turnBudget ? initialTurnBudgetState(params.turnBudget) : undefined;
|
|
495
|
+
let childTargetIndex = 0;
|
|
496
|
+
const childIntercomTargets = childIntercomTarget ? steps.flatMap((step) => {
|
|
497
|
+
if (!("parallel" in step) && step.importAsyncRoot) {
|
|
498
|
+
childTargetIndex++;
|
|
499
|
+
return [undefined];
|
|
500
|
+
}
|
|
501
|
+
if ("parallel" in step) {
|
|
502
|
+
if (!Array.isArray(step.parallel)) {
|
|
503
|
+
childTargetIndex++;
|
|
504
|
+
return [undefined];
|
|
505
|
+
}
|
|
506
|
+
return step.parallel.map((task) => childIntercomTarget(task.agent, childTargetIndex++));
|
|
507
|
+
}
|
|
508
|
+
return [childIntercomTarget(step.agent, childTargetIndex++)];
|
|
509
|
+
}) : undefined;
|
|
510
|
+
let spawnResult = {};
|
|
511
|
+
try {
|
|
512
|
+
spawnResult = spawnRunner({
|
|
513
|
+
id,
|
|
514
|
+
steps,
|
|
515
|
+
resultPath: inheritedNestedRoute ? nestedResultsPath(inheritedNestedRoute.rootRunId, id) : path.join(RESULTS_DIR, `${id}.json`),
|
|
516
|
+
cwd: runnerCwd,
|
|
517
|
+
placeholder: "{previous}",
|
|
518
|
+
maxOutput,
|
|
519
|
+
artifactsDir: artifactConfig.enabled ? artifactsDir : undefined,
|
|
520
|
+
artifactConfig,
|
|
521
|
+
share: shareEnabled,
|
|
522
|
+
sessionDir: sessionRoot ? path.join(sessionRoot, `async-${id}`) : undefined,
|
|
523
|
+
asyncDir,
|
|
524
|
+
sessionId: ctx.currentSessionId,
|
|
525
|
+
piPackageRoot,
|
|
526
|
+
piArgv1: process.argv[1],
|
|
527
|
+
worktreeSetupHook,
|
|
528
|
+
worktreeSetupHookTimeoutMs,
|
|
529
|
+
worktreeBaseDir,
|
|
530
|
+
controlConfig,
|
|
531
|
+
turnBudget: params.turnBudget,
|
|
532
|
+
toolBudget: params.toolBudget,
|
|
533
|
+
controlIntercomTarget,
|
|
534
|
+
childIntercomTargets,
|
|
535
|
+
resultMode,
|
|
536
|
+
dynamicFanoutMaxItems: params.dynamicFanoutMaxItems,
|
|
537
|
+
timeoutMs: params.timeoutMs,
|
|
538
|
+
deadlineAt,
|
|
539
|
+
globalConcurrencyLimit: params.globalConcurrencyLimit,
|
|
540
|
+
workflowGraph,
|
|
541
|
+
nestedRoute: nestedRoute ?? inheritedNestedRoute,
|
|
542
|
+
nestedSelf: inheritedNestedRoute && nestedAddress ? {
|
|
543
|
+
parentRunId: nestedAddress.parentRunId,
|
|
544
|
+
parentStepIndex: nestedAddress.parentStepIndex,
|
|
545
|
+
depth: nestedAddress.depth,
|
|
546
|
+
path: nestedAddress.path
|
|
547
|
+
} : undefined
|
|
548
|
+
}, id, runnerCwd);
|
|
549
|
+
} catch (error) {
|
|
550
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
551
|
+
return formatAsyncStartError(resultMode, `Failed to start async ${resultMode} '${id}': ${message}`);
|
|
552
|
+
}
|
|
553
|
+
if (spawnResult.error) {
|
|
554
|
+
return formatAsyncStartError(resultMode, `Failed to start async ${resultMode} '${id}': ${spawnResult.error}`);
|
|
555
|
+
}
|
|
556
|
+
if (spawnResult.pid) {
|
|
557
|
+
const eventFirstStep = eventChain[0];
|
|
558
|
+
const firstAgents = isParallelStep(eventFirstStep) ? eventFirstStep.parallel.map((t) => t.agent) : isDynamicParallelStep(eventFirstStep) ? [eventFirstStep.parallel.agent] : [eventFirstStep.agent];
|
|
559
|
+
const parallelGroups = [];
|
|
560
|
+
const flatAgents = [];
|
|
561
|
+
let flatStepStart = 0;
|
|
562
|
+
for (let stepIndex = 0;stepIndex < eventChain.length; stepIndex++) {
|
|
563
|
+
const step = eventChain[stepIndex];
|
|
564
|
+
if (isParallelStep(step)) {
|
|
565
|
+
parallelGroups.push({ start: flatStepStart, count: step.parallel.length, stepIndex });
|
|
566
|
+
flatAgents.push(...step.parallel.map((task) => task.agent));
|
|
567
|
+
flatStepStart += step.parallel.length;
|
|
568
|
+
} else if (isDynamicParallelStep(step)) {
|
|
569
|
+
parallelGroups.push({ start: flatStepStart, count: 1, stepIndex });
|
|
570
|
+
flatAgents.push(step.parallel.agent);
|
|
571
|
+
flatStepStart++;
|
|
572
|
+
} else {
|
|
573
|
+
flatAgents.push(step.agent);
|
|
574
|
+
flatStepStart++;
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
if (inheritedNestedRoute && nestedAddress) {
|
|
578
|
+
const now = Date.now();
|
|
579
|
+
try {
|
|
580
|
+
writeNestedEvent(inheritedNestedRoute, {
|
|
581
|
+
type: "subagent.nested.started",
|
|
582
|
+
ts: now,
|
|
583
|
+
parentRunId: nestedAddress.parentRunId,
|
|
584
|
+
parentStepIndex: nestedAddress.parentStepIndex,
|
|
585
|
+
child: {
|
|
586
|
+
id,
|
|
587
|
+
parentRunId: nestedAddress.parentRunId,
|
|
588
|
+
parentStepIndex: nestedAddress.parentStepIndex,
|
|
589
|
+
depth: nestedAddress.depth,
|
|
590
|
+
path: nestedAddress.path,
|
|
591
|
+
asyncDir,
|
|
592
|
+
pid: spawnResult.pid,
|
|
593
|
+
ownerIntercomTarget: process.env.DM_SUBAGENT_INTERCOM_SESSION_NAME,
|
|
594
|
+
leafIntercomTarget: childIntercomTargets?.[0],
|
|
595
|
+
intercomTarget: childIntercomTargets?.[0],
|
|
596
|
+
ownerState: "live",
|
|
597
|
+
mode: resultMode,
|
|
598
|
+
state: "running",
|
|
599
|
+
agent: firstAgents[0],
|
|
600
|
+
agents: flatAgents,
|
|
601
|
+
chainStepCount: eventChain.length,
|
|
602
|
+
parallelGroups,
|
|
603
|
+
...params.timeoutMs !== undefined ? { timeoutMs: params.timeoutMs, deadlineAt } : {},
|
|
604
|
+
...initialTurnBudget ? { turnBudget: initialTurnBudget } : {},
|
|
605
|
+
startedAt: now,
|
|
606
|
+
lastUpdate: now
|
|
607
|
+
}
|
|
608
|
+
});
|
|
609
|
+
} catch (error) {
|
|
610
|
+
console.error("Failed to emit nested async start event:", error);
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
ctx.pi.events.emit(SUBAGENT_ASYNC_STARTED_EVENT, {
|
|
614
|
+
lifecycleArtifactVersion: SUBAGENT_LIFECYCLE_ARTIFACT_VERSION,
|
|
615
|
+
id,
|
|
616
|
+
pid: spawnResult.pid,
|
|
617
|
+
sessionId: ctx.currentSessionId,
|
|
618
|
+
mode: resultMode,
|
|
619
|
+
agent: firstAgents[0],
|
|
620
|
+
agents: flatAgents,
|
|
621
|
+
task: isParallelStep(eventFirstStep) ? eventFirstStep.parallel[0]?.task?.slice(0, 50) : isDynamicParallelStep(eventFirstStep) ? eventFirstStep.parallel.task?.slice(0, 50) : eventFirstStep.task?.slice(0, 50),
|
|
622
|
+
chain: eventChain.map((s) => isParallelStep(s) ? `[${s.parallel.map((t) => t.agent).join("+")}]` : isDynamicParallelStep(s) ? `expand:${s.parallel.agent}` : s.agent),
|
|
623
|
+
chainStepCount: eventChain.length,
|
|
624
|
+
parallelGroups,
|
|
625
|
+
workflowGraph,
|
|
626
|
+
cwd: runnerCwd,
|
|
627
|
+
asyncDir,
|
|
628
|
+
...params.timeoutMs !== undefined ? { timeoutMs: params.timeoutMs, deadlineAt } : {},
|
|
629
|
+
...initialTurnBudget ? { turnBudget: initialTurnBudget } : {},
|
|
630
|
+
nestedRoute
|
|
631
|
+
});
|
|
632
|
+
}
|
|
633
|
+
const chainDesc = chain.map((s) => isParallelStep(s) ? `[${s.parallel.map((t) => t.agent).join("+")}]` : isDynamicParallelStep(s) ? `expand:${s.parallel.agent}` : s.agent).join(" -> ");
|
|
634
|
+
return {
|
|
635
|
+
content: [{ type: "text", text: formatAsyncStartedMessage(`Async ${resultMode}: ${chainDesc} [${id}]`) }],
|
|
636
|
+
details: { mode: resultMode, runId: id, results: [], asyncId: id, asyncDir, workflowGraph, ...params.timeoutMs !== undefined ? { timeoutMs: params.timeoutMs, deadlineAt } : {}, ...params.turnBudget ? { turnBudget: params.turnBudget } : {}, ...params.toolBudget ? { toolBudget: params.toolBudget } : {} }
|
|
637
|
+
};
|
|
638
|
+
}
|
|
639
|
+
export function executeAsyncSingle(id, params) {
|
|
640
|
+
const {
|
|
641
|
+
agent,
|
|
642
|
+
agentConfig,
|
|
643
|
+
ctx,
|
|
644
|
+
cwd,
|
|
645
|
+
maxOutput,
|
|
646
|
+
artifactsDir,
|
|
647
|
+
artifactConfig,
|
|
648
|
+
shareEnabled,
|
|
649
|
+
sessionRoot,
|
|
650
|
+
sessionFile,
|
|
651
|
+
maxSubagentDepth,
|
|
652
|
+
worktreeSetupHook,
|
|
653
|
+
worktreeSetupHookTimeoutMs,
|
|
654
|
+
worktreeBaseDir,
|
|
655
|
+
controlConfig,
|
|
656
|
+
controlIntercomTarget,
|
|
657
|
+
childIntercomTarget,
|
|
658
|
+
nestedRoute
|
|
659
|
+
} = params;
|
|
660
|
+
const task = params.task ?? "";
|
|
661
|
+
const runnerCwd = resolveChildCwd(ctx.cwd, cwd);
|
|
662
|
+
const skillNames = params.skills ?? agentConfig.skills ?? [];
|
|
663
|
+
const availableModels = params.availableModels;
|
|
664
|
+
const { resolved: resolvedSkills, missing: missingSkills } = resolveSkillsWithFallback(skillNames, runnerCwd, ctx.cwd);
|
|
665
|
+
if (missingSkills.includes("dm-subagents"))
|
|
666
|
+
return formatAsyncStartError("single", UNAVAILABLE_SUBAGENT_SKILL_ERROR);
|
|
667
|
+
let systemPrompt = agentConfig.systemPrompt?.trim() ?? "";
|
|
668
|
+
if (resolvedSkills.length > 0) {
|
|
669
|
+
const injection = buildSkillInjection(resolvedSkills);
|
|
670
|
+
systemPrompt = systemPrompt ? `${systemPrompt}
|
|
19
671
|
|
|
20
|
-
|
|
672
|
+
${injection}` : injection;
|
|
673
|
+
}
|
|
674
|
+
const memoryInjection = buildAgentMemoryInjection(agentConfig, runnerCwd);
|
|
675
|
+
if (memoryInjection) {
|
|
676
|
+
systemPrompt = systemPrompt ? `${systemPrompt}
|
|
21
677
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
${W}`:W}function f0($,J,W){if($==="file-only"&&!J)return`${W} sets outputMode: "file-only" but does not configure an output file. Set output to a path or use outputMode: "inline".`;return}import*as k$ from"node:fs";import*as T$ from"node:path";var $8="@duckmind/dm-coding-agent";function J8($){let J=T$.dirname($);while(J!==T$.dirname(J)){let W=T$.join(J,"package.json");if(k$.existsSync(W)){if(JSON.parse(k$.readFileSync(W,"utf-8")).name===$8)return J}J=T$.dirname(J)}return}function I1(){try{let $=process.argv[1];return $?J8(k$.realpathSync($)):void 0}catch{return}}import*as f from"node:fs";import*as u from"node:path";import*as C$ from"node:fs";import*as W$ from"node:path";import{fileURLToPath as M8}from"node:url";class b extends Error{}var Z8=/^[A-Za-z_][A-Za-z0-9_]*$/,Q8=/^[A-Za-z_][A-Za-z0-9_]*$/,W0=/\{([A-Za-z_][A-Za-z0-9_]*)(?:\.([^{}]+))?\}/g,X8=new Set(["task","previous","chain_dir","outputs"]),w1=new Set(["expand","parallel","collect","concurrency","failFast","phase","label","acceptance"]),H8=new Set([...w1,"effectiveAcceptance","sessionFiles","thinkingOverrides"]),K8=new Set(["from","item","key","maxItems","onEmpty"]),Y8=new Set(["output","path"]),f1=new Set(["agent","task","phase","label","outputSchema","cwd","output","outputMode","reads","progress","skill","model","toolBudget","acceptance"]),q8=new Set([...f1,"outputName","structured","inheritProjectContext","inheritSkills","skills","outputPath","maxSubagentDepth","structuredOutput","structuredOutputSchema","tools","extensions","subagentOnlyExtensions","mcpDirectTools","completionGuard","systemPrompt","systemPromptMode","thinking","modelCandidates","sessionFile","effectiveAcceptance","parentSessionId"]),B8=new Set(["as","outputSchema"]);function D1($){return Z8.test($)}function y1($,J){if($==="")return;if(!$.startsWith("/"))throw new b(`${J} must be a JSON Pointer starting with '/'.`);for(let W of $.slice(1).split("/"))if(/~(?![01])/.test(W))throw new b(`${J} contains invalid JSON Pointer escape.`)}function d$($,J,W){if(!$||typeof $!=="object"||Array.isArray($))throw new b(`${W} must be an object.`);for(let Z of Object.keys($))if(!J.has(Z))throw new b(`${W} does not support field '${Z}'.`)}function U8($,J,W){for(let Z of $.matchAll(/\{([^{}]*)\}/g)){let Q=Z[0],X=Z[1];if(X===J||X.startsWith(`${J}.`)){if(!W0.test(Q)||X===`${J}.`||X.includes(".."))throw new b(`Invalid item reference '${Q}' in ${W}.`);W0.lastIndex=0;continue}W0.lastIndex=0;let H=X.match(/^[A-Za-z_][A-Za-z0-9_]*/)?.[0];if(H===J)throw new b(`Invalid item reference '${Q}' in ${W}.`);if(H&&X8.has(H))continue;if(H)throw new b(`Unsupported template reference '${Q}' in ${W}.`)}if(W0.lastIndex=0,$.includes(`{${J}.}`)||new RegExp(`\\{${J}(?:\\.|$)[^}]*$`).test($))throw new b(`Invalid item reference in ${W}.`)}function x1($){return!!$&&typeof $==="object"&&!Array.isArray($)&&(Object.prototype.hasOwnProperty.call($,"expand")||Object.prototype.hasOwnProperty.call($,"collect"))}function b1($,J,W={}){let Z=`Dynamic chain step ${J+1}`;if(d$($,W.allowRunnerFields?H8:w1,Z),!$.expand||!$.expand.from)throw new b(`${Z} requires expand.from.`);if(d$($.expand,K8,`${Z} expand`),d$($.expand.from,Y8,`${Z} expand.from`),!D1($.expand.from.output))throw new b(`${Z} has invalid expand.from.output '${$.expand.from.output}'.`);if(y1($.expand.from.path,`${Z} expand.from.path`),$.expand.key!==void 0)y1($.expand.key,`${Z} expand.key`);let Q=$.expand.item??"item";if(!Q8.test(Q))throw new b(`${Z} has invalid expand.item '${Q}'.`);if($.expand.maxItems===void 0&&W.maxItems===void 0)throw new b(`${Z} requires expand.maxItems or config.chain.dynamicFanout.maxItems.`);if($.expand.maxItems!==void 0&&(!Number.isInteger($.expand.maxItems)||$.expand.maxItems<0))throw new b(`${Z} expand.maxItems must be an integer >= 0.`);if(W.maxItems!==void 0&&(!Number.isInteger(W.maxItems)||W.maxItems<0))throw new b("config.chain.dynamicFanout.maxItems must be an integer >= 0.");if(!$.parallel||Array.isArray($.parallel))throw new b(`${Z} requires a single parallel template object and cannot mix dynamic expand/collect with static parallel arrays.`);if(d$($.parallel,W.allowRunnerFields?q8:f1,`${Z} parallel`),"expand"in $.parallel)throw new b(`${Z} does not support nested dynamic fanout.`);if(!$.parallel.agent)throw new b(`${Z} parallel.agent is required.`);if(!$.collect?.as||!D1($.collect.as))throw new b(`${Z} requires collect.as with a safe output name.`);d$($.collect,B8,`${Z} collect`);for(let[X,H]of[["parallel.task",$.parallel.task],["parallel.label",$.parallel.label]])if(H)U8(H,Q,`${Z} ${X}`)}var G8=/\{outputs\.([^}]*)\}/g,k1=/^[A-Za-z_][A-Za-z0-9_]*$/;class H$ extends Error{}function P1($){if(i($))return $.parallel.map((W)=>W.as).filter((W)=>Boolean(W));if(o($))return[$.collect.as];let J=$.as;return J?[J]:[]}function V8($){if(i($))return $.parallel.map((J)=>J.task??"{previous}");if(o($))return[$.parallel.task??"{previous}",$.parallel.label??""].filter(Boolean);return[$.task??"{previous}"]}function x0($,J={}){z8($,J)}function z8($,J={},W={}){let Z=[...W.priorOutputNames??[]],Q=new Set(Z),X=new Set(Z);for(let H=0;H<$.length;H++){let K=(W.startStepIndex??0)+H+1,Y=$[H];if(x1(Y)){if(!o(Y))throw new H$(`Dynamic chain step ${K} requires expand, a single parallel template object, and collect; dynamic expand/collect cannot be mixed with static parallel arrays.`);try{b1(Y,K-1,J)}catch(B){if(B instanceof b)throw new H$(B.message);throw B}if(!Q.has(Y.expand.from.output))throw new H$(`Dynamic chain step ${K} references unknown output '${Y.expand.from.output}'. Named outputs are only available after producing step/group completes.`)}for(let B of P1(Y)){if(!k1.test(B))throw new H$(`Invalid chain output name '${B}' at step ${K}. Use /^[A-Za-z_][A-Za-z0-9_]*$/.`);if(X.has(B))throw new H$(`Duplicate chain output name '${B}'. Each as name must be unique.`);X.add(B)}for(let B of V8(Y))for(let G of B.matchAll(G8)){let q=G[0],j=G[1];if(!k1.test(j))throw new H$(`Invalid chain output reference '${q}' at step ${K}. Use {outputs.name} with /^[A-Za-z_][A-Za-z0-9_]*$/ names.`);if(!Q.has(j))throw new H$(`Unknown chain output reference '${q}' at step ${K}. Named outputs are only available after producing step/group completes.`)}for(let B of P1(Y))Q.add(B)}}var g1={none:0,attested:1,checked:2,verified:3,reviewed:4};var j8=new Set(["changed-files","tests-added","commands-run","validation-output","residual-risks","no-staged-files","diff-summary","review-findings","manual-notes"]);function A8($){return $??"auto"}function _8($){return[...new Set($)]}function b0($){switch($){case"none":return[];case"attested":return["manual-notes","residual-risks"];case"checked":return["changed-files","tests-added","commands-run","residual-risks","no-staged-files"];case"verified":case"reviewed":return["changed-files","tests-added","commands-run","validation-output","residual-risks","no-staged-files"]}}function L8($){let J=$.agentName.toLowerCase(),W=$.task?.toLowerCase()??"",Z=[],Q=/\b(?:reviewer|scout|context-builder|researcher|analyst)\b/.test(J),X=/\b(?:read[- ]only|review[- ]only|do not edit|don't edit|no edits|without edits|inspect|summari[sz]e)\b/.test(W),H=/\b(?:fix|implement|update|write|edit|modify|migrate|release|security|delete|remove|refactor|commit)\b/.test(W)||/\bworker\b/.test(J);if(Boolean($.async&&H)||Boolean($.dynamic)||Boolean($.dynamicGroup)||/\b(?:release|migration|migrate|security|data[- ]loss|destructive|post-review|fix pass)\b/.test(W)){if(Z.push($.async?"async write-capable or risky run":"risky write-capable run"),$.dynamic||$.dynamicGroup)Z.push("dynamic fanout context");return{level:"reviewed",reasons:Z,criteria:["Implement the requested change without widening scope","Return evidence sufficient for an independent acceptance review"],evidence:b0("reviewed"),review:{agent:"reviewer",required:!0}}}if(H&&!X)return Z.push("write-capable worker/task"),{level:"checked",reasons:Z,criteria:["Implement the requested change without widening scope"],evidence:b0("checked")};if(Q||X)return Z.push(Q?"read-only/reviewer-style agent":"read-only task wording"),{level:"attested",reasons:Z,criteria:["Return concrete findings with file paths and severity when applicable"],evidence:["review-findings","residual-risks"]};return Z.push("default lightweight attestation"),{level:"attested",reasons:Z,criteria:["Return a concise result and residual risks when applicable"],evidence:["manual-notes","residual-risks"]}}function O8($){if($===void 0||$==="auto")return{level:"auto"};if($===!1)return{level:"none",reason:"disabled by deprecated false shorthand"};if(typeof $==="string")return{level:$};return{...$}}function F8($){return $.level==="none"&&typeof $.reason==="string"&&$.reason.trim().length>0}function T8($,J){return($??[]).map((W,Z)=>{if(typeof W==="string")return{id:`criterion-${Z+1}`,must:W,evidence:J,severity:"required"};return{id:W.id?.trim()||`criterion-${Z+1}`,must:W.must??"",evidence:W.evidence?.filter((Q)=>j8.has(Q))??J,severity:W.severity??"required"}}).filter((W)=>W.must.trim())}function Z0($){let J=O8($.explicit),W=L8($),Z=A8(J.level),Q=F8(J)?"none":Z==="auto"?W.level:g1[Z]>=g1[W.level]?Z:W.level,X=_8([...Q===W.level?W.evidence:b0(Q),...J.evidence??[]]),H=T8(J.criteria?.length?J.criteria:W.criteria,X),K=J.review!==void 0?J.review:W.review;if(Q==="reviewed"&&Z!=="auto"&&Z!=="reviewed"&&J.review===void 0&&K&&K!==!1)K={...K,required:!1};return{level:Q,explicit:$.explicit!==void 0,inferredReason:W.reasons,criteria:H,evidence:X,verify:J.verify??[],review:K,stopRules:J.stopRules??[],reason:J.reason}}function m1($){return t$($).baseModel}function N8($){let J=$.replace(/[.+^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");return new RegExp(`^${J}$`,"i")}function E8($,J){return N8(J).test(m1($))}function k0($,J,W){if(!$||!J?.enforce)return;let Z=J.allow;if(!Z||Z.length===0)return;if(Z.some((H)=>E8($,H)))return;let Q=m1($);return{model:Q,severity:W==="explicit"?"error":"warn",allowedPatterns:Z,message:`Model '${Q}' is outside the configured subagent model scope. Allowed patterns: ${Z.join(", ")}.`}}function u1($){let J=$;while(!0){if(c1(X$(J))||c1(W$.join(J,".agents")))return J;let W=W$.dirname(J);if(W===J)return null;J=W}}function c1($){try{return C$.statSync($).isDirectory()}catch{return!1}}var n9=W$.resolve(W$.dirname(M8(import.meta.url)),"..","..","agents");var d1="agent-memory",P0="MEMORY.md",g0=200,D$=16384,R8=new Set(["edit","write","bash"]);function I8($){let J=$.tools;if(!J)return!0;return J.some((W)=>R8.has(W))}function p1($,J){let W=u.relative(J,$);return W!==""&&!W.startsWith("..")&&!u.isAbsolute(W)}function S8($,J){let W=J.trim();if(W.length===0)return{error:"memory path is empty"};if(W.includes("\x00"))return{error:"memory path contains a NUL byte"};if(u.isAbsolute(W)||u.posix.isAbsolute(W)||u.win32.isAbsolute(W)||/^[A-Za-z]:/.test(W))return{error:"memory path must be relative"};let Z=W.split(/[/\\]/).map((X)=>X.trim()).filter((X)=>X.length>0);if(Z.length===0)return{error:"memory path is empty"};for(let X of Z){if(X==="."||X==="..")return{error:`memory path segment '${X}' is not allowed`};if(X.includes(":"))return{error:"memory path segments must not contain ':'"}}let Q=u.resolve($,...Z);if(!p1(Q,$))return{error:"memory path escapes the memory root"};try{if(f.existsSync($)&&f.lstatSync($).isSymbolicLink())return{error:"memory root must not be a symlink"};let X=f.existsSync($)?f.realpathSync($):u.resolve($),H=$;for(let K of Z){if(H=u.join(H,K),!f.existsSync(H))break;let Y=f.realpathSync(H);if(!p1(Y,X))return{error:"memory path resolves outside the memory root"}}}catch{return{error:"memory path could not be verified"}}return{dir:Q}}function D8($){let W=$.split(`
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
`)}function w8($){let J=$.lastIndexOf(":");if(J===-1)return{baseModel:$,thinkingSuffix:""};return{baseModel:$.substring(0,J),thinkingSuffix:$.substring(J)}}var f8="inherit";function N$($){return $.toLowerCase().replace(/[._]+/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"")}function n1($,J,W){let Z=Number($),Q=Number(J),X=Number(W);return Z>=1900&&Z<=2099&&Q>=1&&Q<=12&&X>=1&&X<=31}function l1($){let J=/^(.*)-(\d{4})-(\d{2})-(\d{2})$/.exec($);if(J&&n1(J[2],J[3],J[4]))return J[1];let W=/^(.*)-(\d{4})(\d{2})(\d{2})$/.exec($);if(W&&n1(W[2],W[3],W[4]))return W[1];return $}function o1($,J,W){if($.includes("/")){let Z=J.find((Q)=>Q.fullId===$);if(Z)return Z.fullId}else{let Z=J.filter((Q)=>Q.id===$);if(W){let Q=Z.find((X)=>X.provider===W);if(Q)return Q.fullId}if(Z.length===1)return Z[0].fullId}return x8($,J,W)}function x8($,J,W){let Z,Q=$,X=$.indexOf("/");if(X!==-1)Z=N$($.slice(0,X)),Q=$.slice(X+1);else{let B=[":","."];for(let G of B){let q=$.indexOf(G);if(q<=0)continue;let j=N$($.slice(0,q));if(!J.some((O)=>N$(O.provider)===j))continue;Z=j,Q=$.slice(q+1);break}}let H=N$(Q),K=l1(H),Y=J.filter((B)=>{let G=N$(B.id);if(G!==H&&l1(G)!==K)return!1;if(Z!==void 0&&N$(B.provider)!==Z)return!1;return!0});if(Y.length===0)return;if(W){let B=N$(W),G=Y.find((q)=>N$(q.provider)===B);if(G)return G.fullId}if(Y.length===1)return Y[0].fullId;return}function s1($,J,W){if(!$)return;if(!J||J.length===0)return $;let Z=o1($,J,W);if(Z)return Z;let{baseModel:Q,thinkingSuffix:X}=w8($);if(!X)return $;let H=o1(Q,J,W);if(H)return`${H}${X}`;return $}function i1($){console.warn(`[dm-subagents] ${$.message}`)}function v0($,J,W,Z,Q){let X=typeof $==="string"?$.trim():"",H=X&&X!==f8?X:void 0,K;if(H===void 0)K=J?`${J.provider}/${J.id}`:void 0;else K=s1(H,W,Z);if(K&&Q?.scope?.enforce){let Y=H===void 0?"inherited":Q.source??"inherited",B=k0(K,Q.scope,Y);if(B){if(B.severity==="error")throw Error(B.message);(Q.onWarn??i1)(B)}}return K}function m0($,J,W,Z,Q){let X=new Set,H=[],K=[$,...J??[]];for(let Y=0;Y<K.length;Y++){let B=K[Y];if(!B)continue;let G=s1(B.trim(),W,Z);if(!G||X.has(G))continue;if(Y>0&&Q?.scope?.enforce){let q=k0(G,Q.scope,"inherited");if(q)(Q.onWarn??i1)(q)}X.add(G),H.push(G)}return H}import{spawnSync as b8}from"node:child_process";import*as B$ from"node:fs";import*as Q0 from"node:os";import*as t from"node:path";function r1($,J){let W=b8("git",["-C",$,...J],{encoding:"utf-8"});return{stdout:W.stdout??"",stderr:W.stderr??"",status:W.status}}function a1($,J){let W=r1($,J);if(W.status!==0){let Z=`git -C ${$} ${J.join(" ")}`,Q=W.stderr.trim()||W.stdout.trim()||`${Z} failed`;throw Error(Q)}return W.stdout}function k8($,J){let W=$??process.env.DM_SUBAGENTS_WORKTREE_DIR;if(W===void 0)return Q0.tmpdir();let Z=W.trim();if(!Z)throw Error("worktree base directory cannot be empty");let Q=Z.startsWith("~/")?t.join(Q0.homedir(),Z.slice(2)):Z,X=t.isAbsolute(Q)?Q:t.resolve(J,Q);try{B$.mkdirSync(X,{recursive:!0})}catch(H){let K=H instanceof Error?H.message:String(H);throw Error(`failed to create worktree base directory ${X}: ${K}`)}return X}function P8($,J,W){return t.join($,`dm-worktree-${J}-${W}`)}function g8($){let J=r1($,["rev-parse","--is-inside-work-tree"]);if(J.status!==0||J.stdout.trim()!=="true")throw Error("worktree isolation requires a git repository");let W=a1($,["rev-parse","--show-prefix"]).trim(),Z=W?t.normalize(W.replace(/[\\/]+$/,"")):"";return Z==="."?"":Z}function t1($,J,W,Z){let Q=g8($),X=a1($,["rev-parse","--show-toplevel"]).trim(),H=P8(k8(Z,X),J,W);return Q?t.join(H,Q):H}function h8($){switch($){case"complete":case"completed":return"completed";case"running":return"running";case"failed":return"failed";case"paused":return"paused";case"detached":return"detached";case"pending":return"pending";default:return}}function v8($){if(!$)return;if($.detached)return"detached";if($.interrupted)return"paused";return $.exitCode===0?"completed":"failed"}function c0($,J){return h8($.stepStatuses?.[J]?.status)??v8($.results?.[J])??($.currentFlatIndex===J?"running":"pending")}function u0($,J,W){if(!J)return;let Z=$.find((Q)=>Q.title===J);if(!Z)Z={title:J,nodeIds:[]},$.push(Z);Z.nodeIds.push(W)}function m8($,J){return $.label?.trim()||$.agent||`Step ${J+1}`}function e1($){if($.some((J)=>J==="running"))return"running";if($.some((J)=>J==="failed"))return"failed";if($.some((J)=>J==="paused"))return"paused";if($.some((J)=>J==="detached"))return"detached";if($.length>0&&$.every((J)=>J==="completed"))return"completed";if($.some((J)=>J==="completed"))return"running";return"pending"}function $J($){let J=[],W=[],Z=0,Q;for(let X=0;X<$.steps.length;X++){let H=$.steps[X];if(i(H)){let G=`step-${X}`,q=[],j=[];for(let C=0;C<H.parallel.length;C++){let _=H.parallel[C],M=c0($,Z);j.push(M);let F=`step-${X}-agent-${C}`,g={id:F,kind:"agent",agent:_.agent,phase:_.phase,label:_.label?.trim()||_.agent||`Agent ${C+1}`,status:M,flatIndex:Z,stepIndex:X,outputName:_.as,structured:Boolean(_.outputSchema),acceptanceStatus:$.results?.[Z]?.acceptance?.status,error:$.stepStatuses?.[Z]?.error??$.results?.[Z]?.error};if(q.push(g),u0(W,_.phase,F),M==="running"||$.currentFlatIndex===Z)Q=F;Z++}let O=e1(j);if($.currentStepIndex===X&&!Q)Q=G;J.push({id:G,kind:"parallel-group",label:H.parallel.length===1?"Parallel task":`Parallel group (${H.parallel.length})`,status:O,stepIndex:X,children:q});continue}if(o(H)){let G=`step-${X}`,q=$.dynamicChildren?.[X]??[],j=$.dynamicGroupStatuses?.[X],O=[],C=[];for(let M=0;M<q.length;M++){let F=q[M],g=c0($,F.flatIndex);C.push(g);let p=`step-${X}-item-${F.itemKey.replace(/[^a-zA-Z0-9_-]/g,"-")}`,Z$={id:p,kind:"agent",agent:F.agent,phase:H.parallel.phase??H.phase,label:F.label?.trim()||H.parallel.label?.trim()||`${F.agent} ${F.itemKey}`,status:g,flatIndex:F.flatIndex,stepIndex:X,itemKey:F.itemKey,outputName:F.outputName,structured:F.structured,acceptanceStatus:$.results?.[F.flatIndex]?.acceptance?.status,error:$.stepStatuses?.[F.flatIndex]?.error??$.results?.[F.flatIndex]?.error??F.error};if(O.push(Z$),u0(W,Z$.phase,p),g==="running"||$.currentFlatIndex===F.flatIndex)Q=p}let _=j?.status??(O.length>0?e1(C):$.currentStepIndex===X?"running":"pending");if($.currentStepIndex===X&&!Q)Q=G;if(J.push({id:G,kind:"dynamic-parallel-group",label:H.label?.trim()||H.parallel.label?.trim()||`Dynamic fanout (${H.collect.as})`,status:_,stepIndex:X,outputName:H.collect.as,structured:Boolean(H.collect.outputSchema),acceptanceStatus:j?.acceptance?.status,error:j?.error,dynamic:{sourceOutput:H.expand.from.output,sourcePath:H.expand.from.path,itemName:H.expand.item??"item",maxItems:H.expand.maxItems,collectAs:H.collect.as},children:O}),q.length>0)Z=Math.max(Z,...q.map((M)=>M.flatIndex+1));continue}let K=H,Y=c0($,Z),B=`step-${X}`;if(J.push({id:B,kind:"step",agent:K.agent,phase:K.phase,label:m8(K,X),status:Y,flatIndex:Z,stepIndex:X,outputName:K.as,structured:Boolean(K.outputSchema),acceptanceStatus:$.results?.[Z]?.acceptance?.status,error:$.stepStatuses?.[Z]?.error??$.results?.[Z]?.error}),u0(W,K.phase,B),Y==="running"||$.currentFlatIndex===Z||$.currentStepIndex===X)Q=B;Z++}return{runId:$.runId,mode:$.mode??"chain",phases:W,nodes:J,currentNodeId:Q}}import{randomUUID as i8}from"node:crypto";import*as U$ from"node:fs";import*as d from"node:path";import*as c8 from"node:fs";import*as y$ from"node:path";var u8=[10,25,50,100,200,500,1000,2000,4000],d8=new Set(["EACCES","EBUSY","EPERM"]),JJ=typeof SharedArrayBuffer<"u"?new SharedArrayBuffer(4):void 0,WJ=JJ?new Int32Array(JJ):void 0;function p8($){if($<=0)return;if(WJ)try{Atomics.wait(WJ,0,0,$);return}catch{}let J=Date.now()+$;while(Date.now()<J);}function n8($){let J=$?.code;return typeof J==="string"&&d8.has(J)}function l8($,J,W,Z,Q){for(let X=0;;X++)try{$.renameSync(J,W);return}catch(H){let K=Z[X];if(K===void 0||!n8(H))throw H;Q(K)}}function o8($={}){let J=$.fs??c8,W=$.now??Date.now,Z=$.pid??process.pid,Q=$.random??Math.random,H=$.retryRenameErrors??process.platform==="win32"?$.retryDelaysMs??u8:[],K=$.wait??p8;return(Y,B)=>{J.mkdirSync(y$.dirname(Y),{recursive:!0});let G=y$.join(y$.dirname(Y),`.${y$.basename(Y)}.${Z}.${W()}.${Q().toString(36).slice(2)}.tmp`);try{J.writeFileSync(G,JSON.stringify(B,null,2),"utf-8"),l8(J,G,Y,H,K)}finally{J.rmSync(G,{force:!0})}}}var s8=o8();var ZJ=d.join($$,"nested-subagent-events"),r8="route.json";var HJ=65536,QJ=12,KJ=16,X0=3;function p$($){return G0($)}function a8($,J){if(!p$(J))throw Error(`${$} must be a non-empty safe id token.`)}function H0($,J){a8($,J)}function XJ($,J){let W=d.resolve($),Z=d.resolve(J);return Z===W||Z.startsWith(`${W}${d.sep}`)}function YJ($){return d.dirname(d.resolve($.eventSink))}function qJ($){if(H0("rootRunId",$.rootRunId),H0("capabilityToken",$.capabilityToken),!XJ(ZJ,$.eventSink))throw Error("Nested event sink is outside the subagent nested event root.");if(!XJ(ZJ,$.controlInbox))throw Error("Nested control inbox is outside the subagent nested event root.");if(YJ($)!==d.dirname(d.resolve($.controlInbox)))throw Error("Nested event sink and control inbox must share one route root.")}function t8($=process.env){let J=$[O1],W=$[_1],Z=$[L1],Q=$[E1];if(!J||!W||!Z||!Q)return;let X={rootRunId:J,eventSink:W,controlInbox:Z,capabilityToken:Q};qJ(X);let H=d.join(YJ(X),r8),K=JSON.parse(U$.readFileSync(H,"utf-8"));if(K.rootRunId!==J||K.capabilityToken!==Q)throw Error("Nested event route metadata does not match the provided root id and capability token.");return X}function d0($=process.env){try{return t8($)}catch(J){console.error("Ignoring invalid nested subagent event route:",J);return}}function p0($=process.env){let J=$[F1];if(!p$(J))return;let W=$[T1],Z=W&&/^\d+$/.test(W)?Number(W):void 0,Q=Math.min(Math.max(1,z(Number($[C1]))??1),X0),X=z0($[N1]),H=X.length?X:[{runId:J,...Z!==void 0?{stepIndex:Z}:{}}];return{parentRunId:J,...Z!==void 0?{parentStepIndex:Z}:{},depth:Q,path:H}}function z($){return typeof $==="number"&&Number.isFinite($)?$:void 0}function T($,J=512){return typeof $==="string"&&$.length>0?$.slice(0,J):void 0}function e8($){if(!$||typeof $!=="object")return;let J=$,W=z(J.input),Z=z(J.output),Q=z(J.total);return W!==void 0&&Z!==void 0&&Q!==void 0?{input:W,output:Z,total:Q}:void 0}function $2($){if(!$||typeof $!=="object")return;let J=$,W=z(J.inputTokens),Z=z(J.outputTokens),Q=z(J.costUsd);return W!==void 0&&Z!==void 0&&Q!==void 0?{inputTokens:W,outputTokens:Z,costUsd:Q}:void 0}function K0($){if(!$||typeof $!=="object")return;let J=$,W=z(J.maxTurns),Z=z(J.graceTurns),Q=z(J.turnCount),X=J.outcome==="within-budget"||J.outcome==="wrap-up-requested"||J.outcome==="exceeded"?J.outcome:void 0;if(W===void 0||Z===void 0||Q===void 0||!X)return;return{maxTurns:W,graceTurns:Z,turnCount:Q,outcome:X,...z(J.wrapUpRequestedAtTurn)!==void 0?{wrapUpRequestedAtTurn:z(J.wrapUpRequestedAtTurn)}:{},...z(J.exceededAtTurn)!==void 0?{exceededAtTurn:z(J.exceededAtTurn)}:{}}}function J2($,J){return $==="queued"||$==="running"||$==="complete"||$==="failed"||$==="paused"?$:J}function W2($,J){if(!$||typeof $!=="object")return;let W=$,Z=T(W.agent,128);if(!Z)return;let Q=W.status==="pending"||W.status==="running"||W.status==="complete"||W.status==="completed"||W.status==="failed"||W.status==="paused"?W.status:"pending";return{agent:Z,status:Q,...T(W.sessionFile,2048)?{sessionFile:T(W.sessionFile,2048)}:{},...W.activityState==="active_long_running"||W.activityState==="needs_attention"?{activityState:W.activityState}:{},...z(W.lastActivityAt)!==void 0?{lastActivityAt:z(W.lastActivityAt)}:{},...T(W.currentTool,128)?{currentTool:T(W.currentTool,128)}:{},...z(W.currentToolStartedAt)!==void 0?{currentToolStartedAt:z(W.currentToolStartedAt)}:{},...T(W.currentPath,2048)?{currentPath:T(W.currentPath,2048)}:{},...z(W.turnCount)!==void 0?{turnCount:z(W.turnCount)}:{},...z(W.toolCount)!==void 0?{toolCount:z(W.toolCount)}:{},...z(W.startedAt)!==void 0?{startedAt:z(W.startedAt)}:{},...z(W.endedAt)!==void 0?{endedAt:z(W.endedAt)}:{},...T(W.error,1024)?{error:T(W.error,1024)}:{},...W.timedOut===!0?{timedOut:!0}:{},...K0(W.turnBudget)?{turnBudget:K0(W.turnBudget)}:{},...W.turnBudgetExceeded===!0?{turnBudgetExceeded:!0}:{},...W.wrapUpRequested===!0?{wrapUpRequested:!0}:{},...J<X0&&Array.isArray(W.children)?{children:W.children.map((X)=>n0(X,J+1)).filter((X)=>Boolean(X)).slice(0,KJ)}:{}}}function n0($,J=0){if(!$||typeof $!=="object")return;let W=$;if(!p$(W.id)||!p$(W.parentRunId))return;let Z=V0(W.path),Q=Array.isArray(W.steps)?W.steps.map((K)=>W2(K,J+1)).filter((K)=>Boolean(K)).slice(0,QJ):void 0,X=e8(W.totalTokens),H=$2(W.totalCost);return{id:W.id,parentRunId:W.parentRunId,...z(W.parentStepIndex)!==void 0?{parentStepIndex:z(W.parentStepIndex)}:{},...T(W.parentAgent,128)?{parentAgent:T(W.parentAgent,128)}:{},depth:Math.min(Math.max(0,z(W.depth)??0),X0),path:Z,state:J2(W.state,"running"),...T(W.asyncDir,2048)?{asyncDir:T(W.asyncDir,2048)}:{},...z(W.pid)!==void 0&&z(W.pid)>0&&Number.isInteger(z(W.pid))?{pid:z(W.pid)}:{},...T(W.sessionId,256)?{sessionId:T(W.sessionId,256)}:{},...T(W.sessionFile,2048)?{sessionFile:T(W.sessionFile,2048)}:{},...T(W.intercomTarget,256)?{intercomTarget:T(W.intercomTarget,256)}:{},...T(W.ownerIntercomTarget,256)?{ownerIntercomTarget:T(W.ownerIntercomTarget,256)}:{},...T(W.leafIntercomTarget,256)?{leafIntercomTarget:T(W.leafIntercomTarget,256)}:{},...W.ownerState==="live"||W.ownerState==="gone"||W.ownerState==="unknown"?{ownerState:W.ownerState}:{},...T(W.controlInbox,2048)?{controlInbox:T(W.controlInbox,2048)}:{},...T(W.capabilityToken,128)?{capabilityToken:T(W.capabilityToken,128)}:{},...W.mode==="single"||W.mode==="parallel"||W.mode==="chain"?{mode:W.mode}:{},...T(W.agent,128)?{agent:T(W.agent,128)}:{},...Array.isArray(W.agents)?{agents:W.agents.map((K)=>T(K,128)).filter((K)=>Boolean(K)).slice(0,QJ)}:{},...z(W.currentStep)!==void 0?{currentStep:z(W.currentStep)}:{},...z(W.chainStepCount)!==void 0?{chainStepCount:z(W.chainStepCount)}:{},...W.activityState==="active_long_running"||W.activityState==="needs_attention"?{activityState:W.activityState}:{},...z(W.lastActivityAt)!==void 0?{lastActivityAt:z(W.lastActivityAt)}:{},...T(W.currentTool,128)?{currentTool:T(W.currentTool,128)}:{},...z(W.currentToolStartedAt)!==void 0?{currentToolStartedAt:z(W.currentToolStartedAt)}:{},...T(W.currentPath,2048)?{currentPath:T(W.currentPath,2048)}:{},...z(W.turnCount)!==void 0?{turnCount:z(W.turnCount)}:{},...z(W.toolCount)!==void 0?{toolCount:z(W.toolCount)}:{},...X?{totalTokens:X}:{},...H?{totalCost:H}:{},...z(W.startedAt)!==void 0?{startedAt:z(W.startedAt)}:{},...z(W.endedAt)!==void 0?{endedAt:z(W.endedAt)}:{},...z(W.lastUpdate)!==void 0?{lastUpdate:z(W.lastUpdate)}:{},...z(W.timeoutMs)!==void 0?{timeoutMs:z(W.timeoutMs)}:{},...z(W.deadlineAt)!==void 0?{deadlineAt:z(W.deadlineAt)}:{},...W.timedOut===!0?{timedOut:!0}:{},...K0(W.turnBudget)?{turnBudget:K0(W.turnBudget)}:{},...W.turnBudgetExceeded===!0?{turnBudgetExceeded:!0}:{},...W.wrapUpRequested===!0?{wrapUpRequested:!0}:{},...T(W.error,1024)?{error:T(W.error,1024)}:{},...Q&&Q.length>0?{steps:Q}:{},...J<X0&&Array.isArray(W.children)?{children:W.children.map((K)=>n0(K,J+1)).filter((K)=>Boolean(K)).slice(0,KJ)}:{}}}function Z2($,J){if(Buffer.byteLength($,"utf-8")>HJ)return;let W;try{W=JSON.parse($)}catch{return}if(!W||typeof W!=="object")return;let Z=W;if(Z.type!=="subagent.nested.started"&&Z.type!=="subagent.nested.updated"&&Z.type!=="subagent.nested.completed")return;if(Z.rootRunId!==J.rootRunId||Z.capabilityToken!==J.capabilityToken)return;if(!p$(Z.parentRunId))return;let Q=z(Z.ts);if(Q===void 0)return;let X=n0(Z.child);if(!X||X.id===J.rootRunId)return;let H={...X,controlInbox:J.controlInbox,capabilityToken:J.capabilityToken,ownerState:X.ownerState??"unknown"};return{type:Z.type,ts:Q,rootRunId:J.rootRunId,parentRunId:Z.parentRunId,...z(Z.parentStepIndex)!==void 0?{parentStepIndex:z(Z.parentStepIndex)}:{},capabilityToken:J.capabilityToken,child:H}}function Q2($,J,W){let Z=`${JSON.stringify(W)}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
678
|
+
${memoryInjection}` : memoryInjection;
|
|
679
|
+
}
|
|
680
|
+
const inheritedNestedRoute = resolveInheritedNestedRouteFromEnv();
|
|
681
|
+
const nestedAddress = inheritedNestedRoute ? resolveNestedParentAddressFromEnv() : undefined;
|
|
682
|
+
const asyncDir = inheritedNestedRoute ? path.join(TEMP_ROOT_DIR, "nested-subagent-runs", inheritedNestedRoute.rootRunId, id) : path.join(ASYNC_DIR, id);
|
|
683
|
+
try {
|
|
684
|
+
fs.mkdirSync(asyncDir, { recursive: true });
|
|
685
|
+
} catch (error) {
|
|
686
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
687
|
+
return {
|
|
688
|
+
content: [{ type: "text", text: `Failed to create async run directory '${asyncDir}': ${message}` }],
|
|
689
|
+
isError: true,
|
|
690
|
+
details: { mode: "single", results: [] }
|
|
691
|
+
};
|
|
692
|
+
}
|
|
693
|
+
const effectiveOutput = normalizeSingleOutputOverride(params.output, agentConfig.output);
|
|
694
|
+
const outputPath = resolveSingleOutputPath(effectiveOutput, ctx.cwd, runnerCwd, params.outputBaseDir ?? (artifactsDir ? path.join(artifactsDir, "outputs", id) : undefined));
|
|
695
|
+
systemPrompt = injectOutputPathSystemPrompt(systemPrompt, outputPath);
|
|
696
|
+
const outputMode = params.outputMode ?? "inline";
|
|
697
|
+
const validationError = validateFileOnlyOutputMode(outputMode, outputPath, `Async single run (${agent})`);
|
|
698
|
+
if (validationError)
|
|
699
|
+
return formatAsyncStartError("single", validationError);
|
|
700
|
+
const taskWithOutputInstruction = injectSingleOutputInstruction(task, outputPath);
|
|
701
|
+
const primaryModel = resolveSubagentModelOverride(params.modelOverride ?? agentConfig.model, ctx.currentModel, availableModels, ctx.currentModelProvider);
|
|
702
|
+
const effectiveThinking = params.thinkingOverride ?? agentConfig.thinking;
|
|
703
|
+
const model = applyThinkingSuffix(primaryModel, effectiveThinking, params.thinkingOverride !== undefined);
|
|
704
|
+
const toolBudgetInput = params.toolBudget ?? agentConfig.toolBudget ?? params.configToolBudget;
|
|
705
|
+
const resolvedToolBudget = validateToolBudgetConfig(toolBudgetInput, params.toolBudget ? "toolBudget" : agentConfig.toolBudget ? "agent.toolBudget" : "config.toolBudget");
|
|
706
|
+
if (resolvedToolBudget.error)
|
|
707
|
+
return formatAsyncStartError("single", resolvedToolBudget.error);
|
|
708
|
+
const deadlineAt = params.timeoutMs !== undefined ? Date.now() + params.timeoutMs : undefined;
|
|
709
|
+
const initialTurnBudget = params.turnBudget ? initialTurnBudgetState(params.turnBudget) : undefined;
|
|
710
|
+
let spawnResult = {};
|
|
711
|
+
try {
|
|
712
|
+
spawnResult = spawnRunner({
|
|
713
|
+
id,
|
|
714
|
+
steps: [
|
|
715
|
+
{
|
|
716
|
+
parentSessionId: ctx.parentSessionId ?? ctx.currentSessionId,
|
|
717
|
+
agent,
|
|
718
|
+
task: taskWithOutputInstruction,
|
|
719
|
+
cwd: runnerCwd,
|
|
720
|
+
model,
|
|
721
|
+
thinking: resolveEffectiveThinking(model, effectiveThinking),
|
|
722
|
+
modelCandidates: buildModelCandidates(primaryModel, agentConfig.fallbackModels, availableModels, ctx.currentModelProvider, { scope: ctx.modelScope }).map((candidate) => applyThinkingSuffix(candidate, effectiveThinking, params.thinkingOverride !== undefined)),
|
|
723
|
+
tools: agentConfig.tools,
|
|
724
|
+
extensions: agentConfig.extensions,
|
|
725
|
+
subagentOnlyExtensions: agentConfig.subagentOnlyExtensions,
|
|
726
|
+
mcpDirectTools: agentConfig.mcpDirectTools,
|
|
727
|
+
completionGuard: agentConfig.completionGuard,
|
|
728
|
+
systemPrompt,
|
|
729
|
+
systemPromptMode: agentConfig.systemPromptMode,
|
|
730
|
+
inheritProjectContext: agentConfig.inheritProjectContext,
|
|
731
|
+
inheritSkills: agentConfig.inheritSkills,
|
|
732
|
+
skills: resolvedSkills.map((r) => r.name),
|
|
733
|
+
outputPath,
|
|
734
|
+
outputMode,
|
|
735
|
+
sessionFile,
|
|
736
|
+
maxSubagentDepth: resolveChildMaxSubagentDepth(maxSubagentDepth, agentConfig.maxSubagentDepth),
|
|
737
|
+
effectiveAcceptance: resolveEffectiveAcceptance({
|
|
738
|
+
explicit: params.acceptance,
|
|
739
|
+
agentName: agent,
|
|
740
|
+
task,
|
|
741
|
+
mode: "single",
|
|
742
|
+
async: true
|
|
743
|
+
}),
|
|
744
|
+
...resolvedToolBudget.budget ? { toolBudget: resolvedToolBudget.budget } : {}
|
|
745
|
+
}
|
|
746
|
+
],
|
|
747
|
+
resultPath: inheritedNestedRoute ? nestedResultsPath(inheritedNestedRoute.rootRunId, id) : path.join(RESULTS_DIR, `${id}.json`),
|
|
748
|
+
cwd: runnerCwd,
|
|
749
|
+
placeholder: "{previous}",
|
|
750
|
+
maxOutput,
|
|
751
|
+
artifactsDir: artifactConfig.enabled ? artifactsDir : undefined,
|
|
752
|
+
artifactConfig,
|
|
753
|
+
share: shareEnabled,
|
|
754
|
+
sessionDir: sessionRoot ? path.join(sessionRoot, `async-${id}`) : undefined,
|
|
755
|
+
asyncDir,
|
|
756
|
+
sessionId: ctx.currentSessionId,
|
|
757
|
+
piPackageRoot,
|
|
758
|
+
piArgv1: process.argv[1],
|
|
759
|
+
worktreeSetupHook,
|
|
760
|
+
worktreeSetupHookTimeoutMs,
|
|
761
|
+
worktreeBaseDir,
|
|
762
|
+
controlConfig,
|
|
763
|
+
timeoutMs: params.timeoutMs,
|
|
764
|
+
deadlineAt,
|
|
765
|
+
turnBudget: params.turnBudget,
|
|
766
|
+
toolBudget: params.toolBudget,
|
|
767
|
+
controlIntercomTarget,
|
|
768
|
+
childIntercomTargets: childIntercomTarget ? [childIntercomTarget(agent, 0)] : undefined,
|
|
769
|
+
resultMode: "single",
|
|
770
|
+
nestedRoute: nestedRoute ?? inheritedNestedRoute,
|
|
771
|
+
nestedSelf: inheritedNestedRoute && nestedAddress ? {
|
|
772
|
+
parentRunId: nestedAddress.parentRunId,
|
|
773
|
+
parentStepIndex: nestedAddress.parentStepIndex,
|
|
774
|
+
depth: nestedAddress.depth,
|
|
775
|
+
path: nestedAddress.path
|
|
776
|
+
} : undefined
|
|
777
|
+
}, id, runnerCwd);
|
|
778
|
+
} catch (error) {
|
|
779
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
780
|
+
return formatAsyncStartError("single", `Failed to start async run '${id}': ${message}`);
|
|
781
|
+
}
|
|
782
|
+
if (spawnResult.error) {
|
|
783
|
+
return formatAsyncStartError("single", `Failed to start async run '${id}': ${spawnResult.error}`);
|
|
784
|
+
}
|
|
785
|
+
if (spawnResult.pid) {
|
|
786
|
+
if (inheritedNestedRoute && nestedAddress) {
|
|
787
|
+
const now = Date.now();
|
|
788
|
+
try {
|
|
789
|
+
writeNestedEvent(inheritedNestedRoute, {
|
|
790
|
+
type: "subagent.nested.started",
|
|
791
|
+
ts: now,
|
|
792
|
+
parentRunId: nestedAddress.parentRunId,
|
|
793
|
+
parentStepIndex: nestedAddress.parentStepIndex,
|
|
794
|
+
child: {
|
|
795
|
+
id,
|
|
796
|
+
parentRunId: nestedAddress.parentRunId,
|
|
797
|
+
parentStepIndex: nestedAddress.parentStepIndex,
|
|
798
|
+
depth: nestedAddress.depth,
|
|
799
|
+
path: nestedAddress.path,
|
|
800
|
+
asyncDir,
|
|
801
|
+
pid: spawnResult.pid,
|
|
802
|
+
ownerIntercomTarget: process.env.DM_SUBAGENT_INTERCOM_SESSION_NAME,
|
|
803
|
+
leafIntercomTarget: childIntercomTarget?.(agent, 0),
|
|
804
|
+
intercomTarget: childIntercomTarget?.(agent, 0),
|
|
805
|
+
ownerState: "live",
|
|
806
|
+
mode: "single",
|
|
807
|
+
state: "running",
|
|
808
|
+
agent,
|
|
809
|
+
agents: [agent],
|
|
810
|
+
chainStepCount: 1,
|
|
811
|
+
...params.timeoutMs !== undefined ? { timeoutMs: params.timeoutMs, deadlineAt } : {},
|
|
812
|
+
...initialTurnBudget ? { turnBudget: initialTurnBudget } : {},
|
|
813
|
+
startedAt: now,
|
|
814
|
+
lastUpdate: now
|
|
815
|
+
}
|
|
816
|
+
});
|
|
817
|
+
} catch (error) {
|
|
818
|
+
console.error("Failed to emit nested async start event:", error);
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
ctx.pi.events.emit(SUBAGENT_ASYNC_STARTED_EVENT, {
|
|
822
|
+
lifecycleArtifactVersion: SUBAGENT_LIFECYCLE_ARTIFACT_VERSION,
|
|
823
|
+
id,
|
|
824
|
+
pid: spawnResult.pid,
|
|
825
|
+
sessionId: ctx.currentSessionId,
|
|
826
|
+
mode: "single",
|
|
827
|
+
agent,
|
|
828
|
+
task: task?.slice(0, 50),
|
|
829
|
+
cwd: runnerCwd,
|
|
830
|
+
asyncDir,
|
|
831
|
+
...params.timeoutMs !== undefined ? { timeoutMs: params.timeoutMs, deadlineAt } : {},
|
|
832
|
+
...initialTurnBudget ? { turnBudget: initialTurnBudget } : {},
|
|
833
|
+
nestedRoute
|
|
834
|
+
});
|
|
835
|
+
}
|
|
836
|
+
return {
|
|
837
|
+
content: [{ type: "text", text: formatAsyncStartedMessage(`Async: ${agent} [${id}]`) }],
|
|
838
|
+
details: { mode: "single", runId: id, results: [], asyncId: id, asyncDir, ...params.timeoutMs !== undefined ? { timeoutMs: params.timeoutMs, deadlineAt } : {}, ...params.turnBudget ? { turnBudget: params.turnBudget } : {}, ...params.toolBudget ? { toolBudget: params.toolBudget } : {} }
|
|
839
|
+
};
|
|
840
|
+
}
|