@duckmind/dm-windows-x64 0.60.6 → 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,2 +1,462 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as os from "node:os";
|
|
3
|
+
import * as path from "node:path";
|
|
4
|
+
import { formatToolCall } from "./formatters.js";
|
|
5
|
+
const DEFAULT_CONFIG_DIR_NAME = ".dm";
|
|
6
|
+
const PI_CODING_AGENT_PACKAGE_NAME = "@duckmind/dm-coding-agent";
|
|
7
|
+
export const PI_CODING_AGENT_PACKAGE_ROOT_ENV = "DM_SUBAGENTS_PI_CODING_AGENT_PACKAGE_ROOT";
|
|
8
|
+
function validConfigDirName(value) {
|
|
9
|
+
return typeof value === "string" && value.trim() ? value : undefined;
|
|
10
|
+
}
|
|
11
|
+
function readConfigDirNameFromPackageRoot(packageRoot) {
|
|
12
|
+
if (!packageRoot)
|
|
13
|
+
return;
|
|
14
|
+
try {
|
|
15
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(packageRoot, "package.json"), "utf-8"));
|
|
16
|
+
if (pkg.name !== PI_CODING_AGENT_PACKAGE_NAME)
|
|
17
|
+
return;
|
|
18
|
+
return validConfigDirName(pkg.piConfig?.configDir);
|
|
19
|
+
} catch {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function resolveConfigDirNameFromPackageJson(entryPoint = process.argv[1], packageRoot = process.env[PI_CODING_AGENT_PACKAGE_ROOT_ENV]) {
|
|
24
|
+
const packageRootValue = readConfigDirNameFromPackageRoot(packageRoot);
|
|
25
|
+
if (packageRootValue)
|
|
26
|
+
return packageRootValue;
|
|
27
|
+
if (!entryPoint)
|
|
28
|
+
return;
|
|
29
|
+
try {
|
|
30
|
+
let dir = path.dirname(fs.realpathSync(entryPoint));
|
|
31
|
+
while (dir !== path.dirname(dir)) {
|
|
32
|
+
const value = readConfigDirNameFromPackageRoot(dir);
|
|
33
|
+
if (value)
|
|
34
|
+
return value;
|
|
35
|
+
dir = path.dirname(dir);
|
|
36
|
+
}
|
|
37
|
+
} catch {}
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
export function resolveConfigDirName(codingAgentModule, entryPoint, packageRoot) {
|
|
41
|
+
const moduleValue = codingAgentModule && typeof codingAgentModule === "object" ? validConfigDirName(codingAgentModule.CONFIG_DIR_NAME) : undefined;
|
|
42
|
+
return moduleValue ?? resolveConfigDirNameFromPackageJson(entryPoint, packageRoot) ?? DEFAULT_CONFIG_DIR_NAME;
|
|
43
|
+
}
|
|
44
|
+
export function getConfigDirName() {
|
|
45
|
+
return resolveConfigDirName();
|
|
46
|
+
}
|
|
47
|
+
export function getProjectConfigDir(projectRoot) {
|
|
48
|
+
return path.join(projectRoot, getConfigDirName());
|
|
49
|
+
}
|
|
50
|
+
export function getAgentDir() {
|
|
51
|
+
const configured = process.env.DM_CODING_AGENT_DIR;
|
|
52
|
+
if (configured === "~")
|
|
53
|
+
return os.homedir();
|
|
54
|
+
if (configured?.startsWith("~/"))
|
|
55
|
+
return path.join(os.homedir(), configured.slice(2));
|
|
56
|
+
return configured || path.join(os.homedir(), getConfigDirName(), "agent");
|
|
57
|
+
}
|
|
58
|
+
const statusCache = new Map;
|
|
59
|
+
function getErrorMessage(error) {
|
|
60
|
+
return error instanceof Error ? error.message : String(error);
|
|
61
|
+
}
|
|
62
|
+
export function resolveChildCwd(baseCwd, childCwd) {
|
|
63
|
+
if (!childCwd)
|
|
64
|
+
return baseCwd;
|
|
65
|
+
return path.isAbsolute(childCwd) ? childCwd : path.resolve(baseCwd, childCwd);
|
|
66
|
+
}
|
|
67
|
+
function isNotFoundError(error) {
|
|
68
|
+
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
69
|
+
}
|
|
70
|
+
export function readStatus(asyncDir) {
|
|
71
|
+
const statusPath = path.join(asyncDir, "status.json");
|
|
72
|
+
let stat;
|
|
73
|
+
try {
|
|
74
|
+
stat = fs.statSync(statusPath);
|
|
75
|
+
} catch (error) {
|
|
76
|
+
if (isNotFoundError(error))
|
|
77
|
+
return null;
|
|
78
|
+
throw new Error(`Failed to inspect async status file '${statusPath}': ${getErrorMessage(error)}`, {
|
|
79
|
+
cause: error instanceof Error ? error : undefined
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
const cached = statusCache.get(statusPath);
|
|
83
|
+
if (cached && cached.mtime === stat.mtimeMs) {
|
|
84
|
+
return cached.status;
|
|
85
|
+
}
|
|
86
|
+
let content;
|
|
87
|
+
try {
|
|
88
|
+
content = fs.readFileSync(statusPath, "utf-8");
|
|
89
|
+
} catch (error) {
|
|
90
|
+
if (isNotFoundError(error))
|
|
91
|
+
return null;
|
|
92
|
+
throw new Error(`Failed to read async status file '${statusPath}': ${getErrorMessage(error)}`, {
|
|
93
|
+
cause: error instanceof Error ? error : undefined
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
let status;
|
|
97
|
+
try {
|
|
98
|
+
status = JSON.parse(content);
|
|
99
|
+
} catch (error) {
|
|
100
|
+
throw new Error(`Failed to parse async status file '${statusPath}': ${getErrorMessage(error)}`, {
|
|
101
|
+
cause: error instanceof Error ? error : undefined
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
statusCache.set(statusPath, { mtime: stat.mtimeMs, status });
|
|
105
|
+
if (statusCache.size > 50) {
|
|
106
|
+
const firstKey = statusCache.keys().next().value;
|
|
107
|
+
if (firstKey)
|
|
108
|
+
statusCache.delete(firstKey);
|
|
109
|
+
}
|
|
110
|
+
return status;
|
|
111
|
+
}
|
|
112
|
+
const outputTailCache = new Map;
|
|
113
|
+
function getOutputTail(outputFile, maxLines = 3) {
|
|
114
|
+
if (!outputFile)
|
|
115
|
+
return [];
|
|
116
|
+
let fd = null;
|
|
117
|
+
try {
|
|
118
|
+
const stat = fs.statSync(outputFile);
|
|
119
|
+
if (stat.size === 0)
|
|
120
|
+
return [];
|
|
121
|
+
const cached = outputTailCache.get(outputFile);
|
|
122
|
+
if (cached && cached.mtime === stat.mtimeMs && cached.size === stat.size) {
|
|
123
|
+
return cached.lines;
|
|
124
|
+
}
|
|
125
|
+
const tailBytes = 4096;
|
|
126
|
+
const start = Math.max(0, stat.size - tailBytes);
|
|
127
|
+
fd = fs.openSync(outputFile, "r");
|
|
128
|
+
const buffer = Buffer.alloc(Math.min(tailBytes, stat.size));
|
|
129
|
+
fs.readSync(fd, buffer, 0, buffer.length, start);
|
|
130
|
+
const content = buffer.toString("utf-8");
|
|
131
|
+
const allLines = content.split(`
|
|
132
|
+
`).filter((l) => l.trim());
|
|
133
|
+
const lines = allLines.slice(-maxLines).map((l) => l.slice(0, 120) + (l.length > 120 ? "..." : ""));
|
|
134
|
+
outputTailCache.set(outputFile, { mtime: stat.mtimeMs, size: stat.size, lines });
|
|
135
|
+
if (outputTailCache.size > 20) {
|
|
136
|
+
const firstKey = outputTailCache.keys().next().value;
|
|
137
|
+
if (firstKey)
|
|
138
|
+
outputTailCache.delete(firstKey);
|
|
139
|
+
}
|
|
140
|
+
return lines;
|
|
141
|
+
} catch {
|
|
142
|
+
return [];
|
|
143
|
+
} finally {
|
|
144
|
+
if (fd !== null) {
|
|
145
|
+
try {
|
|
146
|
+
fs.closeSync(fd);
|
|
147
|
+
} catch {}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
export function getLastActivity(outputFile) {
|
|
152
|
+
if (!outputFile)
|
|
153
|
+
return "";
|
|
154
|
+
try {
|
|
155
|
+
const stat = fs.statSync(outputFile);
|
|
156
|
+
const ago = Date.now() - stat.mtimeMs;
|
|
157
|
+
if (ago < 1000)
|
|
158
|
+
return "active now";
|
|
159
|
+
if (ago < 60000)
|
|
160
|
+
return `active ${Math.floor(ago / 1000)}s ago`;
|
|
161
|
+
return `active ${Math.floor(ago / 60000)}m ago`;
|
|
162
|
+
} catch {
|
|
163
|
+
return "";
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
export function findLatestSessionFile(sessionDir) {
|
|
167
|
+
if (!fs.existsSync(sessionDir))
|
|
168
|
+
return null;
|
|
169
|
+
const files = fs.readdirSync(sessionDir).filter((f) => f.endsWith(".jsonl")).map((f) => {
|
|
170
|
+
const filePath = path.join(sessionDir, f);
|
|
171
|
+
return {
|
|
172
|
+
path: filePath,
|
|
173
|
+
mtime: fs.statSync(filePath).mtimeMs
|
|
174
|
+
};
|
|
175
|
+
}).sort((a, b) => b.mtime - a.mtime);
|
|
176
|
+
return files.length > 0 ? files[0].path : null;
|
|
177
|
+
}
|
|
178
|
+
function writePrompt(agent, prompt) {
|
|
179
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "dm-subagent-"));
|
|
180
|
+
const p = path.join(dir, `${agent.replace(/[^\w.-]/g, "_")}.md`);
|
|
181
|
+
fs.writeFileSync(p, prompt, { mode: 384 });
|
|
182
|
+
return { dir, path: p };
|
|
183
|
+
}
|
|
184
|
+
export function getFinalOutput(messages) {
|
|
185
|
+
const validTextParts = [];
|
|
186
|
+
for (let i = messages.length - 1;i >= 0; i--) {
|
|
187
|
+
const msg = messages[i];
|
|
188
|
+
if (msg.role !== "assistant")
|
|
189
|
+
continue;
|
|
190
|
+
const hasAssistantError = "errorMessage" in msg && typeof msg.errorMessage === "string" && msg.errorMessage.length > 0 || "stopReason" in msg && msg.stopReason === "error";
|
|
191
|
+
if (hasAssistantError)
|
|
192
|
+
continue;
|
|
193
|
+
for (let j = msg.content.length - 1;j >= 0; j--) {
|
|
194
|
+
const part = msg.content[j];
|
|
195
|
+
if (part.type !== "text" || part.text.trim().length === 0)
|
|
196
|
+
continue;
|
|
197
|
+
validTextParts.push(part.text);
|
|
198
|
+
if (/```acceptance-report\s*\n[\s\S]*?```/i.test(part.text))
|
|
199
|
+
return part.text;
|
|
200
|
+
for (const match of part.text.matchAll(/```(?:json|jsonc|json5)\s*\n([\s\S]*?)```/gi)) {
|
|
201
|
+
const body = match[1] ?? "";
|
|
202
|
+
if (/"criteriaSatisfied"/.test(body) && /"(?:changedFiles|testsAddedOrUpdated|commandsRun|validationOutput|residualRisks|noStagedFiles|diffSummary|reviewFindings|manualNotes)"/.test(body)) {
|
|
203
|
+
return part.text;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
if (/ACCEPTANCE_REPORT\s*:/i.test(part.text))
|
|
207
|
+
return part.text;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
return validTextParts[0] ?? "";
|
|
211
|
+
}
|
|
212
|
+
export function getSingleResultOutput(result) {
|
|
213
|
+
return result.finalOutput ?? getFinalOutput(result.messages ?? []);
|
|
214
|
+
}
|
|
215
|
+
export function getDisplayItems(messages) {
|
|
216
|
+
if (!messages || messages.length === 0)
|
|
217
|
+
return [];
|
|
218
|
+
const items = [];
|
|
219
|
+
for (const msg of messages) {
|
|
220
|
+
if (msg.role === "assistant") {
|
|
221
|
+
for (const part of msg.content) {
|
|
222
|
+
if (part.type === "text")
|
|
223
|
+
items.push({ type: "text", text: part.text });
|
|
224
|
+
else if (part.type === "toolCall")
|
|
225
|
+
items.push({ type: "tool", name: part.name, args: part.arguments });
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return items;
|
|
230
|
+
}
|
|
231
|
+
function compactCompletedProgress(progress) {
|
|
232
|
+
if (progress.status === "running")
|
|
233
|
+
return progress;
|
|
234
|
+
return {
|
|
235
|
+
index: progress.index,
|
|
236
|
+
agent: progress.agent,
|
|
237
|
+
status: progress.status,
|
|
238
|
+
activityState: progress.activityState,
|
|
239
|
+
task: progress.task,
|
|
240
|
+
skills: progress.skills,
|
|
241
|
+
toolCount: progress.toolCount,
|
|
242
|
+
tokens: progress.tokens,
|
|
243
|
+
durationMs: progress.durationMs,
|
|
244
|
+
error: progress.error,
|
|
245
|
+
failedTool: progress.failedTool,
|
|
246
|
+
recentTools: [],
|
|
247
|
+
recentOutput: []
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
function extractToolCallSummaries(messages) {
|
|
251
|
+
if (!messages?.length)
|
|
252
|
+
return [];
|
|
253
|
+
const summaries = [];
|
|
254
|
+
for (const msg of messages) {
|
|
255
|
+
if (msg.role !== "assistant")
|
|
256
|
+
continue;
|
|
257
|
+
for (const part of msg.content) {
|
|
258
|
+
if (part.type !== "toolCall")
|
|
259
|
+
continue;
|
|
260
|
+
const args = typeof part.arguments === "object" && part.arguments !== null && !Array.isArray(part.arguments) ? part.arguments : {};
|
|
261
|
+
summaries.push({
|
|
262
|
+
text: formatToolCall(part.name, args),
|
|
263
|
+
expandedText: formatToolCall(part.name, args, true)
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
return summaries;
|
|
268
|
+
}
|
|
269
|
+
export function sumResultsUsage(results) {
|
|
270
|
+
const usage = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: 0, turns: 0 };
|
|
271
|
+
for (const result of results) {
|
|
272
|
+
usage.input += result.usage.input;
|
|
273
|
+
usage.output += result.usage.output;
|
|
274
|
+
usage.cacheRead += result.usage.cacheRead;
|
|
275
|
+
usage.cacheWrite += result.usage.cacheWrite;
|
|
276
|
+
usage.cost += result.usage.cost;
|
|
277
|
+
usage.turns += result.usage.turns;
|
|
278
|
+
}
|
|
279
|
+
return usage;
|
|
280
|
+
}
|
|
281
|
+
function addNestedCost(total, children) {
|
|
282
|
+
for (const child of children ?? []) {
|
|
283
|
+
if (child.totalCost) {
|
|
284
|
+
total.inputTokens += child.totalCost.inputTokens;
|
|
285
|
+
total.outputTokens += child.totalCost.outputTokens;
|
|
286
|
+
total.costUsd += child.totalCost.costUsd;
|
|
287
|
+
continue;
|
|
288
|
+
}
|
|
289
|
+
addNestedCost(total, child.children);
|
|
290
|
+
for (const step of child.steps ?? [])
|
|
291
|
+
addNestedCost(total, step.children);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
export function sumResultsCost(results) {
|
|
295
|
+
const total = { inputTokens: 0, outputTokens: 0, costUsd: 0 };
|
|
296
|
+
for (const result of results) {
|
|
297
|
+
total.inputTokens += result.usage.input;
|
|
298
|
+
total.outputTokens += result.usage.output;
|
|
299
|
+
total.costUsd += result.usage.cost;
|
|
300
|
+
addNestedCost(total, result.children);
|
|
301
|
+
}
|
|
302
|
+
return total;
|
|
303
|
+
}
|
|
304
|
+
export function compactForegroundResult(result) {
|
|
305
|
+
if (result.progress?.status === "running")
|
|
306
|
+
return result;
|
|
307
|
+
const toolCalls = result.toolCalls?.length ? result.toolCalls : extractToolCallSummaries(result.messages);
|
|
308
|
+
return {
|
|
309
|
+
...result,
|
|
310
|
+
messages: undefined,
|
|
311
|
+
progress: undefined,
|
|
312
|
+
toolCalls: toolCalls.length ? toolCalls : undefined
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
export function compactForegroundDetails(details) {
|
|
316
|
+
return {
|
|
317
|
+
...details,
|
|
318
|
+
results: details.results.map(compactForegroundResult),
|
|
319
|
+
progress: details.progress ? details.progress.map(compactCompletedProgress) : undefined
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
export function detectSubagentError(messages) {
|
|
323
|
+
let lastAssistantTextIndex = -1;
|
|
324
|
+
for (let i = messages.length - 1;i >= 0; i--) {
|
|
325
|
+
const msg = messages[i];
|
|
326
|
+
if (msg.role === "assistant") {
|
|
327
|
+
const hasText = Array.isArray(msg.content) && msg.content.some((c) => c.type === "text" && ("text" in c) && typeof c.text === "string" && c.text.trim().length > 0);
|
|
328
|
+
if (hasText) {
|
|
329
|
+
lastAssistantTextIndex = i;
|
|
330
|
+
break;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
const scanStart = lastAssistantTextIndex >= 0 ? lastAssistantTextIndex + 1 : 0;
|
|
335
|
+
for (let i = messages.length - 1;i >= scanStart; i--) {
|
|
336
|
+
const msg = messages[i];
|
|
337
|
+
if (msg.role !== "toolResult")
|
|
338
|
+
continue;
|
|
339
|
+
const toolName = "toolName" in msg && typeof msg.toolName === "string" ? msg.toolName : undefined;
|
|
340
|
+
const isError = "isError" in msg && msg.isError === true;
|
|
341
|
+
if (isError) {
|
|
342
|
+
const text = msg.content.find((c) => c.type === "text");
|
|
343
|
+
const details = text && "text" in text ? text.text : undefined;
|
|
344
|
+
const exitMatch = details?.match(/exit(?:ed)?\s*(?:with\s*)?(?:code|status)?\s*[:\s]?\s*(\d+)/i);
|
|
345
|
+
return {
|
|
346
|
+
hasError: true,
|
|
347
|
+
exitCode: exitMatch ? parseInt(exitMatch[1], 10) : 1,
|
|
348
|
+
errorType: toolName || "tool",
|
|
349
|
+
details: details?.slice(0, 200)
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
if (toolName !== "bash")
|
|
353
|
+
continue;
|
|
354
|
+
const text = msg.content.find((c) => c.type === "text");
|
|
355
|
+
if (!text || !("text" in text))
|
|
356
|
+
continue;
|
|
357
|
+
const output = text.text;
|
|
358
|
+
const exitMatch = output.match(/exit(?:ed)?\s*(?:with\s*)?(?:code|status)?\s*[:\s]?\s*(\d+)/i);
|
|
359
|
+
if (exitMatch) {
|
|
360
|
+
const code = parseInt(exitMatch[1], 10);
|
|
361
|
+
if (code !== 0) {
|
|
362
|
+
return { hasError: true, exitCode: code, errorType: "bash", details: output.slice(0, 200) };
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
const fatalPatterns = [
|
|
366
|
+
/command not found/i,
|
|
367
|
+
/permission denied/i,
|
|
368
|
+
/no such file or directory/i,
|
|
369
|
+
/segmentation fault/i,
|
|
370
|
+
/killed|terminated/i,
|
|
371
|
+
/out of memory/i,
|
|
372
|
+
/connection refused/i,
|
|
373
|
+
/timeout/i
|
|
374
|
+
];
|
|
375
|
+
for (const pattern of fatalPatterns) {
|
|
376
|
+
if (pattern.test(output)) {
|
|
377
|
+
return { hasError: true, exitCode: 1, errorType: "bash", details: output.slice(0, 200) };
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
return { hasError: false };
|
|
382
|
+
}
|
|
383
|
+
export function extractToolArgsPreview(args) {
|
|
384
|
+
const truncatePreview = (value, maxLength) => value.length > maxLength ? `${value.slice(0, maxLength - 3)}...` : value;
|
|
385
|
+
const stringifyPreviewValue = (value) => {
|
|
386
|
+
if (typeof value === "string" && value.trim().length > 0)
|
|
387
|
+
return value;
|
|
388
|
+
if (typeof value === "number" || typeof value === "boolean")
|
|
389
|
+
return String(value);
|
|
390
|
+
return;
|
|
391
|
+
};
|
|
392
|
+
const previewArray = (value) => {
|
|
393
|
+
if (!Array.isArray(value) || value.length === 0)
|
|
394
|
+
return;
|
|
395
|
+
const first = stringifyPreviewValue(value[0]);
|
|
396
|
+
if (!first)
|
|
397
|
+
return;
|
|
398
|
+
const suffix = value.length > 1 ? ` (+${value.length - 1} more)` : "";
|
|
399
|
+
return `${first}${suffix}`;
|
|
400
|
+
};
|
|
401
|
+
if (args.tool && typeof args.tool === "string") {
|
|
402
|
+
const server = args.server && typeof args.server === "string" ? `${args.server}/` : "";
|
|
403
|
+
const toolArgs = args.args && typeof args.args === "string" ? ` ${args.args.slice(0, 40)}` : "";
|
|
404
|
+
return `${server}${args.tool}${toolArgs}`;
|
|
405
|
+
}
|
|
406
|
+
const queriesPreview = previewArray(args.queries);
|
|
407
|
+
if (queriesPreview)
|
|
408
|
+
return truncatePreview(queriesPreview, 60);
|
|
409
|
+
if (typeof args.query === "string" && args.query.trim().length > 0)
|
|
410
|
+
return truncatePreview(args.query, 60);
|
|
411
|
+
if (typeof args.workflow === "string" && args.workflow.trim().length > 0)
|
|
412
|
+
return `workflow=${truncatePreview(args.workflow, 48)}`;
|
|
413
|
+
if (typeof args.url === "string" && args.url.trim().length > 0)
|
|
414
|
+
return truncatePreview(args.url, 60);
|
|
415
|
+
const urlsPreview = previewArray(args.urls);
|
|
416
|
+
if (urlsPreview)
|
|
417
|
+
return truncatePreview(urlsPreview, 60);
|
|
418
|
+
if (typeof args.prompt === "string" && args.prompt.trim().length > 0)
|
|
419
|
+
return truncatePreview(args.prompt, 60);
|
|
420
|
+
const previewKeys = ["command", "path", "file_path", "pattern", "query", "url", "task", "describe", "search"];
|
|
421
|
+
for (const key of previewKeys) {
|
|
422
|
+
if (args[key] && typeof args[key] === "string") {
|
|
423
|
+
const value = args[key];
|
|
424
|
+
return truncatePreview(value, 60);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
for (const [key, value] of Object.entries(args)) {
|
|
428
|
+
const arrayPreview = previewArray(value);
|
|
429
|
+
if (arrayPreview)
|
|
430
|
+
return `${key}=${truncatePreview(arrayPreview, 50)}`;
|
|
431
|
+
if (typeof value === "string" && value.length > 0) {
|
|
432
|
+
const preview = truncatePreview(value, 50);
|
|
433
|
+
return `${key}=${preview}`;
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
return "";
|
|
437
|
+
}
|
|
438
|
+
export function extractTextFromContent(content) {
|
|
439
|
+
if (!content)
|
|
440
|
+
return "";
|
|
441
|
+
if (typeof content === "string")
|
|
442
|
+
return content;
|
|
443
|
+
if (!Array.isArray(content))
|
|
444
|
+
return "";
|
|
445
|
+
const texts = [];
|
|
446
|
+
for (const part of content) {
|
|
447
|
+
if (part && typeof part === "object") {
|
|
448
|
+
if ("type" in part && part.type === "text" && "text" in part) {
|
|
449
|
+
texts.push(String(part.text));
|
|
450
|
+
} else if ("type" in part && part.type === "tool_result" && "content" in part) {
|
|
451
|
+
const inner = extractTextFromContent(part.content);
|
|
452
|
+
if (inner)
|
|
453
|
+
texts.push(inner);
|
|
454
|
+
} else if ("text" in part) {
|
|
455
|
+
texts.push(String(part.text));
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
return texts.join(`
|
|
460
|
+
`);
|
|
461
|
+
}
|
|
462
|
+
export { mapConcurrent } from "../runs/shared/parallel-utils.js";
|