@duckmind/dm-darwin-x64 0.43.4 → 0.48.5
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 +0 -0
- package/extensions/.dm-extensions.json +242 -50
- package/extensions/dm-9router-ext/package.json +2 -19
- package/extensions/dm-9router-ext/src/index.js +5 -0
- package/extensions/dm-ask-user/index.js +10 -0
- package/extensions/dm-ask-user/package.json +1 -21
- package/extensions/dm-cli-anything/package.json +0 -6
- package/extensions/dm-context/package.json +2 -12
- package/extensions/dm-context/src/context.js +1 -0
- package/extensions/dm-context/src/index.js +7 -0
- package/extensions/dm-context/src/utils.js +1 -0
- package/extensions/dm-cua/package.json +0 -7
- package/extensions/dm-fff/package.json +1 -28
- package/extensions/dm-fff/src/index.js +15 -0
- package/extensions/dm-fff/src/query.js +1 -0
- package/extensions/dm-goal/package.json +2 -31
- package/extensions/dm-goal/src/goal.js +43 -0
- package/extensions/dm-grill-me/index.js +174 -0
- package/extensions/dm-grill-me/package.json +1 -26
- package/extensions/dm-image2/package.json +0 -7
- package/extensions/dm-subagents/package.json +1 -32
- package/extensions/dm-subagents/src/agents/agent-management.js +37 -0
- package/extensions/dm-subagents/src/agents/agent-memory.js +6 -0
- package/extensions/dm-subagents/src/agents/agent-scope.js +1 -0
- package/extensions/dm-subagents/src/agents/agent-selection.js +1 -0
- package/extensions/dm-subagents/src/agents/agent-serializer.js +7 -0
- package/extensions/dm-subagents/src/agents/agents.js +11 -0
- package/extensions/dm-subagents/src/agents/chain-serializer.js +12 -0
- package/extensions/dm-subagents/src/agents/frontmatter.js +6 -0
- package/extensions/dm-subagents/src/agents/identity.js +1 -0
- package/extensions/dm-subagents/src/agents/proactive-skills.js +1 -0
- package/extensions/dm-subagents/src/agents/skills.js +6 -0
- package/extensions/dm-subagents/src/extension/config.js +2 -0
- package/extensions/dm-subagents/src/extension/control-notices.js +4 -0
- package/extensions/dm-subagents/src/extension/doctor.js +16 -0
- package/extensions/dm-subagents/src/extension/fanout-child.js +231 -0
- package/extensions/dm-subagents/src/extension/index.js +367 -0
- package/extensions/dm-subagents/src/extension/rpc.js +8 -0
- package/extensions/dm-subagents/src/extension/schemas.js +1 -0
- package/extensions/dm-subagents/src/extension/{tool-description.ts → tool-description.js} +6 -126
- package/extensions/dm-subagents/src/intercom/intercom-bridge.js +13 -0
- package/extensions/dm-subagents/src/intercom/native-supervisor-channel.js +5 -0
- package/extensions/dm-subagents/src/intercom/result-intercom.js +3 -0
- package/extensions/dm-subagents/src/profiles/profiles.js +3 -0
- package/extensions/dm-subagents/src/runs/background/async-execution.js +46 -0
- package/extensions/dm-subagents/src/runs/background/async-job-tracker.js +14 -0
- package/extensions/dm-subagents/src/runs/background/async-resume.js +8 -0
- package/extensions/dm-subagents/src/runs/background/async-status.js +12 -0
- package/extensions/dm-subagents/src/runs/background/chain-append.js +2 -0
- package/extensions/dm-subagents/src/runs/background/chain-root-attachment.js +1 -0
- package/extensions/dm-subagents/src/runs/background/completion-batcher.js +1 -0
- package/extensions/dm-subagents/src/runs/background/completion-dedupe.js +1 -0
- package/extensions/dm-subagents/src/runs/background/control-channel.js +1 -0
- package/extensions/dm-subagents/src/runs/background/fleet-view.js +17 -0
- package/extensions/dm-subagents/src/runs/background/notify.js +3 -0
- package/extensions/dm-subagents/src/runs/background/parallel-groups.js +1 -0
- package/extensions/dm-subagents/src/runs/background/result-watcher.js +8 -0
- package/extensions/dm-subagents/src/runs/background/run-id-resolver.js +4 -0
- package/extensions/dm-subagents/src/runs/background/run-status.js +23 -0
- package/extensions/dm-subagents/src/runs/background/scheduled-runs.js +4 -0
- package/extensions/dm-subagents/src/runs/background/stale-run-reconciler.js +11 -0
- package/extensions/dm-subagents/src/runs/background/subagent-runner.js +78 -0
- package/extensions/dm-subagents/src/runs/background/top-level-async.js +1 -0
- package/extensions/dm-subagents/src/runs/background/wait.js +11 -0
- package/extensions/dm-subagents/src/runs/foreground/chain-clarify.js +12 -0
- package/extensions/dm-subagents/src/runs/foreground/chain-execution.js +102 -0
- package/extensions/dm-subagents/src/runs/foreground/execution.js +51 -0
- package/extensions/dm-subagents/src/runs/foreground/subagent-executor.js +228 -0
- package/extensions/dm-subagents/src/runs/shared/acceptance.js +3 -0
- package/extensions/dm-subagents/src/runs/shared/chain-outputs.js +1 -0
- package/extensions/dm-subagents/src/runs/shared/completion-guard.js +3 -0
- package/extensions/dm-subagents/src/runs/shared/dm-args.js +1 -0
- package/extensions/dm-subagents/src/runs/shared/dm-spawn.js +1 -0
- package/extensions/dm-subagents/src/runs/shared/dynamic-fanout.js +1 -0
- package/extensions/dm-subagents/src/runs/shared/long-running-guard.js +1 -0
- package/extensions/dm-subagents/src/runs/shared/mcp-direct-tool-allowlist.js +1 -0
- package/extensions/dm-subagents/src/runs/shared/model-fallback.js +1 -0
- package/extensions/dm-subagents/src/runs/shared/model-scope.js +1 -0
- package/extensions/dm-subagents/src/runs/shared/nested-events.js +8 -0
- package/extensions/dm-subagents/src/runs/shared/nested-path.js +1 -0
- package/extensions/dm-subagents/src/runs/shared/nested-render.js +1 -0
- package/extensions/dm-subagents/src/runs/shared/parallel-utils.js +5 -0
- package/extensions/dm-subagents/src/runs/shared/run-history.js +5 -0
- package/extensions/dm-subagents/src/runs/shared/single-output.js +14 -0
- package/extensions/dm-subagents/src/runs/shared/structured-output.js +1 -0
- package/extensions/dm-subagents/src/runs/shared/subagent-control.js +5 -0
- package/extensions/dm-subagents/src/runs/shared/subagent-prompt-runtime.js +22 -0
- package/extensions/dm-subagents/src/runs/shared/tool-budget.js +1 -0
- package/extensions/dm-subagents/src/runs/shared/turn-budget.js +7 -0
- package/extensions/dm-subagents/src/runs/shared/workflow-graph.js +1 -0
- package/extensions/dm-subagents/src/runs/shared/worktree.js +3 -0
- package/extensions/dm-subagents/src/shared/artifacts.js +2 -0
- package/extensions/dm-subagents/src/shared/atomic-json.js +1 -0
- package/extensions/dm-subagents/src/shared/child-transcript.js +5 -0
- package/extensions/dm-subagents/src/shared/file-coalescer.js +1 -0
- package/extensions/dm-subagents/src/shared/fork-context.js +6 -0
- package/extensions/dm-subagents/src/shared/formatters.js +9 -0
- package/extensions/dm-subagents/src/shared/jsonl-writer.js +2 -0
- package/extensions/dm-subagents/src/shared/model-info.js +1 -0
- package/extensions/dm-subagents/src/shared/post-exit-stdio-guard.js +1 -0
- package/extensions/dm-subagents/src/shared/session-identity.js +1 -0
- package/extensions/dm-subagents/src/shared/session-tokens.js +2 -0
- package/extensions/dm-subagents/src/shared/settings.js +23 -0
- package/extensions/dm-subagents/src/shared/status-format.js +1 -0
- package/extensions/dm-subagents/src/shared/types.js +8 -0
- package/extensions/dm-subagents/src/shared/utils.js +2 -0
- package/extensions/dm-subagents/src/slash/prompt-template-bridge.js +1 -0
- package/extensions/dm-subagents/src/slash/prompt-workflows.js +7 -0
- package/extensions/dm-subagents/src/slash/slash-bridge.js +1 -0
- package/extensions/dm-subagents/src/slash/slash-commands.js +38 -0
- package/extensions/dm-subagents/src/slash/slash-live-state.js +6 -0
- package/extensions/dm-subagents/src/tui/render-helpers.js +1 -0
- package/extensions/dm-subagents/src/tui/render.js +4 -0
- package/extensions/dm-tasks/package.json +1 -30
- package/extensions/dm-tasks/src/auto-clear.js +1 -0
- package/extensions/dm-tasks/src/index.js +212 -0
- package/extensions/dm-tasks/src/process-tracker.js +1 -0
- package/extensions/dm-tasks/src/task-store.js +1 -0
- package/extensions/dm-tasks/src/tasks-config.js +1 -0
- package/extensions/dm-tasks/src/types.js +0 -0
- package/extensions/dm-tasks/src/ui/settings-menu.js +1 -0
- package/extensions/dm-tasks/src/ui/task-widget.js +1 -0
- package/extensions/dm-usage/index.js +9 -0
- package/extensions/dm-usage/package.json +1 -18
- package/extensions/greedysearch-dm/bin/search.mjs +51 -51
- package/extensions/greedysearch-dm/index.js +20 -0
- package/extensions/greedysearch-dm/package.json +1 -22
- package/extensions/greedysearch-dm/src/formatters/results.js +8 -0
- package/extensions/greedysearch-dm/src/formatters/sources.js +1 -0
- package/extensions/greedysearch-dm/src/formatters/synthesis.js +1 -0
- package/extensions/greedysearch-dm/src/search/research.mjs +59 -59
- package/extensions/greedysearch-dm/src/search/synthesis-runner.mjs +10 -10
- package/extensions/greedysearch-dm/src/tools/greedy-search-handler.js +20 -0
- package/extensions/greedysearch-dm/src/tools/shared.js +9 -0
- package/extensions/greedysearch-dm/src/types.js +0 -0
- package/extensions/greedysearch-dm/src/utils/helpers.js +1 -0
- package/package.json +1 -1
- package/extensions/dm-9router-ext/src/index.ts +0 -541
- package/extensions/dm-ask-user/index.ts +0 -857
- package/extensions/dm-context/src/context.ts +0 -158
- package/extensions/dm-context/src/index.ts +0 -439
- package/extensions/dm-context/src/utils.ts +0 -6
- package/extensions/dm-fff/src/index.ts +0 -1023
- package/extensions/dm-fff/src/query.ts +0 -87
- package/extensions/dm-goal/src/goal.ts +0 -1073
- package/extensions/dm-grill-me/index.ts +0 -1085
- package/extensions/dm-subagents/src/agents/agent-management.ts +0 -1052
- package/extensions/dm-subagents/src/agents/agent-memory.ts +0 -254
- package/extensions/dm-subagents/src/agents/agent-scope.ts +0 -6
- package/extensions/dm-subagents/src/agents/agent-selection.ts +0 -25
- package/extensions/dm-subagents/src/agents/agent-serializer.ts +0 -121
- package/extensions/dm-subagents/src/agents/agents.ts +0 -1553
- package/extensions/dm-subagents/src/agents/chain-serializer.ts +0 -277
- package/extensions/dm-subagents/src/agents/frontmatter.ts +0 -93
- package/extensions/dm-subagents/src/agents/identity.ts +0 -30
- package/extensions/dm-subagents/src/agents/proactive-skills.ts +0 -191
- package/extensions/dm-subagents/src/agents/skills.ts +0 -729
- package/extensions/dm-subagents/src/extension/config.ts +0 -39
- package/extensions/dm-subagents/src/extension/control-notices.ts +0 -92
- package/extensions/dm-subagents/src/extension/doctor.ts +0 -214
- package/extensions/dm-subagents/src/extension/fanout-child.ts +0 -172
- package/extensions/dm-subagents/src/extension/index.ts +0 -656
- package/extensions/dm-subagents/src/extension/rpc.ts +0 -369
- package/extensions/dm-subagents/src/extension/schemas.ts +0 -309
- package/extensions/dm-subagents/src/intercom/intercom-bridge.ts +0 -180
- package/extensions/dm-subagents/src/intercom/native-supervisor-channel.ts +0 -519
- package/extensions/dm-subagents/src/intercom/result-intercom.ts +0 -377
- package/extensions/dm-subagents/src/profiles/profiles.ts +0 -637
- package/extensions/dm-subagents/src/runs/background/async-execution.ts +0 -1065
- package/extensions/dm-subagents/src/runs/background/async-job-tracker.ts +0 -441
- package/extensions/dm-subagents/src/runs/background/async-resume.ts +0 -391
- package/extensions/dm-subagents/src/runs/background/async-status.ts +0 -395
- package/extensions/dm-subagents/src/runs/background/chain-append.ts +0 -282
- package/extensions/dm-subagents/src/runs/background/chain-root-attachment.ts +0 -191
- package/extensions/dm-subagents/src/runs/background/completion-batcher.ts +0 -166
- package/extensions/dm-subagents/src/runs/background/completion-dedupe.ts +0 -63
- package/extensions/dm-subagents/src/runs/background/control-channel.ts +0 -332
- package/extensions/dm-subagents/src/runs/background/fleet-view.ts +0 -515
- package/extensions/dm-subagents/src/runs/background/notify.ts +0 -225
- package/extensions/dm-subagents/src/runs/background/parallel-groups.ts +0 -45
- package/extensions/dm-subagents/src/runs/background/result-watcher.ts +0 -315
- package/extensions/dm-subagents/src/runs/background/run-id-resolver.ts +0 -84
- package/extensions/dm-subagents/src/runs/background/run-status.ts +0 -434
- package/extensions/dm-subagents/src/runs/background/scheduled-runs.ts +0 -514
- package/extensions/dm-subagents/src/runs/background/stale-run-reconciler.ts +0 -368
- package/extensions/dm-subagents/src/runs/background/subagent-runner.ts +0 -3171
- package/extensions/dm-subagents/src/runs/background/top-level-async.ts +0 -13
- package/extensions/dm-subagents/src/runs/background/wait.ts +0 -353
- package/extensions/dm-subagents/src/runs/foreground/chain-clarify.ts +0 -1333
- package/extensions/dm-subagents/src/runs/foreground/chain-execution.ts +0 -1313
- package/extensions/dm-subagents/src/runs/foreground/execution.ts +0 -1239
- package/extensions/dm-subagents/src/runs/foreground/subagent-executor.ts +0 -3613
- package/extensions/dm-subagents/src/runs/shared/acceptance.ts +0 -879
- package/extensions/dm-subagents/src/runs/shared/chain-outputs.ts +0 -116
- package/extensions/dm-subagents/src/runs/shared/completion-guard.ts +0 -147
- package/extensions/dm-subagents/src/runs/shared/dm-args.ts +0 -271
- package/extensions/dm-subagents/src/runs/shared/dm-spawn.ts +0 -147
- package/extensions/dm-subagents/src/runs/shared/dynamic-fanout.ts +0 -295
- package/extensions/dm-subagents/src/runs/shared/long-running-guard.ts +0 -175
- package/extensions/dm-subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +0 -365
- package/extensions/dm-subagents/src/runs/shared/model-fallback.ts +0 -292
- package/extensions/dm-subagents/src/runs/shared/model-scope.ts +0 -128
- package/extensions/dm-subagents/src/runs/shared/nested-events.ts +0 -908
- package/extensions/dm-subagents/src/runs/shared/nested-path.ts +0 -52
- package/extensions/dm-subagents/src/runs/shared/nested-render.ts +0 -115
- package/extensions/dm-subagents/src/runs/shared/parallel-utils.ts +0 -198
- package/extensions/dm-subagents/src/runs/shared/run-history.ts +0 -60
- package/extensions/dm-subagents/src/runs/shared/single-output.ts +0 -180
- package/extensions/dm-subagents/src/runs/shared/structured-output.ts +0 -77
- package/extensions/dm-subagents/src/runs/shared/subagent-control.ts +0 -223
- package/extensions/dm-subagents/src/runs/shared/subagent-prompt-runtime.ts +0 -342
- package/extensions/dm-subagents/src/runs/shared/tool-budget.ts +0 -74
- package/extensions/dm-subagents/src/runs/shared/turn-budget.ts +0 -52
- package/extensions/dm-subagents/src/runs/shared/workflow-graph.ts +0 -206
- package/extensions/dm-subagents/src/runs/shared/worktree.ts +0 -600
- package/extensions/dm-subagents/src/shared/artifacts.ts +0 -113
- package/extensions/dm-subagents/src/shared/atomic-json.ts +0 -86
- package/extensions/dm-subagents/src/shared/child-transcript.ts +0 -212
- package/extensions/dm-subagents/src/shared/file-coalescer.ts +0 -40
- package/extensions/dm-subagents/src/shared/fork-context.ts +0 -194
- package/extensions/dm-subagents/src/shared/formatters.ts +0 -133
- package/extensions/dm-subagents/src/shared/jsonl-writer.ts +0 -81
- package/extensions/dm-subagents/src/shared/model-info.ts +0 -78
- package/extensions/dm-subagents/src/shared/post-exit-stdio-guard.ts +0 -85
- package/extensions/dm-subagents/src/shared/session-identity.ts +0 -10
- package/extensions/dm-subagents/src/shared/session-tokens.ts +0 -44
- package/extensions/dm-subagents/src/shared/settings.ts +0 -450
- package/extensions/dm-subagents/src/shared/status-format.ts +0 -49
- package/extensions/dm-subagents/src/shared/types.ts +0 -1257
- package/extensions/dm-subagents/src/shared/utils.ts +0 -554
- package/extensions/dm-subagents/src/slash/prompt-template-bridge.ts +0 -420
- package/extensions/dm-subagents/src/slash/prompt-workflows.ts +0 -330
- package/extensions/dm-subagents/src/slash/slash-bridge.ts +0 -176
- package/extensions/dm-subagents/src/slash/slash-commands.ts +0 -1296
- package/extensions/dm-subagents/src/slash/slash-live-state.ts +0 -292
- package/extensions/dm-subagents/src/tui/render-helpers.ts +0 -80
- package/extensions/dm-subagents/src/tui/render.ts +0 -1748
- package/extensions/dm-tasks/src/auto-clear.ts +0 -91
- package/extensions/dm-tasks/src/index.ts +0 -1145
- package/extensions/dm-tasks/src/process-tracker.ts +0 -140
- package/extensions/dm-tasks/src/task-store.ts +0 -305
- package/extensions/dm-tasks/src/tasks-config.ts +0 -23
- package/extensions/dm-tasks/src/types.ts +0 -40
- package/extensions/dm-tasks/src/ui/settings-menu.ts +0 -100
- package/extensions/dm-tasks/src/ui/task-widget.ts +0 -265
- package/extensions/dm-usage/index.ts +0 -1718
- package/extensions/greedysearch-dm/index.ts +0 -177
- package/extensions/greedysearch-dm/src/formatters/results.ts +0 -163
- package/extensions/greedysearch-dm/src/formatters/sources.ts +0 -116
- package/extensions/greedysearch-dm/src/formatters/synthesis.ts +0 -87
- package/extensions/greedysearch-dm/src/tools/greedy-search-handler.ts +0 -370
- package/extensions/greedysearch-dm/src/tools/shared.ts +0 -187
- package/extensions/greedysearch-dm/src/types.ts +0 -110
- package/extensions/greedysearch-dm/src/utils/helpers.ts +0 -40
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
import { isDynamicParallelStep, isParallelStep, type ChainStep, type SequentialStep } from "../../shared/settings.ts";
|
|
2
|
-
import type { ChainOutputMap, ChainOutputMapEntry, SingleResult } from "../../shared/types.ts";
|
|
3
|
-
import { getSingleResultOutput } from "../../shared/utils.ts";
|
|
4
|
-
import { DynamicFanoutError, hasDynamicFanoutFields, type DynamicFanoutConfig, validateDynamicStepShape } from "./dynamic-fanout.ts";
|
|
5
|
-
|
|
6
|
-
const OUTPUT_REF_PATTERN = /\{outputs\.([^}]*)\}/g;
|
|
7
|
-
const SAFE_OUTPUT_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
8
|
-
|
|
9
|
-
export class ChainOutputValidationError extends Error {}
|
|
10
|
-
|
|
11
|
-
export interface ChainOutputValidationContext {
|
|
12
|
-
priorOutputNames?: Iterable<string>;
|
|
13
|
-
startStepIndex?: number;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function outputNamesForStep(step: ChainStep): string[] {
|
|
17
|
-
if (isParallelStep(step)) return step.parallel.map((task) => task.as).filter((name): name is string => Boolean(name));
|
|
18
|
-
if (isDynamicParallelStep(step)) return [step.collect.as];
|
|
19
|
-
const name = (step as SequentialStep).as;
|
|
20
|
-
return name ? [name] : [];
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function taskTemplatesForStep(step: ChainStep): string[] {
|
|
24
|
-
if (isParallelStep(step)) return step.parallel.map((task) => task.task ?? "{previous}");
|
|
25
|
-
if (isDynamicParallelStep(step)) return [step.parallel.task ?? "{previous}", step.parallel.label ?? ""].filter(Boolean);
|
|
26
|
-
return [(step as SequentialStep).task ?? "{previous}"];
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export function validateChainOutputBindings(steps: ChainStep[], dynamicFanoutConfig: DynamicFanoutConfig = {}): void {
|
|
30
|
-
validateChainOutputBindingsWithContext(steps, dynamicFanoutConfig);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export function validateChainOutputBindingsWithContext(
|
|
34
|
-
steps: ChainStep[],
|
|
35
|
-
dynamicFanoutConfig: DynamicFanoutConfig = {},
|
|
36
|
-
context: ChainOutputValidationContext = {},
|
|
37
|
-
): void {
|
|
38
|
-
const priorOutputNames = [...(context.priorOutputNames ?? [])];
|
|
39
|
-
const available = new Set<string>(priorOutputNames);
|
|
40
|
-
const seen = new Set<string>(priorOutputNames);
|
|
41
|
-
for (let stepIndex = 0; stepIndex < steps.length; stepIndex++) {
|
|
42
|
-
const displayStepIndex = (context.startStepIndex ?? 0) + stepIndex + 1;
|
|
43
|
-
const step = steps[stepIndex]!;
|
|
44
|
-
if (hasDynamicFanoutFields(step)) {
|
|
45
|
-
if (!isDynamicParallelStep(step)) {
|
|
46
|
-
throw new ChainOutputValidationError(`Dynamic chain step ${displayStepIndex} requires expand, a single parallel template object, and collect; dynamic expand/collect cannot be mixed with static parallel arrays.`);
|
|
47
|
-
}
|
|
48
|
-
try {
|
|
49
|
-
validateDynamicStepShape(step, displayStepIndex - 1, dynamicFanoutConfig);
|
|
50
|
-
} catch (error) {
|
|
51
|
-
if (error instanceof DynamicFanoutError) throw new ChainOutputValidationError(error.message);
|
|
52
|
-
throw error;
|
|
53
|
-
}
|
|
54
|
-
if (!available.has(step.expand.from.output)) {
|
|
55
|
-
throw new ChainOutputValidationError(`Dynamic chain step ${displayStepIndex} references unknown output '${step.expand.from.output}'. Named outputs are only available after producing step/group completes.`);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
for (const name of outputNamesForStep(step)) {
|
|
59
|
-
if (!SAFE_OUTPUT_NAME_PATTERN.test(name)) {
|
|
60
|
-
throw new ChainOutputValidationError(`Invalid chain output name '${name}' at step ${displayStepIndex}. Use /^[A-Za-z_][A-Za-z0-9_]*$/.`);
|
|
61
|
-
}
|
|
62
|
-
if (seen.has(name)) {
|
|
63
|
-
throw new ChainOutputValidationError(`Duplicate chain output name '${name}'. Each as name must be unique.`);
|
|
64
|
-
}
|
|
65
|
-
seen.add(name);
|
|
66
|
-
}
|
|
67
|
-
for (const template of taskTemplatesForStep(step)) {
|
|
68
|
-
for (const match of template.matchAll(OUTPUT_REF_PATTERN)) {
|
|
69
|
-
const rawReference = match[0];
|
|
70
|
-
const name = match[1]!;
|
|
71
|
-
if (!SAFE_OUTPUT_NAME_PATTERN.test(name)) {
|
|
72
|
-
throw new ChainOutputValidationError(`Invalid chain output reference '${rawReference}' at step ${displayStepIndex}. Use {outputs.name} with /^[A-Za-z_][A-Za-z0-9_]*$/ names.`);
|
|
73
|
-
}
|
|
74
|
-
if (!available.has(name)) {
|
|
75
|
-
throw new ChainOutputValidationError(`Unknown chain output reference '${rawReference}' at step ${displayStepIndex}. Named outputs are only available after producing step/group completes.`);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
for (const name of outputNamesForStep(step)) {
|
|
80
|
-
available.add(name);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
export function resolveOutputReferences(template: string, outputs: ChainOutputMap): string {
|
|
86
|
-
return template.replace(OUTPUT_REF_PATTERN, (rawReference, name: string) => {
|
|
87
|
-
if (!SAFE_OUTPUT_NAME_PATTERN.test(name)) {
|
|
88
|
-
throw new ChainOutputValidationError(`Invalid chain output reference '${rawReference}'. Use {outputs.name} with /^[A-Za-z_][A-Za-z0-9_]*$/ names.`);
|
|
89
|
-
}
|
|
90
|
-
const entry = outputs[name];
|
|
91
|
-
if (!entry) throw new ChainOutputValidationError(`Unknown chain output reference '${rawReference}'.`);
|
|
92
|
-
return entry.text;
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
function compactStructuredText(value: unknown): string {
|
|
97
|
-
return JSON.stringify(value);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
export function outputEntryFromResult(result: SingleResult, stepIndex: number): ChainOutputMapEntry {
|
|
101
|
-
return {
|
|
102
|
-
text: result.structuredOutput !== undefined ? compactStructuredText(result.structuredOutput) : getSingleResultOutput(result),
|
|
103
|
-
...(result.structuredOutput !== undefined ? { structured: result.structuredOutput } : {}),
|
|
104
|
-
agent: result.agent,
|
|
105
|
-
stepIndex,
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
export function outputEntryFromAsyncResult(result: { agent: string; output: string; structuredOutput?: unknown }, stepIndex: number): ChainOutputMapEntry {
|
|
110
|
-
return {
|
|
111
|
-
text: result.structuredOutput !== undefined ? compactStructuredText(result.structuredOutput) : result.output,
|
|
112
|
-
...(result.structuredOutput !== undefined ? { structured: result.structuredOutput } : {}),
|
|
113
|
-
agent: result.agent,
|
|
114
|
-
stepIndex,
|
|
115
|
-
};
|
|
116
|
-
}
|
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
import type { Message } from "@duckmind/dm-ai";
|
|
2
|
-
import { isMutatingBashCommand } from "./long-running-guard.ts";
|
|
3
|
-
|
|
4
|
-
const REVIEW_ONLY_PATTERNS = [
|
|
5
|
-
/\breview only\b/i,
|
|
6
|
-
/\bsuggest fixes only\b/i,
|
|
7
|
-
/\bonly return findings\b/i,
|
|
8
|
-
/\breturn findings only\b/i,
|
|
9
|
-
];
|
|
10
|
-
|
|
11
|
-
const REVIEWER_REQUIRED_EDIT_PATTERNS = [
|
|
12
|
-
/\bmust\s+(?:edit|modify|change|fix|patch|apply)\b/i,
|
|
13
|
-
/\brequired\s+to\s+(?:edit|modify|change|fix|patch|apply)\b/i,
|
|
14
|
-
/\bregardless\s+of\s+findings\b/i,
|
|
15
|
-
/\balways\s+(?:edit|modify|change|fix|patch|apply)\b/i,
|
|
16
|
-
/\bapply\s+(?:the\s+)?fix(?:es)?\s+directly\b/i,
|
|
17
|
-
/\bmake\s+(?:the\s+)?code\s+changes\b/i,
|
|
18
|
-
];
|
|
19
|
-
|
|
20
|
-
const EXPLICIT_NO_EDIT_PATTERNS = [
|
|
21
|
-
/\bdo not edit\b/i,
|
|
22
|
-
/\bdon't edit\b/i,
|
|
23
|
-
/\bdo not modify\b/i,
|
|
24
|
-
/\bdo not change files\b/i,
|
|
25
|
-
];
|
|
26
|
-
|
|
27
|
-
const SCOPED_NO_EDIT_CONSTRAINT_PATTERNS = [
|
|
28
|
-
/\bdo not edit files?\s+outside\b/i,
|
|
29
|
-
/\bdo not edit\s+outside\b/i,
|
|
30
|
-
/\bdo not edit\s+unrelated files?\b/i,
|
|
31
|
-
/\bdo not change\s+unrelated files?\b/i,
|
|
32
|
-
/\bdo not modify\s+unrelated files?\b/i,
|
|
33
|
-
];
|
|
34
|
-
|
|
35
|
-
const RESEARCH_AGENT_PATTERNS = [
|
|
36
|
-
/\binvestigate\b/i,
|
|
37
|
-
/\bscout\b/i,
|
|
38
|
-
/\bresearch(?:er)?\b/i,
|
|
39
|
-
];
|
|
40
|
-
|
|
41
|
-
const WORKER_IMPLEMENTATION_PATTERNS = [
|
|
42
|
-
/\b(?:implement|fix|edit|modify|patch|refactor|delete)\b/i,
|
|
43
|
-
/\b(?:update|add|remove|replace|create)\b(?!\s+(?:(?:a|an|the)\s+)?(?:report|summary|findings?)(?:\b|$))/i,
|
|
44
|
-
/\bapply\s+(?:the\s+)?(?:changes?|fix(?:es)?|patch)\b/i,
|
|
45
|
-
/\bmake\s+(?:the\s+)?changes\b/i,
|
|
46
|
-
/\bdo those fixes\b/i,
|
|
47
|
-
];
|
|
48
|
-
|
|
49
|
-
const GENERAL_IMPLEMENTATION_PATTERNS = [
|
|
50
|
-
/\b(?:implement|fix|edit|modify|patch|refactor)\b/i,
|
|
51
|
-
/\bapply\s+(?:the\s+)?(?:changes?|fix(?:es)?|patch)\b/i,
|
|
52
|
-
/\bmake\s+(?:the\s+)?changes\b/i,
|
|
53
|
-
/\bdo those fixes\b/i,
|
|
54
|
-
/\b(?:update|add|remove|replace|delete|create)\s+(?:the\s+)?(?:file|files|code|source|implementation|test|tests|component|function|module|class|method|logic|import|imports|readme|docs?|changelog|package\.json|config|manifest|extension|prompt|command)\b/i,
|
|
55
|
-
];
|
|
56
|
-
|
|
57
|
-
const READ_ONLY_BUILTIN_TOOLS = new Set([
|
|
58
|
-
"read",
|
|
59
|
-
"grep",
|
|
60
|
-
"find",
|
|
61
|
-
"ls",
|
|
62
|
-
"web_search",
|
|
63
|
-
"fetch_content",
|
|
64
|
-
"get_search_content",
|
|
65
|
-
"intercom",
|
|
66
|
-
"contact_supervisor",
|
|
67
|
-
]);
|
|
68
|
-
|
|
69
|
-
interface CompletionMutationGuardInput {
|
|
70
|
-
agent: string;
|
|
71
|
-
task: string;
|
|
72
|
-
messages: Message[];
|
|
73
|
-
tools?: string[];
|
|
74
|
-
mcpDirectTools?: string[];
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
interface CompletionMutationGuardResult {
|
|
78
|
-
expectedMutation: boolean;
|
|
79
|
-
attemptedMutation: boolean;
|
|
80
|
-
triggered: boolean;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
function stripFrameworkInstructions(task: string): string {
|
|
84
|
-
return task
|
|
85
|
-
.split("\n")
|
|
86
|
-
.filter((line) => !/^\s*\[(?:Write to|Read from):/i.test(line))
|
|
87
|
-
.filter((line) => !/^\s*(?:Create and maintain progress at:|Update progress at:|\*\*Output:\*\*|Write your findings to(?: exactly this path)?:|This path is authoritative for this run\.|Ignore any other output filename or output path mentioned elsewhere)/i.test(line))
|
|
88
|
-
.join("\n");
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function stripScopedNoEditConstraints(task: string): string {
|
|
92
|
-
let stripped = task;
|
|
93
|
-
for (const pattern of SCOPED_NO_EDIT_CONSTRAINT_PATTERNS) {
|
|
94
|
-
stripped = stripped.replace(pattern, " ");
|
|
95
|
-
}
|
|
96
|
-
return stripped;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
function declaresOnlyReadOnlyTools(tools: string[] | undefined, mcpDirectTools: string[] | undefined): boolean {
|
|
100
|
-
return tools !== undefined
|
|
101
|
-
&& tools.length > 0
|
|
102
|
-
&& (mcpDirectTools?.length ?? 0) === 0
|
|
103
|
-
&& tools.every((tool) => READ_ONLY_BUILTIN_TOOLS.has(tool));
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
export function expectsImplementationMutation(agent: string, task: string): boolean {
|
|
107
|
-
const taskText = stripFrameworkInstructions(task);
|
|
108
|
-
const taskTextWithoutScopedConstraints = stripScopedNoEditConstraints(taskText);
|
|
109
|
-
if (REVIEW_ONLY_PATTERNS.some((pattern) => pattern.test(taskTextWithoutScopedConstraints))) return false;
|
|
110
|
-
if (EXPLICIT_NO_EDIT_PATTERNS.some((pattern) => pattern.test(taskTextWithoutScopedConstraints))) return false;
|
|
111
|
-
|
|
112
|
-
if (RESEARCH_AGENT_PATTERNS.some((pattern) => pattern.test(agent))) return false;
|
|
113
|
-
if (/\breviewer\b/i.test(agent)) return REVIEWER_REQUIRED_EDIT_PATTERNS.some((pattern) => pattern.test(taskText));
|
|
114
|
-
|
|
115
|
-
const workerIntent = agent === "worker" && WORKER_IMPLEMENTATION_PATTERNS.some((pattern) => pattern.test(taskText));
|
|
116
|
-
if (workerIntent) return true;
|
|
117
|
-
|
|
118
|
-
return GENERAL_IMPLEMENTATION_PATTERNS.some((pattern) => pattern.test(taskText));
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
export function hasMutationToolCall(messages: Message[]): boolean {
|
|
122
|
-
for (const message of messages) {
|
|
123
|
-
if (message.role !== "assistant") continue;
|
|
124
|
-
for (const part of message.content) {
|
|
125
|
-
if (part.type !== "toolCall") continue;
|
|
126
|
-
if (part.name === "edit" || part.name === "write") return true;
|
|
127
|
-
if (part.name !== "bash") continue;
|
|
128
|
-
const args = typeof part.arguments === "object" && part.arguments !== null && !Array.isArray(part.arguments)
|
|
129
|
-
? part.arguments as Record<string, unknown>
|
|
130
|
-
: {};
|
|
131
|
-
if (typeof args.command === "string" && isMutatingBashCommand(args.command)) return true;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
return false;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
export function evaluateCompletionMutationGuard(input: CompletionMutationGuardInput): CompletionMutationGuardResult {
|
|
138
|
-
const expectedMutation = declaresOnlyReadOnlyTools(input.tools, input.mcpDirectTools)
|
|
139
|
-
? false
|
|
140
|
-
: expectsImplementationMutation(input.agent, input.task);
|
|
141
|
-
const attemptedMutation = hasMutationToolCall(input.messages);
|
|
142
|
-
return {
|
|
143
|
-
expectedMutation,
|
|
144
|
-
attemptedMutation,
|
|
145
|
-
triggered: expectedMutation && !attemptedMutation,
|
|
146
|
-
};
|
|
147
|
-
}
|
|
@@ -1,271 +0,0 @@
|
|
|
1
|
-
import * as fs from "node:fs";
|
|
2
|
-
import * as os from "node:os";
|
|
3
|
-
import * as path from "node:path";
|
|
4
|
-
import { fileURLToPath } from "node:url";
|
|
5
|
-
import { encodeNestedPathEnv, parseNestedPathEnv, type NestedPathEntry } from "./nested-path.ts";
|
|
6
|
-
import { resolveMcpDirectToolNames } from "./mcp-direct-tool-allowlist.ts";
|
|
7
|
-
import { STRUCTURED_OUTPUT_CAPTURE_ENV, STRUCTURED_OUTPUT_SCHEMA_ENV } from "./structured-output.ts";
|
|
8
|
-
import { TEMP_ROOT_DIR, type JsonSchemaObject, type ResolvedToolBudget } from "../../shared/types.ts";
|
|
9
|
-
import { TOOL_BUDGET_ENV, encodeToolBudgetEnv } from "./tool-budget.ts";
|
|
10
|
-
|
|
11
|
-
const THINKING_LEVELS = ["off", "minimal", "low", "medium", "high", "xhigh"];
|
|
12
|
-
const TASK_ARG_LIMIT = 8000;
|
|
13
|
-
const PROMPT_RUNTIME_EXTENSION_PATH = path.join(path.dirname(fileURLToPath(import.meta.url)), "subagent-prompt-runtime.ts");
|
|
14
|
-
const FANOUT_CHILD_EXTENSION_PATH = path.join(path.dirname(fileURLToPath(import.meta.url)), "..", "..", "extension", "fanout-child.ts");
|
|
15
|
-
export const SUBAGENT_CHILD_ENV = "DM_SUBAGENT_CHILD";
|
|
16
|
-
export const SUBAGENT_ORCHESTRATOR_TARGET_ENV = "DM_SUBAGENT_ORCHESTRATOR_TARGET";
|
|
17
|
-
export const SUBAGENT_ORCHESTRATOR_SESSION_ID_ENV = "DM_SUBAGENT_ORCHESTRATOR_SESSION_ID";
|
|
18
|
-
export const SUBAGENT_SUPERVISOR_CHANNEL_DIR_ENV = "DM_SUBAGENT_SUPERVISOR_CHANNEL_DIR";
|
|
19
|
-
export const SUBAGENT_RUN_ID_ENV = "DM_SUBAGENT_RUN_ID";
|
|
20
|
-
export const SUBAGENT_CHILD_AGENT_ENV = "DM_SUBAGENT_CHILD_AGENT";
|
|
21
|
-
export const SUBAGENT_CHILD_INDEX_ENV = "DM_SUBAGENT_CHILD_INDEX";
|
|
22
|
-
export const SUBAGENT_FANOUT_CHILD_ENV = "DM_SUBAGENT_FANOUT_CHILD";
|
|
23
|
-
export const SUBAGENT_PARENT_EVENT_SINK_ENV = "DM_SUBAGENT_PARENT_EVENT_SINK";
|
|
24
|
-
export const SUBAGENT_PARENT_CONTROL_INBOX_ENV = "DM_SUBAGENT_PARENT_CONTROL_INBOX";
|
|
25
|
-
export const SUBAGENT_PARENT_ROOT_RUN_ID_ENV = "DM_SUBAGENT_PARENT_ROOT_RUN_ID";
|
|
26
|
-
export const SUBAGENT_PARENT_RUN_ID_ENV = "DM_SUBAGENT_PARENT_RUN_ID";
|
|
27
|
-
export const SUBAGENT_PARENT_CHILD_INDEX_ENV = "DM_SUBAGENT_PARENT_CHILD_INDEX";
|
|
28
|
-
export const SUBAGENT_PARENT_DEPTH_ENV = "DM_SUBAGENT_PARENT_DEPTH";
|
|
29
|
-
export const SUBAGENT_PARENT_PATH_ENV = "DM_SUBAGENT_PARENT_PATH";
|
|
30
|
-
export const SUBAGENT_PARENT_CAPABILITY_TOKEN_ENV = "DM_SUBAGENT_PARENT_CAPABILITY_TOKEN";
|
|
31
|
-
export const SUBAGENT_PARENT_SESSION_ENV = "DM_SUBAGENT_PARENT_SESSION";
|
|
32
|
-
export const SUBAGENT_STEER_INBOX_ENV = "DM_SUBAGENT_STEER_INBOX";
|
|
33
|
-
|
|
34
|
-
interface BuildPiArgsInput {
|
|
35
|
-
parentSessionId?: string;
|
|
36
|
-
baseArgs: string[];
|
|
37
|
-
task: string;
|
|
38
|
-
sessionEnabled: boolean;
|
|
39
|
-
sessionDir?: string;
|
|
40
|
-
sessionFile?: string;
|
|
41
|
-
model?: string;
|
|
42
|
-
thinking?: string;
|
|
43
|
-
systemPromptMode?: "append" | "replace";
|
|
44
|
-
inheritProjectContext: boolean;
|
|
45
|
-
inheritSkills: boolean;
|
|
46
|
-
requireReadTool?: boolean;
|
|
47
|
-
tools?: string[];
|
|
48
|
-
extensions?: string[];
|
|
49
|
-
subagentOnlyExtensions?: string[];
|
|
50
|
-
systemPrompt?: string | null;
|
|
51
|
-
mcpDirectTools?: string[];
|
|
52
|
-
cwd?: string;
|
|
53
|
-
promptFileStem?: string;
|
|
54
|
-
intercomSessionName?: string;
|
|
55
|
-
orchestratorIntercomTarget?: string;
|
|
56
|
-
runId?: string;
|
|
57
|
-
childAgentName?: string;
|
|
58
|
-
childIndex?: number;
|
|
59
|
-
parentEventSink?: string;
|
|
60
|
-
parentControlInbox?: string;
|
|
61
|
-
parentRootRunId?: string;
|
|
62
|
-
parentRunId?: string;
|
|
63
|
-
parentChildIndex?: number;
|
|
64
|
-
parentDepth?: number;
|
|
65
|
-
parentPath?: NestedPathEntry[];
|
|
66
|
-
parentCapabilityToken?: string;
|
|
67
|
-
steerInboxDir?: string;
|
|
68
|
-
structuredOutput?: {
|
|
69
|
-
schema: JsonSchemaObject;
|
|
70
|
-
schemaPath: string;
|
|
71
|
-
outputPath: string;
|
|
72
|
-
};
|
|
73
|
-
toolBudget?: ResolvedToolBudget;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
interface BuildPiArgsResult {
|
|
77
|
-
args: string[];
|
|
78
|
-
env: Record<string, string | undefined>;
|
|
79
|
-
tempDir?: string;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
function sanitizeSupervisorChannelSegment(value: string): string {
|
|
83
|
-
return value.trim().replace(/[^A-Za-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "") || "unknown";
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
function supervisorChannelDir(runId: string, agent: string, childIndex: number): string {
|
|
87
|
-
return path.join(TEMP_ROOT_DIR, "supervisor-channels", `${sanitizeSupervisorChannelSegment(runId)}-${sanitizeSupervisorChannelSegment(agent)}-${childIndex}`);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
export function applyThinkingSuffix(model: string | undefined, thinking: string | undefined, replaceExisting = false): string | undefined {
|
|
91
|
-
if (!model || !thinking) return model;
|
|
92
|
-
const colonIdx = model.lastIndexOf(":");
|
|
93
|
-
if (colonIdx !== -1 && THINKING_LEVELS.includes(model.substring(colonIdx + 1))) {
|
|
94
|
-
return replaceExisting ? `${model.slice(0, colonIdx)}:${thinking}` : model;
|
|
95
|
-
}
|
|
96
|
-
return `${model}:${thinking}`;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
export function buildPiArgs(input: BuildPiArgsInput): BuildPiArgsResult {
|
|
100
|
-
const args = [...input.baseArgs];
|
|
101
|
-
|
|
102
|
-
if (input.sessionFile) {
|
|
103
|
-
fs.mkdirSync(path.dirname(input.sessionFile), { recursive: true });
|
|
104
|
-
args.push("--session", input.sessionFile);
|
|
105
|
-
} else {
|
|
106
|
-
if (!input.sessionEnabled) {
|
|
107
|
-
args.push("--no-session");
|
|
108
|
-
}
|
|
109
|
-
if (input.sessionDir) {
|
|
110
|
-
fs.mkdirSync(input.sessionDir, { recursive: true });
|
|
111
|
-
args.push("--session-dir", input.sessionDir);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
const modelArg = applyThinkingSuffix(input.model, input.thinking);
|
|
116
|
-
if (modelArg) {
|
|
117
|
-
args.push("--model", modelArg);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
const declaredBuiltinToolsBase = input.tools?.filter((tool) => !(tool.includes("/") || tool.endsWith(".ts") || tool.endsWith(".js"))) ?? [];
|
|
121
|
-
const declaredBuiltinTools = input.requireReadTool && input.tools?.length && !declaredBuiltinToolsBase.includes("read")
|
|
122
|
-
? ["read", ...declaredBuiltinToolsBase]
|
|
123
|
-
: declaredBuiltinToolsBase;
|
|
124
|
-
const fanoutAuthorized = declaredBuiltinTools.includes("subagent");
|
|
125
|
-
const toolExtensionPaths: string[] = [];
|
|
126
|
-
if (input.tools?.length) {
|
|
127
|
-
const builtinTools = [...declaredBuiltinTools];
|
|
128
|
-
for (const tool of input.tools) {
|
|
129
|
-
if (!declaredBuiltinTools.includes(tool) && (tool.includes("/") || tool.endsWith(".ts") || tool.endsWith(".js"))) {
|
|
130
|
-
toolExtensionPaths.push(tool);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
if (builtinTools.length > 0) {
|
|
134
|
-
if (input.mcpDirectTools?.length) {
|
|
135
|
-
builtinTools.push(...resolveMcpDirectToolNames(input.mcpDirectTools, input.cwd));
|
|
136
|
-
}
|
|
137
|
-
args.push("--tools", builtinTools.join(","));
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
const runtimeExtensions = fanoutAuthorized
|
|
142
|
-
? [PROMPT_RUNTIME_EXTENSION_PATH, FANOUT_CHILD_EXTENSION_PATH]
|
|
143
|
-
: [PROMPT_RUNTIME_EXTENSION_PATH];
|
|
144
|
-
if (input.extensions !== undefined) {
|
|
145
|
-
args.push("--no-extensions");
|
|
146
|
-
for (const extPath of [...new Set([...runtimeExtensions, ...toolExtensionPaths, ...input.extensions, ...(input.subagentOnlyExtensions ?? [])])]) {
|
|
147
|
-
args.push("--extension", extPath);
|
|
148
|
-
}
|
|
149
|
-
} else {
|
|
150
|
-
for (const extPath of [...new Set([...runtimeExtensions, ...toolExtensionPaths, ...(input.subagentOnlyExtensions ?? [])])]) {
|
|
151
|
-
args.push("--extension", extPath);
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
if (!input.inheritSkills) {
|
|
156
|
-
args.push("--no-skills");
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
let tempDir: string | undefined;
|
|
160
|
-
if (input.systemPrompt !== undefined && input.systemPrompt !== null) {
|
|
161
|
-
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "dm-subagent-"));
|
|
162
|
-
const stem = (input.promptFileStem ?? "prompt").replace(/[^\w.-]/g, "_");
|
|
163
|
-
const promptPath = path.join(tempDir, `${stem}.md`);
|
|
164
|
-
fs.writeFileSync(promptPath, input.systemPrompt, { mode: 0o600 });
|
|
165
|
-
args.push(input.systemPromptMode === "replace" ? "--system-prompt" : "--append-system-prompt", promptPath);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
if (input.task.length > TASK_ARG_LIMIT) {
|
|
169
|
-
if (!tempDir) {
|
|
170
|
-
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "dm-subagent-"));
|
|
171
|
-
}
|
|
172
|
-
const taskFilePath = path.join(tempDir, "task.md");
|
|
173
|
-
fs.writeFileSync(taskFilePath, `Task: ${input.task}`, { mode: 0o600 });
|
|
174
|
-
args.push(`@${taskFilePath}`);
|
|
175
|
-
} else {
|
|
176
|
-
args.push(`Task: ${input.task}`);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
const env: Record<string, string | undefined> = {};
|
|
180
|
-
env[SUBAGENT_CHILD_ENV] = "1";
|
|
181
|
-
env[SUBAGENT_FANOUT_CHILD_ENV] = fanoutAuthorized ? "1" : "0";
|
|
182
|
-
const inheritedNestedRoute = Boolean(process.env[SUBAGENT_PARENT_EVENT_SINK_ENV] && process.env[SUBAGENT_PARENT_ROOT_RUN_ID_ENV] && process.env[SUBAGENT_PARENT_CAPABILITY_TOKEN_ENV]);
|
|
183
|
-
const parentRunId = input.parentRunId ?? input.runId ?? (inheritedNestedRoute ? process.env[SUBAGENT_RUN_ID_ENV] : undefined) ?? process.env[SUBAGENT_PARENT_RUN_ID_ENV] ?? "";
|
|
184
|
-
const parentChildIndex = input.parentChildIndex !== undefined
|
|
185
|
-
? String(input.parentChildIndex)
|
|
186
|
-
: input.childIndex !== undefined
|
|
187
|
-
? String(input.childIndex)
|
|
188
|
-
: process.env[SUBAGENT_PARENT_CHILD_INDEX_ENV] ?? "";
|
|
189
|
-
const inheritedDepth = Number(process.env[SUBAGENT_PARENT_DEPTH_ENV]);
|
|
190
|
-
const parentDepth = input.parentDepth ?? (inheritedNestedRoute && Number.isFinite(inheritedDepth) ? inheritedDepth + 1 : 1);
|
|
191
|
-
const parentPath = input.parentPath ?? [
|
|
192
|
-
...parseNestedPathEnv(process.env[SUBAGENT_PARENT_PATH_ENV]),
|
|
193
|
-
...(parentRunId ? [{
|
|
194
|
-
runId: parentRunId,
|
|
195
|
-
...(parentChildIndex && /^\d+$/.test(parentChildIndex) ? { stepIndex: Number(parentChildIndex) } : {}),
|
|
196
|
-
...(input.childAgentName ? { agent: input.childAgentName } : {}),
|
|
197
|
-
}] : []),
|
|
198
|
-
];
|
|
199
|
-
env[SUBAGENT_PARENT_EVENT_SINK_ENV] = fanoutAuthorized
|
|
200
|
-
? input.parentEventSink ?? process.env[SUBAGENT_PARENT_EVENT_SINK_ENV] ?? ""
|
|
201
|
-
: "";
|
|
202
|
-
env[SUBAGENT_PARENT_CONTROL_INBOX_ENV] = fanoutAuthorized
|
|
203
|
-
? input.parentControlInbox ?? process.env[SUBAGENT_PARENT_CONTROL_INBOX_ENV] ?? ""
|
|
204
|
-
: "";
|
|
205
|
-
env[SUBAGENT_PARENT_ROOT_RUN_ID_ENV] = fanoutAuthorized
|
|
206
|
-
? input.parentRootRunId ?? process.env[SUBAGENT_PARENT_ROOT_RUN_ID_ENV] ?? input.runId ?? ""
|
|
207
|
-
: "";
|
|
208
|
-
env[SUBAGENT_PARENT_RUN_ID_ENV] = fanoutAuthorized ? parentRunId : "";
|
|
209
|
-
env[SUBAGENT_PARENT_CHILD_INDEX_ENV] = fanoutAuthorized ? parentChildIndex : "";
|
|
210
|
-
env[SUBAGENT_PARENT_DEPTH_ENV] = fanoutAuthorized ? String(parentDepth) : "";
|
|
211
|
-
env[SUBAGENT_PARENT_PATH_ENV] = fanoutAuthorized ? encodeNestedPathEnv(parentPath) : "";
|
|
212
|
-
env[SUBAGENT_PARENT_CAPABILITY_TOKEN_ENV] = fanoutAuthorized
|
|
213
|
-
? input.parentCapabilityToken ?? process.env[SUBAGENT_PARENT_CAPABILITY_TOKEN_ENV] ?? ""
|
|
214
|
-
: "";
|
|
215
|
-
env.DM_SUBAGENT_INHERIT_PROJECT_CONTEXT = input.inheritProjectContext ? "1" : "0";
|
|
216
|
-
env.DM_SUBAGENT_INHERIT_SKILLS = input.inheritSkills ? "1" : "0";
|
|
217
|
-
if (input.intercomSessionName) {
|
|
218
|
-
env.DM_SUBAGENT_INTERCOM_SESSION_NAME = input.intercomSessionName;
|
|
219
|
-
}
|
|
220
|
-
if (input.orchestratorIntercomTarget) {
|
|
221
|
-
env[SUBAGENT_ORCHESTRATOR_TARGET_ENV] = input.orchestratorIntercomTarget;
|
|
222
|
-
}
|
|
223
|
-
if (input.parentSessionId) {
|
|
224
|
-
env[SUBAGENT_ORCHESTRATOR_SESSION_ID_ENV] = input.parentSessionId;
|
|
225
|
-
}
|
|
226
|
-
if (input.orchestratorIntercomTarget && input.parentSessionId && input.runId && input.childAgentName) {
|
|
227
|
-
const childIndex = input.childIndex ?? 0;
|
|
228
|
-
const channelDir = supervisorChannelDir(input.runId, input.childAgentName, childIndex);
|
|
229
|
-
fs.mkdirSync(path.join(channelDir, "requests"), { recursive: true });
|
|
230
|
-
fs.mkdirSync(path.join(channelDir, "replies"), { recursive: true });
|
|
231
|
-
env[SUBAGENT_SUPERVISOR_CHANNEL_DIR_ENV] = channelDir;
|
|
232
|
-
}
|
|
233
|
-
if (input.runId) {
|
|
234
|
-
env[SUBAGENT_RUN_ID_ENV] = input.runId;
|
|
235
|
-
}
|
|
236
|
-
if (input.childAgentName) {
|
|
237
|
-
env[SUBAGENT_CHILD_AGENT_ENV] = input.childAgentName;
|
|
238
|
-
}
|
|
239
|
-
if (input.childIndex !== undefined) {
|
|
240
|
-
env[SUBAGENT_CHILD_INDEX_ENV] = String(input.childIndex);
|
|
241
|
-
}
|
|
242
|
-
if (input.mcpDirectTools?.length) {
|
|
243
|
-
env.MCP_DIRECT_TOOLS = input.mcpDirectTools.join(",");
|
|
244
|
-
} else {
|
|
245
|
-
env.MCP_DIRECT_TOOLS = "__none__";
|
|
246
|
-
}
|
|
247
|
-
if (input.structuredOutput) {
|
|
248
|
-
env[STRUCTURED_OUTPUT_CAPTURE_ENV] = input.structuredOutput.outputPath;
|
|
249
|
-
env[STRUCTURED_OUTPUT_SCHEMA_ENV] = input.structuredOutput.schemaPath;
|
|
250
|
-
}
|
|
251
|
-
if (input.steerInboxDir) {
|
|
252
|
-
env[SUBAGENT_STEER_INBOX_ENV] = input.steerInboxDir;
|
|
253
|
-
}
|
|
254
|
-
const encodedToolBudget = encodeToolBudgetEnv(input.toolBudget);
|
|
255
|
-
if (encodedToolBudget) env[TOOL_BUDGET_ENV] = encodedToolBudget;
|
|
256
|
-
|
|
257
|
-
env[SUBAGENT_PARENT_SESSION_ENV] = input.parentSessionId ?? process.env[SUBAGENT_PARENT_SESSION_ENV] ?? "";
|
|
258
|
-
|
|
259
|
-
return { args, env, tempDir };
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
export const parseParentPathEnv = parseNestedPathEnv;
|
|
263
|
-
|
|
264
|
-
export function cleanupTempDir(tempDir: string | null | undefined): void {
|
|
265
|
-
if (!tempDir) return;
|
|
266
|
-
try {
|
|
267
|
-
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
268
|
-
} catch {
|
|
269
|
-
// Temp cleanup is best effort.
|
|
270
|
-
}
|
|
271
|
-
}
|
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
import * as fs from "node:fs";
|
|
2
|
-
import * as path from "node:path";
|
|
3
|
-
import { fileURLToPath } from "node:url";
|
|
4
|
-
|
|
5
|
-
export const PI_CODING_AGENT_PACKAGE = "@duckmind/dm-coding-agent";
|
|
6
|
-
export const DM_SUBAGENT_PI_BINARY_ENV = "DM_SUBAGENT_PI_BINARY";
|
|
7
|
-
|
|
8
|
-
export function findPiPackageRootFromEntry(
|
|
9
|
-
entryPoint: string,
|
|
10
|
-
): string | undefined {
|
|
11
|
-
let dir = path.dirname(entryPoint);
|
|
12
|
-
while (dir !== path.dirname(dir)) {
|
|
13
|
-
const packageJsonPath = path.join(dir, "package.json");
|
|
14
|
-
if (fs.existsSync(packageJsonPath)) {
|
|
15
|
-
const pkg = JSON.parse(fs.readFileSync(packageJsonPath, "utf-8")) as {
|
|
16
|
-
name?: unknown;
|
|
17
|
-
};
|
|
18
|
-
if (pkg.name === PI_CODING_AGENT_PACKAGE) return dir;
|
|
19
|
-
}
|
|
20
|
-
dir = path.dirname(dir);
|
|
21
|
-
}
|
|
22
|
-
return undefined;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export function resolveInstalledPiPackageRoot(): string | undefined {
|
|
26
|
-
return findPiPackageRootFromEntry(
|
|
27
|
-
fileURLToPath(import.meta.resolve(PI_CODING_AGENT_PACKAGE)),
|
|
28
|
-
);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export function resolvePiPackageRoot(): string | undefined {
|
|
32
|
-
try {
|
|
33
|
-
const entry = process.argv[1];
|
|
34
|
-
return entry
|
|
35
|
-
? findPiPackageRootFromEntry(fs.realpathSync(entry))
|
|
36
|
-
: undefined;
|
|
37
|
-
} catch {
|
|
38
|
-
// process.argv[1] probing is best-effort; callers can fall back to PATH/package resolution.
|
|
39
|
-
return undefined;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export interface PiSpawnDeps {
|
|
44
|
-
platform?: NodeJS.Platform;
|
|
45
|
-
execPath?: string;
|
|
46
|
-
argv1?: string;
|
|
47
|
-
existsSync?: (filePath: string) => boolean;
|
|
48
|
-
readFileSync?: (filePath: string, encoding: "utf-8") => string;
|
|
49
|
-
resolvePackageJson?: () => string;
|
|
50
|
-
resolvePackageEntry?: () => string;
|
|
51
|
-
piPackageRoot?: string;
|
|
52
|
-
env?: NodeJS.ProcessEnv;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
interface PiSpawnCommand {
|
|
56
|
-
command: string;
|
|
57
|
-
args: string[];
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
function isRunnableNodeScript(
|
|
61
|
-
filePath: string,
|
|
62
|
-
existsSync: (filePath: string) => boolean,
|
|
63
|
-
): boolean {
|
|
64
|
-
if (!existsSync(filePath)) return false;
|
|
65
|
-
return /\.(?:mjs|cjs|js)$/i.test(filePath);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
function normalizePath(filePath: string): string {
|
|
69
|
-
return path.isAbsolute(filePath) ? filePath : path.resolve(filePath);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export function resolveWindowsPiCliScript(
|
|
73
|
-
deps: PiSpawnDeps = {},
|
|
74
|
-
): string | undefined {
|
|
75
|
-
const existsSync = deps.existsSync ?? fs.existsSync;
|
|
76
|
-
const readFileSync =
|
|
77
|
-
deps.readFileSync ??
|
|
78
|
-
((filePath, encoding) => fs.readFileSync(filePath, encoding));
|
|
79
|
-
const argv1 = deps.argv1 ?? process.argv[1];
|
|
80
|
-
|
|
81
|
-
if (argv1) {
|
|
82
|
-
const argvPath = normalizePath(argv1);
|
|
83
|
-
if (isRunnableNodeScript(argvPath, existsSync)) {
|
|
84
|
-
return argvPath;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
try {
|
|
89
|
-
const resolvePackageJson =
|
|
90
|
-
deps.resolvePackageJson ??
|
|
91
|
-
(() => {
|
|
92
|
-
const root = deps.piPackageRoot ?? resolvePiPackageRoot();
|
|
93
|
-
if (root) return path.join(root, "package.json");
|
|
94
|
-
const packageRoot = deps.resolvePackageEntry
|
|
95
|
-
? findPiPackageRootFromEntry(deps.resolvePackageEntry())
|
|
96
|
-
: resolveInstalledPiPackageRoot();
|
|
97
|
-
if (!packageRoot)
|
|
98
|
-
throw new Error(
|
|
99
|
-
`Could not resolve ${PI_CODING_AGENT_PACKAGE} package root`,
|
|
100
|
-
);
|
|
101
|
-
return path.join(packageRoot, "package.json");
|
|
102
|
-
});
|
|
103
|
-
const packageJsonPath = resolvePackageJson();
|
|
104
|
-
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8")) as {
|
|
105
|
-
bin?: string | Record<string, string>;
|
|
106
|
-
};
|
|
107
|
-
const binField = packageJson.bin;
|
|
108
|
-
const binPath =
|
|
109
|
-
typeof binField === "string"
|
|
110
|
-
? binField
|
|
111
|
-
: (binField?.pi ?? Object.values(binField ?? {})[0]);
|
|
112
|
-
if (!binPath) return undefined;
|
|
113
|
-
const candidate = path.resolve(path.dirname(packageJsonPath), binPath);
|
|
114
|
-
if (isRunnableNodeScript(candidate, existsSync)) {
|
|
115
|
-
return candidate;
|
|
116
|
-
}
|
|
117
|
-
} catch {
|
|
118
|
-
// Windows CLI resolution is optional; falling back to `dm` lets PATH handle execution.
|
|
119
|
-
return undefined;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
return undefined;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
export function getPiSpawnCommand(
|
|
126
|
-
args: string[],
|
|
127
|
-
deps: PiSpawnDeps = {},
|
|
128
|
-
): PiSpawnCommand {
|
|
129
|
-
const env = deps.env ?? process.env;
|
|
130
|
-
const piBinary = env[DM_SUBAGENT_PI_BINARY_ENV]?.trim();
|
|
131
|
-
if (piBinary) {
|
|
132
|
-
return { command: piBinary, args };
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
const platform = deps.platform ?? process.platform;
|
|
136
|
-
if (platform === "win32") {
|
|
137
|
-
const piCliPath = resolveWindowsPiCliScript(deps);
|
|
138
|
-
if (piCliPath) {
|
|
139
|
-
return {
|
|
140
|
-
command: deps.execPath ?? process.execPath,
|
|
141
|
-
args: [piCliPath, ...args],
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
return { command: "dm", args };
|
|
147
|
-
}
|