@duckmind/dm-windows-x64 0.60.4 → 0.60.8
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 +1,288 @@
|
|
|
1
|
-
|
|
1
|
+
export const PROMPT_TEMPLATE_SUBAGENT_REQUEST_EVENT = "prompt-template:subagent:request";
|
|
2
|
+
export const PROMPT_TEMPLATE_SUBAGENT_STARTED_EVENT = "prompt-template:subagent:started";
|
|
3
|
+
export const PROMPT_TEMPLATE_SUBAGENT_RESPONSE_EVENT = "prompt-template:subagent:response";
|
|
4
|
+
export const PROMPT_TEMPLATE_SUBAGENT_UPDATE_EVENT = "prompt-template:subagent:update";
|
|
5
|
+
export const PROMPT_TEMPLATE_SUBAGENT_CANCEL_EVENT = "prompt-template:subagent:cancel";
|
|
6
|
+
function parseDelegationTasks(tasks) {
|
|
7
|
+
if (!Array.isArray(tasks))
|
|
8
|
+
return [];
|
|
9
|
+
const parsed = [];
|
|
10
|
+
for (const item of tasks) {
|
|
11
|
+
if (!item || typeof item !== "object")
|
|
12
|
+
return [];
|
|
13
|
+
const value = item;
|
|
14
|
+
if (typeof value.agent !== "string" || !value.agent.trim())
|
|
15
|
+
return [];
|
|
16
|
+
if (typeof value.task !== "string" || !value.task.trim())
|
|
17
|
+
return [];
|
|
18
|
+
const model = typeof value.model === "string" && value.model.trim().length > 0 ? value.model : undefined;
|
|
19
|
+
const cwd = typeof value.cwd === "string" && value.cwd.trim().length > 0 ? value.cwd : undefined;
|
|
20
|
+
parsed.push({
|
|
21
|
+
agent: value.agent,
|
|
22
|
+
task: value.task,
|
|
23
|
+
...model ? { model } : {},
|
|
24
|
+
...cwd ? { cwd } : {}
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
return parsed;
|
|
28
|
+
}
|
|
29
|
+
function parsePromptTemplateRequest(data) {
|
|
30
|
+
if (!data || typeof data !== "object")
|
|
31
|
+
return;
|
|
32
|
+
const value = data;
|
|
33
|
+
if (typeof value.requestId !== "string" || !value.requestId)
|
|
34
|
+
return;
|
|
35
|
+
if (typeof value.model !== "string" || !value.model)
|
|
36
|
+
return;
|
|
37
|
+
if (typeof value.cwd !== "string" || !value.cwd)
|
|
38
|
+
return;
|
|
39
|
+
if (value.context !== "fresh" && value.context !== "fork")
|
|
40
|
+
return;
|
|
41
|
+
const tasks = parseDelegationTasks(value.tasks);
|
|
42
|
+
const worktree = value.worktree === true ? true : undefined;
|
|
43
|
+
const hasSingle = typeof value.agent === "string" && value.agent.length > 0 && typeof value.task === "string" && value.task.length > 0;
|
|
44
|
+
if (!hasSingle && tasks.length === 0)
|
|
45
|
+
return;
|
|
46
|
+
const fallbackTask = tasks[0];
|
|
47
|
+
return {
|
|
48
|
+
requestId: value.requestId,
|
|
49
|
+
agent: hasSingle ? value.agent : fallbackTask.agent,
|
|
50
|
+
task: hasSingle ? value.task : fallbackTask.task,
|
|
51
|
+
...tasks.length > 0 ? { tasks } : {},
|
|
52
|
+
context: value.context,
|
|
53
|
+
model: value.model,
|
|
54
|
+
cwd: value.cwd,
|
|
55
|
+
...worktree ? { worktree } : {}
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
function firstTextContent(content) {
|
|
59
|
+
if (!Array.isArray(content))
|
|
60
|
+
return;
|
|
61
|
+
for (const part of content) {
|
|
62
|
+
if (!part || typeof part !== "object")
|
|
63
|
+
continue;
|
|
64
|
+
if (part.type !== "text")
|
|
65
|
+
continue;
|
|
66
|
+
const text = part.text;
|
|
67
|
+
if (typeof text === "string" && text.trim())
|
|
68
|
+
return text.trim();
|
|
69
|
+
}
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
function filterRecentOutput(lines) {
|
|
73
|
+
if (!lines || lines.length === 0)
|
|
74
|
+
return;
|
|
75
|
+
const filtered = lines.filter((line) => typeof line === "string" && line.trim() && line.trim() !== "(running...)");
|
|
76
|
+
if (filtered.length === 0)
|
|
77
|
+
return;
|
|
78
|
+
return filtered;
|
|
79
|
+
}
|
|
80
|
+
function sanitizeRecentTools(tools) {
|
|
81
|
+
if (!tools || tools.length === 0)
|
|
82
|
+
return;
|
|
83
|
+
const sanitized = tools.flatMap((entry) => {
|
|
84
|
+
if (typeof entry.tool !== "string" || entry.tool.trim().length === 0)
|
|
85
|
+
return [];
|
|
86
|
+
return [{
|
|
87
|
+
tool: entry.tool,
|
|
88
|
+
args: typeof entry.args === "string" ? entry.args : String(entry.args ?? "")
|
|
89
|
+
}];
|
|
90
|
+
});
|
|
91
|
+
return sanitized.length > 0 ? sanitized : undefined;
|
|
92
|
+
}
|
|
93
|
+
function resolveProgressModel(update, entry) {
|
|
94
|
+
const results = update.details?.results;
|
|
95
|
+
if (!results || results.length === 0)
|
|
96
|
+
return;
|
|
97
|
+
if (typeof entry.index === "number" && entry.index >= 0) {
|
|
98
|
+
const byIndex = results[entry.index];
|
|
99
|
+
if (typeof byIndex?.model === "string")
|
|
100
|
+
return byIndex.model;
|
|
101
|
+
}
|
|
102
|
+
if (entry.agent) {
|
|
103
|
+
const byAgent = results.find((result) => result.agent === entry.agent && typeof result.model === "string");
|
|
104
|
+
if (byAgent?.model)
|
|
105
|
+
return byAgent.model;
|
|
106
|
+
}
|
|
107
|
+
const firstWithModel = results.find((result) => typeof result.model === "string");
|
|
108
|
+
return firstWithModel?.model;
|
|
109
|
+
}
|
|
110
|
+
function toolCallNameFromSummary(summary) {
|
|
111
|
+
const text = typeof summary.expandedText === "string" && summary.expandedText.trim().length > 0 ? summary.expandedText.trim() : typeof summary.text === "string" ? summary.text.trim() : "";
|
|
112
|
+
if (!text)
|
|
113
|
+
return;
|
|
114
|
+
if (text.startsWith("$ "))
|
|
115
|
+
return "bash";
|
|
116
|
+
return text.match(/^[A-Za-z_][\w.-]*/)?.[0];
|
|
117
|
+
}
|
|
118
|
+
function buildDelegationMessages(result, fallbackText) {
|
|
119
|
+
if (Array.isArray(result.messages) && result.messages.length > 0)
|
|
120
|
+
return result.messages;
|
|
121
|
+
const toolCallParts = (result.toolCalls ?? []).flatMap((summary) => {
|
|
122
|
+
const name = toolCallNameFromSummary(summary);
|
|
123
|
+
return name ? [{ type: "toolCall", name, arguments: { summary: summary.expandedText ?? summary.text ?? "" } }] : [];
|
|
124
|
+
});
|
|
125
|
+
const text = typeof result.finalOutput === "string" && result.finalOutput.trim().length > 0 ? result.finalOutput.trim() : fallbackText;
|
|
126
|
+
const content = [
|
|
127
|
+
...toolCallParts,
|
|
128
|
+
...text ? [{ type: "text", text }] : []
|
|
129
|
+
];
|
|
130
|
+
if (content.length === 0)
|
|
131
|
+
return [];
|
|
132
|
+
return [{ role: "assistant", content }];
|
|
133
|
+
}
|
|
134
|
+
function toDelegationUpdate(requestId, update) {
|
|
135
|
+
const progress = update.details?.progress?.[0];
|
|
136
|
+
const taskProgress = update.details?.progress?.map((entry) => {
|
|
137
|
+
const lastOutput = entry.recentOutput?.[entry.recentOutput.length - 1];
|
|
138
|
+
const safeLastOutput = typeof lastOutput === "string" && lastOutput.trim() && lastOutput !== "(running...)" ? lastOutput : undefined;
|
|
139
|
+
return {
|
|
140
|
+
index: entry.index,
|
|
141
|
+
agent: entry.agent ?? "delegate",
|
|
142
|
+
status: entry.status,
|
|
143
|
+
currentTool: entry.currentTool,
|
|
144
|
+
currentToolArgs: entry.currentToolArgs,
|
|
145
|
+
recentOutput: safeLastOutput,
|
|
146
|
+
recentOutputLines: filterRecentOutput(entry.recentOutput),
|
|
147
|
+
recentTools: sanitizeRecentTools(entry.recentTools),
|
|
148
|
+
model: resolveProgressModel(update, entry),
|
|
149
|
+
toolCount: entry.toolCount,
|
|
150
|
+
durationMs: entry.durationMs,
|
|
151
|
+
tokens: entry.tokens
|
|
152
|
+
};
|
|
153
|
+
});
|
|
154
|
+
if (!progress && (!taskProgress || taskProgress.length === 0))
|
|
155
|
+
return;
|
|
156
|
+
const lastOutput = progress?.recentOutput?.[progress.recentOutput.length - 1];
|
|
157
|
+
const safeLastOutput = typeof lastOutput === "string" && lastOutput.trim() && lastOutput !== "(running...)" ? lastOutput : undefined;
|
|
158
|
+
return {
|
|
159
|
+
requestId,
|
|
160
|
+
currentTool: progress?.currentTool,
|
|
161
|
+
currentToolArgs: progress?.currentToolArgs,
|
|
162
|
+
recentOutput: safeLastOutput,
|
|
163
|
+
recentOutputLines: filterRecentOutput(progress?.recentOutput),
|
|
164
|
+
recentTools: sanitizeRecentTools(progress?.recentTools),
|
|
165
|
+
model: progress ? resolveProgressModel(update, progress) : undefined,
|
|
166
|
+
toolCount: progress?.toolCount,
|
|
167
|
+
durationMs: progress?.durationMs,
|
|
168
|
+
tokens: progress?.tokens,
|
|
169
|
+
taskProgress
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
export function registerPromptTemplateDelegationBridge(options) {
|
|
173
|
+
const controllers = new Map;
|
|
174
|
+
const pendingCancels = new Set;
|
|
175
|
+
const subscriptions = [];
|
|
176
|
+
const subscribe = (event, handler) => {
|
|
177
|
+
const unsubscribe = options.events.on(event, handler);
|
|
178
|
+
if (typeof unsubscribe === "function")
|
|
179
|
+
subscriptions.push(unsubscribe);
|
|
180
|
+
};
|
|
181
|
+
subscribe(PROMPT_TEMPLATE_SUBAGENT_CANCEL_EVENT, (data) => {
|
|
182
|
+
if (!data || typeof data !== "object")
|
|
183
|
+
return;
|
|
184
|
+
const requestId = data.requestId;
|
|
185
|
+
if (typeof requestId !== "string")
|
|
186
|
+
return;
|
|
187
|
+
const controller = controllers.get(requestId);
|
|
188
|
+
if (controller) {
|
|
189
|
+
controller.abort();
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
pendingCancels.add(requestId);
|
|
193
|
+
});
|
|
194
|
+
subscribe(PROMPT_TEMPLATE_SUBAGENT_REQUEST_EVENT, async (data) => {
|
|
195
|
+
const request = parsePromptTemplateRequest(data);
|
|
196
|
+
if (!request)
|
|
197
|
+
return;
|
|
198
|
+
const ctx = options.getContext();
|
|
199
|
+
if (!ctx) {
|
|
200
|
+
const response = {
|
|
201
|
+
...request,
|
|
202
|
+
messages: [],
|
|
203
|
+
isError: true,
|
|
204
|
+
errorText: "No active extension context for delegated subagent execution."
|
|
205
|
+
};
|
|
206
|
+
options.events.emit(PROMPT_TEMPLATE_SUBAGENT_RESPONSE_EVENT, response);
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
const controller = new AbortController;
|
|
210
|
+
controllers.set(request.requestId, controller);
|
|
211
|
+
if (pendingCancels.delete(request.requestId)) {
|
|
212
|
+
controller.abort();
|
|
213
|
+
const response = {
|
|
214
|
+
...request,
|
|
215
|
+
messages: [],
|
|
216
|
+
isError: true,
|
|
217
|
+
errorText: "Delegated prompt cancelled."
|
|
218
|
+
};
|
|
219
|
+
options.events.emit(PROMPT_TEMPLATE_SUBAGENT_RESPONSE_EVENT, response);
|
|
220
|
+
controllers.delete(request.requestId);
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
options.events.emit(PROMPT_TEMPLATE_SUBAGENT_STARTED_EVENT, { requestId: request.requestId });
|
|
224
|
+
try {
|
|
225
|
+
const result = await options.execute(request.requestId, request, controller.signal, ctx, (update) => {
|
|
226
|
+
const payload = toDelegationUpdate(request.requestId, update);
|
|
227
|
+
if (!payload)
|
|
228
|
+
return;
|
|
229
|
+
options.events.emit(PROMPT_TEMPLATE_SUBAGENT_UPDATE_EVENT, payload);
|
|
230
|
+
});
|
|
231
|
+
const contentText = firstTextContent(result.content);
|
|
232
|
+
const messages = buildDelegationMessages(result.details?.results?.[0] ?? {}, contentText);
|
|
233
|
+
const parallelResults = request.tasks ? request.tasks.map((task, index) => {
|
|
234
|
+
const step = result.details?.results?.[index];
|
|
235
|
+
if (!step) {
|
|
236
|
+
return {
|
|
237
|
+
agent: task.agent,
|
|
238
|
+
messages: [],
|
|
239
|
+
isError: true,
|
|
240
|
+
errorText: "Missing result for delegated parallel task."
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
const exitCode = typeof step.exitCode === "number" ? step.exitCode : undefined;
|
|
244
|
+
const errorText = step.error;
|
|
245
|
+
return {
|
|
246
|
+
agent: step.agent ?? task.agent,
|
|
247
|
+
messages: buildDelegationMessages(step),
|
|
248
|
+
isError: exitCode !== undefined && exitCode !== 0 || !!errorText,
|
|
249
|
+
errorText: errorText || undefined
|
|
250
|
+
};
|
|
251
|
+
}) : undefined;
|
|
252
|
+
const response = {
|
|
253
|
+
...request,
|
|
254
|
+
messages,
|
|
255
|
+
...parallelResults ? { parallelResults } : {},
|
|
256
|
+
...contentText ? { contentText } : {},
|
|
257
|
+
isError: result.isError === true,
|
|
258
|
+
errorText: result.isError ? contentText : undefined
|
|
259
|
+
};
|
|
260
|
+
options.events.emit(PROMPT_TEMPLATE_SUBAGENT_RESPONSE_EVENT, response);
|
|
261
|
+
} catch (error) {
|
|
262
|
+
const response = {
|
|
263
|
+
...request,
|
|
264
|
+
messages: [],
|
|
265
|
+
isError: true,
|
|
266
|
+
errorText: error instanceof Error ? error.message : String(error)
|
|
267
|
+
};
|
|
268
|
+
options.events.emit(PROMPT_TEMPLATE_SUBAGENT_RESPONSE_EVENT, response);
|
|
269
|
+
} finally {
|
|
270
|
+
controllers.delete(request.requestId);
|
|
271
|
+
}
|
|
272
|
+
});
|
|
273
|
+
return {
|
|
274
|
+
cancelAll: () => {
|
|
275
|
+
for (const controller of controllers.values()) {
|
|
276
|
+
controller.abort();
|
|
277
|
+
}
|
|
278
|
+
controllers.clear();
|
|
279
|
+
pendingCancels.clear();
|
|
280
|
+
},
|
|
281
|
+
dispose: () => {
|
|
282
|
+
for (const unsubscribe of subscriptions)
|
|
283
|
+
unsubscribe();
|
|
284
|
+
subscriptions.length = 0;
|
|
285
|
+
pendingCancels.clear();
|
|
286
|
+
}
|
|
287
|
+
};
|
|
288
|
+
}
|
|
@@ -1,7 +1,297 @@
|
|
|
1
|
-
import*as
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { parseFrontmatter } from "../agents/frontmatter.js";
|
|
5
|
+
import { getAgentDir, getProjectConfigDir } from "../shared/utils.js";
|
|
6
|
+
const RESERVED_COMMAND_NAMES = new Set([
|
|
7
|
+
"chain-prompts",
|
|
8
|
+
"prompt-workflow",
|
|
9
|
+
"run",
|
|
10
|
+
"chain",
|
|
11
|
+
"parallel",
|
|
12
|
+
"run-chain",
|
|
13
|
+
"subagents-doctor",
|
|
14
|
+
"subagents-models"
|
|
15
|
+
]);
|
|
16
|
+
function packagePromptsDir() {
|
|
17
|
+
return path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..", "..", "prompts");
|
|
18
|
+
}
|
|
19
|
+
function promptDirs(cwd) {
|
|
20
|
+
return [
|
|
21
|
+
packagePromptsDir(),
|
|
22
|
+
path.join(getAgentDir(), "prompts"),
|
|
23
|
+
path.join(getProjectConfigDir(cwd), "prompts")
|
|
24
|
+
];
|
|
25
|
+
}
|
|
26
|
+
function readPromptFiles(cwd) {
|
|
27
|
+
const files = [];
|
|
28
|
+
for (const dir of promptDirs(cwd)) {
|
|
29
|
+
let entries;
|
|
30
|
+
try {
|
|
31
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
32
|
+
} catch {
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
for (const entry of entries) {
|
|
36
|
+
if (entry.isFile() && entry.name.endsWith(".md"))
|
|
37
|
+
files.push(path.join(dir, entry.name));
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return files;
|
|
41
|
+
}
|
|
42
|
+
function firstNonEmptyLine(value) {
|
|
43
|
+
return value.split(/\r?\n/).map((line) => line.trim()).find(Boolean) ?? "Prompt workflow";
|
|
44
|
+
}
|
|
45
|
+
function stringField(frontmatter, key) {
|
|
46
|
+
const value = frontmatter[key]?.trim();
|
|
47
|
+
return value ? value : undefined;
|
|
48
|
+
}
|
|
49
|
+
function booleanField(frontmatter, key) {
|
|
50
|
+
const value = frontmatter[key]?.trim().toLowerCase();
|
|
51
|
+
if (value === "true" || value === "yes" || value === "1")
|
|
52
|
+
return true;
|
|
53
|
+
if (value === "false" || value === "no" || value === "0")
|
|
54
|
+
return false;
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
function parseSkill(value) {
|
|
58
|
+
if (!value)
|
|
59
|
+
return;
|
|
60
|
+
if (value === "false")
|
|
61
|
+
return false;
|
|
62
|
+
const parts = value.split(",").map((part) => part.trim()).filter(Boolean);
|
|
63
|
+
return parts.length > 1 ? parts : parts[0];
|
|
64
|
+
}
|
|
65
|
+
function parseAgent(frontmatter) {
|
|
66
|
+
const subagent = stringField(frontmatter, "subagent");
|
|
67
|
+
if (!subagent || subagent === "true")
|
|
68
|
+
return "delegate";
|
|
69
|
+
return subagent;
|
|
70
|
+
}
|
|
71
|
+
function loadPromptWorkflow(filePath) {
|
|
72
|
+
const content = fs.readFileSync(filePath, "utf-8");
|
|
73
|
+
const { frontmatter, body } = parseFrontmatter(content);
|
|
74
|
+
const name = path.basename(filePath, ".md");
|
|
75
|
+
if (!name || RESERVED_COMMAND_NAMES.has(name))
|
|
76
|
+
return;
|
|
77
|
+
const model = stringField(frontmatter, "model");
|
|
78
|
+
const skill = parseSkill(stringField(frontmatter, "skill"));
|
|
79
|
+
const cwd = stringField(frontmatter, "cwd");
|
|
80
|
+
const chain = stringField(frontmatter, "chain");
|
|
81
|
+
return {
|
|
82
|
+
name,
|
|
83
|
+
description: stringField(frontmatter, "description") ?? firstNonEmptyLine(body),
|
|
84
|
+
body,
|
|
85
|
+
filePath,
|
|
86
|
+
agent: parseAgent(frontmatter),
|
|
87
|
+
...booleanField(frontmatter, "inheritContext") === true || booleanField(frontmatter, "fork") === true ? { context: "fork" } : {},
|
|
88
|
+
...booleanField(frontmatter, "fresh") === true ? { context: "fresh" } : {},
|
|
89
|
+
...model ? { model } : {},
|
|
90
|
+
...skill !== undefined ? { skill } : {},
|
|
91
|
+
...cwd ? { cwd } : {},
|
|
92
|
+
...booleanField(frontmatter, "worktree") === true ? { worktree: true } : {},
|
|
93
|
+
...chain ? { chain } : {}
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
export function discoverPromptWorkflows(cwd) {
|
|
97
|
+
const workflows = new Map;
|
|
98
|
+
for (const file of readPromptFiles(cwd)) {
|
|
99
|
+
const workflow = loadPromptWorkflow(file);
|
|
100
|
+
if (workflow)
|
|
101
|
+
workflows.set(workflow.name, workflow);
|
|
102
|
+
}
|
|
103
|
+
return [...workflows.values()].sort((a, b) => a.name.localeCompare(b.name));
|
|
104
|
+
}
|
|
105
|
+
function shellWords(input) {
|
|
106
|
+
const words = [];
|
|
107
|
+
let current = "";
|
|
108
|
+
let quote;
|
|
109
|
+
let escaped = false;
|
|
110
|
+
for (const ch of input) {
|
|
111
|
+
if (escaped) {
|
|
112
|
+
current += ch;
|
|
113
|
+
escaped = false;
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
if (ch === "\\") {
|
|
117
|
+
escaped = true;
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
if (quote) {
|
|
121
|
+
if (ch === quote)
|
|
122
|
+
quote = undefined;
|
|
123
|
+
else
|
|
124
|
+
current += ch;
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
if (ch === "'" || ch === '"') {
|
|
128
|
+
quote = ch;
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
if (/\s/.test(ch)) {
|
|
132
|
+
if (current) {
|
|
133
|
+
words.push(current);
|
|
134
|
+
current = "";
|
|
135
|
+
}
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
current += ch;
|
|
139
|
+
}
|
|
140
|
+
if (current)
|
|
141
|
+
words.push(current);
|
|
142
|
+
return words;
|
|
143
|
+
}
|
|
144
|
+
function substituteArgs(template, args) {
|
|
145
|
+
const all = args.join(" ");
|
|
146
|
+
return template.replace(/\$ARGUMENTS/g, all).replace(/\$@/g, all).replace(/\$\{(\d+):-([^}]*)\}/g, (_match, index, fallback) => args[Number(index) - 1] || fallback).replace(/\$(\d+)/g, (_match, index) => args[Number(index) - 1] ?? "");
|
|
147
|
+
}
|
|
148
|
+
function parseRuntimeOptions(words) {
|
|
149
|
+
const args = [];
|
|
150
|
+
let agentOverride;
|
|
151
|
+
let fork = false;
|
|
152
|
+
let fresh = false;
|
|
153
|
+
let worktree = false;
|
|
154
|
+
let bg = false;
|
|
155
|
+
for (let i = 0;i < words.length; i++) {
|
|
156
|
+
const word = words[i];
|
|
157
|
+
if (word === "--fork") {
|
|
158
|
+
fork = true;
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
if (word === "--fresh") {
|
|
162
|
+
fresh = true;
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
if (word === "--worktree") {
|
|
166
|
+
worktree = true;
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
if (word === "--bg" || word === "--async") {
|
|
170
|
+
bg = true;
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
if (word === "--subagent") {
|
|
174
|
+
agentOverride = words[++i];
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
const eq = word.match(/^--subagent(?:=|:)(.+)$/);
|
|
178
|
+
if (eq) {
|
|
179
|
+
agentOverride = eq[1];
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
args.push(word);
|
|
183
|
+
}
|
|
184
|
+
return { args, agentOverride, fork, fresh, worktree, bg };
|
|
185
|
+
}
|
|
186
|
+
function splitChainDeclaration(input) {
|
|
187
|
+
const delimiter = input.indexOf(" -- ");
|
|
188
|
+
if (delimiter === -1)
|
|
189
|
+
return { declaration: input.trim(), argsText: "" };
|
|
190
|
+
return { declaration: input.slice(0, delimiter).trim(), argsText: input.slice(delimiter + 4).trim() };
|
|
191
|
+
}
|
|
192
|
+
function splitPromptChain(input) {
|
|
193
|
+
return input.split(" -> ").map((part) => part.trim()).filter(Boolean);
|
|
194
|
+
}
|
|
195
|
+
function workflowParams(workflow, args, runtime) {
|
|
196
|
+
const task = substituteArgs(workflow.body, args).trim();
|
|
197
|
+
const context = runtime.fork ? "fork" : runtime.fresh ? "fresh" : workflow.context;
|
|
198
|
+
return {
|
|
199
|
+
agent: runtime.agentOverride ?? workflow.agent,
|
|
200
|
+
task,
|
|
201
|
+
clarify: false,
|
|
202
|
+
agentScope: "both",
|
|
203
|
+
...context ? { context } : {},
|
|
204
|
+
...workflow.model ? { model: workflow.model } : {},
|
|
205
|
+
...workflow.skill !== undefined ? { skill: workflow.skill } : {},
|
|
206
|
+
...workflow.cwd ? { cwd: workflow.cwd } : {},
|
|
207
|
+
...runtime.worktree || workflow.worktree ? { worktree: true } : {},
|
|
208
|
+
...runtime.bg ? { async: true } : {}
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
function workflowChainStep(workflow, args, runtime) {
|
|
212
|
+
const params = workflowParams(workflow, args, runtime);
|
|
213
|
+
return {
|
|
214
|
+
agent: params.agent ?? "delegate",
|
|
215
|
+
task: params.task,
|
|
216
|
+
...params.model ? { model: params.model } : {},
|
|
217
|
+
...params.skill !== undefined ? { skill: params.skill } : {},
|
|
218
|
+
...params.cwd ? { cwd: params.cwd } : {}
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
function findWorkflow(workflows, name) {
|
|
222
|
+
return workflows.find((workflow) => workflow.name === name);
|
|
223
|
+
}
|
|
224
|
+
function formatWorkflowList(workflows) {
|
|
225
|
+
if (workflows.length === 0)
|
|
226
|
+
return "No prompt workflows found in package, user, or project prompts.";
|
|
227
|
+
return [
|
|
228
|
+
"Prompt workflows:",
|
|
229
|
+
...workflows.map((workflow) => `- ${workflow.name}: ${workflow.description} (${workflow.filePath})`)
|
|
230
|
+
].join(`
|
|
231
|
+
`);
|
|
232
|
+
}
|
|
233
|
+
export function registerPromptWorkflowCommands(input) {
|
|
234
|
+
const { pi, run } = input;
|
|
235
|
+
pi.registerCommand("prompt-workflow", {
|
|
236
|
+
description: "Run a prompt template through native dm-subagents: /prompt-workflow <name> [args]",
|
|
237
|
+
handler: async (rawArgs, ctx) => {
|
|
238
|
+
const words = shellWords(rawArgs);
|
|
239
|
+
const name = words.shift();
|
|
240
|
+
const workflows = discoverPromptWorkflows(ctx.cwd);
|
|
241
|
+
if (!name || name === "list") {
|
|
242
|
+
pi.sendMessage({ content: formatWorkflowList(workflows), display: true });
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
const workflow = findWorkflow(workflows, name);
|
|
246
|
+
if (!workflow) {
|
|
247
|
+
ctx.ui.notify(`Unknown prompt workflow: ${name}`, "error");
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
const runtime = parseRuntimeOptions(words);
|
|
251
|
+
try {
|
|
252
|
+
if (workflow.chain) {
|
|
253
|
+
const chainNames = splitPromptChain(workflow.chain);
|
|
254
|
+
const chain = chainNames.map((stepName) => {
|
|
255
|
+
const step = findWorkflow(workflows, stepName);
|
|
256
|
+
if (!step)
|
|
257
|
+
throw new Error(`Unknown prompt workflow in chain '${workflow.name}': ${stepName}`);
|
|
258
|
+
return workflowChainStep(step, runtime.args, runtime);
|
|
259
|
+
});
|
|
260
|
+
await run({ chain, task: runtime.args.join(" "), clarify: false, agentScope: "both", ...runtime.bg ? { async: true } : {} }, ctx);
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
await run(workflowParams(workflow, runtime.args, runtime), ctx);
|
|
264
|
+
} catch (error) {
|
|
265
|
+
ctx.ui.notify(error instanceof Error ? error.message : String(error), "error");
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
pi.registerCommand("chain-prompts", {
|
|
270
|
+
description: "Run prompt templates as a native subagent chain: /chain-prompts analyze -> fix -- args",
|
|
271
|
+
handler: async (rawArgs, ctx) => {
|
|
272
|
+
const { declaration, argsText } = splitChainDeclaration(rawArgs);
|
|
273
|
+
const workflows = discoverPromptWorkflows(ctx.cwd);
|
|
274
|
+
if (!declaration || declaration === "list") {
|
|
275
|
+
pi.sendMessage({ content: formatWorkflowList(workflows), display: true });
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
const runtime = parseRuntimeOptions(shellWords(argsText));
|
|
279
|
+
const names = splitPromptChain(declaration);
|
|
280
|
+
if (names.length === 0) {
|
|
281
|
+
ctx.ui.notify("Usage: /chain-prompts prompt-a -> prompt-b -- args", "error");
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
try {
|
|
285
|
+
const chain = names.map((name) => {
|
|
286
|
+
const workflow = findWorkflow(workflows, name);
|
|
287
|
+
if (!workflow)
|
|
288
|
+
throw new Error(`Unknown prompt workflow: ${name}`);
|
|
289
|
+
return workflowChainStep(workflow, runtime.args, runtime);
|
|
290
|
+
});
|
|
291
|
+
await run({ chain, task: runtime.args.join(" "), clarify: false, agentScope: "both", ...runtime.bg ? { async: true } : {} }, ctx);
|
|
292
|
+
} catch (error) {
|
|
293
|
+
ctx.ui.notify(error instanceof Error ? error.message : String(error), "error");
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
});
|
|
297
|
+
}
|