@duckmind/dm-windows-x64 0.61.5 → 0.61.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dm.exe +0 -0
- package/extensions/.dm-extensions.json +211 -67
- package/extensions/dm-subagents/agents/claude-code-writer.md +15 -0
- package/extensions/dm-subagents/agents/claude-code.md +15 -0
- package/extensions/dm-subagents/agents/codex-exec-writer.md +15 -0
- package/extensions/dm-subagents/agents/codex-exec.md +15 -0
- package/extensions/dm-subagents/agents/cursor-agent-writer.md +14 -0
- package/extensions/dm-subagents/agents/cursor-agent.md +14 -0
- package/extensions/dm-subagents/agents/delegate.md +3 -2
- package/extensions/dm-subagents/agents/oracle.md +10 -5
- package/extensions/dm-subagents/agents/researcher.md +2 -2
- package/extensions/dm-subagents/agents/reviewer.md +17 -7
- package/extensions/dm-subagents/agents/scout.md +5 -5
- package/extensions/dm-subagents/agents/worker.md +6 -2
- package/extensions/dm-subagents/async-retention-discovery-worker.mjs +167 -0
- package/extensions/dm-subagents/index.js +4 -0
- package/extensions/dm-subagents/inspector-runner.mjs +10 -0
- package/extensions/dm-subagents/install.mjs +3 -2
- package/extensions/dm-subagents/package.json +2 -2
- package/extensions/dm-subagents/prompts/council.md +60 -0
- package/extensions/dm-subagents/prompts/parallel-review.md +5 -1
- package/extensions/dm-subagents/prompts/review-loop.md +13 -7
- package/extensions/dm-subagents/skills/council-mode/SKILL.md +59 -0
- package/extensions/dm-subagents/skills/council-mode/references/pass-contracts.md +150 -0
- package/extensions/dm-subagents/skills/dm-subagents/SKILL.md +96 -911
- package/extensions/dm-subagents/skills/dm-subagents/references/constraints-and-recipes.md +70 -0
- package/extensions/dm-subagents/skills/dm-subagents/references/execution-controls.md +539 -0
- package/extensions/dm-subagents/skills/dm-subagents/references/management-authoring-rpc.md +161 -0
- package/extensions/dm-subagents/skills/dm-subagents/references/multi-lane-orchestration.md +51 -0
- package/extensions/dm-subagents/skills/dm-subagents/references/prompting-and-roles.md +295 -0
- package/extensions/dm-subagents/skills/dm-subagents/references/review-and-validation.md +73 -0
- package/extensions/dm-subagents/src/agents/agent-management.js +716 -484
- package/extensions/dm-subagents/src/agents/agent-refinements.js +563 -0
- package/extensions/dm-subagents/src/agents/agent-serializer.js +70 -5
- package/extensions/dm-subagents/src/agents/agents.js +1447 -299
- package/extensions/dm-subagents/src/agents/builtin-names.js +15 -0
- package/extensions/dm-subagents/src/agents/chain-serializer.js +12 -7
- package/extensions/dm-subagents/src/agents/frontmatter.js +64 -14
- package/extensions/dm-subagents/src/agents/identity.js +1 -1
- package/extensions/dm-subagents/src/agents/proactive-skills.js +14 -11
- package/extensions/dm-subagents/src/agents/runtime-agent-events.js +49 -0
- package/extensions/dm-subagents/src/agents/runtime-agent-registry.js +412 -0
- package/extensions/dm-subagents/src/agents/skills.js +52 -35
- package/extensions/dm-subagents/src/api/agents.js +6 -0
- package/extensions/dm-subagents/src/api/background-work.js +151 -0
- package/extensions/dm-subagents/src/api/capability-ceiling.js +12 -0
- package/extensions/dm-subagents/src/api/control-channel.js +3 -0
- package/extensions/dm-subagents/src/api/delegation.js +5 -0
- package/extensions/dm-subagents/src/api/dm-args.js +3 -0
- package/extensions/dm-subagents/src/api/external-job-provider.js +137 -0
- package/extensions/dm-subagents/src/api/external-runs.js +233 -0
- package/extensions/dm-subagents/src/api/intercom-bridge.js +3 -0
- package/extensions/dm-subagents/src/api/preflight.js +322 -0
- package/extensions/dm-subagents/src/api/project-panes.js +11 -0
- package/extensions/dm-subagents/src/api/shared-types.js +4 -0
- package/extensions/dm-subagents/src/extension/config.js +175 -0
- package/extensions/dm-subagents/src/extension/control-notices.js +4 -43
- package/extensions/dm-subagents/src/extension/doctor.js +71 -17
- package/extensions/dm-subagents/src/extension/fanout-child.js +49 -32
- package/extensions/dm-subagents/src/extension/index.js +711 -265
- package/extensions/dm-subagents/src/extension/public-execution.js +114 -0
- package/extensions/dm-subagents/src/extension/rpc.js +427 -22
- package/extensions/dm-subagents/src/extension/schemas.js +158 -65
- package/extensions/dm-subagents/src/extension/steering-notices.js +23 -0
- package/extensions/dm-subagents/src/extension/subagent-guide.js +31 -0
- package/extensions/dm-subagents/src/extension/tool-description.js +92 -74
- package/extensions/dm-subagents/src/extension/tool-result.js +7 -0
- package/extensions/dm-subagents/src/inspectors/herdr/actions.js +218 -0
- package/extensions/dm-subagents/src/inspectors/herdr/client.js +123 -0
- package/extensions/dm-subagents/src/inspectors/herdr/focus.js +47 -0
- package/extensions/dm-subagents/src/inspectors/herdr/inspector-runner.js +160 -0
- package/extensions/dm-subagents/src/inspectors/herdr/project-panes.js +618 -0
- package/extensions/dm-subagents/src/inspectors/herdr/session-roots-codec.js +21 -0
- package/extensions/dm-subagents/src/inspectors/herdr/shell-command.js +15 -0
- package/extensions/dm-subagents/src/integrations/herdr-status.js +377 -0
- package/extensions/dm-subagents/src/intercom/intercom-bridge.js +17 -13
- package/extensions/dm-subagents/src/intercom/native-supervisor-channel.js +371 -79
- package/extensions/dm-subagents/src/intercom/result-intercom.js +47 -7
- package/extensions/dm-subagents/src/missions/actions.js +394 -0
- package/extensions/dm-subagents/src/missions/goal-driver.js +149 -0
- package/extensions/dm-subagents/src/missions/lifecycle.js +331 -0
- package/extensions/dm-subagents/src/missions/store.js +548 -0
- package/extensions/dm-subagents/src/missions/types.js +9 -0
- package/extensions/dm-subagents/src/missions/workflow-state.js +245 -0
- package/extensions/dm-subagents/src/policy/authority.js +37 -0
- package/extensions/dm-subagents/src/profiles/profiles.js +36 -18
- package/extensions/dm-subagents/src/runs/background/active-async-capacity.js +427 -0
- package/extensions/dm-subagents/src/runs/background/active-run-index.js +122 -0
- package/extensions/dm-subagents/src/runs/background/async-execution.js +925 -137
- package/extensions/dm-subagents/src/runs/background/async-job-tracker.js +515 -148
- package/extensions/dm-subagents/src/runs/background/async-resume.js +378 -51
- package/extensions/dm-subagents/src/runs/background/async-retention.js +828 -0
- package/extensions/dm-subagents/src/runs/background/async-status-snapshot.js +31 -0
- package/extensions/dm-subagents/src/runs/background/async-status.js +259 -22
- package/extensions/dm-subagents/src/runs/background/auto-drain.js +46 -0
- package/extensions/dm-subagents/src/runs/background/chain-append.js +50 -15
- package/extensions/dm-subagents/src/runs/background/chain-root-attachment.js +67 -12
- package/extensions/dm-subagents/src/runs/background/completion-batcher.js +5 -1
- package/extensions/dm-subagents/src/runs/background/completion-dedupe.js +3 -11
- package/extensions/dm-subagents/src/runs/background/completion-replay.js +245 -0
- package/extensions/dm-subagents/src/runs/background/control-channel.js +423 -36
- package/extensions/dm-subagents/src/runs/background/fleet-view.js +132 -59
- package/extensions/dm-subagents/src/runs/background/index-segment.js +38 -0
- package/extensions/dm-subagents/src/runs/background/inspect-rpc.js +373 -0
- package/extensions/dm-subagents/src/runs/background/notify.js +357 -57
- package/extensions/dm-subagents/src/runs/background/owned-process-tree.js +86 -0
- package/extensions/dm-subagents/src/runs/background/process-terminal.js +269 -0
- package/extensions/dm-subagents/src/runs/background/result-delivery-ownership.js +34 -0
- package/extensions/dm-subagents/src/runs/background/result-files.js +469 -0
- package/extensions/dm-subagents/src/runs/background/result-watcher.js +540 -75
- package/extensions/dm-subagents/src/runs/background/resume-guidance.js +44 -0
- package/extensions/dm-subagents/src/runs/background/retained-children.js +119 -0
- package/extensions/dm-subagents/src/runs/background/run-id-query.js +5 -0
- package/extensions/dm-subagents/src/runs/background/run-id-resolver.js +93 -9
- package/extensions/dm-subagents/src/runs/background/run-status.js +303 -32
- package/extensions/dm-subagents/src/runs/background/scheduled-runs.js +784 -376
- package/extensions/dm-subagents/src/runs/background/stale-run-reconciler.js +75 -34
- package/extensions/dm-subagents/src/runs/background/steering.js +221 -0
- package/extensions/dm-subagents/src/runs/background/subagent-runner.js +3106 -844
- package/extensions/dm-subagents/src/runs/background/subagent-wait.js +529 -0
- package/extensions/dm-subagents/src/runs/background/terminal-run-index.js +106 -0
- package/extensions/dm-subagents/src/runs/background/top-level-async.js +1 -1
- package/extensions/dm-subagents/src/runs/background/wait-completions.js +155 -0
- package/extensions/dm-subagents/src/runs/background/wait-config.js +46 -0
- package/extensions/dm-subagents/src/runs/background/wait-subscriptions.js +278 -0
- package/extensions/dm-subagents/src/runs/background/wait-tool.js +47 -0
- package/extensions/dm-subagents/src/runs/foreground/async-dismiss-action.js +81 -0
- package/extensions/dm-subagents/src/runs/foreground/async-steering-action.js +245 -0
- package/extensions/dm-subagents/src/runs/foreground/async-stop-action.js +74 -0
- package/extensions/dm-subagents/src/runs/foreground/execution.js +1401 -342
- package/extensions/dm-subagents/src/runs/foreground/foreground-control.js +133 -0
- package/extensions/dm-subagents/src/runs/foreground/foreground-history.js +148 -0
- package/extensions/dm-subagents/src/runs/foreground/prompt-audit.js +139 -0
- package/extensions/dm-subagents/src/runs/foreground/subagent-executor.js +4278 -1441
- package/extensions/dm-subagents/src/runs/foreground/workflow-detach-reconcile.js +278 -0
- package/extensions/dm-subagents/src/runs/foreground/workflow-foreground-steering.js +155 -0
- package/extensions/dm-subagents/src/runs/shared/abort-recovery.js +97 -0
- package/extensions/dm-subagents/src/runs/shared/acceptance.js +597 -148
- package/extensions/dm-subagents/src/runs/shared/agent-contract.js +35 -0
- package/extensions/dm-subagents/src/runs/shared/async-status-projection.js +472 -0
- package/extensions/dm-subagents/src/runs/shared/background-process-options.js +6 -0
- package/extensions/dm-subagents/src/runs/shared/capability-ceiling.js +175 -0
- package/extensions/dm-subagents/src/runs/shared/child-identity.js +32 -0
- package/extensions/dm-subagents/src/runs/shared/child-launch-plan.js +65 -0
- package/extensions/dm-subagents/src/runs/shared/child-protocol.js +447 -0
- package/extensions/dm-subagents/src/runs/shared/claude-code-adapter.js +120 -0
- package/extensions/dm-subagents/src/runs/shared/codex-exec-adapter.js +129 -0
- package/extensions/dm-subagents/src/runs/shared/completion-evidence.js +40 -0
- package/extensions/dm-subagents/src/runs/shared/completion-guard.js +140 -83
- package/extensions/dm-subagents/src/runs/shared/context-mode.js +38 -0
- package/extensions/dm-subagents/src/runs/shared/cursor-agent-adapter.js +101 -0
- package/extensions/dm-subagents/src/runs/shared/dm-args.js +445 -72
- package/extensions/dm-subagents/src/runs/shared/dm-spawn.js +27 -16
- package/extensions/dm-subagents/src/runs/shared/dynamic-fanout.js +19 -6
- package/extensions/dm-subagents/src/runs/shared/extension-bindings.js +81 -0
- package/extensions/dm-subagents/src/runs/shared/external-cli-contract.js +134 -0
- package/extensions/dm-subagents/src/runs/shared/external-cli-preflight.js +98 -0
- package/extensions/dm-subagents/src/runs/shared/external-cli-runner.js +419 -0
- package/extensions/dm-subagents/src/runs/shared/external-job-bridge.js +404 -0
- package/extensions/dm-subagents/src/runs/shared/external-job-runner.js +334 -0
- package/extensions/dm-subagents/src/runs/shared/fast-mode-extension.js +8 -0
- package/extensions/dm-subagents/src/runs/shared/host-step-status.js +228 -0
- package/extensions/dm-subagents/src/runs/shared/lane-metadata.js +104 -0
- package/extensions/dm-subagents/src/runs/shared/launch-cwd.js +17 -0
- package/extensions/dm-subagents/src/runs/shared/llm-intent-arbiter.js +190 -0
- package/extensions/dm-subagents/src/runs/shared/long-running-guard.js +48 -3
- package/extensions/dm-subagents/src/runs/shared/mcp-config-sources.js +387 -0
- package/extensions/dm-subagents/src/runs/shared/mcp-direct-tool-allowlist.js +212 -137
- package/extensions/dm-subagents/src/runs/shared/mcp-direct-tool-grant.js +131 -0
- package/extensions/dm-subagents/src/runs/shared/model-exclusions.js +207 -0
- package/extensions/dm-subagents/src/runs/shared/model-fallback.js +225 -55
- package/extensions/dm-subagents/src/runs/shared/model-scope.js +85 -28
- package/extensions/dm-subagents/src/runs/shared/mutation-evidence.js +182 -0
- package/extensions/dm-subagents/src/runs/shared/nested-events.js +264 -102
- package/extensions/dm-subagents/src/runs/shared/nested-render.js +15 -5
- package/extensions/dm-subagents/src/runs/shared/orca-progress-tabs.js +505 -0
- package/extensions/dm-subagents/src/runs/shared/parallel-handoff.js +653 -0
- package/extensions/dm-subagents/src/runs/shared/parallel-utils.js +29 -12
- package/extensions/dm-subagents/src/runs/shared/permissions.js +108 -0
- package/extensions/dm-subagents/src/runs/shared/process-signal.js +13 -0
- package/extensions/dm-subagents/src/runs/shared/run-fanout-budget.js +257 -0
- package/extensions/dm-subagents/src/runs/shared/run-history.js +133 -13
- package/extensions/dm-subagents/src/runs/shared/runtime-acknowledged-extensions.js +62 -0
- package/extensions/dm-subagents/src/runs/shared/session-lease.js +225 -0
- package/extensions/dm-subagents/src/runs/shared/single-output.js +129 -27
- package/extensions/dm-subagents/src/runs/shared/spawn-budget.js +95 -0
- package/extensions/dm-subagents/src/runs/shared/structured-output.js +129 -10
- package/extensions/dm-subagents/src/runs/shared/subagent-control.js +66 -11
- package/extensions/dm-subagents/src/runs/shared/subagent-prompt-runtime.js +548 -70
- package/extensions/dm-subagents/src/runs/shared/subagent-startup-retry.js +50 -0
- package/extensions/dm-subagents/src/runs/shared/task-intent.js +130 -0
- package/extensions/dm-subagents/src/runs/shared/tool-availability.js +59 -0
- package/extensions/dm-subagents/src/runs/shared/tool-budget.js +7 -5
- package/extensions/dm-subagents/src/runs/shared/tool-timeout.js +64 -0
- package/extensions/dm-subagents/src/runs/shared/usage-budget.js +74 -0
- package/extensions/dm-subagents/src/runs/shared/workflow-graph.js +22 -0
- package/extensions/dm-subagents/src/runs/shared/worktree-cleanup-plan.js +721 -0
- package/extensions/dm-subagents/src/runs/shared/worktree.js +168 -19
- package/extensions/dm-subagents/src/shared/accessible-dir.js +35 -0
- package/extensions/dm-subagents/src/shared/agent-stream-options.js +3 -0
- package/extensions/dm-subagents/src/shared/artifacts.js +170 -11
- package/extensions/dm-subagents/src/shared/atomic-json.js +36 -38
- package/extensions/dm-subagents/src/shared/capacity-resilient-json.js +77 -0
- package/extensions/dm-subagents/src/shared/child-session-name.js +15 -0
- package/extensions/dm-subagents/src/shared/child-transcript.js +57 -2
- package/extensions/dm-subagents/src/shared/completion-owner.js +7 -0
- package/extensions/dm-subagents/src/shared/display-text.js +142 -0
- package/extensions/dm-subagents/src/shared/extension-context.js +17 -0
- package/extensions/dm-subagents/src/shared/file-coalescer.js +9 -0
- package/extensions/dm-subagents/src/shared/file-system-retry.js +56 -0
- package/extensions/dm-subagents/src/shared/fork-context.js +96 -33
- package/extensions/dm-subagents/src/shared/formatters.js +21 -7
- package/extensions/dm-subagents/src/shared/launch-contract.js +94 -0
- package/extensions/dm-subagents/src/shared/model-info.js +10 -5
- package/extensions/dm-subagents/src/shared/node-executable.js +19 -0
- package/extensions/dm-subagents/src/shared/prompt-resources.js +10 -0
- package/extensions/dm-subagents/src/shared/pruned-fork.js +427 -0
- package/extensions/dm-subagents/src/shared/session-file-trust.js +19 -0
- package/extensions/dm-subagents/src/shared/session-tokens.js +14 -3
- package/extensions/dm-subagents/src/shared/settings.js +39 -47
- package/extensions/dm-subagents/src/shared/shortcuts.js +16 -0
- package/extensions/dm-subagents/src/shared/status-format.js +9 -2
- package/extensions/dm-subagents/src/shared/thinking-ceiling.js +41 -0
- package/extensions/dm-subagents/src/shared/types.js +47 -7
- package/extensions/dm-subagents/src/shared/utf8.js +12 -0
- package/extensions/dm-subagents/src/shared/utils.js +151 -131
- package/extensions/dm-subagents/src/shared/watch-strategy.js +3 -0
- package/extensions/dm-subagents/src/shared/workflow-child-permit.js +84 -0
- package/extensions/dm-subagents/src/slash/delegation-adapters.js +274 -0
- package/extensions/dm-subagents/src/slash/delegation-json.js +113 -0
- package/extensions/dm-subagents/src/slash/delegation-request.js +152 -0
- package/extensions/dm-subagents/src/slash/prompt-template-bridge.js +294 -243
- package/extensions/dm-subagents/src/slash/prompt-workflows.js +35 -73
- package/extensions/dm-subagents/src/slash/selector.js +101 -0
- package/extensions/dm-subagents/src/slash/slash-bridge.js +17 -1
- package/extensions/dm-subagents/src/slash/slash-commands.js +722 -732
- package/extensions/dm-subagents/src/slash/slash-live-state.js +37 -19
- package/extensions/dm-subagents/src/slash/subagents-admin.js +410 -0
- package/extensions/dm-subagents/src/tui/fleet-status.js +824 -0
- package/extensions/dm-subagents/src/tui/fleet-transcript.js +479 -0
- package/extensions/dm-subagents/src/tui/fleet.js +1326 -0
- package/extensions/dm-subagents/src/tui/render-helpers.js +22 -0
- package/extensions/dm-subagents/src/tui/render.js +1511 -261
- package/extensions/dm-subagents/src/watchdog/change-signature.js +220 -0
- package/extensions/dm-subagents/src/watchdog/child-status.js +151 -0
- package/extensions/dm-subagents/src/watchdog/emission-guard.js +90 -0
- package/extensions/dm-subagents/src/watchdog/lsp-diagnostics.js +484 -0
- package/extensions/dm-subagents/src/watchdog/model-selection.js +154 -0
- package/extensions/dm-subagents/src/watchdog/permission-arbiter.js +138 -0
- package/extensions/dm-subagents/src/watchdog/register-child.js +112 -0
- package/extensions/dm-subagents/src/watchdog/register-main.js +419 -0
- package/extensions/dm-subagents/src/watchdog/render.js +54 -0
- package/extensions/dm-subagents/src/watchdog/review.js +251 -0
- package/extensions/dm-subagents/src/watchdog/runtime.js +803 -0
- package/extensions/dm-subagents/src/watchdog/scope.js +56 -0
- package/extensions/dm-subagents/src/watchdog/settings.js +515 -0
- package/extensions/dm-subagents/src/watchdog/tool-actions.js +151 -0
- package/extensions/dm-subagents/src/watchdog/turn-delta.js +169 -0
- package/extensions/dm-subagents/src/watchdog/types.js +29 -0
- package/extensions/dm-subagents/src/watchdog/warning-format.js +58 -0
- package/extensions/dm-subagents/src/workflows/chat-progress.js +116 -0
- package/extensions/dm-subagents/src/workflows/host-command.js +227 -0
- package/extensions/dm-subagents/src/workflows/scripted-workflow.js +2011 -0
- package/extensions/dm-subagents/src/workflows/workflow-child-summary.js +116 -0
- package/extensions/dm-subagents/src/workflows/workflow-preflight.js +243 -0
- package/extensions/dm-subagents/src/workflows/workflow-receipt.js +387 -0
- package/extensions/dm-subagents/src/workflows/workflow-settlement.js +189 -0
- package/package.json +4 -3
- package/extensions/dm-fff/package.json +0 -21
- package/extensions/dm-fff/src/index.js +0 -691
- package/extensions/dm-fff/src/query.js +0 -60
- package/extensions/dm-subagents/agents/context-builder.md +0 -46
- package/extensions/dm-subagents/agents/planner.md +0 -55
- package/extensions/dm-subagents/prompts/parallel-context-build.md +0 -55
- package/extensions/dm-subagents/prompts/parallel-handoff-plan.md +0 -61
- package/extensions/dm-subagents/src/runs/background/wait.js +0 -206
- package/extensions/dm-subagents/src/runs/foreground/chain-clarify.js +0 -1013
- package/extensions/dm-subagents/src/runs/foreground/chain-execution.js +0 -981
- package/extensions/dm-subagents/src/runs/shared/turn-budget.js +0 -50
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as os from "node:os";
|
|
3
3
|
import * as path from "node:path";
|
|
4
|
+
import { previewDisplayText, sanitizeDisplayText, truncateDisplayText } from "./display-text.js";
|
|
4
5
|
import { formatToolCall } from "./formatters.js";
|
|
6
|
+
import { validateAsyncStatusLaneMetadata } from "../runs/shared/lane-metadata.js";
|
|
5
7
|
const DEFAULT_CONFIG_DIR_NAME = ".dm";
|
|
6
|
-
const
|
|
7
|
-
export const
|
|
8
|
+
const DM_CODING_AGENT_PACKAGE_NAME = "@duckmind/dm-coding-agent";
|
|
9
|
+
export const DM_CODING_AGENT_PACKAGE_ROOT_ENV = "DM_SUBAGENTS_DM_CODING_AGENT_PACKAGE_ROOT";
|
|
10
|
+
export const PROMPT_REDACTED = "[prompt redacted]";
|
|
11
|
+
export function resolveWatchPath(watchPath, nativeRealpath = fs.realpathSync.native) {
|
|
12
|
+
try {
|
|
13
|
+
return nativeRealpath(watchPath);
|
|
14
|
+
} catch {
|
|
15
|
+
return watchPath;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
8
18
|
function validConfigDirName(value) {
|
|
9
19
|
return typeof value === "string" && value.trim() ? value : undefined;
|
|
10
20
|
}
|
|
@@ -13,14 +23,14 @@ function readConfigDirNameFromPackageRoot(packageRoot) {
|
|
|
13
23
|
return;
|
|
14
24
|
try {
|
|
15
25
|
const pkg = JSON.parse(fs.readFileSync(path.join(packageRoot, "package.json"), "utf-8"));
|
|
16
|
-
if (pkg.name !==
|
|
26
|
+
if (pkg.name !== DM_CODING_AGENT_PACKAGE_NAME)
|
|
17
27
|
return;
|
|
18
28
|
return validConfigDirName(pkg.piConfig?.configDir);
|
|
19
29
|
} catch {
|
|
20
30
|
return;
|
|
21
31
|
}
|
|
22
32
|
}
|
|
23
|
-
function resolveConfigDirNameFromPackageJson(entryPoint = process.argv[1], packageRoot = process.env[
|
|
33
|
+
function resolveConfigDirNameFromPackageJson(entryPoint = process.argv[1], packageRoot = process.env[DM_CODING_AGENT_PACKAGE_ROOT_ENV]) {
|
|
24
34
|
const packageRootValue = readConfigDirNameFromPackageRoot(packageRoot);
|
|
25
35
|
if (packageRootValue)
|
|
26
36
|
return packageRootValue;
|
|
@@ -41,21 +51,45 @@ export function resolveConfigDirName(codingAgentModule, entryPoint, packageRoot)
|
|
|
41
51
|
const moduleValue = codingAgentModule && typeof codingAgentModule === "object" ? validConfigDirName(codingAgentModule.CONFIG_DIR_NAME) : undefined;
|
|
42
52
|
return moduleValue ?? resolveConfigDirNameFromPackageJson(entryPoint, packageRoot) ?? DEFAULT_CONFIG_DIR_NAME;
|
|
43
53
|
}
|
|
54
|
+
let cachedConfigDirName;
|
|
44
55
|
export function getConfigDirName() {
|
|
45
|
-
|
|
56
|
+
const entryPoint = process.argv[1];
|
|
57
|
+
const packageRoot = process.env[DM_CODING_AGENT_PACKAGE_ROOT_ENV];
|
|
58
|
+
if (cachedConfigDirName && cachedConfigDirName.entryPoint === entryPoint && cachedConfigDirName.packageRoot === packageRoot) {
|
|
59
|
+
return cachedConfigDirName.value;
|
|
60
|
+
}
|
|
61
|
+
const value = resolveConfigDirName(undefined, entryPoint, packageRoot);
|
|
62
|
+
cachedConfigDirName = { entryPoint, packageRoot, value };
|
|
63
|
+
return value;
|
|
46
64
|
}
|
|
47
65
|
export function getProjectConfigDir(projectRoot) {
|
|
48
66
|
return path.join(projectRoot, getConfigDirName());
|
|
49
67
|
}
|
|
50
68
|
export function getAgentDir() {
|
|
51
69
|
const configured = process.env.DM_CODING_AGENT_DIR;
|
|
70
|
+
const home = process.env.HOME || process.env.USERPROFILE || os.homedir();
|
|
52
71
|
if (configured === "~")
|
|
53
|
-
return
|
|
54
|
-
if (configured?.startsWith("~/"))
|
|
55
|
-
return path.join(
|
|
56
|
-
return configured || path.join(
|
|
72
|
+
return home;
|
|
73
|
+
if (configured?.startsWith("~/") || configured?.startsWith("~\\"))
|
|
74
|
+
return path.join(home, configured.slice(2));
|
|
75
|
+
return configured || path.join(home, getConfigDirName(), "agent");
|
|
57
76
|
}
|
|
58
77
|
const statusCache = new Map;
|
|
78
|
+
const MAX_STATUS_CACHE_ENTRIES = 512;
|
|
79
|
+
export function pruneStatusCacheForAsyncRoot(asyncDirRoot, runIds) {
|
|
80
|
+
const root = path.resolve(asyncDirRoot);
|
|
81
|
+
const currentStatusPaths = new Set(Array.from(runIds, (runId) => path.resolve(root, runId, "status.json")));
|
|
82
|
+
let removed = 0;
|
|
83
|
+
for (const statusPath of statusCache.keys()) {
|
|
84
|
+
const resolved = path.resolve(statusPath);
|
|
85
|
+
const relative = path.relative(root, resolved);
|
|
86
|
+
if (relative && !relative.startsWith("..") && !path.isAbsolute(relative) && !currentStatusPaths.has(resolved)) {
|
|
87
|
+
statusCache.delete(statusPath);
|
|
88
|
+
removed++;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
return removed;
|
|
92
|
+
}
|
|
59
93
|
function getErrorMessage(error) {
|
|
60
94
|
return error instanceof Error ? error.message : String(error);
|
|
61
95
|
}
|
|
@@ -73,22 +107,28 @@ export function readStatus(asyncDir) {
|
|
|
73
107
|
try {
|
|
74
108
|
stat = fs.statSync(statusPath);
|
|
75
109
|
} catch (error) {
|
|
76
|
-
if (isNotFoundError(error))
|
|
110
|
+
if (isNotFoundError(error)) {
|
|
111
|
+
statusCache.delete(statusPath);
|
|
77
112
|
return null;
|
|
113
|
+
}
|
|
78
114
|
throw new Error(`Failed to inspect async status file '${statusPath}': ${getErrorMessage(error)}`, {
|
|
79
115
|
cause: error instanceof Error ? error : undefined
|
|
80
116
|
});
|
|
81
117
|
}
|
|
82
118
|
const cached = statusCache.get(statusPath);
|
|
83
|
-
if (cached && cached.mtime === stat.mtimeMs) {
|
|
119
|
+
if (cached && cached.mtime === stat.mtimeMs && cached.ctime === stat.ctimeMs && cached.size === stat.size && cached.ino === stat.ino) {
|
|
120
|
+
statusCache.delete(statusPath);
|
|
121
|
+
statusCache.set(statusPath, cached);
|
|
84
122
|
return cached.status;
|
|
85
123
|
}
|
|
86
124
|
let content;
|
|
87
125
|
try {
|
|
88
126
|
content = fs.readFileSync(statusPath, "utf-8");
|
|
89
127
|
} catch (error) {
|
|
90
|
-
if (isNotFoundError(error))
|
|
128
|
+
if (isNotFoundError(error)) {
|
|
129
|
+
statusCache.delete(statusPath);
|
|
91
130
|
return null;
|
|
131
|
+
}
|
|
92
132
|
throw new Error(`Failed to read async status file '${statusPath}': ${getErrorMessage(error)}`, {
|
|
93
133
|
cause: error instanceof Error ? error : undefined
|
|
94
134
|
});
|
|
@@ -101,52 +141,27 @@ export function readStatus(asyncDir) {
|
|
|
101
141
|
cause: error instanceof Error ? error : undefined
|
|
102
142
|
});
|
|
103
143
|
}
|
|
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
144
|
try {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
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
|
-
}
|
|
145
|
+
validateAsyncStatusLaneMetadata(status, `Invalid async status '${statusPath}'`);
|
|
146
|
+
} catch (error) {
|
|
147
|
+
throw new Error(`Failed to validate async status file '${statusPath}': ${getErrorMessage(error)}`, {
|
|
148
|
+
cause: error instanceof Error ? error : undefined
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
statusCache.set(statusPath, {
|
|
152
|
+
mtime: stat.mtimeMs,
|
|
153
|
+
ctime: stat.ctimeMs,
|
|
154
|
+
size: stat.size,
|
|
155
|
+
ino: stat.ino,
|
|
156
|
+
status
|
|
157
|
+
});
|
|
158
|
+
while (statusCache.size > MAX_STATUS_CACHE_ENTRIES) {
|
|
159
|
+
const oldest = statusCache.keys().next().value;
|
|
160
|
+
if (oldest === undefined)
|
|
161
|
+
break;
|
|
162
|
+
statusCache.delete(oldest);
|
|
149
163
|
}
|
|
164
|
+
return status;
|
|
150
165
|
}
|
|
151
166
|
export function getLastActivity(outputFile) {
|
|
152
167
|
if (!outputFile)
|
|
@@ -173,38 +188,35 @@ export function findLatestSessionFile(sessionDir) {
|
|
|
173
188
|
mtime: fs.statSync(filePath).mtimeMs
|
|
174
189
|
};
|
|
175
190
|
}).sort((a, b) => b.mtime - a.mtime);
|
|
176
|
-
|
|
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 };
|
|
191
|
+
const latest = files[0];
|
|
192
|
+
return latest ? latest.path : null;
|
|
183
193
|
}
|
|
184
194
|
export function getFinalOutput(messages) {
|
|
185
195
|
const validTextParts = [];
|
|
186
196
|
for (let i = messages.length - 1;i >= 0; i--) {
|
|
187
197
|
const msg = messages[i];
|
|
188
|
-
if (msg.role !== "assistant")
|
|
198
|
+
if (!msg || msg.role !== "assistant")
|
|
189
199
|
continue;
|
|
190
200
|
const hasAssistantError = "errorMessage" in msg && typeof msg.errorMessage === "string" && msg.errorMessage.length > 0 || "stopReason" in msg && msg.stopReason === "error";
|
|
191
201
|
if (hasAssistantError)
|
|
192
202
|
continue;
|
|
203
|
+
const messageText = msg.content.filter((part) => part.type === "text" && part.text.trim().length > 0).map((part) => part.type === "text" ? part.text : "").join(`
|
|
204
|
+
`);
|
|
193
205
|
for (let j = msg.content.length - 1;j >= 0; j--) {
|
|
194
206
|
const part = msg.content[j];
|
|
195
|
-
if (part.type !== "text" || part.text.trim().length === 0)
|
|
207
|
+
if (!part || part.type !== "text" || part.text.trim().length === 0)
|
|
196
208
|
continue;
|
|
197
209
|
validTextParts.push(part.text);
|
|
198
|
-
if (/```acceptance-report\s*\n[\s\S]*?```/i.test(part.text))
|
|
199
|
-
return
|
|
210
|
+
if (/```acceptance[-_]report\s*\n[\s\S]*?```/i.test(part.text))
|
|
211
|
+
return messageText;
|
|
200
212
|
for (const match of part.text.matchAll(/```(?:json|jsonc|json5)\s*\n([\s\S]*?)```/gi)) {
|
|
201
213
|
const body = match[1] ?? "";
|
|
202
|
-
if (/"criteriaSatisfied"/.test(body) && /"(?:changedFiles|testsAddedOrUpdated|commandsRun|validationOutput|residualRisks|noStagedFiles|diffSummary|reviewFindings|manualNotes)"/.test(body)) {
|
|
203
|
-
return
|
|
214
|
+
if (/"(?:criteriaSatisfied|criteria_satisfied)"/.test(body) && /"(?:changedFiles|changed_files|testsAddedOrUpdated|tests_added_or_updated|commandsRun|commands_run|validationOutput|validation_output|residualRisks|residual_risks|noStagedFiles|no_staged_files|diffSummary|diff_summary|reviewFindings|review_findings|manualNotes|manual_notes)"/.test(body)) {
|
|
215
|
+
return messageText;
|
|
204
216
|
}
|
|
205
217
|
}
|
|
206
218
|
if (/ACCEPTANCE_REPORT\s*:/i.test(part.text))
|
|
207
|
-
return
|
|
219
|
+
return messageText;
|
|
208
220
|
}
|
|
209
221
|
}
|
|
210
222
|
return validTextParts[0] ?? "";
|
|
@@ -234,9 +246,10 @@ function compactCompletedProgress(progress) {
|
|
|
234
246
|
return {
|
|
235
247
|
index: progress.index,
|
|
236
248
|
agent: progress.agent,
|
|
249
|
+
...progress.sessionName ? { sessionName: progress.sessionName } : {},
|
|
237
250
|
status: progress.status,
|
|
238
251
|
activityState: progress.activityState,
|
|
239
|
-
task:
|
|
252
|
+
task: "[prompt redacted]",
|
|
240
253
|
skills: progress.skills,
|
|
241
254
|
toolCount: progress.toolCount,
|
|
242
255
|
tokens: progress.tokens,
|
|
@@ -278,6 +291,16 @@ export function sumResultsUsage(results) {
|
|
|
278
291
|
}
|
|
279
292
|
return usage;
|
|
280
293
|
}
|
|
294
|
+
export function toAgentToolUsage(usage) {
|
|
295
|
+
return {
|
|
296
|
+
input: usage.input,
|
|
297
|
+
output: usage.output,
|
|
298
|
+
cacheRead: usage.cacheRead,
|
|
299
|
+
cacheWrite: usage.cacheWrite,
|
|
300
|
+
totalTokens: usage.input + usage.output + usage.cacheRead + usage.cacheWrite,
|
|
301
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: usage.cost }
|
|
302
|
+
};
|
|
303
|
+
}
|
|
281
304
|
function addNestedCost(total, children) {
|
|
282
305
|
for (const child of children ?? []) {
|
|
283
306
|
if (child.totalCost) {
|
|
@@ -307,6 +330,7 @@ export function compactForegroundResult(result) {
|
|
|
307
330
|
const toolCalls = result.toolCalls?.length ? result.toolCalls : extractToolCallSummaries(result.messages);
|
|
308
331
|
return {
|
|
309
332
|
...result,
|
|
333
|
+
task: "[prompt redacted]",
|
|
310
334
|
messages: undefined,
|
|
311
335
|
progress: undefined,
|
|
312
336
|
toolCalls: toolCalls.length ? toolCalls : undefined
|
|
@@ -319,11 +343,38 @@ export function compactForegroundDetails(details) {
|
|
|
319
343
|
progress: details.progress ? details.progress.map(compactCompletedProgress) : undefined
|
|
320
344
|
};
|
|
321
345
|
}
|
|
346
|
+
export const MAX_STREAMED_RECENT_TOOLS = 32;
|
|
347
|
+
export const MAX_STREAMED_TOOL_CALLS = 64;
|
|
348
|
+
export const MAX_STREAMED_OUTPUT_LINE_CHARS = 2000;
|
|
349
|
+
export function boundStreamedRecentTools(recentTools) {
|
|
350
|
+
return recentTools.slice(-MAX_STREAMED_RECENT_TOOLS).map((tool) => ({ ...tool }));
|
|
351
|
+
}
|
|
352
|
+
export function boundStreamedRecentOutput(recentOutput) {
|
|
353
|
+
return recentOutput.map((line) => line.length > MAX_STREAMED_OUTPUT_LINE_CHARS ? `${line.slice(0, MAX_STREAMED_OUTPUT_LINE_CHARS)}… [truncated]` : line);
|
|
354
|
+
}
|
|
355
|
+
export function boundStreamedToolCalls(result) {
|
|
356
|
+
const summaries = result.toolCalls?.length ? result.toolCalls : extractToolCallSummaries(result.messages);
|
|
357
|
+
if (!summaries.length)
|
|
358
|
+
return;
|
|
359
|
+
return summaries.slice(-MAX_STREAMED_TOOL_CALLS).map((summary) => ({ ...summary }));
|
|
360
|
+
}
|
|
361
|
+
export function hasEmptyTerminalAssistantResponse(messages) {
|
|
362
|
+
const lastAssistant = messages.findLast((message) => message.role === "assistant");
|
|
363
|
+
return lastAssistant?.role === "assistant" && Array.isArray(lastAssistant.content) && lastAssistant.content.length === 0 && lastAssistant.usage.output === 0;
|
|
364
|
+
}
|
|
365
|
+
export function formatEmptyTerminalAssistantResponseError(messages) {
|
|
366
|
+
const lastAssistant = messages.findLast((message) => message.role === "assistant");
|
|
367
|
+
const errorMessage = lastAssistant && "errorMessage" in lastAssistant && typeof lastAssistant.errorMessage === "string" && lastAssistant.errorMessage.trim() ? lastAssistant.errorMessage.trim() : undefined;
|
|
368
|
+
if (errorMessage)
|
|
369
|
+
return errorMessage;
|
|
370
|
+
const stopReason = lastAssistant && "stopReason" in lastAssistant && typeof lastAssistant.stopReason === "string" && lastAssistant.stopReason.trim() ? lastAssistant.stopReason.trim() : undefined;
|
|
371
|
+
return stopReason && stopReason !== "stop" ? `Subagent produced no output after terminal assistant stopReason "${stopReason}".` : "Subagent produced no output (possible model cold-start or empty response).";
|
|
372
|
+
}
|
|
322
373
|
export function detectSubagentError(messages) {
|
|
323
374
|
let lastAssistantTextIndex = -1;
|
|
324
375
|
for (let i = messages.length - 1;i >= 0; i--) {
|
|
325
376
|
const msg = messages[i];
|
|
326
|
-
if (msg
|
|
377
|
+
if (msg?.role === "assistant") {
|
|
327
378
|
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
379
|
if (hasText) {
|
|
329
380
|
lastAssistantTextIndex = i;
|
|
@@ -334,57 +385,29 @@ export function detectSubagentError(messages) {
|
|
|
334
385
|
const scanStart = lastAssistantTextIndex >= 0 ? lastAssistantTextIndex + 1 : 0;
|
|
335
386
|
for (let i = messages.length - 1;i >= scanStart; i--) {
|
|
336
387
|
const msg = messages[i];
|
|
337
|
-
if (msg.role !== "toolResult")
|
|
388
|
+
if (!msg || msg.role !== "toolResult")
|
|
338
389
|
continue;
|
|
339
390
|
const toolName = "toolName" in msg && typeof msg.toolName === "string" ? msg.toolName : undefined;
|
|
340
391
|
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")
|
|
392
|
+
if (!isError)
|
|
353
393
|
continue;
|
|
354
394
|
const text = msg.content.find((c) => c.type === "text");
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
const
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
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
|
-
}
|
|
395
|
+
const details = text && "text" in text ? text.text : undefined;
|
|
396
|
+
const exitMatch = details?.match(/exit(?:ed)?\s*(?:with\s*)?(?:code|status)?\s*[:\s]?\s*(\d+)/i);
|
|
397
|
+
const exitCodeText = exitMatch?.[1];
|
|
398
|
+
return {
|
|
399
|
+
hasError: true,
|
|
400
|
+
exitCode: exitCodeText ? parseInt(exitCodeText, 10) : 1,
|
|
401
|
+
errorType: toolName || "tool",
|
|
402
|
+
details: details?.slice(0, 200)
|
|
403
|
+
};
|
|
380
404
|
}
|
|
381
405
|
return { hasError: false };
|
|
382
406
|
}
|
|
383
407
|
export function extractToolArgsPreview(args) {
|
|
384
|
-
const truncatePreview = (value, maxLength) => value.length > maxLength ? `${value.slice(0, maxLength - 3)}...` : value;
|
|
385
408
|
const stringifyPreviewValue = (value) => {
|
|
386
409
|
if (typeof value === "string" && value.trim().length > 0)
|
|
387
|
-
return value;
|
|
410
|
+
return sanitizeDisplayText(value);
|
|
388
411
|
if (typeof value === "number" || typeof value === "boolean")
|
|
389
412
|
return String(value);
|
|
390
413
|
return;
|
|
@@ -398,40 +421,37 @@ export function extractToolArgsPreview(args) {
|
|
|
398
421
|
const suffix = value.length > 1 ? ` (+${value.length - 1} more)` : "";
|
|
399
422
|
return `${first}${suffix}`;
|
|
400
423
|
};
|
|
401
|
-
if (
|
|
402
|
-
const server =
|
|
403
|
-
const toolArgs =
|
|
404
|
-
return `${server}${args.tool}${toolArgs}
|
|
424
|
+
if (typeof args.tool === "string") {
|
|
425
|
+
const server = typeof args.server === "string" ? `${sanitizeDisplayText(args.server)}/` : "";
|
|
426
|
+
const toolArgs = typeof args.args === "string" ? ` ${truncateDisplayText(sanitizeDisplayText(args.args), 40)}` : "";
|
|
427
|
+
return sanitizeDisplayText(`${server}${args.tool}${toolArgs}`);
|
|
405
428
|
}
|
|
406
429
|
const queriesPreview = previewArray(args.queries);
|
|
407
430
|
if (queriesPreview)
|
|
408
|
-
return
|
|
431
|
+
return previewDisplayText(queriesPreview, 60);
|
|
409
432
|
if (typeof args.query === "string" && args.query.trim().length > 0)
|
|
410
|
-
return
|
|
433
|
+
return previewDisplayText(args.query, 60);
|
|
411
434
|
if (typeof args.workflow === "string" && args.workflow.trim().length > 0)
|
|
412
|
-
return `workflow=${
|
|
435
|
+
return `workflow=${previewDisplayText(args.workflow, 48)}`;
|
|
413
436
|
if (typeof args.url === "string" && args.url.trim().length > 0)
|
|
414
|
-
return
|
|
437
|
+
return previewDisplayText(args.url, 60);
|
|
415
438
|
const urlsPreview = previewArray(args.urls);
|
|
416
439
|
if (urlsPreview)
|
|
417
|
-
return
|
|
440
|
+
return previewDisplayText(urlsPreview, 60);
|
|
418
441
|
if (typeof args.prompt === "string" && args.prompt.trim().length > 0)
|
|
419
|
-
return
|
|
442
|
+
return previewDisplayText(args.prompt, 60);
|
|
420
443
|
const previewKeys = ["command", "path", "file_path", "pattern", "query", "url", "task", "describe", "search"];
|
|
421
444
|
for (const key of previewKeys) {
|
|
422
|
-
if (
|
|
423
|
-
|
|
424
|
-
return truncatePreview(value, 60);
|
|
425
|
-
}
|
|
445
|
+
if (typeof args[key] === "string")
|
|
446
|
+
return previewDisplayText(args[key], 60);
|
|
426
447
|
}
|
|
427
448
|
for (const [key, value] of Object.entries(args)) {
|
|
449
|
+
const displayKey = sanitizeDisplayText(key);
|
|
428
450
|
const arrayPreview = previewArray(value);
|
|
429
451
|
if (arrayPreview)
|
|
430
|
-
return `${
|
|
431
|
-
if (typeof value === "string" && value.length > 0)
|
|
432
|
-
|
|
433
|
-
return `${key}=${preview}`;
|
|
434
|
-
}
|
|
452
|
+
return `${displayKey}=${previewDisplayText(arrayPreview, 50)}`;
|
|
453
|
+
if (typeof value === "string" && value.length > 0)
|
|
454
|
+
return `${displayKey}=${previewDisplayText(value, 50)}`;
|
|
435
455
|
}
|
|
436
456
|
return "";
|
|
437
457
|
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { stableJsonDigest } from "./launch-contract.js";
|
|
2
|
+
const records = new WeakMap;
|
|
3
|
+
function projectionDigest(input) {
|
|
4
|
+
return stableJsonDigest({
|
|
5
|
+
version: 1,
|
|
6
|
+
childKey: input.childKey,
|
|
7
|
+
agent: input.agent,
|
|
8
|
+
launchContractDigest: input.launchContractDigest,
|
|
9
|
+
context: input.context,
|
|
10
|
+
runner: input.runner
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
function required(value, label) {
|
|
14
|
+
if (!value.trim() || value !== value.trim())
|
|
15
|
+
throw new Error(`${label} must be a non-empty trimmed string.`);
|
|
16
|
+
return value;
|
|
17
|
+
}
|
|
18
|
+
export function createWorkflowChildPermit(input) {
|
|
19
|
+
const permit = Object.freeze(Object.create(null));
|
|
20
|
+
const record = {
|
|
21
|
+
issuerPackage: required(input.issuerPackage, "issuerPackage"),
|
|
22
|
+
workflowRunId: required(input.workflowRunId, "workflowRunId"),
|
|
23
|
+
childKey: required(input.childKey, "childKey"),
|
|
24
|
+
agent: required(input.agent, "agent"),
|
|
25
|
+
expectedProjectionDigest: projectionDigest({
|
|
26
|
+
childKey: input.childKey,
|
|
27
|
+
agent: input.agent,
|
|
28
|
+
launchContractDigest: required(input.launchContractDigest, "launchContractDigest"),
|
|
29
|
+
context: input.context,
|
|
30
|
+
runner: "dm"
|
|
31
|
+
}),
|
|
32
|
+
state: "available"
|
|
33
|
+
};
|
|
34
|
+
records.set(permit, record);
|
|
35
|
+
return permit;
|
|
36
|
+
}
|
|
37
|
+
export function validateWorkflowChildPermitRoot(permit, workflowRunId) {
|
|
38
|
+
const record = records.get(permit);
|
|
39
|
+
if (!record)
|
|
40
|
+
return "Workflow child permit is invalid.";
|
|
41
|
+
if (record.state !== "available")
|
|
42
|
+
return "Workflow child permit is already consumed.";
|
|
43
|
+
if (record.workflowRunId !== workflowRunId)
|
|
44
|
+
return "Workflow child permit does not match this workflow root.";
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
export function claimWorkflowChildPermit(permit, workflowRunId, childKey) {
|
|
48
|
+
const record = records.get(permit);
|
|
49
|
+
if (!record)
|
|
50
|
+
return "Workflow child permit is invalid.";
|
|
51
|
+
if (record.state !== "available")
|
|
52
|
+
return "Workflow child permit is already consumed.";
|
|
53
|
+
if (record.workflowRunId !== workflowRunId)
|
|
54
|
+
return "Workflow child permit does not match this workflow root.";
|
|
55
|
+
record.state = record.childKey === childKey ? "claimed" : "consumed";
|
|
56
|
+
if (record.childKey !== childKey)
|
|
57
|
+
return "Workflow child permit child key mismatch.";
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
export function consumeWorkflowChildPermit(permit, launch) {
|
|
61
|
+
const record = records.get(permit);
|
|
62
|
+
if (!record)
|
|
63
|
+
return "Workflow child permit is invalid.";
|
|
64
|
+
if (record.state === "available")
|
|
65
|
+
return "Workflow child permit launch was not claimed.";
|
|
66
|
+
if (record.state === "consumed")
|
|
67
|
+
return "Workflow child permit is already consumed.";
|
|
68
|
+
if (record.workflowRunId !== launch.workflowRunId)
|
|
69
|
+
return "Workflow child permit does not match this workflow root.";
|
|
70
|
+
record.state = "consumed";
|
|
71
|
+
if (record.childKey !== launch.childKey)
|
|
72
|
+
return "Workflow child permit child key mismatch.";
|
|
73
|
+
if (record.agent !== launch.agent)
|
|
74
|
+
return "Workflow child permit agent mismatch.";
|
|
75
|
+
if (launch.runner !== "dm")
|
|
76
|
+
return "Workflow child permit supports native DM children only.";
|
|
77
|
+
if (record.expectedProjectionDigest !== projectionDigest(launch))
|
|
78
|
+
return "Workflow child permit does not match the final launch projection.";
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
export function workflowChildPermitConsumed(permit) {
|
|
82
|
+
const state = records.get(permit)?.state;
|
|
83
|
+
return state === "claimed" || state === "consumed";
|
|
84
|
+
}
|