@duckmind/dm-windows-x64 0.61.4 → 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,27 +1,23 @@
|
|
|
1
1
|
import { execSync } from "node:child_process";
|
|
2
2
|
import * as fs from "node:fs";
|
|
3
|
+
import { parse as parseYaml } from "yaml";
|
|
3
4
|
import * as os from "node:os";
|
|
4
5
|
import * as path from "node:path";
|
|
5
6
|
import { fileURLToPath } from "node:url";
|
|
7
|
+
import { CODE_OWNED_EXTERNAL_CLI_ADAPTER_LABEL, isCodeOwnedExternalCliAdapterId, parseExternalCliCapabilityNarrowing, validateCodeOwnedProfileRunner } from "../runs/shared/external-cli-contract.js";
|
|
6
8
|
import { getAgentDir, getProjectConfigDir } from "../shared/utils.js";
|
|
7
9
|
import { KNOWN_FIELDS } from "./agent-serializer.js";
|
|
8
10
|
import { parseChain, parseJsonChain } from "./chain-serializer.js";
|
|
9
11
|
import { mergeAgentsForScope } from "./agent-selection.js";
|
|
10
|
-
import { parseFrontmatter } from "./frontmatter.js";
|
|
12
|
+
import { parseFrontmatter, parseFrontmatterList } from "./frontmatter.js";
|
|
11
13
|
import { buildRuntimeName, parsePackageName } from "./identity.js";
|
|
12
14
|
import { parseModelScopeConfig } from "../runs/shared/model-scope.js";
|
|
15
|
+
export { BUILTIN_AGENT_NAMES } from "./builtin-names.js";
|
|
13
16
|
export { buildRuntimeName, frontmatterNameForConfig, parsePackageName } from "./identity.js";
|
|
14
17
|
import { parseMemoryFrontmatter } from "./agent-memory.js";
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
"oracle",
|
|
19
|
-
"planner",
|
|
20
|
-
"researcher",
|
|
21
|
-
"reviewer",
|
|
22
|
-
"scout",
|
|
23
|
-
"worker"
|
|
24
|
-
];
|
|
18
|
+
import { validateAcceptanceInput } from "../runs/shared/acceptance.js";
|
|
19
|
+
import { validatePermissionRules } from "../runs/shared/permissions.js";
|
|
20
|
+
import { parseThinkingLevel } from "../shared/thinking-ceiling.js";
|
|
25
21
|
export function defaultSystemPromptMode(name) {
|
|
26
22
|
return name === "delegate" ? "append" : "replace";
|
|
27
23
|
}
|
|
@@ -31,8 +27,54 @@ export function defaultInheritProjectContext(name) {
|
|
|
31
27
|
export function defaultInheritSkills() {
|
|
32
28
|
return false;
|
|
33
29
|
}
|
|
34
|
-
const EMPTY_SUBAGENT_SETTINGS = { overrides: {} };
|
|
30
|
+
const EMPTY_SUBAGENT_SETTINGS = { overrides: {}, providerOverrides: {} };
|
|
35
31
|
const agentFrontmatterFields = new WeakMap;
|
|
32
|
+
const AGENT_SOURCE_PRIORITY = {
|
|
33
|
+
builtin: 0,
|
|
34
|
+
package: 1,
|
|
35
|
+
user: 2,
|
|
36
|
+
project: 3,
|
|
37
|
+
runtime: 4
|
|
38
|
+
};
|
|
39
|
+
function agentDefinitionPriority(definition) {
|
|
40
|
+
return AGENT_SOURCE_PRIORITY[definition.source] * 1e6 + (definition.discoveryPriority ?? 0);
|
|
41
|
+
}
|
|
42
|
+
export function findBlockingAgentDiagnostic(name, agent, diagnostics) {
|
|
43
|
+
const normalizedName = name.trim();
|
|
44
|
+
const agents = Array.isArray(agent) ? agent : agent ? [agent] : [];
|
|
45
|
+
let match;
|
|
46
|
+
for (const diagnostic of diagnostics ?? []) {
|
|
47
|
+
if ((diagnostic.runtimeName === normalizedName || diagnostic.name === normalizedName && (!diagnostic.packageSpecified || diagnostic.runtimeName === undefined || agents.some((agent) => agent.name === diagnostic.runtimeName && agent.localName === diagnostic.name))) && (!match || agentDefinitionPriority(diagnostic) > agentDefinitionPriority(match))) {
|
|
48
|
+
match = diagnostic;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
const highestPriority = Math.max(...agents.map(agentDefinitionPriority), -1 / 0);
|
|
52
|
+
return !agents.length || match && agentDefinitionPriority(match) > highestPriority ? match : undefined;
|
|
53
|
+
}
|
|
54
|
+
export function unknownAgentDiagnosticContext(discovered) {
|
|
55
|
+
return {
|
|
56
|
+
cwd: discovered.cwd,
|
|
57
|
+
scope: discovered.scope,
|
|
58
|
+
directories: discovered.directories,
|
|
59
|
+
agents: discovered.agents
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
export function formatUnknownAgentError(name, context, prefix = "Unknown agent") {
|
|
63
|
+
const directories = context.directories.map((directory) => {
|
|
64
|
+
const state = directory.state === "candidates" ? `${directory.candidateCount ?? 0} candidate${directory.candidateCount === 1 ? "" : "s"}` : directory.state === "empty" ? "present but empty" : directory.state === "not-directory" ? "not a directory" : directory.state;
|
|
65
|
+
return `- ${directory.source}: ${directory.path} (${state})`;
|
|
66
|
+
});
|
|
67
|
+
const agents = [...context.agents].sort((left, right) => left.name.localeCompare(right.name) || left.source.localeCompare(right.source)).map((agent) => `- ${agent.name} (${agent.source})`);
|
|
68
|
+
return [
|
|
69
|
+
`${prefix}: ${name}`,
|
|
70
|
+
`Effective cwd: ${path.resolve(context.cwd)}`,
|
|
71
|
+
"Consulted agent-definition directories:",
|
|
72
|
+
...directories.length ? directories : ["- (none)"],
|
|
73
|
+
"Discovered agents:",
|
|
74
|
+
...agents.length ? agents : ["- (none)"]
|
|
75
|
+
].join(`
|
|
76
|
+
`);
|
|
77
|
+
}
|
|
36
78
|
function getUserChainDir() {
|
|
37
79
|
return path.join(getAgentDir(), "chains");
|
|
38
80
|
}
|
|
@@ -44,16 +86,6 @@ function readJsonFileBestEffort(filePath) {
|
|
|
44
86
|
return null;
|
|
45
87
|
}
|
|
46
88
|
}
|
|
47
|
-
function readOptionalJsonFile(filePath) {
|
|
48
|
-
try {
|
|
49
|
-
return JSON.parse(fs.readFileSync(filePath, "utf-8"));
|
|
50
|
-
} catch (error) {
|
|
51
|
-
const code = typeof error === "object" && error !== null && "code" in error ? error.code : undefined;
|
|
52
|
-
if (code === "ENOENT")
|
|
53
|
-
return null;
|
|
54
|
-
throw error;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
89
|
function isSafePackagePath(value) {
|
|
58
90
|
return value.length > 0 && !path.isAbsolute(value) && value.split(/[\\/]/).every((part) => part.length > 0 && part !== "." && part !== "..");
|
|
59
91
|
}
|
|
@@ -124,13 +156,29 @@ function resolveSettingsPackageRoot(source, baseDir) {
|
|
|
124
156
|
if (normalized === "." || normalized === ".." || normalized.startsWith("./") || normalized.startsWith("../")) {
|
|
125
157
|
return path.resolve(baseDir, normalized);
|
|
126
158
|
}
|
|
159
|
+
if (/^https?:\/\//i.test(trimmed)) {
|
|
160
|
+
const parsed = parseGitPackagePath(`git:${trimmed}`);
|
|
161
|
+
return parsed ? path.join(baseDir, "git", parsed.host, parsed.repoPath) : undefined;
|
|
162
|
+
}
|
|
127
163
|
return;
|
|
128
164
|
}
|
|
129
165
|
function getGlobalNpmRoot() {
|
|
166
|
+
const offline = process.env.PI_OFFLINE?.toLowerCase();
|
|
167
|
+
if (offline === "1" || offline === "true" || offline === "yes")
|
|
168
|
+
return null;
|
|
130
169
|
if (cachedGlobalNpmRoot !== null)
|
|
131
170
|
return cachedGlobalNpmRoot;
|
|
171
|
+
const windowsGlobalRoot = process.platform === "win32" && process.env.APPDATA ? path.join(process.env.APPDATA, "npm", "node_modules") : undefined;
|
|
172
|
+
if (windowsGlobalRoot) {
|
|
173
|
+
try {
|
|
174
|
+
if (fs.statSync(windowsGlobalRoot).isDirectory()) {
|
|
175
|
+
cachedGlobalNpmRoot = fs.realpathSync(windowsGlobalRoot);
|
|
176
|
+
return cachedGlobalNpmRoot;
|
|
177
|
+
}
|
|
178
|
+
} catch {}
|
|
179
|
+
}
|
|
132
180
|
try {
|
|
133
|
-
cachedGlobalNpmRoot = fs.realpathSync(execSync("npm root -g", { encoding: "utf-8", timeout: 5000 }).trim());
|
|
181
|
+
cachedGlobalNpmRoot = fs.realpathSync(execSync("npm root -g", { encoding: "utf-8", timeout: 5000, windowsHide: true }).trim());
|
|
134
182
|
return cachedGlobalNpmRoot;
|
|
135
183
|
} catch {
|
|
136
184
|
cachedGlobalNpmRoot = "";
|
|
@@ -142,19 +190,30 @@ function stringArray(value) {
|
|
|
142
190
|
return [];
|
|
143
191
|
return value.filter((entry) => typeof entry === "string" && entry.trim().length > 0);
|
|
144
192
|
}
|
|
145
|
-
function
|
|
193
|
+
function packageMetadata(pkg, packageRoot) {
|
|
194
|
+
const name = typeof pkg.name === "string" && pkg.name.trim() ? pkg.name.trim() : undefined;
|
|
195
|
+
const version = typeof pkg.version === "string" && pkg.version.trim() ? pkg.version.trim() : undefined;
|
|
196
|
+
return {
|
|
197
|
+
packageRoot,
|
|
198
|
+
...name ? { packageName: name } : {},
|
|
199
|
+
...version ? { packageVersion: version } : {}
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
function extractSubagentPathsFromPackageRoot(packageRoot, scope) {
|
|
146
203
|
const packageJsonPath = path.join(packageRoot, "package.json");
|
|
147
204
|
const pkg = readJsonFileBestEffort(packageJsonPath);
|
|
148
205
|
if (!pkg || typeof pkg !== "object" || Array.isArray(pkg))
|
|
149
|
-
return { agents: [], chains: [] };
|
|
206
|
+
return { agents: [], chains: [], watchPaths: [packageJsonPath], settingsErrors: {} };
|
|
207
|
+
const pkgRecord = pkg;
|
|
208
|
+
const metadata = packageMetadata(pkgRecord, packageRoot);
|
|
150
209
|
const roots = [];
|
|
151
|
-
const piSubagents =
|
|
210
|
+
const piSubagents = pkgRecord["dm-subagents"];
|
|
152
211
|
if (piSubagents && typeof piSubagents === "object" && !Array.isArray(piSubagents)) {
|
|
153
212
|
roots.push(piSubagents);
|
|
154
213
|
}
|
|
155
|
-
const
|
|
156
|
-
if (
|
|
157
|
-
const subagents =
|
|
214
|
+
const dm = pkgRecord.dm;
|
|
215
|
+
if (dm && typeof dm === "object" && !Array.isArray(dm)) {
|
|
216
|
+
const subagents = dm.subagents;
|
|
158
217
|
if (subagents && typeof subagents === "object" && !Array.isArray(subagents)) {
|
|
159
218
|
roots.push(subagents);
|
|
160
219
|
}
|
|
@@ -163,14 +222,15 @@ function extractSubagentPathsFromPackageRoot(packageRoot) {
|
|
|
163
222
|
const chains = [];
|
|
164
223
|
for (const root of roots) {
|
|
165
224
|
for (const entry of stringArray(root.agents))
|
|
166
|
-
agents.push(path.resolve(packageRoot, entry));
|
|
225
|
+
agents.push({ dir: path.resolve(packageRoot, entry), scope, ...metadata });
|
|
167
226
|
for (const entry of stringArray(root.chains))
|
|
168
|
-
chains.push(path.resolve(packageRoot, entry));
|
|
227
|
+
chains.push({ dir: path.resolve(packageRoot, entry), scope, packageRoot });
|
|
169
228
|
}
|
|
170
|
-
return { agents, chains };
|
|
229
|
+
return { agents, chains, watchPaths: [packageJsonPath], settingsErrors: {} };
|
|
171
230
|
}
|
|
172
|
-
function collectPackageRootsFromNodeModules(nodeModulesDir) {
|
|
231
|
+
function collectPackageRootsFromNodeModules(nodeModulesDir, watchPaths) {
|
|
173
232
|
const roots = [];
|
|
233
|
+
watchPaths?.push(nodeModulesDir);
|
|
174
234
|
if (!fs.existsSync(nodeModulesDir))
|
|
175
235
|
return roots;
|
|
176
236
|
let entries;
|
|
@@ -186,6 +246,7 @@ function collectPackageRootsFromNodeModules(nodeModulesDir) {
|
|
|
186
246
|
continue;
|
|
187
247
|
if (entry.name.startsWith("@")) {
|
|
188
248
|
const scopeDir = path.join(nodeModulesDir, entry.name);
|
|
249
|
+
watchPaths?.push(scopeDir);
|
|
189
250
|
let scopeEntries;
|
|
190
251
|
try {
|
|
191
252
|
scopeEntries = fs.readdirSync(scopeDir, { withFileTypes: true });
|
|
@@ -206,9 +267,7 @@ function collectPackageRootsFromNodeModules(nodeModulesDir) {
|
|
|
206
267
|
return roots;
|
|
207
268
|
}
|
|
208
269
|
function collectSettingsPackageRoots(settingsFile, baseDir) {
|
|
209
|
-
const settings =
|
|
210
|
-
if (!settings || typeof settings !== "object" || Array.isArray(settings))
|
|
211
|
-
return [];
|
|
270
|
+
const settings = readSettingsFileStrict(settingsFile);
|
|
212
271
|
const packages = settings.packages;
|
|
213
272
|
if (!Array.isArray(packages))
|
|
214
273
|
return [];
|
|
@@ -225,47 +284,112 @@ function collectSettingsPackageRoots(settingsFile, baseDir) {
|
|
|
225
284
|
}
|
|
226
285
|
function collectPackageSubagentPaths(cwd, options = { includeUser: true, includeProject: true }) {
|
|
227
286
|
const agentDir = getAgentDir();
|
|
228
|
-
const projectRoot =
|
|
287
|
+
const projectRoot = findConfiguredProjectRoot(cwd) ?? cwd;
|
|
229
288
|
const packageRoots = [
|
|
230
|
-
projectRoot
|
|
289
|
+
{ root: projectRoot, scope: "root" }
|
|
231
290
|
];
|
|
291
|
+
const watchPaths = [path.join(projectRoot, "package.json")];
|
|
292
|
+
const settingsErrors = {};
|
|
293
|
+
const collectScopedSettingsRoots = (scope, settingsFile, baseDir) => {
|
|
294
|
+
try {
|
|
295
|
+
return collectSettingsPackageRoots(settingsFile, baseDir);
|
|
296
|
+
} catch (error) {
|
|
297
|
+
settingsErrors[scope] = error instanceof Error ? error : new Error(`Failed to read settings file '${settingsFile}': ${String(error)}`, { cause: error });
|
|
298
|
+
return [];
|
|
299
|
+
}
|
|
300
|
+
};
|
|
232
301
|
if (options.includeProject) {
|
|
233
302
|
const projectConfigDir = getProjectConfigDir(projectRoot);
|
|
234
|
-
|
|
303
|
+
const nodeModulesDir = path.join(projectConfigDir, "npm", "node_modules");
|
|
304
|
+
packageRoots.push(...collectPackageRootsFromNodeModules(nodeModulesDir, watchPaths).map((root) => ({ root, scope: "project" })));
|
|
305
|
+
packageRoots.push(...collectScopedSettingsRoots("project", path.join(projectConfigDir, "settings.json"), projectConfigDir).map((root) => ({ root, scope: "project" })));
|
|
235
306
|
}
|
|
236
307
|
if (options.includeUser) {
|
|
237
|
-
|
|
308
|
+
const nodeModulesDir = path.join(agentDir, "npm", "node_modules");
|
|
309
|
+
packageRoots.push(...collectPackageRootsFromNodeModules(nodeModulesDir, watchPaths).map((root) => ({ root, scope: "user" })));
|
|
310
|
+
packageRoots.push(...collectScopedSettingsRoots("user", path.join(agentDir, "settings.json"), agentDir).map((root) => ({ root, scope: "user" })));
|
|
238
311
|
}
|
|
239
312
|
if (options.includeUser) {
|
|
240
313
|
const globalRoot = getGlobalNpmRoot();
|
|
241
|
-
if (globalRoot)
|
|
242
|
-
packageRoots.push(...collectPackageRootsFromNodeModules(globalRoot));
|
|
314
|
+
if (globalRoot) {
|
|
315
|
+
packageRoots.push(...collectPackageRootsFromNodeModules(globalRoot, watchPaths).map((root) => ({ root, scope: "user" })));
|
|
316
|
+
}
|
|
243
317
|
}
|
|
244
|
-
const seenRoots = new
|
|
245
|
-
const seenAgents = new
|
|
246
|
-
const seenChains = new
|
|
318
|
+
const seenRoots = new Map;
|
|
319
|
+
const seenAgents = new Map;
|
|
320
|
+
const seenChains = new Map;
|
|
247
321
|
const agents = [];
|
|
248
322
|
const chains = [];
|
|
249
|
-
for (const packageRoot of packageRoots) {
|
|
323
|
+
for (const { root: packageRoot, scope } of packageRoots) {
|
|
250
324
|
const resolvedRoot = path.resolve(packageRoot);
|
|
251
|
-
|
|
325
|
+
const scopes = seenRoots.get(resolvedRoot);
|
|
326
|
+
if (scopes !== undefined) {
|
|
327
|
+
scopes.add(scope);
|
|
252
328
|
continue;
|
|
253
|
-
|
|
254
|
-
const
|
|
255
|
-
|
|
256
|
-
|
|
329
|
+
}
|
|
330
|
+
const packageScopes = new Set([scope]);
|
|
331
|
+
seenRoots.set(resolvedRoot, packageScopes);
|
|
332
|
+
const paths = extractSubagentPathsFromPackageRoot(resolvedRoot, packageScopes);
|
|
333
|
+
watchPaths.push(...paths.watchPaths);
|
|
334
|
+
for (const agentPath of paths.agents) {
|
|
335
|
+
const agentKey = `${agentPath.dir}\x00${agentPath.packageRoot}`;
|
|
336
|
+
const existing = seenAgents.get(agentKey);
|
|
337
|
+
if (existing) {
|
|
338
|
+
for (const packageScope of agentPath.scope)
|
|
339
|
+
existing.scope.add(packageScope);
|
|
257
340
|
continue;
|
|
258
|
-
|
|
259
|
-
|
|
341
|
+
}
|
|
342
|
+
seenAgents.set(agentKey, agentPath);
|
|
343
|
+
agents.push(agentPath);
|
|
260
344
|
}
|
|
261
345
|
for (const chainDir of paths.chains) {
|
|
262
|
-
|
|
346
|
+
const chainKey = `${chainDir.dir}\x00${chainDir.packageRoot}`;
|
|
347
|
+
const existing = seenChains.get(chainKey);
|
|
348
|
+
if (existing) {
|
|
349
|
+
for (const packageScope of chainDir.scope)
|
|
350
|
+
existing.scope.add(packageScope);
|
|
263
351
|
continue;
|
|
264
|
-
|
|
352
|
+
}
|
|
353
|
+
seenChains.set(chainKey, chainDir);
|
|
265
354
|
chains.push(chainDir);
|
|
266
355
|
}
|
|
267
356
|
}
|
|
268
|
-
return { agents, chains };
|
|
357
|
+
return { agents, chains, watchPaths, settingsErrors };
|
|
358
|
+
}
|
|
359
|
+
function normalizeAgentAliases(rawAliases, agentName) {
|
|
360
|
+
const aliases = [...new Set((rawAliases ?? []).map((alias) => alias.trim()).filter(Boolean))].filter((alias) => alias !== agentName);
|
|
361
|
+
return aliases.length > 0 ? aliases : undefined;
|
|
362
|
+
}
|
|
363
|
+
function effectiveAgentMatch(matches) {
|
|
364
|
+
const distinctNames = [...new Set(matches.map((agent) => agent.name))];
|
|
365
|
+
if (distinctNames.length === 1) {
|
|
366
|
+
const sourceRank = new Map([["builtin", 0], ["package", 1], ["user", 2], ["project", 3], ["runtime", 4]]);
|
|
367
|
+
const agent = [...matches].sort((a, b) => (sourceRank.get(b.source) ?? 0) - (sourceRank.get(a.source) ?? 0))[0];
|
|
368
|
+
return agent ? { agent } : {};
|
|
369
|
+
}
|
|
370
|
+
return {};
|
|
371
|
+
}
|
|
372
|
+
export function resolveAgentName(name, agents) {
|
|
373
|
+
const raw = name.trim();
|
|
374
|
+
const exact = agents.filter((agent) => agent.name === raw || agent.localName === raw);
|
|
375
|
+
if (exact.length === 1)
|
|
376
|
+
return exact[0] ? { agent: exact[0] } : {};
|
|
377
|
+
if (exact.length > 1) {
|
|
378
|
+
const effective = effectiveAgentMatch(exact);
|
|
379
|
+
if (effective.agent)
|
|
380
|
+
return effective;
|
|
381
|
+
return { error: `Ambiguous agent name '${name}': ${exact.map((agent) => agent.name).join(", ")}` };
|
|
382
|
+
}
|
|
383
|
+
const aliases = agents.filter((agent) => agent.aliases?.includes(raw));
|
|
384
|
+
if (aliases.length === 1)
|
|
385
|
+
return aliases[0] ? { agent: aliases[0] } : {};
|
|
386
|
+
if (aliases.length > 1) {
|
|
387
|
+
const effective = effectiveAgentMatch(aliases);
|
|
388
|
+
if (effective.agent)
|
|
389
|
+
return effective;
|
|
390
|
+
return { error: `Ambiguous agent alias '${name}': ${aliases.map((agent) => agent.name).join(", ")}` };
|
|
391
|
+
}
|
|
392
|
+
return {};
|
|
269
393
|
}
|
|
270
394
|
function splitToolList(rawTools) {
|
|
271
395
|
const mcpDirectTools = [];
|
|
@@ -278,7 +402,7 @@ function splitToolList(rawTools) {
|
|
|
278
402
|
}
|
|
279
403
|
}
|
|
280
404
|
return {
|
|
281
|
-
...
|
|
405
|
+
...rawTools !== undefined ? { tools } : {},
|
|
282
406
|
...mcpDirectTools.length > 0 ? { mcpDirectTools } : {}
|
|
283
407
|
};
|
|
284
408
|
}
|
|
@@ -304,58 +428,137 @@ function arraysEqual(a, b) {
|
|
|
304
428
|
}
|
|
305
429
|
function cloneOverrideBase(agent) {
|
|
306
430
|
return {
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
431
|
+
description: agent.description,
|
|
432
|
+
...agent.output !== undefined ? { output: agent.output } : {},
|
|
433
|
+
...agent.outputMode !== undefined ? { outputMode: agent.outputMode } : {},
|
|
434
|
+
...agent.defaultReads !== undefined ? { defaultReads: [...agent.defaultReads] } : {},
|
|
435
|
+
...agent.model !== undefined ? { model: agent.model } : {},
|
|
436
|
+
...agent.modelProvider !== undefined ? { modelProvider: agent.modelProvider } : {},
|
|
437
|
+
...agent.fallbackModels ? { fallbackModels: [...agent.fallbackModels] } : {},
|
|
438
|
+
...agent.fast !== undefined ? { fast: agent.fast } : {},
|
|
439
|
+
...agent.thinking !== undefined ? { thinking: agent.thinking } : {},
|
|
310
440
|
systemPromptMode: agent.systemPromptMode,
|
|
311
441
|
inheritProjectContext: agent.inheritProjectContext,
|
|
442
|
+
inheritGlobalContext: agent.inheritGlobalContext,
|
|
312
443
|
inheritSkills: agent.inheritSkills,
|
|
313
|
-
defaultContext: agent.defaultContext,
|
|
314
|
-
|
|
444
|
+
...agent.defaultContext !== undefined ? { defaultContext: agent.defaultContext } : {},
|
|
445
|
+
...agent.acceptanceRole !== undefined ? { acceptanceRole: agent.acceptanceRole } : {},
|
|
446
|
+
...agent.disabled !== undefined ? { disabled: agent.disabled } : {},
|
|
315
447
|
systemPrompt: agent.systemPrompt,
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
448
|
+
...agent.skills ? { skills: [...agent.skills] } : {},
|
|
449
|
+
...agent.skillPath ? { skillPath: [...agent.skillPath] } : {},
|
|
450
|
+
...agent.tools ? { tools: [...agent.tools] } : {},
|
|
451
|
+
...agent.allowNestedSubagents !== undefined ? { allowNestedSubagents: agent.allowNestedSubagents } : {},
|
|
452
|
+
...agent.mcpDirectTools ? { mcpDirectTools: [...agent.mcpDirectTools] } : {},
|
|
453
|
+
...!agent.extensionsFromDefault && agent.extensions ? { extensions: [...agent.extensions] } : {},
|
|
454
|
+
...agent.subagentOnlyExtensions ? { subagentOnlyExtensions: [...agent.subagentOnlyExtensions] } : {},
|
|
455
|
+
...agent.mutationTools ? { mutationTools: [...agent.mutationTools] } : {},
|
|
456
|
+
...agent.completionGuard !== undefined ? { completionGuard: agent.completionGuard } : {},
|
|
457
|
+
...agent.toolBudget !== undefined ? { toolBudget: agent.toolBudget } : {}
|
|
322
458
|
};
|
|
323
459
|
}
|
|
324
460
|
function cloneOverrideValue(override) {
|
|
325
461
|
return {
|
|
462
|
+
...override.description !== undefined ? { description: override.description } : {},
|
|
463
|
+
...override.output !== undefined ? { output: override.output } : {},
|
|
464
|
+
...override.outputMode !== undefined ? { outputMode: override.outputMode } : {},
|
|
465
|
+
...override.defaultReads !== undefined ? { defaultReads: override.defaultReads === false ? false : [...override.defaultReads] } : {},
|
|
326
466
|
...override.model !== undefined ? { model: override.model } : {},
|
|
467
|
+
...override.defaultProvider !== undefined ? { defaultProvider: override.defaultProvider } : {},
|
|
327
468
|
...override.fallbackModels !== undefined ? { fallbackModels: override.fallbackModels === false ? false : [...override.fallbackModels] } : {},
|
|
469
|
+
...override.fast !== undefined ? { fast: override.fast } : {},
|
|
328
470
|
...override.thinking !== undefined ? { thinking: override.thinking } : {},
|
|
329
471
|
...override.systemPromptMode !== undefined ? { systemPromptMode: override.systemPromptMode } : {},
|
|
330
472
|
...override.inheritProjectContext !== undefined ? { inheritProjectContext: override.inheritProjectContext } : {},
|
|
473
|
+
...override.inheritGlobalContext !== undefined ? { inheritGlobalContext: override.inheritGlobalContext } : {},
|
|
331
474
|
...override.inheritSkills !== undefined ? { inheritSkills: override.inheritSkills } : {},
|
|
332
475
|
...override.defaultContext !== undefined ? { defaultContext: override.defaultContext } : {},
|
|
476
|
+
...override.acceptanceRole !== undefined ? { acceptanceRole: override.acceptanceRole } : {},
|
|
333
477
|
...override.disabled !== undefined ? { disabled: override.disabled } : {},
|
|
334
478
|
...override.systemPrompt !== undefined ? { systemPrompt: override.systemPrompt } : {},
|
|
335
479
|
...override.skills !== undefined ? { skills: override.skills === false ? false : [...override.skills] } : {},
|
|
336
|
-
...override.tools !== undefined ? { tools: override.tools
|
|
480
|
+
...override.tools !== undefined ? { tools: Array.isArray(override.tools) ? [...override.tools] : override.tools } : {},
|
|
481
|
+
...override.allowNestedSubagents !== undefined ? { allowNestedSubagents: override.allowNestedSubagents } : {},
|
|
482
|
+
...override.extensions !== undefined ? { extensions: override.extensions === false ? false : [...override.extensions] } : {},
|
|
337
483
|
...override.subagentOnlyExtensions !== undefined ? { subagentOnlyExtensions: override.subagentOnlyExtensions === false ? false : [...override.subagentOnlyExtensions] } : {},
|
|
484
|
+
...override.mutationTools !== undefined ? { mutationTools: override.mutationTools === false ? false : [...override.mutationTools] } : {},
|
|
338
485
|
...override.completionGuard !== undefined ? { completionGuard: override.completionGuard } : {},
|
|
339
486
|
...override.toolBudget !== undefined ? { toolBudget: override.toolBudget === false ? false : { ...override.toolBudget, ...Array.isArray(override.toolBudget.block) ? { block: [...override.toolBudget.block] } : {} } } : {}
|
|
340
487
|
};
|
|
341
488
|
}
|
|
342
|
-
|
|
489
|
+
function isProjectRootCandidate(dir) {
|
|
490
|
+
return isDirectory(getProjectConfigDir(dir)) || isDirectory(path.join(dir, ".agents"));
|
|
491
|
+
}
|
|
492
|
+
function findProjectRootCandidates(cwd) {
|
|
493
|
+
const roots = [];
|
|
494
|
+
let currentDir = cwd;
|
|
495
|
+
while (true) {
|
|
496
|
+
if (isProjectRootCandidate(currentDir))
|
|
497
|
+
roots.push(currentDir);
|
|
498
|
+
const parentDir = path.dirname(currentDir);
|
|
499
|
+
if (parentDir === currentDir)
|
|
500
|
+
return roots;
|
|
501
|
+
currentDir = parentDir;
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
function findNearestGitRoot(cwd) {
|
|
343
505
|
let currentDir = cwd;
|
|
344
506
|
while (true) {
|
|
345
|
-
if (
|
|
507
|
+
if (fs.existsSync(path.join(currentDir, ".git")))
|
|
346
508
|
return currentDir;
|
|
347
|
-
}
|
|
348
509
|
const parentDir = path.dirname(currentDir);
|
|
349
510
|
if (parentDir === currentDir)
|
|
350
511
|
return null;
|
|
351
512
|
currentDir = parentDir;
|
|
352
513
|
}
|
|
353
514
|
}
|
|
515
|
+
function readProjectRootResolution(projectRoot) {
|
|
516
|
+
const settingsPath = path.join(getProjectConfigDir(projectRoot), "settings.json");
|
|
517
|
+
if (!fs.existsSync(settingsPath))
|
|
518
|
+
return;
|
|
519
|
+
const settings = readSettingsFileStrict(settingsPath);
|
|
520
|
+
const subagents = settings.subagents;
|
|
521
|
+
if (!subagents || typeof subagents !== "object" || Array.isArray(subagents))
|
|
522
|
+
return;
|
|
523
|
+
const value = subagents.projectRootResolution;
|
|
524
|
+
if (value === undefined)
|
|
525
|
+
return;
|
|
526
|
+
if (value === "nearest" || value === "git-root")
|
|
527
|
+
return value;
|
|
528
|
+
throw new Error(`Subagent settings in '${settingsPath}' have invalid 'projectRootResolution'; expected 'nearest' or 'git-root'.`);
|
|
529
|
+
}
|
|
530
|
+
export function findNearestProjectRoot(cwd) {
|
|
531
|
+
return findProjectRootCandidates(cwd)[0] ?? null;
|
|
532
|
+
}
|
|
533
|
+
export function findConfiguredProjectRoot(cwd) {
|
|
534
|
+
const candidates = findProjectRootCandidates(cwd);
|
|
535
|
+
const nearestRoot = candidates[0];
|
|
536
|
+
if (!nearestRoot)
|
|
537
|
+
return null;
|
|
538
|
+
let policyRoot;
|
|
539
|
+
let policyRootIndex = -1;
|
|
540
|
+
for (const [index, candidate] of candidates.entries()) {
|
|
541
|
+
const mode = readProjectRootResolution(candidate);
|
|
542
|
+
if (mode === "nearest")
|
|
543
|
+
return nearestRoot;
|
|
544
|
+
if (mode === "git-root") {
|
|
545
|
+
policyRoot = candidate;
|
|
546
|
+
policyRootIndex = index;
|
|
547
|
+
break;
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
if (!policyRoot)
|
|
551
|
+
return nearestRoot;
|
|
552
|
+
const gitRoot = findNearestGitRoot(cwd);
|
|
553
|
+
const gitProjectRoot = gitRoot ? candidates.slice(policyRootIndex).find((candidate) => path.resolve(candidate) === path.resolve(gitRoot)) : undefined;
|
|
554
|
+
const configuredGitRoot = fs.existsSync(path.join(policyRoot, ".git")) ? policyRoot : undefined;
|
|
555
|
+
return gitProjectRoot ?? configuredGitRoot ?? nearestRoot;
|
|
556
|
+
}
|
|
354
557
|
function getUserAgentSettingsPath() {
|
|
355
558
|
return path.join(getAgentDir(), "settings.json");
|
|
356
559
|
}
|
|
357
560
|
function getProjectAgentSettingsPath(cwd) {
|
|
358
|
-
const projectRoot =
|
|
561
|
+
const projectRoot = findConfiguredProjectRoot(cwd);
|
|
359
562
|
return projectRoot ? path.join(getProjectConfigDir(projectRoot), "settings.json") : null;
|
|
360
563
|
}
|
|
361
564
|
function readSettingsFileStrict(filePath) {
|
|
@@ -404,18 +607,52 @@ function parseOverrideStringArrayOrFalse(value, meta) {
|
|
|
404
607
|
}
|
|
405
608
|
return items;
|
|
406
609
|
}
|
|
610
|
+
function parseToolsOverride(value, meta) {
|
|
611
|
+
if (typeof value === "string" && value.trim() === "inherit")
|
|
612
|
+
return "inherit";
|
|
613
|
+
if (value === undefined || value === false || Array.isArray(value)) {
|
|
614
|
+
return parseOverrideStringArrayOrFalse(value, { ...meta, field: "tools" });
|
|
615
|
+
}
|
|
616
|
+
throw new Error(`Builtin override '${meta.name}' in '${meta.filePath}' has invalid 'tools'; expected an array of strings, "inherit", or false.`);
|
|
617
|
+
}
|
|
407
618
|
function parseBuiltinOverrideEntry(name, value, filePath) {
|
|
408
619
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
409
620
|
throw new Error(`Builtin override '${name}' in '${filePath}' must be an object.`);
|
|
410
621
|
}
|
|
411
622
|
const input = value;
|
|
412
623
|
const override = {};
|
|
624
|
+
if ("description" in input) {
|
|
625
|
+
if (typeof input.description === "string" && input.description.trim()) {
|
|
626
|
+
override.description = input.description.trim();
|
|
627
|
+
} else {
|
|
628
|
+
throw new Error(`Builtin override '${name}' in '${filePath}' has invalid 'description'; expected a non-empty string.`);
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
if ("output" in input) {
|
|
632
|
+
if (typeof input.output === "string" && input.output.trim() || input.output === false)
|
|
633
|
+
override.output = input.output;
|
|
634
|
+
else
|
|
635
|
+
throw new Error(`Builtin override '${name}' in '${filePath}' has invalid 'output'; expected a non-empty string or false.`);
|
|
636
|
+
}
|
|
637
|
+
if ("outputMode" in input) {
|
|
638
|
+
if (input.outputMode === "inline" || input.outputMode === "file-only") {
|
|
639
|
+
override.outputMode = input.outputMode;
|
|
640
|
+
} else {
|
|
641
|
+
throw new Error(`Builtin override '${name}' in '${filePath}' has invalid 'outputMode'; expected 'inline' or 'file-only'.`);
|
|
642
|
+
}
|
|
643
|
+
}
|
|
413
644
|
if ("model" in input) {
|
|
414
645
|
if (typeof input.model === "string" || input.model === false)
|
|
415
646
|
override.model = input.model;
|
|
416
647
|
else
|
|
417
648
|
throw new Error(`Builtin override '${name}' in '${filePath}' has invalid 'model'; expected a string or false.`);
|
|
418
649
|
}
|
|
650
|
+
if ("fast" in input) {
|
|
651
|
+
if (typeof input.fast === "boolean")
|
|
652
|
+
override.fast = input.fast;
|
|
653
|
+
else
|
|
654
|
+
throw new Error(`Builtin override '${name}' in '${filePath}' has invalid 'fast'; expected a boolean.`);
|
|
655
|
+
}
|
|
419
656
|
if ("thinking" in input) {
|
|
420
657
|
if (typeof input.thinking === "string" || input.thinking === false)
|
|
421
658
|
override.thinking = input.thinking;
|
|
@@ -436,6 +673,13 @@ function parseBuiltinOverrideEntry(name, value, filePath) {
|
|
|
436
673
|
throw new Error(`Builtin override '${name}' in '${filePath}' has invalid 'inheritProjectContext'; expected a boolean.`);
|
|
437
674
|
}
|
|
438
675
|
}
|
|
676
|
+
if ("inheritGlobalContext" in input) {
|
|
677
|
+
if (typeof input.inheritGlobalContext === "boolean") {
|
|
678
|
+
override.inheritGlobalContext = input.inheritGlobalContext;
|
|
679
|
+
} else {
|
|
680
|
+
throw new Error(`Builtin override '${name}' in '${filePath}' has invalid 'inheritGlobalContext'; expected a boolean.`);
|
|
681
|
+
}
|
|
682
|
+
}
|
|
439
683
|
if ("inheritSkills" in input) {
|
|
440
684
|
if (typeof input.inheritSkills === "boolean") {
|
|
441
685
|
override.inheritSkills = input.inheritSkills;
|
|
@@ -450,6 +694,13 @@ function parseBuiltinOverrideEntry(name, value, filePath) {
|
|
|
450
694
|
throw new Error(`Builtin override '${name}' in '${filePath}' has invalid 'defaultContext'; expected 'fresh', 'fork', or false.`);
|
|
451
695
|
}
|
|
452
696
|
}
|
|
697
|
+
if ("acceptanceRole" in input) {
|
|
698
|
+
if (input.acceptanceRole === "read-only" || input.acceptanceRole === "writer" || input.acceptanceRole === false) {
|
|
699
|
+
override.acceptanceRole = input.acceptanceRole;
|
|
700
|
+
} else {
|
|
701
|
+
throw new Error(`Builtin override '${name}' in '${filePath}' has invalid 'acceptanceRole'; expected 'read-only', 'writer', or false.`);
|
|
702
|
+
}
|
|
703
|
+
}
|
|
453
704
|
if ("disabled" in input) {
|
|
454
705
|
if (typeof input.disabled === "boolean") {
|
|
455
706
|
override.disabled = input.disabled;
|
|
@@ -479,18 +730,41 @@ function parseBuiltinOverrideEntry(name, value, filePath) {
|
|
|
479
730
|
else
|
|
480
731
|
throw new Error(`Builtin override '${name}' in '${filePath}' has invalid 'systemPrompt'; expected a string.`);
|
|
481
732
|
}
|
|
733
|
+
const defaultReads = parseOverrideStringArrayOrFalse(input.defaultReads, { filePath, name, field: "defaultReads" });
|
|
734
|
+
if (defaultReads !== undefined)
|
|
735
|
+
override.defaultReads = defaultReads;
|
|
482
736
|
const fallbackModels = parseOverrideStringArrayOrFalse(input.fallbackModels, { filePath, name, field: "fallbackModels" });
|
|
483
737
|
if (fallbackModels !== undefined)
|
|
484
738
|
override.fallbackModels = fallbackModels;
|
|
739
|
+
if ("defaultProvider" in input) {
|
|
740
|
+
if (input.defaultProvider === false)
|
|
741
|
+
override.defaultProvider = false;
|
|
742
|
+
else if (typeof input.defaultProvider === "string" && input.defaultProvider.trim())
|
|
743
|
+
override.defaultProvider = input.defaultProvider.trim();
|
|
744
|
+
else
|
|
745
|
+
throw new Error(`Builtin override '${name}' in '${filePath}' has invalid 'defaultProvider'; expected a non-empty string or false.`);
|
|
746
|
+
}
|
|
485
747
|
const skills = parseOverrideStringArrayOrFalse(input.skills, { filePath, name, field: "skills" });
|
|
486
748
|
if (skills !== undefined)
|
|
487
749
|
override.skills = skills;
|
|
488
|
-
const tools =
|
|
750
|
+
const tools = parseToolsOverride(input.tools, { filePath, name });
|
|
489
751
|
if (tools !== undefined)
|
|
490
752
|
override.tools = tools;
|
|
753
|
+
if ("allowNestedSubagents" in input) {
|
|
754
|
+
if (typeof input.allowNestedSubagents === "boolean")
|
|
755
|
+
override.allowNestedSubagents = input.allowNestedSubagents;
|
|
756
|
+
else
|
|
757
|
+
throw new Error(`Builtin override '${name}' in '${filePath}' has invalid 'allowNestedSubagents'; expected a boolean.`);
|
|
758
|
+
}
|
|
759
|
+
const extensions = parseOverrideStringArrayOrFalse(input.extensions, { filePath, name, field: "extensions" });
|
|
760
|
+
if (extensions !== undefined)
|
|
761
|
+
override.extensions = extensions;
|
|
491
762
|
const subagentOnlyExtensions = parseOverrideStringArrayOrFalse(input.subagentOnlyExtensions, { filePath, name, field: "subagentOnlyExtensions" });
|
|
492
763
|
if (subagentOnlyExtensions !== undefined)
|
|
493
764
|
override.subagentOnlyExtensions = subagentOnlyExtensions;
|
|
765
|
+
const mutationTools = parseOverrideStringArrayOrFalse(input.mutationTools, { filePath, name, field: "mutationTools" });
|
|
766
|
+
if (mutationTools !== undefined)
|
|
767
|
+
override.mutationTools = mutationTools;
|
|
494
768
|
return Object.keys(override).length > 0 ? override : undefined;
|
|
495
769
|
}
|
|
496
770
|
function readSubagentSettings(filePath) {
|
|
@@ -525,86 +799,300 @@ function readSubagentSettings(filePath) {
|
|
|
525
799
|
throw new Error(`Subagent settings in '${filePath}' have invalid 'defaultModel'; expected a non-empty string.`);
|
|
526
800
|
}
|
|
527
801
|
}
|
|
802
|
+
let defaultProvider;
|
|
803
|
+
if ("defaultProvider" in subagentsObject) {
|
|
804
|
+
if (typeof subagentsObject.defaultProvider === "string" && subagentsObject.defaultProvider.trim()) {
|
|
805
|
+
defaultProvider = subagentsObject.defaultProvider.trim();
|
|
806
|
+
} else {
|
|
807
|
+
throw new Error(`Subagent settings in '${filePath}' have invalid 'defaultProvider'; expected a non-empty string.`);
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
let defaultThinking;
|
|
811
|
+
if ("defaultThinking" in subagentsObject) {
|
|
812
|
+
if (typeof subagentsObject.defaultThinking === "string" && subagentsObject.defaultThinking.trim()) {
|
|
813
|
+
defaultThinking = subagentsObject.defaultThinking.trim();
|
|
814
|
+
} else {
|
|
815
|
+
throw new Error(`Subagent settings in '${filePath}' have invalid 'defaultThinking'; expected a non-empty string.`);
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
let maxThinking;
|
|
819
|
+
if ("maxThinking" in subagentsObject) {
|
|
820
|
+
try {
|
|
821
|
+
maxThinking = parseThinkingLevel(subagentsObject.maxThinking, `'${filePath}' subagents.maxThinking`);
|
|
822
|
+
} catch (error) {
|
|
823
|
+
throw new Error(`Subagent settings in '${filePath}' have invalid 'maxThinking'; expected one of off, minimal, low, medium, high, xhigh, or max.`, { cause: error instanceof Error ? error : undefined });
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
let defaultExtensions;
|
|
827
|
+
if ("defaultExtensions" in subagentsObject) {
|
|
828
|
+
if (!Array.isArray(subagentsObject.defaultExtensions) || subagentsObject.defaultExtensions.some((item) => typeof item !== "string" || !item.trim())) {
|
|
829
|
+
throw new Error(`Subagent settings in '${filePath}' have invalid 'defaultExtensions'; expected an array of non-empty strings.`);
|
|
830
|
+
}
|
|
831
|
+
defaultExtensions = subagentsObject.defaultExtensions.map((item) => item.trim());
|
|
832
|
+
}
|
|
528
833
|
const modelScope = parseModelScopeConfig(subagentsObject.modelScope, { filePath });
|
|
529
834
|
const parsed = {};
|
|
835
|
+
const providerOverrides = {};
|
|
530
836
|
const agentOverrides = subagentsObject.agentOverrides;
|
|
531
|
-
|
|
532
|
-
|
|
837
|
+
const agentOverridesByProvider = subagentsObject.agentOverridesByProvider;
|
|
838
|
+
const parsedSettings = {
|
|
839
|
+
overrides: parsed,
|
|
840
|
+
providerOverrides,
|
|
841
|
+
...defaultModel !== undefined ? { defaultModel } : {},
|
|
842
|
+
...defaultProvider !== undefined ? { defaultProvider } : {},
|
|
843
|
+
...defaultThinking !== undefined ? { defaultThinking } : {},
|
|
844
|
+
...maxThinking !== undefined ? { maxThinking } : {},
|
|
845
|
+
...defaultExtensions !== undefined ? { defaultExtensions } : {},
|
|
846
|
+
...disableBuiltins !== undefined ? { disableBuiltins } : {},
|
|
847
|
+
...disableThinking !== undefined ? { disableThinking } : {},
|
|
848
|
+
...modelScope !== undefined ? { modelScope } : {}
|
|
849
|
+
};
|
|
850
|
+
if (agentOverrides && typeof agentOverrides === "object" && !Array.isArray(agentOverrides)) {
|
|
851
|
+
for (const [name, value] of Object.entries(agentOverrides)) {
|
|
852
|
+
const override = parseBuiltinOverrideEntry(name, value, filePath);
|
|
853
|
+
if (override)
|
|
854
|
+
parsed[name] = override;
|
|
855
|
+
}
|
|
533
856
|
}
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
857
|
+
if (agentOverridesByProvider !== undefined) {
|
|
858
|
+
if (!agentOverridesByProvider || typeof agentOverridesByProvider !== "object" || Array.isArray(agentOverridesByProvider)) {
|
|
859
|
+
throw new Error(`Subagent settings in '${filePath}' have invalid 'agentOverridesByProvider'; expected an object keyed by provider.`);
|
|
860
|
+
}
|
|
861
|
+
for (const [provider, value] of Object.entries(agentOverridesByProvider)) {
|
|
862
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
863
|
+
throw new Error(`Subagent settings in '${filePath}' have invalid 'agentOverridesByProvider.${provider}'; expected an object keyed by agent.`);
|
|
864
|
+
}
|
|
865
|
+
const entries = {};
|
|
866
|
+
for (const [agentName, agentValue] of Object.entries(value)) {
|
|
867
|
+
const override = parseBuiltinOverrideEntry(`agentOverridesByProvider.${provider}.${agentName}`, agentValue, filePath);
|
|
868
|
+
if (override)
|
|
869
|
+
entries[agentName] = override;
|
|
870
|
+
}
|
|
871
|
+
providerOverrides[provider] = entries;
|
|
872
|
+
}
|
|
538
873
|
}
|
|
539
|
-
return
|
|
874
|
+
return parsedSettings;
|
|
875
|
+
}
|
|
876
|
+
function selectProviderOverrides(settings, provider) {
|
|
877
|
+
if (!provider)
|
|
878
|
+
return settings;
|
|
879
|
+
const selected = settings.providerOverrides[provider];
|
|
880
|
+
if (!selected)
|
|
881
|
+
return settings;
|
|
882
|
+
const overrides = { ...settings.overrides };
|
|
883
|
+
for (const [name, override] of Object.entries(selected)) {
|
|
884
|
+
overrides[name] = { ...overrides[name], ...override };
|
|
885
|
+
}
|
|
886
|
+
return { ...settings, overrides };
|
|
540
887
|
}
|
|
541
|
-
function
|
|
888
|
+
function resolveSubagentDefaultProvider(userSettings, projectSettings, projectSettingsPath) {
|
|
889
|
+
if (projectSettingsPath && projectSettings.defaultProvider !== undefined)
|
|
890
|
+
return projectSettings.defaultProvider;
|
|
891
|
+
return userSettings.defaultProvider;
|
|
892
|
+
}
|
|
893
|
+
function resolveSubagentDefaultModel(userSettings, projectSettings, userSettingsPath, projectSettingsPath, defaultProvider) {
|
|
542
894
|
if (projectSettingsPath && projectSettings.defaultModel !== undefined) {
|
|
543
|
-
return { type: "subagents.defaultModel", scope: "project", path: projectSettingsPath, model: projectSettings.defaultModel };
|
|
895
|
+
return { type: "subagents.defaultModel", scope: "project", path: projectSettingsPath, model: projectSettings.defaultModel, ...defaultProvider ? { defaultProvider } : {} };
|
|
544
896
|
}
|
|
545
|
-
return userSettings.defaultModel !== undefined ? { type: "subagents.defaultModel", scope: "user", path: userSettingsPath, model: userSettings.defaultModel } : undefined;
|
|
897
|
+
return userSettings.defaultModel !== undefined ? { type: "subagents.defaultModel", scope: "user", path: userSettingsPath, model: userSettings.defaultModel, ...defaultProvider ? { defaultProvider } : {} } : undefined;
|
|
898
|
+
}
|
|
899
|
+
function applySubagentDefaultModel(agents, defaultModel, defaultProvider) {
|
|
900
|
+
if (!defaultModel && !defaultProvider)
|
|
901
|
+
return agents;
|
|
902
|
+
return agents.map((agent) => {
|
|
903
|
+
if (agent.model !== undefined && (agent.modelProvider !== undefined || !defaultProvider))
|
|
904
|
+
return agent;
|
|
905
|
+
const next = {
|
|
906
|
+
...agent,
|
|
907
|
+
...agent.model === undefined && defaultModel ? { model: defaultModel.model, modelSource: defaultModel } : {},
|
|
908
|
+
...defaultProvider ? { modelProvider: defaultProvider } : {}
|
|
909
|
+
};
|
|
910
|
+
const frontmatterFields = agentFrontmatterFields.get(agent);
|
|
911
|
+
if (frontmatterFields)
|
|
912
|
+
agentFrontmatterFields.set(next, frontmatterFields);
|
|
913
|
+
return next;
|
|
914
|
+
});
|
|
915
|
+
}
|
|
916
|
+
function resolveSubagentDefaultThinking(userSettings, projectSettings, projectSettingsPath) {
|
|
917
|
+
if (projectSettingsPath && projectSettings.defaultThinking !== undefined)
|
|
918
|
+
return projectSettings.defaultThinking;
|
|
919
|
+
return userSettings.defaultThinking;
|
|
546
920
|
}
|
|
547
|
-
function
|
|
548
|
-
if (
|
|
921
|
+
function applySubagentDefaultThinking(agents, defaultThinking) {
|
|
922
|
+
if (defaultThinking === undefined)
|
|
549
923
|
return agents;
|
|
550
924
|
return agents.map((agent) => {
|
|
551
|
-
if (agent.
|
|
925
|
+
if (agent.thinking !== undefined)
|
|
552
926
|
return agent;
|
|
553
|
-
const next = { ...agent,
|
|
927
|
+
const next = { ...agent, thinking: defaultThinking };
|
|
554
928
|
const frontmatterFields = agentFrontmatterFields.get(agent);
|
|
555
929
|
if (frontmatterFields)
|
|
556
930
|
agentFrontmatterFields.set(next, frontmatterFields);
|
|
557
931
|
return next;
|
|
558
932
|
});
|
|
559
933
|
}
|
|
934
|
+
function resolveSubagentMaxThinking(userSettings, projectSettings, projectSettingsPath) {
|
|
935
|
+
if (projectSettingsPath && projectSettings.maxThinking !== undefined)
|
|
936
|
+
return projectSettings.maxThinking;
|
|
937
|
+
return userSettings.maxThinking;
|
|
938
|
+
}
|
|
939
|
+
function applySubagentMaxThinking(agents, maxThinking) {
|
|
940
|
+
if (maxThinking === undefined)
|
|
941
|
+
return agents;
|
|
942
|
+
return agents.map((agent) => agent.maxThinking === maxThinking ? agent : { ...agent, maxThinking });
|
|
943
|
+
}
|
|
944
|
+
function resolveSubagentDefaultExtensions(userSettings, projectSettings, projectSettingsPath) {
|
|
945
|
+
if (projectSettingsPath && projectSettings.defaultExtensions !== undefined)
|
|
946
|
+
return projectSettings.defaultExtensions;
|
|
947
|
+
return userSettings.defaultExtensions;
|
|
948
|
+
}
|
|
949
|
+
function applySubagentDefaultExtensions(agents, defaultExtensions) {
|
|
950
|
+
if (defaultExtensions === undefined)
|
|
951
|
+
return agents;
|
|
952
|
+
return agents.map((agent) => {
|
|
953
|
+
if (agent.extensions !== undefined)
|
|
954
|
+
return agent;
|
|
955
|
+
const next = { ...agent, extensions: [...defaultExtensions], extensionsFromDefault: true };
|
|
956
|
+
const frontmatterFields = agentFrontmatterFields.get(agent);
|
|
957
|
+
if (frontmatterFields)
|
|
958
|
+
agentFrontmatterFields.set(next, frontmatterFields);
|
|
959
|
+
return next;
|
|
960
|
+
});
|
|
961
|
+
}
|
|
962
|
+
function applySubagentDefaults(agents, defaultModel, defaultProvider, defaultThinking, defaultExtensions) {
|
|
963
|
+
return applySubagentDefaultExtensions(applySubagentDefaultThinking(applySubagentDefaultModel(agents, defaultModel, defaultProvider), defaultThinking), defaultExtensions);
|
|
964
|
+
}
|
|
965
|
+
function applyToolsOverride(target, toolsOverride) {
|
|
966
|
+
if (toolsOverride === "inherit") {
|
|
967
|
+
delete target.tools;
|
|
968
|
+
delete target.mcpDirectTools;
|
|
969
|
+
return;
|
|
970
|
+
}
|
|
971
|
+
const { tools, mcpDirectTools } = splitToolList(toolsOverride === false ? [] : toolsOverride);
|
|
972
|
+
if (tools === undefined)
|
|
973
|
+
delete target.tools;
|
|
974
|
+
else
|
|
975
|
+
target.tools = tools;
|
|
976
|
+
if (mcpDirectTools === undefined)
|
|
977
|
+
delete target.mcpDirectTools;
|
|
978
|
+
else
|
|
979
|
+
target.mcpDirectTools = mcpDirectTools;
|
|
980
|
+
}
|
|
560
981
|
function applyBuiltinOverride(agent, override, meta) {
|
|
561
982
|
const next = {
|
|
562
983
|
...agent,
|
|
563
984
|
override: { ...meta, base: cloneOverrideBase(agent) }
|
|
564
985
|
};
|
|
565
|
-
if (override.
|
|
566
|
-
next.
|
|
986
|
+
if (override.description !== undefined)
|
|
987
|
+
next.description = override.description;
|
|
988
|
+
if (override.output !== undefined) {
|
|
989
|
+
if (override.output === false)
|
|
990
|
+
delete next.output;
|
|
991
|
+
else
|
|
992
|
+
next.output = override.output;
|
|
993
|
+
}
|
|
994
|
+
if (override.outputMode !== undefined)
|
|
995
|
+
next.outputMode = override.outputMode;
|
|
996
|
+
if (override.defaultReads !== undefined) {
|
|
997
|
+
if (override.defaultReads === false)
|
|
998
|
+
delete next.defaultReads;
|
|
999
|
+
else
|
|
1000
|
+
next.defaultReads = [...override.defaultReads];
|
|
1001
|
+
}
|
|
1002
|
+
if (override.model !== undefined) {
|
|
1003
|
+
if (override.model === false)
|
|
1004
|
+
delete next.model;
|
|
1005
|
+
else
|
|
1006
|
+
next.model = override.model;
|
|
1007
|
+
delete next.modelSource;
|
|
1008
|
+
}
|
|
1009
|
+
if (override.defaultProvider !== undefined) {
|
|
1010
|
+
if (override.defaultProvider === false)
|
|
1011
|
+
delete next.modelProvider;
|
|
1012
|
+
else
|
|
1013
|
+
next.modelProvider = override.defaultProvider;
|
|
1014
|
+
}
|
|
567
1015
|
if (override.fallbackModels !== undefined) {
|
|
568
|
-
|
|
1016
|
+
if (override.fallbackModels === false)
|
|
1017
|
+
delete next.fallbackModels;
|
|
1018
|
+
else
|
|
1019
|
+
next.fallbackModels = [...override.fallbackModels];
|
|
1020
|
+
}
|
|
1021
|
+
if (override.fast !== undefined)
|
|
1022
|
+
next.fast = override.fast;
|
|
1023
|
+
if (override.thinking !== undefined) {
|
|
1024
|
+
if (override.thinking === false)
|
|
1025
|
+
delete next.thinking;
|
|
1026
|
+
else
|
|
1027
|
+
next.thinking = override.thinking;
|
|
569
1028
|
}
|
|
570
|
-
if (override.thinking !== undefined)
|
|
571
|
-
next.thinking = override.thinking === false ? undefined : override.thinking;
|
|
572
1029
|
if (override.systemPromptMode !== undefined)
|
|
573
1030
|
next.systemPromptMode = override.systemPromptMode;
|
|
574
1031
|
if (override.inheritProjectContext !== undefined)
|
|
575
1032
|
next.inheritProjectContext = override.inheritProjectContext;
|
|
1033
|
+
if (override.inheritGlobalContext !== undefined)
|
|
1034
|
+
next.inheritGlobalContext = override.inheritGlobalContext;
|
|
576
1035
|
if (override.inheritSkills !== undefined)
|
|
577
1036
|
next.inheritSkills = override.inheritSkills;
|
|
578
|
-
if (override.defaultContext !== undefined)
|
|
579
|
-
|
|
1037
|
+
if (override.defaultContext !== undefined) {
|
|
1038
|
+
if (override.defaultContext === false)
|
|
1039
|
+
delete next.defaultContext;
|
|
1040
|
+
else
|
|
1041
|
+
next.defaultContext = override.defaultContext;
|
|
1042
|
+
}
|
|
1043
|
+
if (override.acceptanceRole !== undefined) {
|
|
1044
|
+
if (override.acceptanceRole === false)
|
|
1045
|
+
delete next.acceptanceRole;
|
|
1046
|
+
else
|
|
1047
|
+
next.acceptanceRole = override.acceptanceRole;
|
|
1048
|
+
}
|
|
580
1049
|
if (override.disabled !== undefined)
|
|
581
1050
|
next.disabled = override.disabled;
|
|
582
1051
|
if (override.systemPrompt !== undefined)
|
|
583
1052
|
next.systemPrompt = override.systemPrompt;
|
|
584
|
-
if (override.skills !== undefined)
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
1053
|
+
if (override.skills !== undefined) {
|
|
1054
|
+
if (override.skills === false)
|
|
1055
|
+
delete next.skills;
|
|
1056
|
+
else
|
|
1057
|
+
next.skills = [...override.skills];
|
|
1058
|
+
}
|
|
1059
|
+
if (override.tools !== undefined)
|
|
1060
|
+
applyToolsOverride(next, override.tools);
|
|
1061
|
+
if (override.allowNestedSubagents !== undefined)
|
|
1062
|
+
next.allowNestedSubagents = override.allowNestedSubagents;
|
|
1063
|
+
if (override.extensions !== undefined) {
|
|
1064
|
+
if (override.extensions === false)
|
|
1065
|
+
delete next.extensions;
|
|
1066
|
+
else
|
|
1067
|
+
next.extensions = [...override.extensions];
|
|
590
1068
|
}
|
|
591
1069
|
if (override.subagentOnlyExtensions !== undefined) {
|
|
592
|
-
|
|
1070
|
+
if (override.subagentOnlyExtensions === false)
|
|
1071
|
+
delete next.subagentOnlyExtensions;
|
|
1072
|
+
else
|
|
1073
|
+
next.subagentOnlyExtensions = [...override.subagentOnlyExtensions];
|
|
1074
|
+
}
|
|
1075
|
+
if (override.mutationTools !== undefined) {
|
|
1076
|
+
if (override.mutationTools === false)
|
|
1077
|
+
delete next.mutationTools;
|
|
1078
|
+
else
|
|
1079
|
+
next.mutationTools = [...override.mutationTools];
|
|
593
1080
|
}
|
|
594
1081
|
if (override.completionGuard !== undefined)
|
|
595
1082
|
next.completionGuard = override.completionGuard;
|
|
596
|
-
if (override.toolBudget !== undefined)
|
|
597
|
-
|
|
1083
|
+
if (override.toolBudget !== undefined) {
|
|
1084
|
+
if (override.toolBudget === false)
|
|
1085
|
+
delete next.toolBudget;
|
|
1086
|
+
else
|
|
1087
|
+
next.toolBudget = override.toolBudget;
|
|
1088
|
+
}
|
|
598
1089
|
return next;
|
|
599
1090
|
}
|
|
600
1091
|
function clearBuiltinThinking(agent, meta) {
|
|
601
1092
|
if (agent.thinking === undefined)
|
|
602
1093
|
return agent;
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
thinking: undefined,
|
|
606
|
-
override: agent.override ?? { ...meta, base: cloneOverrideBase(agent) }
|
|
607
|
-
};
|
|
1094
|
+
const { thinking: _thinking, ...next } = agent;
|
|
1095
|
+
return { ...next, override: agent.override ?? { ...meta, base: cloneOverrideBase(agent) } };
|
|
608
1096
|
}
|
|
609
1097
|
function applyBuiltinOverrides(builtinAgents, userSettings, projectSettings, userSettingsPath, projectSettingsPath) {
|
|
610
1098
|
const projectBulkDisabled = projectSettings.disableBuiltins === true && projectSettingsPath !== null;
|
|
@@ -635,7 +1123,7 @@ function applyBuiltinOverrides(builtinAgents, userSettings, projectSettings, use
|
|
|
635
1123
|
return applyGlobalThinking(agent, false);
|
|
636
1124
|
});
|
|
637
1125
|
}
|
|
638
|
-
function
|
|
1126
|
+
export function agentHasFrontmatterField(agent, ...fields) {
|
|
639
1127
|
const frontmatterFields = agentFrontmatterFields.get(agent);
|
|
640
1128
|
return frontmatterFields ? fields.some((field) => frontmatterFields.has(field)) : false;
|
|
641
1129
|
}
|
|
@@ -647,17 +1135,46 @@ function applyCustomAgentOverride(agent, override, meta) {
|
|
|
647
1135
|
return next;
|
|
648
1136
|
};
|
|
649
1137
|
const fill = (field, frontmatterFields, value) => {
|
|
650
|
-
if (
|
|
1138
|
+
if (agentHasFrontmatterField(agent, ...frontmatterFields))
|
|
651
1139
|
return;
|
|
652
|
-
mutable()
|
|
1140
|
+
const target = mutable();
|
|
1141
|
+
if (value === undefined)
|
|
1142
|
+
delete target[field];
|
|
1143
|
+
else
|
|
1144
|
+
target[field] = value;
|
|
653
1145
|
anyFilled = true;
|
|
654
1146
|
};
|
|
655
|
-
if (override.
|
|
656
|
-
|
|
1147
|
+
if (override.description !== undefined) {
|
|
1148
|
+
mutable().description = override.description;
|
|
1149
|
+
anyFilled = true;
|
|
1150
|
+
}
|
|
1151
|
+
if (override.output !== undefined) {
|
|
1152
|
+
fill("output", ["output"], override.output === false ? undefined : override.output);
|
|
1153
|
+
}
|
|
1154
|
+
if (override.outputMode !== undefined) {
|
|
1155
|
+
fill("outputMode", ["outputMode"], override.outputMode);
|
|
1156
|
+
}
|
|
1157
|
+
if (override.defaultReads !== undefined) {
|
|
1158
|
+
fill("defaultReads", ["defaultReads"], override.defaultReads === false ? undefined : [...override.defaultReads]);
|
|
1159
|
+
}
|
|
1160
|
+
if (override.model !== undefined && !agentHasFrontmatterField(agent, "model")) {
|
|
1161
|
+
const target = mutable();
|
|
1162
|
+
if (override.model === false)
|
|
1163
|
+
delete target.model;
|
|
1164
|
+
else
|
|
1165
|
+
target.model = override.model;
|
|
1166
|
+
delete target.modelSource;
|
|
1167
|
+
anyFilled = true;
|
|
1168
|
+
}
|
|
1169
|
+
if (override.defaultProvider !== undefined) {
|
|
1170
|
+
fill("modelProvider", ["modelProvider", "defaultProvider"], override.defaultProvider === false ? undefined : override.defaultProvider);
|
|
657
1171
|
}
|
|
658
1172
|
if (override.fallbackModels !== undefined) {
|
|
659
1173
|
fill("fallbackModels", ["fallbackModels"], override.fallbackModels === false ? undefined : [...override.fallbackModels]);
|
|
660
1174
|
}
|
|
1175
|
+
if (override.fast !== undefined) {
|
|
1176
|
+
fill("fast", ["fast"], override.fast);
|
|
1177
|
+
}
|
|
661
1178
|
if (override.thinking !== undefined) {
|
|
662
1179
|
fill("thinking", ["thinking"], override.thinking === false ? undefined : override.thinking);
|
|
663
1180
|
}
|
|
@@ -667,29 +1184,41 @@ function applyCustomAgentOverride(agent, override, meta) {
|
|
|
667
1184
|
if (override.inheritProjectContext !== undefined) {
|
|
668
1185
|
fill("inheritProjectContext", ["inheritProjectContext"], override.inheritProjectContext);
|
|
669
1186
|
}
|
|
1187
|
+
if (override.inheritGlobalContext !== undefined) {
|
|
1188
|
+
fill("inheritGlobalContext", ["inheritGlobalContext"], override.inheritGlobalContext);
|
|
1189
|
+
}
|
|
670
1190
|
if (override.inheritSkills !== undefined) {
|
|
671
1191
|
fill("inheritSkills", ["inheritSkills"], override.inheritSkills);
|
|
672
1192
|
}
|
|
673
1193
|
if (override.defaultContext !== undefined) {
|
|
674
1194
|
fill("defaultContext", ["defaultContext"], override.defaultContext === false ? undefined : override.defaultContext);
|
|
675
1195
|
}
|
|
676
|
-
if (override.
|
|
1196
|
+
if (override.acceptanceRole !== undefined) {
|
|
1197
|
+
fill("acceptanceRole", ["acceptanceRole"], override.acceptanceRole === false ? undefined : override.acceptanceRole);
|
|
1198
|
+
}
|
|
1199
|
+
if (override.disabled !== undefined) {
|
|
677
1200
|
mutable().disabled = override.disabled;
|
|
678
1201
|
anyFilled = true;
|
|
679
1202
|
}
|
|
680
1203
|
if (override.skills !== undefined) {
|
|
681
1204
|
fill("skills", ["skill", "skills"], override.skills === false ? undefined : [...override.skills]);
|
|
682
1205
|
}
|
|
683
|
-
if (override.tools !== undefined && !
|
|
684
|
-
|
|
685
|
-
const target = mutable();
|
|
686
|
-
target.tools = tools;
|
|
687
|
-
target.mcpDirectTools = mcpDirectTools;
|
|
1206
|
+
if (override.tools !== undefined && !agentHasFrontmatterField(agent, "tools")) {
|
|
1207
|
+
applyToolsOverride(mutable(), override.tools);
|
|
688
1208
|
anyFilled = true;
|
|
689
1209
|
}
|
|
1210
|
+
if (override.allowNestedSubagents !== undefined) {
|
|
1211
|
+
fill("allowNestedSubagents", ["allowNestedSubagents"], override.allowNestedSubagents);
|
|
1212
|
+
}
|
|
1213
|
+
if (override.extensions !== undefined) {
|
|
1214
|
+
fill("extensions", ["extensions"], override.extensions === false ? undefined : [...override.extensions]);
|
|
1215
|
+
}
|
|
690
1216
|
if (override.subagentOnlyExtensions !== undefined) {
|
|
691
1217
|
fill("subagentOnlyExtensions", ["subagentOnlyExtensions"], override.subagentOnlyExtensions === false ? undefined : [...override.subagentOnlyExtensions]);
|
|
692
1218
|
}
|
|
1219
|
+
if (override.mutationTools !== undefined) {
|
|
1220
|
+
fill("mutationTools", ["mutationTools"], override.mutationTools === false ? undefined : [...override.mutationTools]);
|
|
1221
|
+
}
|
|
693
1222
|
if (override.completionGuard !== undefined) {
|
|
694
1223
|
fill("completionGuard", ["completionGuard"], override.completionGuard);
|
|
695
1224
|
}
|
|
@@ -698,38 +1227,58 @@ function applyCustomAgentOverride(agent, override, meta) {
|
|
|
698
1227
|
}
|
|
699
1228
|
if (!anyFilled || !next)
|
|
700
1229
|
return agent;
|
|
701
|
-
next.override = { ...meta, base: cloneOverrideBase(agent) };
|
|
1230
|
+
next.override = { ...meta, base: agent.override?.base ?? cloneOverrideBase(agent) };
|
|
1231
|
+
const frontmatterFields = agentFrontmatterFields.get(agent);
|
|
1232
|
+
if (frontmatterFields)
|
|
1233
|
+
agentFrontmatterFields.set(next, frontmatterFields);
|
|
702
1234
|
return next;
|
|
703
1235
|
}
|
|
704
1236
|
function applyCustomAgentOverrides(agents, userSettings, projectSettings, userSettingsPath, projectSettingsPath) {
|
|
705
1237
|
return agents.map((agent) => {
|
|
1238
|
+
const userOverride = userSettings.overrides[agent.name];
|
|
1239
|
+
const withUserOverride = userOverride ? applyCustomAgentOverride(agent, userOverride, { scope: "user", path: userSettingsPath }) : agent;
|
|
706
1240
|
const projectOverride = projectSettings.overrides[agent.name];
|
|
707
1241
|
if (projectOverride && projectSettingsPath) {
|
|
708
|
-
return applyCustomAgentOverride(
|
|
1242
|
+
return applyCustomAgentOverride(withUserOverride, projectOverride, { scope: "project", path: projectSettingsPath });
|
|
709
1243
|
}
|
|
710
|
-
|
|
711
|
-
if (userOverride) {
|
|
712
|
-
return applyCustomAgentOverride(agent, userOverride, { scope: "user", path: userSettingsPath });
|
|
713
|
-
}
|
|
714
|
-
return agent;
|
|
1244
|
+
return withUserOverride;
|
|
715
1245
|
});
|
|
716
1246
|
}
|
|
717
1247
|
export function buildBuiltinOverrideConfig(base, draft) {
|
|
718
1248
|
const override = {};
|
|
1249
|
+
if (draft.description !== undefined) {
|
|
1250
|
+
const description = draft.description.trim();
|
|
1251
|
+
if (description && description !== base.description)
|
|
1252
|
+
override.description = description;
|
|
1253
|
+
}
|
|
1254
|
+
if (draft.output !== base.output)
|
|
1255
|
+
override.output = draft.output ?? false;
|
|
1256
|
+
if (draft.outputMode !== undefined && draft.outputMode !== base.outputMode)
|
|
1257
|
+
override.outputMode = draft.outputMode;
|
|
1258
|
+
if (!arraysEqual(draft.defaultReads, base.defaultReads))
|
|
1259
|
+
override.defaultReads = draft.defaultReads ? [...draft.defaultReads] : false;
|
|
719
1260
|
if (draft.model !== base.model)
|
|
720
1261
|
override.model = draft.model ?? false;
|
|
1262
|
+
if (draft.modelProvider !== base.modelProvider)
|
|
1263
|
+
override.defaultProvider = draft.modelProvider ?? false;
|
|
721
1264
|
if (!arraysEqual(draft.fallbackModels, base.fallbackModels))
|
|
722
1265
|
override.fallbackModels = draft.fallbackModels ? [...draft.fallbackModels] : false;
|
|
1266
|
+
if (draft.fast !== base.fast)
|
|
1267
|
+
override.fast = draft.fast === true;
|
|
723
1268
|
if (draft.thinking !== base.thinking)
|
|
724
1269
|
override.thinking = draft.thinking ?? false;
|
|
725
1270
|
if (draft.systemPromptMode !== base.systemPromptMode)
|
|
726
1271
|
override.systemPromptMode = draft.systemPromptMode;
|
|
727
1272
|
if (draft.inheritProjectContext !== base.inheritProjectContext)
|
|
728
1273
|
override.inheritProjectContext = draft.inheritProjectContext;
|
|
1274
|
+
if (draft.inheritGlobalContext !== base.inheritGlobalContext)
|
|
1275
|
+
override.inheritGlobalContext = draft.inheritGlobalContext;
|
|
729
1276
|
if (draft.inheritSkills !== base.inheritSkills)
|
|
730
1277
|
override.inheritSkills = draft.inheritSkills;
|
|
731
1278
|
if (draft.defaultContext !== base.defaultContext)
|
|
732
1279
|
override.defaultContext = draft.defaultContext ?? false;
|
|
1280
|
+
if (draft.acceptanceRole !== base.acceptanceRole)
|
|
1281
|
+
override.acceptanceRole = draft.acceptanceRole ?? false;
|
|
733
1282
|
if (draft.disabled !== base.disabled)
|
|
734
1283
|
override.disabled = draft.disabled ?? false;
|
|
735
1284
|
if (draft.systemPrompt !== base.systemPrompt)
|
|
@@ -740,9 +1289,15 @@ export function buildBuiltinOverrideConfig(base, draft) {
|
|
|
740
1289
|
const draftTools = joinToolList(draft);
|
|
741
1290
|
if (!arraysEqual(draftTools, baseTools))
|
|
742
1291
|
override.tools = draftTools ? [...draftTools] : false;
|
|
1292
|
+
if (draft.allowNestedSubagents !== base.allowNestedSubagents)
|
|
1293
|
+
override.allowNestedSubagents = draft.allowNestedSubagents === true;
|
|
1294
|
+
if (!arraysEqual(draft.extensions, base.extensions))
|
|
1295
|
+
override.extensions = draft.extensions ? [...draft.extensions] : false;
|
|
743
1296
|
if (!arraysEqual(draft.subagentOnlyExtensions, base.subagentOnlyExtensions)) {
|
|
744
1297
|
override.subagentOnlyExtensions = draft.subagentOnlyExtensions ? [...draft.subagentOnlyExtensions] : false;
|
|
745
1298
|
}
|
|
1299
|
+
if (!arraysEqual(draft.mutationTools, base.mutationTools))
|
|
1300
|
+
override.mutationTools = draft.mutationTools ? [...draft.mutationTools] : false;
|
|
746
1301
|
if (draft.completionGuard !== false !== (base.completionGuard !== false)) {
|
|
747
1302
|
override.completionGuard = draft.completionGuard !== false;
|
|
748
1303
|
}
|
|
@@ -851,10 +1406,31 @@ export function removeBuiltinAgentOverrideFields(cwd, name, scope, fields) {
|
|
|
851
1406
|
writeSettingsFile(filePath, settings);
|
|
852
1407
|
return { path: filePath, removed: true };
|
|
853
1408
|
}
|
|
854
|
-
|
|
1409
|
+
const DISCOVERY_PRUNED_DIR_NAMES = new Set([".git", "node_modules", ".dm", "sync-backups"]);
|
|
1410
|
+
function isDiscoveryNestedProjectRoot(dir) {
|
|
1411
|
+
return isDirectory(getProjectConfigDir(dir)) || isDirectory(path.join(dir, ".agents"));
|
|
1412
|
+
}
|
|
1413
|
+
function shouldPruneDiscoveryDir(rootDir, dir, dirName) {
|
|
1414
|
+
if (DISCOVERY_PRUNED_DIR_NAMES.has(dirName))
|
|
1415
|
+
return true;
|
|
1416
|
+
if (fs.existsSync(path.join(dir, ".git")))
|
|
1417
|
+
return true;
|
|
1418
|
+
return path.resolve(dir) !== path.resolve(rootDir) && isDiscoveryNestedProjectRoot(dir);
|
|
1419
|
+
}
|
|
1420
|
+
function listFilesRecursive(dir, predicate, rootDir = dir, visitedDirectories = new Set, inspectedDirectories = new Set) {
|
|
855
1421
|
const files = [];
|
|
856
1422
|
if (!fs.existsSync(dir))
|
|
857
1423
|
return files;
|
|
1424
|
+
inspectedDirectories.add(path.resolve(dir));
|
|
1425
|
+
let realDir;
|
|
1426
|
+
try {
|
|
1427
|
+
realDir = fs.realpathSync(dir);
|
|
1428
|
+
} catch {
|
|
1429
|
+
return files;
|
|
1430
|
+
}
|
|
1431
|
+
if (visitedDirectories.has(realDir))
|
|
1432
|
+
return files;
|
|
1433
|
+
visitedDirectories.add(realDir);
|
|
858
1434
|
let entries;
|
|
859
1435
|
try {
|
|
860
1436
|
entries = fs.readdirSync(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
|
|
@@ -863,8 +1439,18 @@ function listFilesRecursive(dir, predicate) {
|
|
|
863
1439
|
}
|
|
864
1440
|
for (const entry of entries) {
|
|
865
1441
|
const filePath = path.join(dir, entry.name);
|
|
866
|
-
|
|
867
|
-
|
|
1442
|
+
let isDirectory = entry.isDirectory();
|
|
1443
|
+
if (entry.isSymbolicLink()) {
|
|
1444
|
+
try {
|
|
1445
|
+
isDirectory = fs.statSync(filePath).isDirectory();
|
|
1446
|
+
} catch {
|
|
1447
|
+
isDirectory = false;
|
|
1448
|
+
}
|
|
1449
|
+
}
|
|
1450
|
+
if (isDirectory) {
|
|
1451
|
+
if (!shouldPruneDiscoveryDir(rootDir, filePath, entry.name)) {
|
|
1452
|
+
files.push(...listFilesRecursive(filePath, predicate, rootDir, visitedDirectories, inspectedDirectories));
|
|
1453
|
+
}
|
|
868
1454
|
continue;
|
|
869
1455
|
}
|
|
870
1456
|
if (!entry.isFile() && !entry.isSymbolicLink())
|
|
@@ -875,6 +1461,75 @@ function listFilesRecursive(dir, predicate) {
|
|
|
875
1461
|
}
|
|
876
1462
|
return files;
|
|
877
1463
|
}
|
|
1464
|
+
const agentDefinitionInspectionDirectories = new WeakMap;
|
|
1465
|
+
function rememberAgentDefinitionInspection(inspection, directories) {
|
|
1466
|
+
agentDefinitionInspectionDirectories.set(inspection, [...new Set([...directories].map((directory) => path.resolve(directory)))]);
|
|
1467
|
+
return inspection;
|
|
1468
|
+
}
|
|
1469
|
+
function inspectedAgentDefinitionDirectories(inspection, root) {
|
|
1470
|
+
return agentDefinitionInspectionDirectories.get(inspection) ?? [path.resolve(root)];
|
|
1471
|
+
}
|
|
1472
|
+
const DEFAULT_AGENT_DEFINITION_INSPECTION_FS = {
|
|
1473
|
+
existsSync: fs.existsSync,
|
|
1474
|
+
realpathSync: fs.realpathSync,
|
|
1475
|
+
statSync: fs.statSync,
|
|
1476
|
+
readdirSync: (dir) => fs.readdirSync(dir, { withFileTypes: true })
|
|
1477
|
+
};
|
|
1478
|
+
export function inspectAgentDefinitionDirectory(dir, operations = DEFAULT_AGENT_DEFINITION_INSPECTION_FS) {
|
|
1479
|
+
const root = path.resolve(dir);
|
|
1480
|
+
try {
|
|
1481
|
+
if (!operations.existsSync(root))
|
|
1482
|
+
return rememberAgentDefinitionInspection({ files: [], state: "absent" }, [root]);
|
|
1483
|
+
if (!operations.statSync(root).isDirectory())
|
|
1484
|
+
return rememberAgentDefinitionInspection({ files: [], state: "not-directory" }, [root]);
|
|
1485
|
+
} catch {
|
|
1486
|
+
return rememberAgentDefinitionInspection({ files: [], state: "unreadable" }, [root]);
|
|
1487
|
+
}
|
|
1488
|
+
const files = [];
|
|
1489
|
+
let unreadable = false;
|
|
1490
|
+
const visitedDirectories = new Set;
|
|
1491
|
+
const inspectedDirectories = new Set;
|
|
1492
|
+
const visit = (current) => {
|
|
1493
|
+
inspectedDirectories.add(path.resolve(current));
|
|
1494
|
+
let realDir;
|
|
1495
|
+
try {
|
|
1496
|
+
realDir = operations.realpathSync?.(current) ?? path.resolve(current);
|
|
1497
|
+
} catch {
|
|
1498
|
+
unreadable = true;
|
|
1499
|
+
return;
|
|
1500
|
+
}
|
|
1501
|
+
if (visitedDirectories.has(realDir))
|
|
1502
|
+
return;
|
|
1503
|
+
visitedDirectories.add(realDir);
|
|
1504
|
+
let entries;
|
|
1505
|
+
try {
|
|
1506
|
+
entries = operations.readdirSync(current).sort((a, b) => a.name.localeCompare(b.name));
|
|
1507
|
+
} catch {
|
|
1508
|
+
unreadable = true;
|
|
1509
|
+
return;
|
|
1510
|
+
}
|
|
1511
|
+
for (const entry of entries) {
|
|
1512
|
+
const filePath = path.join(current, entry.name);
|
|
1513
|
+
let isDirectory = entry.isDirectory();
|
|
1514
|
+
if (entry.isSymbolicLink()) {
|
|
1515
|
+
try {
|
|
1516
|
+
isDirectory = operations.statSync(filePath).isDirectory();
|
|
1517
|
+
} catch {
|
|
1518
|
+
isDirectory = false;
|
|
1519
|
+
}
|
|
1520
|
+
}
|
|
1521
|
+
if (isDirectory) {
|
|
1522
|
+
if (!shouldPruneDiscoveryDir(root, filePath, entry.name))
|
|
1523
|
+
visit(filePath);
|
|
1524
|
+
continue;
|
|
1525
|
+
}
|
|
1526
|
+
if ((entry.isFile() || entry.isSymbolicLink()) && entry.name.endsWith(".md") && !entry.name.endsWith(".chain.md") && !isLegacyAgentSkillPath(root, filePath))
|
|
1527
|
+
files.push(filePath);
|
|
1528
|
+
}
|
|
1529
|
+
};
|
|
1530
|
+
visit(root);
|
|
1531
|
+
return rememberAgentDefinitionInspection({ files, state: unreadable ? "unreadable" : files.length ? "candidates" : "empty" }, inspectedDirectories);
|
|
1532
|
+
}
|
|
878
1533
|
function isLegacyAgentSkillPath(rootDir, filePath) {
|
|
879
1534
|
const relative = path.relative(rootDir, filePath);
|
|
880
1535
|
const parts = relative.split(path.sep).map((part) => part.toLowerCase());
|
|
@@ -883,110 +1538,327 @@ function isLegacyAgentSkillPath(rootDir, filePath) {
|
|
|
883
1538
|
}
|
|
884
1539
|
return parts.some((part, index) => part === ".agents" && parts[index + 1] === "skills");
|
|
885
1540
|
}
|
|
886
|
-
function
|
|
887
|
-
|
|
888
|
-
|
|
1541
|
+
function isJsonSerializable(value) {
|
|
1542
|
+
if (value === null || typeof value === "string" || typeof value === "boolean")
|
|
1543
|
+
return true;
|
|
1544
|
+
if (typeof value === "number")
|
|
1545
|
+
return Number.isFinite(value);
|
|
1546
|
+
if (Array.isArray(value))
|
|
1547
|
+
return value.every(isJsonSerializable);
|
|
1548
|
+
if (value && typeof value === "object")
|
|
1549
|
+
return Object.values(value).every(isJsonSerializable);
|
|
1550
|
+
return false;
|
|
1551
|
+
}
|
|
1552
|
+
function parseAgentRunnerFrontmatter(raw, agentName) {
|
|
1553
|
+
if (raw === undefined || !raw.trim())
|
|
1554
|
+
return;
|
|
1555
|
+
let parsed;
|
|
1556
|
+
try {
|
|
1557
|
+
parsed = parseYaml(raw);
|
|
1558
|
+
} catch (error) {
|
|
1559
|
+
throw new Error(`Agent '${agentName}' has invalid runner frontmatter: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
|
|
1560
|
+
}
|
|
1561
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
1562
|
+
throw new Error(`Agent '${agentName}' has invalid runner frontmatter; expected an object.`);
|
|
1563
|
+
}
|
|
1564
|
+
const runner = parsed;
|
|
1565
|
+
if (runner.type === "dm") {
|
|
1566
|
+
if (Object.keys(runner).some((key) => key !== "type"))
|
|
1567
|
+
throw new Error(`Agent '${agentName}' has invalid DM runner frontmatter; only 'type' is supported.`);
|
|
1568
|
+
return { type: "dm" };
|
|
1569
|
+
}
|
|
1570
|
+
if (runner.type === "external-job") {
|
|
1571
|
+
if (typeof runner.provider !== "string" || !runner.provider.trim() || runner.provider.trim() !== runner.provider) {
|
|
1572
|
+
throw new Error(`Agent '${agentName}' external-job runner requires a non-empty trimmed provider string.`);
|
|
1573
|
+
}
|
|
1574
|
+
if (runner.options !== undefined && (!runner.options || typeof runner.options !== "object" || Array.isArray(runner.options) || !isJsonSerializable(runner.options))) {
|
|
1575
|
+
throw new Error(`Agent '${agentName}' external-job runner options must be a JSON-serializable object.`);
|
|
1576
|
+
}
|
|
1577
|
+
const supported = new Set(["type", "provider", "options"]);
|
|
1578
|
+
const unknown = Object.keys(runner).filter((key) => !supported.has(key));
|
|
1579
|
+
if (unknown.length > 0)
|
|
1580
|
+
throw new Error(`Agent '${agentName}' external-job runner has unsupported fields: ${unknown.join(", ")}.`);
|
|
1581
|
+
return {
|
|
1582
|
+
type: "external-job",
|
|
1583
|
+
provider: runner.provider,
|
|
1584
|
+
...runner.options ? { options: runner.options } : {}
|
|
1585
|
+
};
|
|
1586
|
+
}
|
|
1587
|
+
if (runner.type !== "external-cli") {
|
|
1588
|
+
throw new Error(`Agent '${agentName}' has invalid runner.type; expected 'dm', 'external-cli', or 'external-job'.`);
|
|
1589
|
+
}
|
|
1590
|
+
if (typeof runner.command !== "string" || !runner.command.trim()) {
|
|
1591
|
+
throw new Error(`Agent '${agentName}' external-cli runner requires a non-empty command string.`);
|
|
1592
|
+
}
|
|
1593
|
+
if (runner.args !== undefined && (!Array.isArray(runner.args) || runner.args.some((arg) => typeof arg !== "string"))) {
|
|
1594
|
+
throw new Error(`Agent '${agentName}' external-cli runner args must be an array of strings.`);
|
|
1595
|
+
}
|
|
1596
|
+
if (runner.adapter !== undefined && !isCodeOwnedExternalCliAdapterId(runner.adapter))
|
|
1597
|
+
throw new Error(`Agent '${agentName}' external-cli runner adapter must be ${CODE_OWNED_EXTERNAL_CLI_ADAPTER_LABEL}.`);
|
|
1598
|
+
if (runner.adapter !== undefined && Array.isArray(runner.args) && runner.args.length > 0)
|
|
1599
|
+
throw new Error(`Agent '${agentName}' ${runner.adapter} adapter owns its argv; runner args are not supported.`);
|
|
1600
|
+
if (runner.promptDelivery !== undefined && runner.promptDelivery !== "stdin") {
|
|
1601
|
+
throw new Error(`Agent '${agentName}' external-cli runner promptDelivery must be 'stdin'.`);
|
|
1602
|
+
}
|
|
1603
|
+
const capabilities = parseExternalCliCapabilityNarrowing(runner.capabilities, `Agent '${agentName}' external-cli runner capabilities`);
|
|
1604
|
+
const supported = new Set(["type", "adapter", "command", "args", "promptDelivery", "capabilities"]);
|
|
1605
|
+
const unknown = Object.keys(runner).filter((key) => !supported.has(key));
|
|
1606
|
+
if (unknown.length > 0)
|
|
1607
|
+
throw new Error(`Agent '${agentName}' external-cli runner has unsupported fields: ${unknown.join(", ")}.`);
|
|
1608
|
+
const runnerArgs = Array.isArray(runner.args) ? runner.args.filter((arg) => typeof arg === "string") : undefined;
|
|
1609
|
+
return {
|
|
1610
|
+
type: "external-cli",
|
|
1611
|
+
...isCodeOwnedExternalCliAdapterId(runner.adapter) ? { adapter: runner.adapter } : {},
|
|
1612
|
+
command: runner.command.trim(),
|
|
1613
|
+
...runnerArgs?.length ? { args: runnerArgs } : {},
|
|
1614
|
+
...runner.promptDelivery ? { promptDelivery: "stdin" } : {},
|
|
1615
|
+
...capabilities ? { capabilities } : {}
|
|
1616
|
+
};
|
|
1617
|
+
}
|
|
1618
|
+
function validateExternalRunnerProfile(frontmatter, agentName, runner) {
|
|
1619
|
+
if (runner?.type !== "external-cli" && runner?.type !== "external-job")
|
|
1620
|
+
return;
|
|
1621
|
+
const unsupported = ["tools", "allowNestedSubagents", "model", "fallbackModels", "thinking", "extensions", "subagentOnlyExtensions", "mutationTools", "maxSubagentDepth", "completionGuard", "skills", "skill", "skillPath", "toolBudget", "permission", "permissions"].filter((field) => frontmatter[field] !== undefined);
|
|
1622
|
+
if (unsupported.length > 0) {
|
|
1623
|
+
throw new Error(`Agent '${agentName}' uses runner.type='${runner.type}' and declares unsupported DM-only fields: ${unsupported.join(", ")}.`);
|
|
1624
|
+
}
|
|
1625
|
+
}
|
|
1626
|
+
function parseAgentAcceptanceFrontmatter(raw, agentName) {
|
|
1627
|
+
if (raw === undefined || !raw.trim())
|
|
1628
|
+
return;
|
|
1629
|
+
let parsed;
|
|
1630
|
+
try {
|
|
1631
|
+
parsed = parseYaml(raw);
|
|
1632
|
+
} catch (error) {
|
|
1633
|
+
throw new Error(`Agent '${agentName}' has invalid acceptance frontmatter: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
|
|
1634
|
+
}
|
|
1635
|
+
const errors = validateAcceptanceInput(parsed, `Agent '${agentName}' acceptance frontmatter`);
|
|
1636
|
+
if (errors.length > 0)
|
|
1637
|
+
throw new Error(errors.join(" "));
|
|
1638
|
+
return parsed;
|
|
1639
|
+
}
|
|
1640
|
+
function readAgentDefinitionFiles(dir, inspection = inspectAgentDefinitionDirectory(dir)) {
|
|
1641
|
+
const files = [];
|
|
1642
|
+
for (const filePath of inspection.files) {
|
|
889
1643
|
if (isLegacyAgentSkillPath(dir, filePath)) {
|
|
890
1644
|
continue;
|
|
891
1645
|
}
|
|
892
|
-
let content;
|
|
893
1646
|
try {
|
|
894
|
-
content
|
|
1647
|
+
files.push({ filePath, content: fs.readFileSync(filePath, "utf-8") });
|
|
895
1648
|
} catch {
|
|
896
1649
|
continue;
|
|
897
1650
|
}
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
1651
|
+
}
|
|
1652
|
+
return files;
|
|
1653
|
+
}
|
|
1654
|
+
function resolveAgentRelativeExtensionPaths(paths, agentFilePath) {
|
|
1655
|
+
if (paths === undefined)
|
|
1656
|
+
return;
|
|
1657
|
+
const baseDir = path.dirname(agentFilePath);
|
|
1658
|
+
return paths.map((entry) => {
|
|
1659
|
+
const trimmed = entry.trim();
|
|
1660
|
+
if (trimmed === "." || trimmed === ".." || trimmed.startsWith("./") || trimmed.startsWith("../")) {
|
|
1661
|
+
return path.resolve(baseDir, trimmed);
|
|
901
1662
|
}
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
1663
|
+
return entry;
|
|
1664
|
+
});
|
|
1665
|
+
}
|
|
1666
|
+
function loadAgentsFromDefinitionFiles(files, source, discoveryPriority, packageSource) {
|
|
1667
|
+
const agents = [];
|
|
1668
|
+
const diagnostics = [];
|
|
1669
|
+
for (const { filePath, content } of files) {
|
|
1670
|
+
let name;
|
|
1671
|
+
let runtimeName;
|
|
1672
|
+
let packageSpecified = false;
|
|
1673
|
+
try {
|
|
1674
|
+
const { frontmatter, body } = parseFrontmatter(content);
|
|
1675
|
+
if (!frontmatter.name || !frontmatter.description) {
|
|
1676
|
+
continue;
|
|
1677
|
+
}
|
|
1678
|
+
const localName = frontmatter.name;
|
|
1679
|
+
name = localName;
|
|
1680
|
+
const parsedPackage = parsePackageName(frontmatter.package, `Agent '${localName}' package`);
|
|
1681
|
+
packageSpecified = parsedPackage.packageName !== undefined || parsedPackage.error !== undefined;
|
|
1682
|
+
if (parsedPackage.error)
|
|
1683
|
+
throw new Error(parsedPackage.error);
|
|
1684
|
+
const packageName = parsedPackage.packageName;
|
|
1685
|
+
runtimeName = buildRuntimeName(localName, packageName);
|
|
1686
|
+
const runner = parseAgentRunnerFrontmatter(frontmatter.runner, localName);
|
|
1687
|
+
validateExternalRunnerProfile(frontmatter, localName, runner);
|
|
1688
|
+
const rawTools = parseFrontmatterList(frontmatter.tools);
|
|
1689
|
+
const parsedTools = splitToolList(rawTools);
|
|
1690
|
+
const tools = parsedTools.tools ?? [];
|
|
1691
|
+
const mcpDirectTools = parsedTools.mcpDirectTools ?? [];
|
|
1692
|
+
const defaultReads = parseFrontmatterList(frontmatter.defaultReads);
|
|
1693
|
+
const aliases = normalizeAgentAliases(parseFrontmatterList(frontmatter.aliases ?? frontmatter.alias), runtimeName);
|
|
1694
|
+
const profileError = validateCodeOwnedProfileRunner({ name: runtimeName, localName, aliases, runner });
|
|
1695
|
+
if (profileError)
|
|
1696
|
+
throw new Error(profileError);
|
|
1697
|
+
const skillStr = frontmatter.skill || frontmatter.skills;
|
|
1698
|
+
const skills = parseFrontmatterList(skillStr);
|
|
1699
|
+
const skillPath = parseFrontmatterList(frontmatter.skillPath);
|
|
1700
|
+
const fallbackModels = parseFrontmatterList(frontmatter.fallbackModels);
|
|
1701
|
+
const systemPromptMode = frontmatter.systemPromptMode === "replace" ? "replace" : frontmatter.systemPromptMode === "append" ? "append" : defaultSystemPromptMode(localName);
|
|
1702
|
+
const inheritProjectContext = frontmatter.inheritProjectContext === "true" ? true : frontmatter.inheritProjectContext === "false" ? false : defaultInheritProjectContext(localName);
|
|
1703
|
+
const inheritGlobalContext = frontmatter.inheritGlobalContext === "true";
|
|
1704
|
+
const inheritSkills = frontmatter.inheritSkills === "true" ? true : frontmatter.inheritSkills === "false" ? false : defaultInheritSkills();
|
|
1705
|
+
const defaultContext = frontmatter.defaultContext === "fork" ? "fork" : frontmatter.defaultContext === "fresh" ? "fresh" : undefined;
|
|
1706
|
+
let defaultAsync;
|
|
1707
|
+
if (frontmatter.async !== undefined) {
|
|
1708
|
+
if (frontmatter.async === "true")
|
|
1709
|
+
defaultAsync = true;
|
|
1710
|
+
else if (frontmatter.async === "false")
|
|
1711
|
+
defaultAsync = false;
|
|
1712
|
+
else
|
|
1713
|
+
throw new Error(`Agent '${localName}' has invalid async frontmatter; expected true or false.`);
|
|
1714
|
+
}
|
|
1715
|
+
let defaultTimeoutMs;
|
|
1716
|
+
if (frontmatter.timeoutMs !== undefined) {
|
|
1717
|
+
const parsed = Number(frontmatter.timeoutMs);
|
|
1718
|
+
if (!Number.isInteger(parsed) || parsed <= 0) {
|
|
1719
|
+
throw new Error(`Agent '${localName}' has invalid timeoutMs frontmatter; expected a positive integer.`);
|
|
917
1720
|
}
|
|
1721
|
+
defaultTimeoutMs = parsed;
|
|
918
1722
|
}
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
subagentOnlyExtensions = frontmatter.subagentOnlyExtensions.split(",").map((e) => e.trim()).filter(Boolean);
|
|
935
|
-
}
|
|
936
|
-
const extraFields = {};
|
|
937
|
-
for (const [key, value] of Object.entries(frontmatter)) {
|
|
938
|
-
if (!KNOWN_FIELDS.has(key))
|
|
939
|
-
extraFields[key] = value;
|
|
940
|
-
}
|
|
941
|
-
const parsedMaxSubagentDepth = Number(frontmatter.maxSubagentDepth);
|
|
942
|
-
let toolBudget;
|
|
943
|
-
if (frontmatter.toolBudget !== undefined && frontmatter.toolBudget.trim()) {
|
|
944
|
-
const parsed = JSON.parse(frontmatter.toolBudget);
|
|
945
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
946
|
-
throw new Error(`Agent '${localName}' has invalid toolBudget frontmatter; expected a JSON object.`);
|
|
1723
|
+
let defaultToolTimeoutMs;
|
|
1724
|
+
if (frontmatter.toolTimeoutMs !== undefined) {
|
|
1725
|
+
const parsed = Number(frontmatter.toolTimeoutMs);
|
|
1726
|
+
if (!Number.isInteger(parsed) || parsed <= 0 || parsed > 2147483647) {
|
|
1727
|
+
throw new Error(`Agent '${localName}' has invalid toolTimeoutMs frontmatter; expected a positive integer no larger than 2147483647.`);
|
|
1728
|
+
}
|
|
1729
|
+
defaultToolTimeoutMs = parsed;
|
|
1730
|
+
}
|
|
1731
|
+
const defaultAcceptance = parseAgentAcceptanceFrontmatter(frontmatter.acceptance, localName);
|
|
1732
|
+
let outputMode;
|
|
1733
|
+
if (frontmatter.outputMode !== undefined) {
|
|
1734
|
+
if (frontmatter.outputMode === "inline" || frontmatter.outputMode === "file-only")
|
|
1735
|
+
outputMode = frontmatter.outputMode;
|
|
1736
|
+
else
|
|
1737
|
+
throw new Error(`Agent '${localName}' has invalid outputMode frontmatter; expected 'inline' or 'file-only'.`);
|
|
947
1738
|
}
|
|
948
|
-
|
|
1739
|
+
let acceptanceRole;
|
|
1740
|
+
if (frontmatter.acceptanceRole !== undefined && frontmatter.acceptanceRole.trim()) {
|
|
1741
|
+
if (frontmatter.acceptanceRole === "read-only" || frontmatter.acceptanceRole === "writer")
|
|
1742
|
+
acceptanceRole = frontmatter.acceptanceRole;
|
|
1743
|
+
else
|
|
1744
|
+
throw new Error(`Agent '${localName}' has invalid acceptanceRole frontmatter; expected 'read-only' or 'writer'.`);
|
|
1745
|
+
}
|
|
1746
|
+
const extensions = resolveAgentRelativeExtensionPaths(parseFrontmatterList(frontmatter.extensions), filePath);
|
|
1747
|
+
const subagentOnlyExtensions = resolveAgentRelativeExtensionPaths(parseFrontmatterList(frontmatter.subagentOnlyExtensions), filePath);
|
|
1748
|
+
const mutationTools = parseFrontmatterList(frontmatter.mutationTools);
|
|
1749
|
+
let fast;
|
|
1750
|
+
if (frontmatter.fast !== undefined) {
|
|
1751
|
+
if (frontmatter.fast === "true")
|
|
1752
|
+
fast = true;
|
|
1753
|
+
else if (frontmatter.fast === "false")
|
|
1754
|
+
fast = false;
|
|
1755
|
+
else
|
|
1756
|
+
throw new Error(`Agent '${localName}' has invalid fast frontmatter; expected true or false.`);
|
|
1757
|
+
}
|
|
1758
|
+
let allowNestedSubagents;
|
|
1759
|
+
if (frontmatter.allowNestedSubagents !== undefined) {
|
|
1760
|
+
if (frontmatter.allowNestedSubagents === "true")
|
|
1761
|
+
allowNestedSubagents = true;
|
|
1762
|
+
else if (frontmatter.allowNestedSubagents === "false")
|
|
1763
|
+
allowNestedSubagents = false;
|
|
1764
|
+
else
|
|
1765
|
+
throw new Error(`Agent '${localName}' has invalid allowNestedSubagents frontmatter; expected true or false.`);
|
|
1766
|
+
}
|
|
1767
|
+
const extraFields = {};
|
|
1768
|
+
for (const [key, value] of Object.entries(frontmatter)) {
|
|
1769
|
+
if (!KNOWN_FIELDS.has(key))
|
|
1770
|
+
extraFields[key] = value;
|
|
1771
|
+
}
|
|
1772
|
+
const parsedMaxSubagentDepth = Number(frontmatter.maxSubagentDepth);
|
|
1773
|
+
if (frontmatter.permission !== undefined && frontmatter.permissions !== undefined) {
|
|
1774
|
+
throw new Error(`Agent '${localName}' cannot declare both permission and permissions frontmatter.`);
|
|
1775
|
+
}
|
|
1776
|
+
const permissionSource = frontmatter.permissions ?? frontmatter.permission;
|
|
1777
|
+
const permissions = permissionSource?.trim() ? validatePermissionRules(parseYaml(permissionSource), `Agent '${localName}' permissions`) : undefined;
|
|
1778
|
+
let toolBudget;
|
|
1779
|
+
if (frontmatter.toolBudget !== undefined && frontmatter.toolBudget.trim()) {
|
|
1780
|
+
const parsed = JSON.parse(frontmatter.toolBudget);
|
|
1781
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
1782
|
+
throw new Error(`Agent '${localName}' has invalid toolBudget frontmatter; expected a JSON object.`);
|
|
1783
|
+
}
|
|
1784
|
+
toolBudget = parsed;
|
|
1785
|
+
}
|
|
1786
|
+
const completionGuard = frontmatter.completionGuard === "false" ? false : frontmatter.completionGuard === "true" ? true : undefined;
|
|
1787
|
+
const maxSubagentDepth = Number.isInteger(parsedMaxSubagentDepth) && parsedMaxSubagentDepth >= 0 ? parsedMaxSubagentDepth : undefined;
|
|
1788
|
+
const memory = parseMemoryFrontmatter(frontmatter.memory);
|
|
1789
|
+
const agent = {
|
|
1790
|
+
name: runtimeName,
|
|
1791
|
+
...runner !== undefined ? { runner } : {},
|
|
1792
|
+
localName,
|
|
1793
|
+
...packageName !== undefined ? { packageName } : {},
|
|
1794
|
+
...packageSource?.packageName ? { packageSourceName: packageSource.packageName } : {},
|
|
1795
|
+
...packageSource?.packageVersion ? { packageSourceVersion: packageSource.packageVersion } : {},
|
|
1796
|
+
...packageSource?.packageRoot ? { packageSourceRoot: packageSource.packageRoot } : {},
|
|
1797
|
+
description: frontmatter.description,
|
|
1798
|
+
...aliases !== undefined ? { aliases } : {},
|
|
1799
|
+
...rawTools !== undefined ? { tools } : {},
|
|
1800
|
+
...allowNestedSubagents !== undefined ? { allowNestedSubagents } : {},
|
|
1801
|
+
...mcpDirectTools.length > 0 ? { mcpDirectTools } : {},
|
|
1802
|
+
...frontmatter.model !== undefined ? { model: frontmatter.model } : {},
|
|
1803
|
+
...fallbackModels?.length ? { fallbackModels } : {},
|
|
1804
|
+
...fast !== undefined ? { fast } : {},
|
|
1805
|
+
...frontmatter.thinking !== undefined ? { thinking: frontmatter.thinking === "false" ? false : frontmatter.thinking } : {},
|
|
1806
|
+
systemPromptMode,
|
|
1807
|
+
inheritProjectContext,
|
|
1808
|
+
inheritGlobalContext,
|
|
1809
|
+
inheritSkills,
|
|
1810
|
+
...defaultContext !== undefined ? { defaultContext } : {},
|
|
1811
|
+
...defaultAsync !== undefined ? { defaultAsync } : {},
|
|
1812
|
+
...defaultTimeoutMs !== undefined ? { defaultTimeoutMs } : {},
|
|
1813
|
+
...defaultToolTimeoutMs !== undefined ? { defaultToolTimeoutMs } : {},
|
|
1814
|
+
...defaultAcceptance !== undefined ? { defaultAcceptance } : {},
|
|
1815
|
+
...acceptanceRole !== undefined ? { acceptanceRole } : {},
|
|
1816
|
+
systemPrompt: body,
|
|
1817
|
+
source,
|
|
1818
|
+
filePath,
|
|
1819
|
+
...discoveryPriority !== undefined ? { discoveryPriority } : {},
|
|
1820
|
+
...skills?.length ? { skills } : {},
|
|
1821
|
+
...skillPath?.length ? { skillPath } : {},
|
|
1822
|
+
...extensions !== undefined ? { extensions } : {},
|
|
1823
|
+
...subagentOnlyExtensions !== undefined ? { subagentOnlyExtensions } : {},
|
|
1824
|
+
...mutationTools?.length ? { mutationTools } : {},
|
|
1825
|
+
...frontmatter.output !== undefined ? { output: frontmatter.output } : {},
|
|
1826
|
+
...outputMode !== undefined ? { outputMode } : {},
|
|
1827
|
+
...defaultReads?.length ? { defaultReads } : {},
|
|
1828
|
+
defaultProgress: frontmatter.defaultProgress === "true",
|
|
1829
|
+
interactive: frontmatter.interactive === "true",
|
|
1830
|
+
...maxSubagentDepth !== undefined ? { maxSubagentDepth } : {},
|
|
1831
|
+
...completionGuard !== undefined ? { completionGuard } : {},
|
|
1832
|
+
...toolBudget !== undefined ? { toolBudget } : {},
|
|
1833
|
+
...permissions !== undefined ? { permissions } : {},
|
|
1834
|
+
...memory !== undefined ? { memory } : {},
|
|
1835
|
+
...Object.keys(extraFields).length > 0 ? { extraFields } : {}
|
|
1836
|
+
};
|
|
1837
|
+
agentFrontmatterFields.set(agent, new Set(Object.keys(frontmatter)));
|
|
1838
|
+
agents.push(agent);
|
|
1839
|
+
} catch (error) {
|
|
1840
|
+
diagnostics.push({ source, filePath, ...name ? { name } : {}, ...runtimeName && runtimeName !== name ? { runtimeName } : {}, ...packageSpecified ? { packageSpecified: true } : {}, ...discoveryPriority !== undefined ? { discoveryPriority } : {}, error: error instanceof Error ? error.message : String(error) });
|
|
949
1841
|
}
|
|
950
|
-
const completionGuard = frontmatter.completionGuard === "false" ? false : frontmatter.completionGuard === "true" ? true : undefined;
|
|
951
|
-
const agent = {
|
|
952
|
-
name: runtimeName,
|
|
953
|
-
localName,
|
|
954
|
-
packageName,
|
|
955
|
-
description: frontmatter.description,
|
|
956
|
-
tools: tools.length > 0 ? tools : undefined,
|
|
957
|
-
mcpDirectTools: mcpDirectTools.length > 0 ? mcpDirectTools : undefined,
|
|
958
|
-
model: frontmatter.model,
|
|
959
|
-
fallbackModels: fallbackModels && fallbackModels.length > 0 ? fallbackModels : undefined,
|
|
960
|
-
thinking: frontmatter.thinking,
|
|
961
|
-
systemPromptMode,
|
|
962
|
-
inheritProjectContext,
|
|
963
|
-
inheritSkills,
|
|
964
|
-
defaultContext,
|
|
965
|
-
systemPrompt: body,
|
|
966
|
-
source,
|
|
967
|
-
filePath,
|
|
968
|
-
skills: skills && skills.length > 0 ? skills : undefined,
|
|
969
|
-
extensions,
|
|
970
|
-
subagentOnlyExtensions,
|
|
971
|
-
output: frontmatter.output,
|
|
972
|
-
defaultReads: defaultReads && defaultReads.length > 0 ? defaultReads : undefined,
|
|
973
|
-
defaultProgress: frontmatter.defaultProgress === "true",
|
|
974
|
-
interactive: frontmatter.interactive === "true",
|
|
975
|
-
maxSubagentDepth: Number.isInteger(parsedMaxSubagentDepth) && parsedMaxSubagentDepth >= 0 ? parsedMaxSubagentDepth : undefined,
|
|
976
|
-
completionGuard,
|
|
977
|
-
toolBudget,
|
|
978
|
-
memory: parseMemoryFrontmatter(frontmatter.memory),
|
|
979
|
-
extraFields: Object.keys(extraFields).length > 0 ? extraFields : undefined
|
|
980
|
-
};
|
|
981
|
-
agentFrontmatterFields.set(agent, new Set(Object.keys(frontmatter)));
|
|
982
|
-
agents.push(agent);
|
|
983
1842
|
}
|
|
984
|
-
return agents;
|
|
1843
|
+
return { agents, diagnostics };
|
|
1844
|
+
}
|
|
1845
|
+
function loadAgentsFromDir(dir, source, discoveryPriority, packageSource, inspection = inspectAgentDefinitionDirectory(dir)) {
|
|
1846
|
+
return loadAgentsFromDefinitionFiles(readAgentDefinitionFiles(dir, inspection), source, discoveryPriority, packageSource);
|
|
1847
|
+
}
|
|
1848
|
+
function reportAgentDefinitionDirectory(source, dir, inspection) {
|
|
1849
|
+
return {
|
|
1850
|
+
source,
|
|
1851
|
+
path: path.resolve(dir),
|
|
1852
|
+
state: inspection.state,
|
|
1853
|
+
...inspection.state === "candidates" ? { candidateCount: inspection.files.length } : {}
|
|
1854
|
+
};
|
|
985
1855
|
}
|
|
986
1856
|
function loadChainsFromDir(dir, source) {
|
|
987
1857
|
const chains = new Map;
|
|
988
1858
|
const diagnostics = [];
|
|
989
|
-
|
|
1859
|
+
const directories = new Set;
|
|
1860
|
+
const files = listFilesRecursive(dir, (fileName) => fileName.endsWith(".chain.md") || fileName.endsWith(".chain.json"), dir, new Set, directories);
|
|
1861
|
+
for (const filePath of files) {
|
|
990
1862
|
let content;
|
|
991
1863
|
try {
|
|
992
1864
|
content = fs.readFileSync(filePath, "utf-8");
|
|
@@ -1004,7 +1876,7 @@ function loadChainsFromDir(dir, source) {
|
|
|
1004
1876
|
continue;
|
|
1005
1877
|
}
|
|
1006
1878
|
}
|
|
1007
|
-
return { chains: Array.from(chains.values()), diagnostics };
|
|
1879
|
+
return { chains: Array.from(chains.values()), diagnostics, files, directories: [...directories] };
|
|
1008
1880
|
}
|
|
1009
1881
|
function isDirectory(p) {
|
|
1010
1882
|
try {
|
|
@@ -1014,23 +1886,21 @@ function isDirectory(p) {
|
|
|
1014
1886
|
}
|
|
1015
1887
|
}
|
|
1016
1888
|
function resolveNearestProjectAgentDirs(cwd) {
|
|
1017
|
-
const projectRoot =
|
|
1889
|
+
const projectRoot = findConfiguredProjectRoot(cwd);
|
|
1018
1890
|
if (!projectRoot)
|
|
1019
|
-
return { readDirs: [], preferredDir: null };
|
|
1891
|
+
return { readDirs: [], candidateDirs: [], preferredDir: null };
|
|
1020
1892
|
const legacyDir = path.join(projectRoot, ".agents");
|
|
1021
1893
|
const preferredDir = path.join(getProjectConfigDir(projectRoot), "agents");
|
|
1894
|
+
const candidateDirs = [legacyDir, preferredDir];
|
|
1022
1895
|
const readDirs = [];
|
|
1023
1896
|
if (isDirectory(legacyDir))
|
|
1024
1897
|
readDirs.push(legacyDir);
|
|
1025
1898
|
if (isDirectory(preferredDir))
|
|
1026
1899
|
readDirs.push(preferredDir);
|
|
1027
|
-
return {
|
|
1028
|
-
readDirs,
|
|
1029
|
-
preferredDir
|
|
1030
|
-
};
|
|
1900
|
+
return { readDirs, candidateDirs, preferredDir };
|
|
1031
1901
|
}
|
|
1032
1902
|
function resolveNearestProjectChainDirs(cwd) {
|
|
1033
|
-
const projectRoot =
|
|
1903
|
+
const projectRoot = findConfiguredProjectRoot(cwd);
|
|
1034
1904
|
if (!projectRoot)
|
|
1035
1905
|
return { readDirs: [], preferredDir: null };
|
|
1036
1906
|
const preferredDir = path.join(getProjectConfigDir(projectRoot), "chains");
|
|
@@ -1040,6 +1910,8 @@ function resolveNearestProjectChainDirs(cwd) {
|
|
|
1040
1910
|
};
|
|
1041
1911
|
}
|
|
1042
1912
|
const BUILTIN_AGENTS_DIR = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..", "..", "agents");
|
|
1913
|
+
const BUILTIN_AGENT_DEFINITION_INSPECTION = inspectAgentDefinitionDirectory(BUILTIN_AGENTS_DIR);
|
|
1914
|
+
const BUILTIN_AGENT_DEFINITION_FILES = readAgentDefinitionFiles(BUILTIN_AGENTS_DIR, BUILTIN_AGENT_DEFINITION_INSPECTION);
|
|
1043
1915
|
export const EXTRA_AGENT_DIRS_ENV = "DM_SUBAGENT_EXTRA_AGENT_DIRS";
|
|
1044
1916
|
function extraUserAgentDirs() {
|
|
1045
1917
|
const raw = process.env[EXTRA_AGENT_DIRS_ENV];
|
|
@@ -1047,93 +1919,369 @@ function extraUserAgentDirs() {
|
|
|
1047
1919
|
return [];
|
|
1048
1920
|
return raw.split(path.delimiter).map((dir) => dir.trim()).filter((dir) => dir.length > 0);
|
|
1049
1921
|
}
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
const
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
const
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1922
|
+
const agentDiscoveryCache = new Map;
|
|
1923
|
+
function isPathWithin(root, candidate) {
|
|
1924
|
+
const relative = path.relative(path.resolve(root), path.resolve(candidate));
|
|
1925
|
+
return relative === "" || !relative.startsWith("..") && !path.isAbsolute(relative);
|
|
1926
|
+
}
|
|
1927
|
+
function addDirectoryWatchPaths(paths, root, files, directories = []) {
|
|
1928
|
+
const resolvedRoot = path.resolve(root);
|
|
1929
|
+
paths.add(resolvedRoot);
|
|
1930
|
+
for (const directory of directories) {
|
|
1931
|
+
if (isPathWithin(resolvedRoot, directory))
|
|
1932
|
+
paths.add(path.resolve(directory));
|
|
1933
|
+
}
|
|
1934
|
+
for (const file of files) {
|
|
1935
|
+
paths.add(path.resolve(file));
|
|
1936
|
+
let current = path.resolve(path.dirname(file));
|
|
1937
|
+
while (isPathWithin(resolvedRoot, current)) {
|
|
1938
|
+
paths.add(current);
|
|
1939
|
+
if (current === resolvedRoot)
|
|
1940
|
+
break;
|
|
1941
|
+
current = path.dirname(current);
|
|
1942
|
+
}
|
|
1943
|
+
}
|
|
1944
|
+
}
|
|
1945
|
+
function watchPathSignature(filePath) {
|
|
1946
|
+
try {
|
|
1947
|
+
const stat = fs.statSync(filePath);
|
|
1948
|
+
if (stat.isDirectory()) {
|
|
1949
|
+
const entries = fs.readdirSync(filePath, { withFileTypes: true }).sort((left, right) => left.name.localeCompare(right.name)).map((entry) => `${entry.name}:${entry.isDirectory() ? "d" : entry.isSymbolicLink() ? "l" : "f"}`).join("|");
|
|
1950
|
+
return `directory:${entries}`;
|
|
1951
|
+
}
|
|
1952
|
+
return `file:${stat.size}:${stat.mtimeMs}`;
|
|
1953
|
+
} catch {
|
|
1954
|
+
return "missing";
|
|
1955
|
+
}
|
|
1956
|
+
}
|
|
1957
|
+
function discoveryFingerprint(paths) {
|
|
1958
|
+
return [...new Set(paths)].sort((left, right) => left.localeCompare(right)).map((filePath) => `${filePath}:${watchPathSignature(filePath)}`).join(`
|
|
1959
|
+
`);
|
|
1960
|
+
}
|
|
1961
|
+
function discoveryCacheKey(cwd, preferredModelProvider) {
|
|
1962
|
+
return JSON.stringify([
|
|
1963
|
+
path.resolve(cwd),
|
|
1964
|
+
preferredModelProvider ?? null,
|
|
1965
|
+
getProjectConfigDir(path.resolve(cwd)),
|
|
1966
|
+
getAgentDir(),
|
|
1967
|
+
os.homedir(),
|
|
1968
|
+
process.env.HOME ?? "",
|
|
1969
|
+
process.env.USERPROFILE ?? "",
|
|
1970
|
+
process.env[EXTRA_AGENT_DIRS_ENV] ?? "",
|
|
1971
|
+
process.env.PI_OFFLINE ?? "",
|
|
1972
|
+
process.env.APPDATA ?? ""
|
|
1973
|
+
]);
|
|
1974
|
+
}
|
|
1975
|
+
function projectDiscoveryWatchPaths(cwd) {
|
|
1976
|
+
const paths = [];
|
|
1977
|
+
let current = path.resolve(cwd);
|
|
1978
|
+
while (true) {
|
|
1979
|
+
paths.push(getProjectConfigDir(current), path.join(current, ".agents"), path.join(current, ".git"));
|
|
1980
|
+
const parent = path.dirname(current);
|
|
1981
|
+
if (parent === current)
|
|
1982
|
+
break;
|
|
1983
|
+
current = parent;
|
|
1984
|
+
}
|
|
1985
|
+
return paths;
|
|
1986
|
+
}
|
|
1987
|
+
function packageEntryIncluded(scope, packageScopes) {
|
|
1988
|
+
if (scope === "both" || packageScopes.has("root"))
|
|
1989
|
+
return true;
|
|
1990
|
+
return packageScopes.has(scope);
|
|
1991
|
+
}
|
|
1992
|
+
function buildAgentDiscoverySources(cwd, preferredModelProvider) {
|
|
1993
|
+
const effectiveCwd = path.resolve(cwd);
|
|
1075
1994
|
const userDirOld = path.join(getAgentDir(), "agents");
|
|
1076
1995
|
const userDirNew = path.join(os.homedir(), ".agents");
|
|
1077
1996
|
const userChainDir = getUserChainDir();
|
|
1078
|
-
const { readDirs:
|
|
1079
|
-
const { readDirs: projectChainDirs, preferredDir: projectChainDir } = resolveNearestProjectChainDirs(
|
|
1997
|
+
const { readDirs: projectAgentDirs, candidateDirs: projectCandidateDirs, preferredDir: projectAgentsDir } = resolveNearestProjectAgentDirs(effectiveCwd);
|
|
1998
|
+
const { readDirs: projectChainDirs, preferredDir: projectChainDir } = resolveNearestProjectChainDirs(effectiveCwd);
|
|
1080
1999
|
const userSettingsPath = getUserAgentSettingsPath();
|
|
1081
|
-
const projectSettingsPath = getProjectAgentSettingsPath(
|
|
1082
|
-
const
|
|
1083
|
-
const
|
|
1084
|
-
const
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
2000
|
+
const projectSettingsPath = getProjectAgentSettingsPath(effectiveCwd);
|
|
2001
|
+
const packageSubagentPaths = collectPackageSubagentPaths(effectiveCwd);
|
|
2002
|
+
const builtinLoaded = loadAgentsFromDefinitionFiles(BUILTIN_AGENT_DEFINITION_FILES, "builtin");
|
|
2003
|
+
const userLoaded = [...extraUserAgentDirs(), userDirOld, userDirNew].map((dir, discoveryPriority) => {
|
|
2004
|
+
const inspection = inspectAgentDefinitionDirectory(dir);
|
|
2005
|
+
return { dir, inspection, loaded: loadAgentsFromDir(dir, "user", discoveryPriority, undefined, inspection) };
|
|
2006
|
+
});
|
|
2007
|
+
const projectInspections = new Map(projectCandidateDirs.map((dir) => [dir, inspectAgentDefinitionDirectory(dir)]));
|
|
2008
|
+
const projectLoaded = projectAgentDirs.map((dir) => {
|
|
2009
|
+
const inspection = projectInspections.get(dir);
|
|
2010
|
+
return { dir, inspection, loaded: loadAgentsFromDir(dir, "project", dir === projectAgentsDir ? 1 : 0, undefined, inspection) };
|
|
2011
|
+
});
|
|
2012
|
+
const packageLoaded = packageSubagentPaths.agents.map((entry, index) => {
|
|
2013
|
+
const inspection = inspectAgentDefinitionDirectory(entry.dir);
|
|
2014
|
+
return { dir: entry.dir, inspection, packageEntry: entry, loaded: loadAgentsFromDir(entry.dir, "package", packageSubagentPaths.agents.length - index, entry, inspection) };
|
|
2015
|
+
});
|
|
2016
|
+
const watchPaths = new Set([
|
|
2017
|
+
userSettingsPath,
|
|
2018
|
+
...projectSettingsPath ? [projectSettingsPath] : [],
|
|
2019
|
+
...projectDiscoveryWatchPaths(effectiveCwd),
|
|
2020
|
+
...findProjectRootCandidates(effectiveCwd).map((root) => path.join(getProjectConfigDir(root), "settings.json")),
|
|
2021
|
+
...packageSubagentPaths.watchPaths
|
|
2022
|
+
]);
|
|
2023
|
+
for (const directory of userLoaded)
|
|
2024
|
+
addDirectoryWatchPaths(watchPaths, directory.dir, directory.inspection.files, inspectedAgentDefinitionDirectories(directory.inspection, directory.dir));
|
|
2025
|
+
for (const dir of projectCandidateDirs) {
|
|
2026
|
+
const inspection = projectInspections.get(dir);
|
|
2027
|
+
addDirectoryWatchPaths(watchPaths, dir, inspection?.files ?? [], inspection ? inspectedAgentDefinitionDirectories(inspection, dir) : []);
|
|
2028
|
+
}
|
|
2029
|
+
for (const directory of packageLoaded)
|
|
2030
|
+
addDirectoryWatchPaths(watchPaths, directory.dir, directory.inspection.files, inspectedAgentDefinitionDirectories(directory.inspection, directory.dir));
|
|
2031
|
+
const userDir = process.env.DM_CODING_AGENT_DIR ? userDirOld : fs.existsSync(userDirNew) ? userDirNew : userDirOld;
|
|
2032
|
+
return {
|
|
2033
|
+
cwd: effectiveCwd,
|
|
2034
|
+
...preferredModelProvider !== undefined ? { preferredModelProvider } : {},
|
|
2035
|
+
userDir,
|
|
2036
|
+
userDirOld,
|
|
2037
|
+
userDirNew,
|
|
2038
|
+
userChainDir,
|
|
2039
|
+
projectAgentDirs,
|
|
2040
|
+
projectCandidateDirs,
|
|
2041
|
+
projectAgentsDir,
|
|
2042
|
+
projectChainDirs,
|
|
2043
|
+
projectChainDir,
|
|
2044
|
+
userSettingsPath,
|
|
2045
|
+
projectSettingsPath,
|
|
2046
|
+
packageSubagentPaths,
|
|
2047
|
+
builtinLoaded,
|
|
2048
|
+
userLoaded,
|
|
2049
|
+
projectLoaded,
|
|
2050
|
+
projectInspections,
|
|
2051
|
+
packageLoaded,
|
|
2052
|
+
watchPaths: [...watchPaths]
|
|
2053
|
+
};
|
|
2054
|
+
}
|
|
2055
|
+
function ensureDiscoveryChains(sources) {
|
|
2056
|
+
if (sources.userChains)
|
|
2057
|
+
return;
|
|
2058
|
+
sources.packageChainLoaded = sources.packageSubagentPaths.chains.map((entry) => ({ entry, loaded: loadChainsFromDir(entry.dir, "package") }));
|
|
2059
|
+
sources.userChains = loadChainsFromDir(sources.userChainDir, "user");
|
|
2060
|
+
sources.projectChainLoaded = sources.projectChainDirs.map((dir) => ({ dir, loaded: loadChainsFromDir(dir, "project") }));
|
|
2061
|
+
const watchPaths = new Set(sources.watchPaths);
|
|
2062
|
+
addDirectoryWatchPaths(watchPaths, sources.userChainDir, sources.userChains.files, sources.userChains.directories);
|
|
2063
|
+
for (const chain of sources.projectChainLoaded)
|
|
2064
|
+
addDirectoryWatchPaths(watchPaths, chain.dir, chain.loaded.files, chain.loaded.directories);
|
|
2065
|
+
for (const chain of sources.packageChainLoaded)
|
|
2066
|
+
addDirectoryWatchPaths(watchPaths, chain.entry.dir, chain.loaded.files, chain.loaded.directories);
|
|
2067
|
+
sources.watchPaths = [...watchPaths];
|
|
2068
|
+
}
|
|
2069
|
+
function getAgentDiscoverySources(cwd, preferredModelProvider, includeChains = false) {
|
|
2070
|
+
const key = discoveryCacheKey(cwd, preferredModelProvider);
|
|
2071
|
+
const cached = agentDiscoveryCache.get(key);
|
|
2072
|
+
if (cached && cached.fingerprint === discoveryFingerprint(cached.sources.watchPaths)) {
|
|
2073
|
+
if (includeChains) {
|
|
2074
|
+
ensureDiscoveryChains(cached.sources);
|
|
2075
|
+
cached.fingerprint = discoveryFingerprint(cached.sources.watchPaths);
|
|
1097
2076
|
}
|
|
2077
|
+
return cached.sources;
|
|
2078
|
+
}
|
|
2079
|
+
const sources = buildAgentDiscoverySources(cwd, preferredModelProvider);
|
|
2080
|
+
const entry = { sources, fingerprint: discoveryFingerprint(sources.watchPaths) };
|
|
2081
|
+
agentDiscoveryCache.set(key, entry);
|
|
2082
|
+
if (includeChains) {
|
|
2083
|
+
ensureDiscoveryChains(sources);
|
|
2084
|
+
entry.fingerprint = discoveryFingerprint(sources.watchPaths);
|
|
2085
|
+
}
|
|
2086
|
+
return sources;
|
|
2087
|
+
}
|
|
2088
|
+
export function clearAgentDiscoveryCache() {
|
|
2089
|
+
agentDiscoveryCache.clear();
|
|
2090
|
+
}
|
|
2091
|
+
function ensureSettingsForScope(sources, scope, preferredModelProvider) {
|
|
2092
|
+
if (scope !== "project" && sources.userSettings === undefined) {
|
|
2093
|
+
if (sources.packageSubagentPaths.settingsErrors.user)
|
|
2094
|
+
throw sources.packageSubagentPaths.settingsErrors.user;
|
|
2095
|
+
sources.userSettings = selectProviderOverrides(readSubagentSettings(sources.userSettingsPath), preferredModelProvider);
|
|
2096
|
+
}
|
|
2097
|
+
if (scope !== "user" && sources.projectSettings === undefined) {
|
|
2098
|
+
if (sources.packageSubagentPaths.settingsErrors.project)
|
|
2099
|
+
throw sources.packageSubagentPaths.settingsErrors.project;
|
|
2100
|
+
sources.projectSettings = selectProviderOverrides(readSubagentSettings(sources.projectSettingsPath), preferredModelProvider);
|
|
1098
2101
|
}
|
|
1099
|
-
|
|
2102
|
+
}
|
|
2103
|
+
function settingsForScope(sources, scope) {
|
|
2104
|
+
ensureSettingsForScope(sources, scope, sources.preferredModelProvider);
|
|
2105
|
+
return {
|
|
2106
|
+
user: scope === "project" ? EMPTY_SUBAGENT_SETTINGS : sources.userSettings ?? EMPTY_SUBAGENT_SETTINGS,
|
|
2107
|
+
project: scope === "user" ? EMPTY_SUBAGENT_SETTINGS : sources.projectSettings ?? EMPTY_SUBAGENT_SETTINGS
|
|
2108
|
+
};
|
|
2109
|
+
}
|
|
2110
|
+
function configuredAgentsForScope(sources, scope, settingsScope = scope) {
|
|
2111
|
+
const { user: userSettings, project: projectSettings } = settingsForScope(sources, settingsScope);
|
|
2112
|
+
const defaultProvider = resolveSubagentDefaultProvider(userSettings, projectSettings, sources.projectSettingsPath);
|
|
2113
|
+
const defaultModel = resolveSubagentDefaultModel(userSettings, projectSettings, sources.userSettingsPath, sources.projectSettingsPath, defaultProvider);
|
|
2114
|
+
const defaultThinking = resolveSubagentDefaultThinking(userSettings, projectSettings, sources.projectSettingsPath);
|
|
2115
|
+
const maxThinking = resolveSubagentMaxThinking(userSettings, projectSettings, sources.projectSettingsPath);
|
|
2116
|
+
const defaultExtensions = resolveSubagentDefaultExtensions(userSettings, projectSettings, sources.projectSettingsPath);
|
|
2117
|
+
const applyDefaults = (agents) => applySubagentDefaults(agents, defaultModel, defaultProvider, defaultThinking, defaultExtensions);
|
|
2118
|
+
const builtin = applyBuiltinOverrides(applyDefaults(sources.builtinLoaded.agents), userSettings, projectSettings, sources.userSettingsPath, sources.projectSettingsPath);
|
|
2119
|
+
const user = applyCustomAgentOverrides(applyDefaults(scope === "project" ? [] : sources.userLoaded.flatMap((loaded) => loaded.loaded.agents)), userSettings, projectSettings, sources.userSettingsPath, sources.projectSettingsPath);
|
|
1100
2120
|
const projectMap = new Map;
|
|
1101
|
-
|
|
1102
|
-
for (const
|
|
1103
|
-
|
|
1104
|
-
|
|
2121
|
+
if (scope !== "user")
|
|
2122
|
+
for (const loaded of sources.projectLoaded)
|
|
2123
|
+
for (const agent of loaded.loaded.agents)
|
|
2124
|
+
projectMap.set(agent.name, agent);
|
|
2125
|
+
const project = applyCustomAgentOverrides(applyDefaults(Array.from(projectMap.values())), userSettings, projectSettings, sources.userSettingsPath, sources.projectSettingsPath);
|
|
2126
|
+
const packageMap = new Map;
|
|
2127
|
+
for (const loaded of sources.packageLoaded) {
|
|
2128
|
+
if (!loaded.packageEntry || !packageEntryIncluded(scope, loaded.packageEntry.scope))
|
|
2129
|
+
continue;
|
|
2130
|
+
for (const agent of loaded.loaded.agents)
|
|
2131
|
+
if (!packageMap.has(agent.name))
|
|
2132
|
+
packageMap.set(agent.name, agent);
|
|
1105
2133
|
}
|
|
1106
|
-
const
|
|
1107
|
-
|
|
1108
|
-
|
|
2134
|
+
const packageAgents = applyCustomAgentOverrides(applyDefaults(Array.from(packageMap.values())), userSettings, projectSettings, sources.userSettingsPath, sources.projectSettingsPath);
|
|
2135
|
+
return {
|
|
2136
|
+
builtin,
|
|
2137
|
+
package: packageAgents,
|
|
2138
|
+
user,
|
|
2139
|
+
project,
|
|
2140
|
+
userSettings,
|
|
2141
|
+
projectSettings,
|
|
2142
|
+
maxThinking,
|
|
2143
|
+
modelScope: projectSettings.modelScope ?? userSettings.modelScope
|
|
2144
|
+
};
|
|
2145
|
+
}
|
|
2146
|
+
function discoveryDirectories(sources, scope) {
|
|
2147
|
+
const directories = [reportAgentDefinitionDirectory("builtin", BUILTIN_AGENTS_DIR, BUILTIN_AGENT_DEFINITION_INSPECTION)];
|
|
2148
|
+
if (scope !== "project")
|
|
2149
|
+
for (const directory of sources.userLoaded)
|
|
2150
|
+
directories.push(reportAgentDefinitionDirectory("user", directory.dir, directory.inspection));
|
|
2151
|
+
if (scope !== "user")
|
|
2152
|
+
for (const dir of sources.projectCandidateDirs)
|
|
2153
|
+
directories.push(reportAgentDefinitionDirectory("project", dir, sources.projectInspections.get(dir)));
|
|
2154
|
+
for (const directory of sources.packageLoaded) {
|
|
2155
|
+
if (directory.packageEntry && packageEntryIncluded(scope, directory.packageEntry.scope))
|
|
2156
|
+
directories.push(reportAgentDefinitionDirectory("package", directory.dir, directory.inspection));
|
|
2157
|
+
}
|
|
2158
|
+
return directories;
|
|
2159
|
+
}
|
|
2160
|
+
function discoveryDiagnostics(sources, scope) {
|
|
2161
|
+
return [
|
|
2162
|
+
...sources.builtinLoaded.diagnostics,
|
|
2163
|
+
...scope === "project" ? [] : sources.userLoaded.flatMap((loaded) => loaded.loaded.diagnostics),
|
|
2164
|
+
...scope === "user" ? [] : sources.projectLoaded.flatMap((loaded) => loaded.loaded.diagnostics),
|
|
2165
|
+
...sources.packageLoaded.filter((loaded) => loaded.packageEntry && packageEntryIncluded(scope, loaded.packageEntry.scope)).flatMap((loaded) => loaded.loaded.diagnostics)
|
|
2166
|
+
];
|
|
2167
|
+
}
|
|
2168
|
+
function buildEffectiveDiscovery(sources, scope) {
|
|
2169
|
+
const configured = configuredAgentsForScope(sources, scope);
|
|
2170
|
+
const agents = applySubagentMaxThinking(mergeAgentsForScope(scope, configured.user, configured.project, configured.builtin, configured.package).filter((agent) => agent.disabled !== true), configured.maxThinking);
|
|
2171
|
+
return {
|
|
2172
|
+
agents,
|
|
2173
|
+
agentDiagnostics: discoveryDiagnostics(sources, scope),
|
|
2174
|
+
projectAgentsDir: sources.projectAgentsDir,
|
|
2175
|
+
cwd: sources.cwd,
|
|
2176
|
+
scope,
|
|
2177
|
+
directories: discoveryDirectories(sources, scope),
|
|
2178
|
+
...configured.modelScope !== undefined ? { modelScope: configured.modelScope } : {},
|
|
2179
|
+
...configured.maxThinking !== undefined ? { maxThinking: configured.maxThinking } : {}
|
|
2180
|
+
};
|
|
2181
|
+
}
|
|
2182
|
+
function buildAllDiscovery(sources, includeChains, settingsScope) {
|
|
2183
|
+
if (includeChains)
|
|
2184
|
+
ensureDiscoveryChains(sources);
|
|
2185
|
+
const configured = configuredAgentsForScope(sources, "both", settingsScope);
|
|
1109
2186
|
const packageChainMap = new Map;
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
packageChainDiagnostics.push(...loaded.diagnostics);
|
|
1113
|
-
for (const
|
|
1114
|
-
if (!packageChainMap.has(
|
|
1115
|
-
packageChainMap.set(
|
|
1116
|
-
}
|
|
2187
|
+
const packageChainDiagnostics = [];
|
|
2188
|
+
for (const chain of sources.packageChainLoaded ?? []) {
|
|
2189
|
+
packageChainDiagnostics.push(...chain.loaded.diagnostics);
|
|
2190
|
+
for (const definition of chain.loaded.chains)
|
|
2191
|
+
if (!packageChainMap.has(definition.name))
|
|
2192
|
+
packageChainMap.set(definition.name, definition);
|
|
1117
2193
|
}
|
|
2194
|
+
const projectChainMap = new Map;
|
|
1118
2195
|
const projectChainDiagnostics = [];
|
|
1119
|
-
for (const
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
chainMap.set(chain.name, chain);
|
|
1124
|
-
}
|
|
2196
|
+
for (const chain of sources.projectChainLoaded ?? []) {
|
|
2197
|
+
projectChainDiagnostics.push(...chain.loaded.diagnostics);
|
|
2198
|
+
for (const definition of chain.loaded.chains)
|
|
2199
|
+
projectChainMap.set(definition.name, definition);
|
|
1125
2200
|
}
|
|
1126
|
-
const userChains = loadChainsFromDir(userChainDir, "user");
|
|
1127
2201
|
const chains = [
|
|
1128
2202
|
...Array.from(packageChainMap.values()),
|
|
1129
|
-
...userChains
|
|
1130
|
-
...Array.from(
|
|
2203
|
+
...sources.userChains?.chains ?? [],
|
|
2204
|
+
...Array.from(projectChainMap.values())
|
|
1131
2205
|
];
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
2206
|
+
return {
|
|
2207
|
+
builtin: applySubagentMaxThinking(configured.builtin, configured.maxThinking),
|
|
2208
|
+
package: applySubagentMaxThinking(configured.package, configured.maxThinking),
|
|
2209
|
+
user: applySubagentMaxThinking(configured.user, configured.maxThinking),
|
|
2210
|
+
project: applySubagentMaxThinking(configured.project, configured.maxThinking),
|
|
2211
|
+
agentDiagnostics: [
|
|
2212
|
+
...sources.builtinLoaded.diagnostics,
|
|
2213
|
+
...sources.userLoaded.flatMap((loaded) => loaded.loaded.diagnostics),
|
|
2214
|
+
...sources.packageLoaded.flatMap((loaded) => loaded.loaded.diagnostics),
|
|
2215
|
+
...sources.projectLoaded.flatMap((loaded) => loaded.loaded.diagnostics)
|
|
2216
|
+
],
|
|
2217
|
+
chains,
|
|
2218
|
+
chainDiagnostics: [...packageChainDiagnostics, ...sources.userChains?.diagnostics ?? [], ...projectChainDiagnostics],
|
|
2219
|
+
userDir: sources.userDir,
|
|
2220
|
+
projectDir: sources.projectAgentsDir,
|
|
2221
|
+
userChainDir: sources.userChainDir,
|
|
2222
|
+
projectChainDir: sources.projectChainDir,
|
|
2223
|
+
userSettingsPath: sources.userSettingsPath,
|
|
2224
|
+
projectSettingsPath: sources.projectSettingsPath,
|
|
2225
|
+
...configured.maxThinking !== undefined ? { maxThinking: configured.maxThinking } : {}
|
|
2226
|
+
};
|
|
2227
|
+
}
|
|
2228
|
+
export function discoverAgentSnapshot(cwd, scope, preferredModelProvider, options = {}) {
|
|
2229
|
+
const includeChains = options.includeChains !== false;
|
|
2230
|
+
const sources = getAgentDiscoverySources(cwd, preferredModelProvider, includeChains);
|
|
2231
|
+
return { effective: buildEffectiveDiscovery(sources, scope), all: buildAllDiscovery(sources, includeChains, scope) };
|
|
2232
|
+
}
|
|
2233
|
+
function discoverAgentsUncached(cwd, scope, preferredModelProvider) {
|
|
2234
|
+
const effectiveCwd = path.resolve(cwd);
|
|
2235
|
+
const userDirOld = path.join(getAgentDir(), "agents");
|
|
2236
|
+
const userDirNew = path.join(os.homedir(), ".agents");
|
|
2237
|
+
const { readDirs: projectAgentDirs, candidateDirs: projectCandidateDirs, preferredDir: projectAgentsDir } = resolveNearestProjectAgentDirs(effectiveCwd);
|
|
2238
|
+
const userSettingsPath = getUserAgentSettingsPath();
|
|
2239
|
+
const projectSettingsPath = getProjectAgentSettingsPath(effectiveCwd);
|
|
2240
|
+
const userSettings = selectProviderOverrides(scope === "project" ? EMPTY_SUBAGENT_SETTINGS : readSubagentSettings(userSettingsPath), preferredModelProvider);
|
|
2241
|
+
const projectSettings = selectProviderOverrides(scope === "user" ? EMPTY_SUBAGENT_SETTINGS : readSubagentSettings(projectSettingsPath), preferredModelProvider);
|
|
2242
|
+
const defaultProvider = resolveSubagentDefaultProvider(userSettings, projectSettings, projectSettingsPath);
|
|
2243
|
+
const defaultModel = resolveSubagentDefaultModel(userSettings, projectSettings, userSettingsPath, projectSettingsPath, defaultProvider);
|
|
2244
|
+
const defaultThinking = resolveSubagentDefaultThinking(userSettings, projectSettings, projectSettingsPath);
|
|
2245
|
+
const maxThinking = resolveSubagentMaxThinking(userSettings, projectSettings, projectSettingsPath);
|
|
2246
|
+
const defaultExtensions = resolveSubagentDefaultExtensions(userSettings, projectSettings, projectSettingsPath);
|
|
2247
|
+
const modelScope = projectSettings.modelScope ?? userSettings.modelScope;
|
|
2248
|
+
const packageSubagentPaths = collectPackageSubagentPaths(effectiveCwd, { includeUser: scope !== "project", includeProject: scope !== "user" });
|
|
2249
|
+
const directories = [reportAgentDefinitionDirectory("builtin", BUILTIN_AGENTS_DIR, BUILTIN_AGENT_DEFINITION_INSPECTION)];
|
|
2250
|
+
const builtinLoaded = loadAgentsFromDefinitionFiles(BUILTIN_AGENT_DEFINITION_FILES, "builtin");
|
|
2251
|
+
const builtinAgents = applyBuiltinOverrides(applySubagentDefaults(builtinLoaded.agents, defaultModel, defaultProvider, defaultThinking, defaultExtensions), userSettings, projectSettings, userSettingsPath, projectSettingsPath);
|
|
2252
|
+
const userLoaded = scope === "project" ? [] : [...extraUserAgentDirs(), userDirOld, userDirNew].map((dir, discoveryPriority) => {
|
|
2253
|
+
const inspection = inspectAgentDefinitionDirectory(dir);
|
|
2254
|
+
directories.push(reportAgentDefinitionDirectory("user", dir, inspection));
|
|
2255
|
+
return loadAgentsFromDir(dir, "user", discoveryPriority, undefined, inspection);
|
|
2256
|
+
});
|
|
2257
|
+
const userAgents = applyCustomAgentOverrides(applySubagentDefaults(userLoaded.flatMap((loaded) => loaded.agents), defaultModel, defaultProvider, defaultThinking, defaultExtensions), userSettings, projectSettings, userSettingsPath, projectSettingsPath);
|
|
2258
|
+
const projectInspections = scope === "user" ? new Map : new Map(projectCandidateDirs.map((dir) => [dir, inspectAgentDefinitionDirectory(dir)]));
|
|
2259
|
+
if (scope !== "user")
|
|
2260
|
+
for (const dir of projectCandidateDirs)
|
|
2261
|
+
directories.push(reportAgentDefinitionDirectory("project", dir, projectInspections.get(dir)));
|
|
2262
|
+
const projectLoaded = scope === "user" ? [] : projectAgentDirs.map((dir) => loadAgentsFromDir(dir, "project", dir === projectAgentsDir ? 1 : 0, undefined, projectInspections.get(dir)));
|
|
2263
|
+
const projectAgents = applyCustomAgentOverrides(applySubagentDefaults(projectLoaded.flatMap((loaded) => loaded.agents), defaultModel, defaultProvider, defaultThinking, defaultExtensions), userSettings, projectSettings, userSettingsPath, projectSettingsPath);
|
|
2264
|
+
const packageLoaded = packageSubagentPaths.agents.map((entry, index) => {
|
|
2265
|
+
const inspection = inspectAgentDefinitionDirectory(entry.dir);
|
|
2266
|
+
directories.push(reportAgentDefinitionDirectory("package", entry.dir, inspection));
|
|
2267
|
+
return loadAgentsFromDir(entry.dir, "package", packageSubagentPaths.agents.length - index, entry, inspection);
|
|
2268
|
+
});
|
|
2269
|
+
const packageMap = new Map;
|
|
2270
|
+
for (const loaded of packageLoaded)
|
|
2271
|
+
for (const agent of loaded.agents)
|
|
2272
|
+
if (!packageMap.has(agent.name))
|
|
2273
|
+
packageMap.set(agent.name, agent);
|
|
2274
|
+
const packageAgents = applyCustomAgentOverrides(applySubagentDefaults(Array.from(packageMap.values()), defaultModel, defaultProvider, defaultThinking, defaultExtensions), userSettings, projectSettings, userSettingsPath, projectSettingsPath);
|
|
2275
|
+
const agents = applySubagentMaxThinking(mergeAgentsForScope(scope, userAgents, projectAgents, builtinAgents, packageAgents).filter((agent) => agent.disabled !== true), maxThinking);
|
|
2276
|
+
const agentDiagnostics = [...builtinLoaded.diagnostics, ...userLoaded.flatMap((loaded) => loaded.diagnostics), ...projectLoaded.flatMap((loaded) => loaded.diagnostics), ...packageLoaded.flatMap((loaded) => loaded.diagnostics)];
|
|
2277
|
+
return { agents, agentDiagnostics, projectAgentsDir, cwd: effectiveCwd, scope, directories, ...modelScope !== undefined ? { modelScope } : {}, ...maxThinking !== undefined ? { maxThinking } : {} };
|
|
2278
|
+
}
|
|
2279
|
+
export function discoverAgents(cwd, scope, preferredModelProvider) {
|
|
2280
|
+
if (scope !== "both")
|
|
2281
|
+
return discoverAgentsUncached(cwd, scope, preferredModelProvider);
|
|
2282
|
+
const sources = getAgentDiscoverySources(cwd, preferredModelProvider);
|
|
2283
|
+
return buildEffectiveDiscovery(sources, scope);
|
|
2284
|
+
}
|
|
2285
|
+
export function discoverAgentsAll(cwd, preferredModelProvider) {
|
|
2286
|
+
return discoverAgentSnapshot(cwd, "both", preferredModelProvider).all;
|
|
1139
2287
|
}
|