@selesai/code 0.5.19 → 0.5.21
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/dist/extensions/handoff-new.test.ts +8 -9
- package/dist/extensions/handoff-new.ts +6 -8
- package/dist/extensions/pi-intercom/broker/spawn.test.ts +31 -0
- package/dist/extensions/pi-intercom/broker/spawn.ts +5 -3
- package/dist/extensions/pi-subagents/CHANGELOG.md +1367 -0
- package/dist/extensions/pi-subagents/README.md +602 -220
- package/dist/extensions/pi-subagents/banner.png +0 -0
- package/dist/extensions/pi-subagents/index.ts +1 -0
- package/dist/extensions/pi-subagents/install.mjs +3 -3
- package/dist/extensions/pi-subagents/package-lock.json +3405 -0
- package/dist/extensions/pi-subagents/package.json +26 -14
- package/dist/extensions/pi-subagents/prompts/gather-context-and-clarify.md +1 -1
- package/dist/extensions/pi-subagents/prompts/parallel-cleanup.md +9 -9
- package/dist/extensions/pi-subagents/prompts/parallel-context-build.md +3 -3
- package/dist/extensions/pi-subagents/prompts/parallel-handoff-plan.md +7 -7
- package/dist/extensions/pi-subagents/prompts/parallel-research.md +6 -6
- package/dist/extensions/pi-subagents/prompts/parallel-review.md +8 -8
- package/dist/extensions/pi-subagents/prompts/review-loop.md +13 -11
- package/dist/extensions/pi-subagents/skills/pi-subagents/SKILL.md +267 -176
- package/dist/extensions/pi-subagents/src/agents/agent-management.ts +89 -16
- package/dist/extensions/pi-subagents/src/agents/agent-serializer.ts +19 -0
- package/dist/extensions/pi-subagents/src/agents/agents.ts +218 -120
- package/dist/extensions/pi-subagents/src/agents/frontmatter.ts +67 -13
- package/dist/extensions/pi-subagents/src/agents/proactive-skills.ts +2 -2
- package/dist/extensions/pi-subagents/src/agents/skills.ts +25 -12
- package/dist/extensions/pi-subagents/src/api/background-work.ts +197 -0
- package/dist/extensions/pi-subagents/src/api/capability-ceiling.ts +17 -0
- package/dist/extensions/pi-subagents/src/api/delegation.ts +285 -0
- package/dist/extensions/pi-subagents/src/api/preflight.ts +399 -0
- package/dist/extensions/pi-subagents/src/extension/chain-validation.ts +165 -0
- package/dist/extensions/pi-subagents/src/extension/config.ts +7 -1
- package/dist/extensions/pi-subagents/src/extension/doctor.ts +15 -0
- package/dist/extensions/pi-subagents/src/extension/fanout-child.ts +3 -1
- package/dist/extensions/pi-subagents/src/extension/index.ts +113 -157
- package/dist/extensions/pi-subagents/src/extension/rpc.ts +41 -4
- package/dist/extensions/pi-subagents/src/extension/schemas.ts +45 -15
- package/dist/extensions/pi-subagents/src/extension/steering-notices.ts +35 -0
- package/dist/extensions/pi-subagents/src/extension/tool-description.ts +28 -15
- package/dist/extensions/pi-subagents/src/intercom/intercom-bridge.ts +4 -3
- package/dist/extensions/pi-subagents/src/intercom/native-supervisor-channel.ts +225 -29
- package/dist/extensions/pi-subagents/src/intercom/result-intercom.ts +11 -0
- package/dist/extensions/pi-subagents/src/profiles/profiles.ts +8 -10
- package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +452 -62
- package/dist/extensions/pi-subagents/src/runs/background/async-job-tracker.ts +60 -9
- package/dist/extensions/pi-subagents/src/runs/background/async-resume.ts +198 -52
- package/dist/extensions/pi-subagents/src/runs/background/async-status.ts +119 -21
- package/dist/extensions/pi-subagents/src/runs/background/auto-drain.ts +67 -0
- package/dist/extensions/pi-subagents/src/runs/background/chain-append.ts +2 -0
- package/dist/extensions/pi-subagents/src/runs/background/chain-root-attachment.ts +16 -8
- package/dist/extensions/pi-subagents/src/runs/background/completion-batcher.ts +6 -4
- package/dist/extensions/pi-subagents/src/runs/background/completion-dedupe.ts +2 -11
- package/dist/extensions/pi-subagents/src/runs/background/control-channel.ts +260 -13
- package/dist/extensions/pi-subagents/src/runs/background/fleet-view.ts +32 -6
- package/dist/extensions/pi-subagents/src/runs/background/notify.ts +171 -90
- package/dist/extensions/pi-subagents/src/runs/background/process-terminal.ts +280 -0
- package/dist/extensions/pi-subagents/src/runs/background/result-watcher.ts +149 -88
- package/dist/extensions/pi-subagents/src/runs/background/run-id-resolver.ts +14 -2
- package/dist/extensions/pi-subagents/src/runs/background/run-status.ts +33 -17
- package/dist/extensions/pi-subagents/src/runs/background/scheduled-runs.ts +9 -1
- package/dist/extensions/pi-subagents/src/runs/background/stale-run-reconciler.ts +38 -10
- package/dist/extensions/pi-subagents/src/runs/background/steering.ts +237 -0
- package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +1297 -307
- package/dist/extensions/pi-subagents/src/runs/background/subagent-wait.ts +610 -0
- package/dist/extensions/pi-subagents/src/runs/background/top-level-async.ts +2 -1
- package/dist/extensions/pi-subagents/src/runs/background/wait-config.ts +36 -0
- package/dist/extensions/pi-subagents/src/runs/background/wait-tool.ts +26 -0
- package/dist/extensions/pi-subagents/src/runs/foreground/async-steering-action.ts +230 -0
- package/dist/extensions/pi-subagents/src/runs/foreground/chain-clarify.ts +22 -6
- package/dist/extensions/pi-subagents/src/runs/foreground/chain-execution.ts +228 -140
- package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +452 -138
- package/dist/extensions/pi-subagents/src/runs/foreground/foreground-control.ts +90 -0
- package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +1001 -416
- package/dist/extensions/pi-subagents/src/runs/shared/acceptance.ts +443 -132
- package/dist/extensions/pi-subagents/src/runs/shared/agent-contract.ts +38 -0
- package/dist/extensions/pi-subagents/src/runs/shared/capability-ceiling.ts +178 -0
- package/dist/extensions/pi-subagents/src/runs/shared/child-protocol.ts +121 -0
- package/dist/extensions/pi-subagents/src/runs/shared/completion-guard.ts +41 -93
- package/dist/extensions/pi-subagents/src/runs/shared/context-mode.ts +44 -0
- package/dist/extensions/pi-subagents/src/runs/shared/dynamic-fanout.ts +11 -9
- package/dist/extensions/pi-subagents/src/runs/shared/long-running-guard.ts +4 -0
- package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +12 -6
- package/dist/extensions/pi-subagents/src/runs/shared/model-fallback.ts +36 -0
- package/dist/extensions/pi-subagents/src/runs/shared/nested-events.ts +44 -7
- package/dist/extensions/pi-subagents/src/runs/shared/nested-render.ts +4 -1
- package/dist/extensions/pi-subagents/src/runs/shared/parallel-handoff.ts +154 -0
- package/dist/extensions/pi-subagents/src/runs/shared/parallel-utils.ts +18 -0
- package/dist/extensions/pi-subagents/src/runs/shared/pi-args.ts +174 -54
- package/dist/extensions/pi-subagents/src/runs/shared/pi-spawn.ts +38 -31
- package/dist/extensions/pi-subagents/src/runs/shared/run-history.ts +90 -5
- package/dist/extensions/pi-subagents/src/runs/shared/session-lease.ts +299 -0
- package/dist/extensions/pi-subagents/src/runs/shared/single-output.ts +61 -6
- package/dist/extensions/pi-subagents/src/runs/shared/spawn-budget.ts +128 -0
- package/dist/extensions/pi-subagents/src/runs/shared/structured-output.ts +112 -7
- package/dist/extensions/pi-subagents/src/runs/shared/subagent-control.ts +14 -6
- package/dist/extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.ts +149 -36
- package/dist/extensions/pi-subagents/src/runs/shared/task-intent.ts +181 -0
- package/dist/extensions/pi-subagents/src/runs/shared/tool-availability.ts +83 -0
- package/dist/extensions/pi-subagents/src/runs/shared/tool-budget.ts +11 -5
- package/dist/extensions/pi-subagents/src/runs/shared/turn-budget.ts +50 -4
- package/dist/extensions/pi-subagents/src/runs/shared/worktree.ts +63 -14
- package/dist/extensions/pi-subagents/src/shared/accessible-dir.ts +25 -0
- package/dist/extensions/pi-subagents/src/shared/artifacts.ts +37 -7
- package/dist/extensions/pi-subagents/src/shared/atomic-json.ts +18 -43
- package/dist/extensions/pi-subagents/src/shared/child-transcript.ts +52 -0
- package/dist/extensions/pi-subagents/src/shared/env.ts +16 -0
- package/dist/extensions/pi-subagents/src/shared/file-system-retry.ts +47 -0
- package/dist/extensions/pi-subagents/src/shared/fork-context.ts +28 -3
- package/dist/extensions/pi-subagents/src/shared/launch-contract.ts +123 -0
- package/dist/extensions/pi-subagents/src/shared/model-info.ts +8 -5
- package/dist/extensions/pi-subagents/src/shared/settings.ts +9 -1
- package/dist/extensions/pi-subagents/src/shared/status-format.ts +7 -1
- package/dist/extensions/pi-subagents/src/shared/types.ts +522 -51
- package/dist/extensions/pi-subagents/src/shared/utils.ts +59 -53
- package/dist/extensions/pi-subagents/src/slash/delegation-adapters.ts +604 -0
- package/dist/extensions/pi-subagents/src/slash/delegation-json.ts +108 -0
- package/dist/extensions/pi-subagents/src/slash/delegation-request.ts +249 -0
- package/dist/extensions/pi-subagents/src/slash/prompt-template-bridge.ts +353 -345
- package/dist/extensions/pi-subagents/src/slash/prompt-workflows.ts +2 -2
- package/dist/extensions/pi-subagents/src/slash/selector.ts +147 -0
- package/dist/extensions/pi-subagents/src/slash/slash-commands.ts +265 -23
- package/dist/extensions/pi-subagents/src/slash/slash-live-state.ts +2 -2
- package/dist/extensions/pi-subagents/src/slash/subagents-admin.ts +428 -0
- package/dist/extensions/pi-subagents/src/tui/fleet-status.ts +362 -0
- package/dist/extensions/pi-subagents/src/tui/fleet-transcript.ts +472 -0
- package/dist/extensions/pi-subagents/src/tui/fleet.ts +664 -0
- package/dist/extensions/pi-subagents/src/tui/render.ts +115 -31
- package/dist/extensions/pi-subagents/src/watchdog/change-signature.ts +220 -0
- package/dist/extensions/pi-subagents/src/watchdog/child-status.ts +205 -0
- package/dist/extensions/pi-subagents/src/watchdog/emission-guard.ts +123 -0
- package/dist/extensions/pi-subagents/src/watchdog/lsp-diagnostics.ts +532 -0
- package/dist/extensions/pi-subagents/src/watchdog/model-selection.ts +167 -0
- package/dist/extensions/pi-subagents/src/watchdog/register-child.ts +117 -0
- package/dist/extensions/pi-subagents/src/watchdog/register-main.ts +433 -0
- package/dist/extensions/pi-subagents/src/watchdog/render.ts +54 -0
- package/dist/extensions/pi-subagents/src/watchdog/review.ts +298 -0
- package/dist/extensions/pi-subagents/src/watchdog/runtime.ts +714 -0
- package/dist/extensions/pi-subagents/src/watchdog/settings.ts +528 -0
- package/dist/extensions/pi-subagents/src/watchdog/tool-actions.ts +155 -0
- package/dist/extensions/pi-subagents/src/watchdog/turn-delta.ts +161 -0
- package/dist/extensions/pi-subagents/src/watchdog/types.ts +188 -0
- package/dist/extensions/pi-subagents/src/watchdog/warning-format.ts +73 -0
- package/dist/extensions/pi-subagents/test/e2e/real-session-subagent.test.ts +130 -2
- package/dist/extensions/pi-subagents/test/integration/acceptance-file-report.test.ts +439 -0
- package/dist/extensions/pi-subagents/test/integration/async-execution.test.ts +1632 -61
- package/dist/extensions/pi-subagents/test/integration/async-job-tracker.test.ts +54 -1
- package/dist/extensions/pi-subagents/test/integration/async-status.test.ts +112 -0
- package/dist/extensions/pi-subagents/test/integration/chain-clarify.test.ts +98 -1
- package/dist/extensions/pi-subagents/test/integration/chain-execution.test.ts +179 -9
- package/dist/extensions/pi-subagents/test/integration/detect-error.test.ts +16 -9
- package/dist/extensions/pi-subagents/test/integration/error-handling.test.ts +6 -5
- package/dist/extensions/pi-subagents/test/integration/fork-context-execution.test.ts +589 -9
- package/dist/extensions/pi-subagents/test/integration/intercom-result-delivery.test.ts +528 -21
- package/dist/extensions/pi-subagents/test/integration/parallel-execution.test.ts +227 -3
- package/dist/extensions/pi-subagents/test/integration/render-fork-badge.test.ts +235 -7
- package/dist/extensions/pi-subagents/test/integration/render-widget.test.ts +27 -0
- package/dist/extensions/pi-subagents/test/integration/result-watcher.test.ts +172 -2
- package/dist/extensions/pi-subagents/test/integration/single-execution.test.ts +1502 -18
- package/dist/extensions/pi-subagents/test/integration/slash-commands.test.ts +993 -4
- package/dist/extensions/pi-subagents/test/integration/slash-live-state.test.ts +27 -0
- package/dist/extensions/pi-subagents/test/integration/top-level-async.test.ts +7 -1
- package/dist/extensions/pi-subagents/test/support/helpers.ts +32 -0
- package/dist/extensions/pi-subagents/test/support/mock-pi-script.mjs +59 -2
- package/dist/extensions/pi-subagents/test/support/mock-pi.ts +32 -6
- package/dist/extensions/pi-subagents/test/support/real-session-child-cli.mjs +25 -24
- package/dist/extensions/pi-subagents/test/support/real-session-runner.ts +59 -35
- package/dist/extensions/pi-subagents/test/support/session-lease-child.mjs +42 -0
- package/dist/extensions/pi-subagents/test/unit/acceptance.test.ts +703 -69
- package/dist/extensions/pi-subagents/test/unit/accessible-dir.test.ts +82 -0
- package/dist/extensions/pi-subagents/test/unit/agent-disabled.test.ts +15 -15
- package/dist/extensions/pi-subagents/test/unit/agent-eject-disable.test.ts +66 -66
- package/dist/extensions/pi-subagents/test/unit/agent-frontmatter.test.ts +478 -19
- package/dist/extensions/pi-subagents/test/unit/agent-management.test.ts +228 -7
- package/dist/extensions/pi-subagents/test/unit/agent-memory.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/agent-overrides.test.ts +198 -78
- package/dist/extensions/pi-subagents/test/unit/async-execution.test.ts +15 -1
- package/dist/extensions/pi-subagents/test/unit/async-interrupt-action.test.ts +102 -7
- package/dist/extensions/pi-subagents/test/unit/async-resume.test.ts +439 -6
- package/dist/extensions/pi-subagents/test/unit/atomic-json.test.ts +41 -1
- package/dist/extensions/pi-subagents/test/unit/auto-drain.test.ts +79 -0
- package/dist/extensions/pi-subagents/test/unit/background-work.test.ts +285 -0
- package/dist/extensions/pi-subagents/test/unit/capability-ceiling-pi-args.test.ts +84 -0
- package/dist/extensions/pi-subagents/test/unit/capability-ceiling.test.ts +68 -0
- package/dist/extensions/pi-subagents/test/unit/chain-validation.test.ts +326 -0
- package/dist/extensions/pi-subagents/test/unit/child-protocol.test.ts +82 -0
- package/dist/extensions/pi-subagents/test/unit/child-transcript.test.ts +46 -4
- package/dist/extensions/pi-subagents/test/unit/completion-batcher.test.ts +3 -1
- package/dist/extensions/pi-subagents/test/unit/completion-dedupe.test.ts +9 -17
- package/dist/extensions/pi-subagents/test/unit/completion-guard.test.ts +175 -3
- package/dist/extensions/pi-subagents/test/unit/config-dir-runtime.test.ts +10 -5
- package/dist/extensions/pi-subagents/test/unit/control-channel.test.ts +126 -6
- package/dist/extensions/pi-subagents/test/unit/default-extensions.test.ts +219 -0
- package/dist/extensions/pi-subagents/test/unit/delegation-api.test.ts +913 -0
- package/dist/extensions/pi-subagents/test/unit/doctor.test.ts +13 -2
- package/dist/extensions/pi-subagents/test/unit/dynamic-fanout.test.ts +3 -3
- package/dist/extensions/pi-subagents/test/unit/fleet-status.test.ts +351 -0
- package/dist/extensions/pi-subagents/test/unit/fleet-transcript.test.ts +280 -0
- package/dist/extensions/pi-subagents/test/unit/fleet.test.ts +575 -0
- package/dist/extensions/pi-subagents/test/unit/foreground-control.test.ts +65 -0
- package/dist/extensions/pi-subagents/test/unit/fork-context.test.ts +94 -1
- package/dist/extensions/pi-subagents/test/unit/get-final-output.test.ts +23 -0
- package/dist/extensions/pi-subagents/test/unit/host-peer-runtime-imports.test.ts +157 -0
- package/dist/extensions/pi-subagents/test/unit/index-child-registration.test.ts +367 -5
- package/dist/extensions/pi-subagents/test/unit/intercom-bridge.test.ts +11 -0
- package/dist/extensions/pi-subagents/test/unit/model-fallback.test.ts +36 -0
- package/dist/extensions/pi-subagents/test/unit/model-info.test.ts +25 -3
- package/dist/extensions/pi-subagents/test/unit/model-scope.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/native-supervisor-channel.test.ts +341 -10
- package/dist/extensions/pi-subagents/test/unit/nested-control.test.ts +16 -0
- package/dist/extensions/pi-subagents/test/unit/nested-events.test.ts +52 -0
- package/dist/extensions/pi-subagents/test/unit/notify.test.ts +168 -7
- package/dist/extensions/pi-subagents/test/unit/package-manifest.test.ts +85 -7
- package/dist/extensions/pi-subagents/test/unit/parallel-handoff.test.ts +175 -0
- package/dist/extensions/pi-subagents/test/unit/path-resolution.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/pi-args.test.ts +243 -16
- package/dist/extensions/pi-subagents/test/unit/pi-coding-agent-dir.test.ts +79 -36
- package/dist/extensions/pi-subagents/test/unit/pi-spawn.test.ts +174 -56
- package/dist/extensions/pi-subagents/test/unit/preflight.test.ts +322 -0
- package/dist/extensions/pi-subagents/test/unit/process-terminal.test.ts +204 -0
- package/dist/extensions/pi-subagents/test/unit/recursion-guard.test.ts +20 -12
- package/dist/extensions/pi-subagents/test/unit/rpc.test.ts +117 -4
- package/dist/extensions/pi-subagents/test/unit/run-status.test.ts +40 -7
- package/dist/extensions/pi-subagents/test/unit/scheduled-runs.test.ts +48 -1
- package/dist/extensions/pi-subagents/test/unit/schemas.test.ts +21 -3
- package/dist/extensions/pi-subagents/test/unit/selector.test.ts +57 -0
- package/dist/extensions/pi-subagents/test/unit/session-lease.test.ts +326 -0
- package/dist/extensions/pi-subagents/test/unit/single-output.test.ts +101 -2
- package/dist/extensions/pi-subagents/test/unit/skills-fallback.test.ts +111 -1
- package/dist/extensions/pi-subagents/test/unit/spawn-budget.test.ts +124 -0
- package/dist/extensions/pi-subagents/test/unit/stale-run-reconciler.test.ts +6 -4
- package/dist/extensions/pi-subagents/test/unit/status-format.test.ts +7 -0
- package/dist/extensions/pi-subagents/test/unit/steering-action.test.ts +397 -0
- package/dist/extensions/pi-subagents/test/unit/steering-notices.test.ts +58 -0
- package/dist/extensions/pi-subagents/test/unit/steering.test.ts +173 -0
- package/dist/extensions/pi-subagents/test/unit/subagent-control.test.ts +25 -4
- package/dist/extensions/pi-subagents/test/unit/subagent-prompt-runtime.test.ts +390 -25
- package/dist/extensions/pi-subagents/test/unit/subagent-wait.test.ts +837 -0
- package/dist/extensions/pi-subagents/test/unit/task-intent.test.ts +86 -0
- package/dist/extensions/pi-subagents/test/unit/tool-budget.test.ts +15 -0
- package/dist/extensions/pi-subagents/test/unit/tool-description.test.ts +47 -1
- package/dist/extensions/pi-subagents/test/unit/turn-budget.test.ts +56 -10
- package/dist/extensions/pi-subagents/test/unit/watchdog-change-signature.test.ts +387 -0
- package/dist/extensions/pi-subagents/test/unit/watchdog-child-status.test.ts +110 -0
- package/dist/extensions/pi-subagents/test/unit/watchdog-emission-guard.test.ts +62 -0
- package/dist/extensions/pi-subagents/test/unit/watchdog-lsp-diagnostics.test.ts +144 -0
- package/dist/extensions/pi-subagents/test/unit/watchdog-model-selection.test.ts +121 -0
- package/dist/extensions/pi-subagents/test/unit/watchdog-render.test.ts +76 -0
- package/dist/extensions/pi-subagents/test/unit/watchdog-review.test.ts +327 -0
- package/dist/extensions/pi-subagents/test/unit/watchdog-runtime.test.ts +863 -0
- package/dist/extensions/pi-subagents/test/unit/watchdog-settings.test.ts +290 -0
- package/dist/extensions/pi-subagents/test/unit/watchdog-tool-actions.test.ts +91 -0
- package/dist/extensions/pi-subagents/test/unit/watchdog-turn-delta.test.ts +130 -0
- package/dist/extensions/pi-subagents/test/unit/widget-nested-render.test.ts +32 -4
- package/dist/extensions/pi-subagents/test/unit/worktree.test.ts +5 -1
- package/dist/extensions/pi-subagents/test/unit/writer-budget-guidance.test.ts +30 -0
- package/dist/extensions/question/batch.ts +39 -0
- package/dist/extensions/question/dialog-adapter.ts +23 -1
- package/dist/extensions/question/index.ts +237 -7
- package/dist/extensions/question/schemas.ts +28 -15
- package/dist/extensions/question/tests/batch.test.ts +26 -0
- package/dist/extensions/question/tests/ui-protocol.test.ts +23 -3
- package/dist/extensions/question/tui-adapter.ts +2 -3
- package/dist/extensions/question/types.ts +37 -0
- package/dist/extensions/question/ui-protocol.ts +3 -3
- package/dist/skills/batch-grill-me/SKILL.md +3 -1
- package/package.json +2 -1
|
@@ -4,19 +4,23 @@
|
|
|
4
4
|
|
|
5
5
|
import { execSync } from "node:child_process";
|
|
6
6
|
import * as fs from "node:fs";
|
|
7
|
+
import { parse as parseYaml } from "yaml";
|
|
7
8
|
import * as os from "node:os";
|
|
9
|
+
import "../shared/env.ts";
|
|
8
10
|
import * as path from "node:path";
|
|
9
11
|
import { fileURLToPath } from "node:url";
|
|
10
|
-
import type { AcceptanceInput, OutputMode, ToolBudgetConfig } from "../shared/types.ts";
|
|
12
|
+
import type { AcceptanceInput, AcceptanceRole, OutputMode, ToolBudgetConfig, TurnBudgetConfig } from "../shared/types.ts";
|
|
11
13
|
import { getAgentDir, getProjectConfigDir } from "../shared/utils.ts";
|
|
12
14
|
import { KNOWN_FIELDS } from "./agent-serializer.ts";
|
|
13
15
|
import { parseChain, parseJsonChain } from "./chain-serializer.ts";
|
|
14
16
|
import { mergeAgentsForScope } from "./agent-selection.ts";
|
|
15
|
-
import { parseFrontmatter } from "./frontmatter.ts";
|
|
17
|
+
import { parseFrontmatter, parseFrontmatterList } from "./frontmatter.ts";
|
|
16
18
|
import { buildRuntimeName, parsePackageName } from "./identity.ts";
|
|
17
19
|
import { parseModelScopeConfig, type ModelScopeConfig } from "../runs/shared/model-scope.ts";
|
|
18
20
|
export { buildRuntimeName, frontmatterNameForConfig, parsePackageName } from "./identity.ts";
|
|
19
21
|
import { parseMemoryFrontmatter } from "./agent-memory.ts";
|
|
22
|
+
import { resolveTurnBudgetConfig } from "../runs/shared/turn-budget.ts";
|
|
23
|
+
import { validateAcceptanceInput } from "../runs/shared/acceptance.ts";
|
|
20
24
|
|
|
21
25
|
export type AgentScope = "user" | "project" | "both";
|
|
22
26
|
|
|
@@ -32,14 +36,12 @@ export interface AgentMemoryConfig {
|
|
|
32
36
|
}
|
|
33
37
|
|
|
34
38
|
export const BUILTIN_AGENT_NAMES = [
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
+
"architect",
|
|
40
|
+
"builder",
|
|
41
|
+
"commentator",
|
|
42
|
+
"explorer",
|
|
43
|
+
"recapper",
|
|
39
44
|
"researcher",
|
|
40
|
-
"reviewer",
|
|
41
|
-
"scout",
|
|
42
|
-
"worker",
|
|
43
45
|
] as const;
|
|
44
46
|
|
|
45
47
|
export function defaultSystemPromptMode(name: string): SystemPromptMode {
|
|
@@ -57,16 +59,19 @@ export function defaultInheritSkills(): boolean {
|
|
|
57
59
|
export interface BuiltinAgentOverrideBase {
|
|
58
60
|
model?: string;
|
|
59
61
|
fallbackModels?: string[];
|
|
60
|
-
thinking?: string;
|
|
62
|
+
thinking?: string | false;
|
|
61
63
|
systemPromptMode: SystemPromptMode;
|
|
62
64
|
inheritProjectContext: boolean;
|
|
63
65
|
inheritSkills: boolean;
|
|
64
66
|
defaultContext?: AgentDefaultContext;
|
|
67
|
+
acceptanceRole?: AcceptanceRole;
|
|
65
68
|
disabled?: boolean;
|
|
66
69
|
systemPrompt: string;
|
|
67
70
|
skills?: string[];
|
|
71
|
+
skillPath?: string[];
|
|
68
72
|
tools?: string[];
|
|
69
73
|
mcpDirectTools?: string[];
|
|
74
|
+
extensions?: string[];
|
|
70
75
|
subagentOnlyExtensions?: string[];
|
|
71
76
|
completionGuard?: boolean;
|
|
72
77
|
toolBudget?: ToolBudgetConfig;
|
|
@@ -80,10 +85,12 @@ interface BuiltinAgentOverrideConfig {
|
|
|
80
85
|
inheritProjectContext?: boolean;
|
|
81
86
|
inheritSkills?: boolean;
|
|
82
87
|
defaultContext?: AgentDefaultContext | false;
|
|
88
|
+
acceptanceRole?: AcceptanceRole | false;
|
|
83
89
|
disabled?: boolean;
|
|
84
90
|
systemPrompt?: string;
|
|
85
91
|
skills?: string[] | false;
|
|
86
92
|
tools?: string[] | false;
|
|
93
|
+
extensions?: string[] | false;
|
|
87
94
|
subagentOnlyExtensions?: string[] | false;
|
|
88
95
|
completionGuard?: boolean;
|
|
89
96
|
toolBudget?: ToolBudgetConfig | false;
|
|
@@ -111,16 +118,23 @@ export interface AgentConfig {
|
|
|
111
118
|
mcpDirectTools?: string[];
|
|
112
119
|
model?: string;
|
|
113
120
|
fallbackModels?: string[];
|
|
114
|
-
thinking?: string;
|
|
121
|
+
thinking?: string | false;
|
|
115
122
|
systemPromptMode: SystemPromptMode;
|
|
116
123
|
inheritProjectContext: boolean;
|
|
117
124
|
inheritSkills: boolean;
|
|
118
125
|
defaultContext?: AgentDefaultContext;
|
|
126
|
+
defaultAsync?: boolean;
|
|
127
|
+
defaultTimeoutMs?: number;
|
|
128
|
+
defaultTurnBudget?: TurnBudgetConfig;
|
|
129
|
+
defaultAcceptance?: AcceptanceInput;
|
|
130
|
+
acceptanceRole?: AcceptanceRole;
|
|
119
131
|
systemPrompt: string;
|
|
120
132
|
source: AgentSource;
|
|
121
133
|
filePath: string;
|
|
122
134
|
skills?: string[];
|
|
135
|
+
skillPath?: string[];
|
|
123
136
|
extensions?: string[];
|
|
137
|
+
extensionsFromDefault?: boolean;
|
|
124
138
|
subagentOnlyExtensions?: string[];
|
|
125
139
|
output?: string;
|
|
126
140
|
defaultReads?: string[];
|
|
@@ -139,6 +153,8 @@ export interface AgentConfig {
|
|
|
139
153
|
interface SubagentSettings {
|
|
140
154
|
overrides: Record<string, BuiltinAgentOverrideConfig>;
|
|
141
155
|
defaultModel?: string;
|
|
156
|
+
defaultThinking?: string;
|
|
157
|
+
defaultExtensions?: string[];
|
|
142
158
|
disableBuiltins?: boolean;
|
|
143
159
|
disableThinking?: boolean;
|
|
144
160
|
modelScope?: ModelScopeConfig;
|
|
@@ -301,6 +317,8 @@ function resolveSettingsPackageRoot(source: string, baseDir: string): string | u
|
|
|
301
317
|
}
|
|
302
318
|
|
|
303
319
|
function getGlobalNpmRoot(): string | null {
|
|
320
|
+
const offline = process.env.PI_OFFLINE?.toLowerCase();
|
|
321
|
+
if (offline === "1" || offline === "true" || offline === "yes") return null;
|
|
304
322
|
if (cachedGlobalNpmRoot !== null) return cachedGlobalNpmRoot;
|
|
305
323
|
try {
|
|
306
324
|
cachedGlobalNpmRoot = fs.realpathSync(execSync("npm root -g", { encoding: "utf-8", timeout: 5000 }).trim());
|
|
@@ -462,7 +480,7 @@ function splitToolList(rawTools: string[] | undefined): { tools?: string[]; mcpD
|
|
|
462
480
|
}
|
|
463
481
|
}
|
|
464
482
|
return {
|
|
465
|
-
...(
|
|
483
|
+
...(rawTools !== undefined ? { tools } : {}),
|
|
466
484
|
...(mcpDirectTools.length > 0 ? { mcpDirectTools } : {}),
|
|
467
485
|
};
|
|
468
486
|
}
|
|
@@ -494,11 +512,14 @@ function cloneOverrideBase(agent: AgentConfig): BuiltinAgentOverrideBase {
|
|
|
494
512
|
inheritProjectContext: agent.inheritProjectContext,
|
|
495
513
|
inheritSkills: agent.inheritSkills,
|
|
496
514
|
defaultContext: agent.defaultContext,
|
|
515
|
+
acceptanceRole: agent.acceptanceRole,
|
|
497
516
|
disabled: agent.disabled,
|
|
498
517
|
systemPrompt: agent.systemPrompt,
|
|
499
518
|
skills: agent.skills ? [...agent.skills] : undefined,
|
|
519
|
+
skillPath: agent.skillPath ? [...agent.skillPath] : undefined,
|
|
500
520
|
tools: agent.tools ? [...agent.tools] : undefined,
|
|
501
521
|
mcpDirectTools: agent.mcpDirectTools ? [...agent.mcpDirectTools] : undefined,
|
|
522
|
+
extensions: agent.extensionsFromDefault ? undefined : agent.extensions ? [...agent.extensions] : undefined,
|
|
502
523
|
subagentOnlyExtensions: agent.subagentOnlyExtensions ? [...agent.subagentOnlyExtensions] : undefined,
|
|
503
524
|
completionGuard: agent.completionGuard,
|
|
504
525
|
toolBudget: agent.toolBudget,
|
|
@@ -516,10 +537,12 @@ function cloneOverrideValue(override: BuiltinAgentOverrideConfig): BuiltinAgentO
|
|
|
516
537
|
...(override.inheritProjectContext !== undefined ? { inheritProjectContext: override.inheritProjectContext } : {}),
|
|
517
538
|
...(override.inheritSkills !== undefined ? { inheritSkills: override.inheritSkills } : {}),
|
|
518
539
|
...(override.defaultContext !== undefined ? { defaultContext: override.defaultContext } : {}),
|
|
540
|
+
...(override.acceptanceRole !== undefined ? { acceptanceRole: override.acceptanceRole } : {}),
|
|
519
541
|
...(override.disabled !== undefined ? { disabled: override.disabled } : {}),
|
|
520
542
|
...(override.systemPrompt !== undefined ? { systemPrompt: override.systemPrompt } : {}),
|
|
521
543
|
...(override.skills !== undefined ? { skills: override.skills === false ? false : [...override.skills] } : {}),
|
|
522
544
|
...(override.tools !== undefined ? { tools: override.tools === false ? false : [...override.tools] } : {}),
|
|
545
|
+
...(override.extensions !== undefined ? { extensions: override.extensions === false ? false : [...override.extensions] } : {}),
|
|
523
546
|
...(override.subagentOnlyExtensions !== undefined ? { subagentOnlyExtensions: override.subagentOnlyExtensions === false ? false : [...override.subagentOnlyExtensions] } : {}),
|
|
524
547
|
...(override.completionGuard !== undefined ? { completionGuard: override.completionGuard } : {}),
|
|
525
548
|
...(override.toolBudget !== undefined ? { toolBudget: override.toolBudget === false ? false : { ...override.toolBudget, ...(Array.isArray(override.toolBudget.block) ? { block: [...override.toolBudget.block] } : {}) } } : {}),
|
|
@@ -543,52 +566,6 @@ function getUserAgentSettingsPath(): string {
|
|
|
543
566
|
return path.join(getAgentDir(), "settings.json");
|
|
544
567
|
}
|
|
545
568
|
|
|
546
|
-
/**
|
|
547
|
-
* Seed the user-visible subagent configuration on first session startup.
|
|
548
|
-
*
|
|
549
|
-
* Builtin agents normally inherit the parent session model. Recording that
|
|
550
|
-
* model as `subagents.defaultModel` makes the default explicit. Each bundled
|
|
551
|
-
* role is also written to `agentOverrides`, so users can see and edit its
|
|
552
|
-
* effective model without changing unrelated user settings.
|
|
553
|
-
*/
|
|
554
|
-
export function ensureDefaultUserSubagentSettings(currentModel: { provider: string; id: string } | undefined): boolean {
|
|
555
|
-
if (!currentModel?.provider || !currentModel.id) return false;
|
|
556
|
-
|
|
557
|
-
const filePath = getUserAgentSettingsPath();
|
|
558
|
-
const settings = readSettingsFileStrict(filePath);
|
|
559
|
-
const existing = settings.subagents;
|
|
560
|
-
if (existing !== undefined && (!existing || typeof existing !== "object" || Array.isArray(existing))) return false;
|
|
561
|
-
|
|
562
|
-
const subagents = (existing ?? {}) as Record<string, unknown>;
|
|
563
|
-
const currentModelId = `${currentModel.provider}/${currentModel.id}`;
|
|
564
|
-
if ("defaultModel" in subagents && (typeof subagents.defaultModel !== "string" || !subagents.defaultModel.trim())) return false;
|
|
565
|
-
|
|
566
|
-
let changed = false;
|
|
567
|
-
if (!("defaultModel" in subagents)) {
|
|
568
|
-
subagents.defaultModel = currentModelId;
|
|
569
|
-
changed = true;
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
const defaultModel = subagents.defaultModel as string;
|
|
573
|
-
const overrides = subagents.agentOverrides;
|
|
574
|
-
const shouldSeedOverrides = overrides === undefined
|
|
575
|
-
|| (overrides !== null && typeof overrides === "object" && !Array.isArray(overrides) && Object.keys(overrides).length === 0);
|
|
576
|
-
if (shouldSeedOverrides) {
|
|
577
|
-
subagents.agentOverrides = Object.fromEntries(
|
|
578
|
-
loadAgentsFromDir(BUILTIN_AGENTS_DIR, "builtin").map((agent) => [
|
|
579
|
-
agent.name,
|
|
580
|
-
{ model: agent.model ?? defaultModel },
|
|
581
|
-
]),
|
|
582
|
-
);
|
|
583
|
-
changed = true;
|
|
584
|
-
}
|
|
585
|
-
if (!changed) return false;
|
|
586
|
-
|
|
587
|
-
settings.subagents = subagents;
|
|
588
|
-
writeSettingsFile(filePath, settings);
|
|
589
|
-
return true;
|
|
590
|
-
}
|
|
591
|
-
|
|
592
569
|
function getProjectAgentSettingsPath(cwd: string): string | null {
|
|
593
570
|
const projectRoot = findNearestProjectRoot(cwd);
|
|
594
571
|
return projectRoot ? path.join(getProjectConfigDir(projectRoot), "settings.json") : null;
|
|
@@ -697,6 +674,14 @@ function parseBuiltinOverrideEntry(
|
|
|
697
674
|
}
|
|
698
675
|
}
|
|
699
676
|
|
|
677
|
+
if ("acceptanceRole" in input) {
|
|
678
|
+
if (input.acceptanceRole === "read-only" || input.acceptanceRole === "writer" || input.acceptanceRole === false) {
|
|
679
|
+
override.acceptanceRole = input.acceptanceRole;
|
|
680
|
+
} else {
|
|
681
|
+
throw new Error(`Builtin override '${name}' in '${filePath}' has invalid 'acceptanceRole'; expected 'read-only', 'writer', or false.`);
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
|
|
700
685
|
if ("disabled" in input) {
|
|
701
686
|
if (typeof input.disabled === "boolean") {
|
|
702
687
|
override.disabled = input.disabled;
|
|
@@ -737,6 +722,9 @@ function parseBuiltinOverrideEntry(
|
|
|
737
722
|
const tools = parseOverrideStringArrayOrFalse(input.tools, { filePath, name, field: "tools" });
|
|
738
723
|
if (tools !== undefined) override.tools = tools;
|
|
739
724
|
|
|
725
|
+
const extensions = parseOverrideStringArrayOrFalse(input.extensions, { filePath, name, field: "extensions" });
|
|
726
|
+
if (extensions !== undefined) override.extensions = extensions;
|
|
727
|
+
|
|
740
728
|
const subagentOnlyExtensions = parseOverrideStringArrayOrFalse(input.subagentOnlyExtensions, { filePath, name, field: "subagentOnlyExtensions" });
|
|
741
729
|
if (subagentOnlyExtensions !== undefined) override.subagentOnlyExtensions = subagentOnlyExtensions;
|
|
742
730
|
|
|
@@ -774,18 +762,34 @@ function readSubagentSettings(filePath: string | null): SubagentSettings {
|
|
|
774
762
|
throw new Error(`Subagent settings in '${filePath}' have invalid 'defaultModel'; expected a non-empty string.`);
|
|
775
763
|
}
|
|
776
764
|
}
|
|
765
|
+
let defaultThinking: string | undefined;
|
|
766
|
+
if ("defaultThinking" in subagentsObject) {
|
|
767
|
+
if (typeof subagentsObject.defaultThinking === "string" && subagentsObject.defaultThinking.trim()) {
|
|
768
|
+
defaultThinking = subagentsObject.defaultThinking.trim();
|
|
769
|
+
} else {
|
|
770
|
+
throw new Error(`Subagent settings in '${filePath}' have invalid 'defaultThinking'; expected a non-empty string.`);
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
let defaultExtensions: string[] | undefined;
|
|
774
|
+
if ("defaultExtensions" in subagentsObject) {
|
|
775
|
+
if (!Array.isArray(subagentsObject.defaultExtensions)
|
|
776
|
+
|| subagentsObject.defaultExtensions.some((item) => typeof item !== "string" || !item.trim())) {
|
|
777
|
+
throw new Error(`Subagent settings in '${filePath}' have invalid 'defaultExtensions'; expected an array of non-empty strings.`);
|
|
778
|
+
}
|
|
779
|
+
defaultExtensions = subagentsObject.defaultExtensions.map((item) => item.trim());
|
|
780
|
+
}
|
|
777
781
|
const modelScope = parseModelScopeConfig(subagentsObject.modelScope, { filePath });
|
|
778
782
|
|
|
779
783
|
const parsed: Record<string, BuiltinAgentOverrideConfig> = {};
|
|
780
784
|
const agentOverrides = subagentsObject.agentOverrides;
|
|
781
785
|
if (!agentOverrides || typeof agentOverrides !== "object" || Array.isArray(agentOverrides)) {
|
|
782
|
-
return { overrides: parsed, defaultModel, disableBuiltins, disableThinking, modelScope };
|
|
786
|
+
return { overrides: parsed, defaultModel, defaultThinking, defaultExtensions, disableBuiltins, disableThinking, modelScope };
|
|
783
787
|
}
|
|
784
788
|
for (const [name, value] of Object.entries(agentOverrides)) {
|
|
785
789
|
const override = parseBuiltinOverrideEntry(name, value, filePath);
|
|
786
790
|
if (override) parsed[name] = override;
|
|
787
791
|
}
|
|
788
|
-
return { overrides: parsed, defaultModel, disableBuiltins, disableThinking, modelScope };
|
|
792
|
+
return { overrides: parsed, defaultModel, defaultThinking, defaultExtensions, disableBuiltins, disableThinking, modelScope };
|
|
789
793
|
}
|
|
790
794
|
|
|
791
795
|
function resolveSubagentDefaultModel(
|
|
@@ -813,6 +817,58 @@ function applySubagentDefaultModel(agents: AgentConfig[], defaultModel: AgentMod
|
|
|
813
817
|
});
|
|
814
818
|
}
|
|
815
819
|
|
|
820
|
+
function resolveSubagentDefaultThinking(
|
|
821
|
+
userSettings: SubagentSettings,
|
|
822
|
+
projectSettings: SubagentSettings,
|
|
823
|
+
projectSettingsPath: string | null,
|
|
824
|
+
): string | undefined {
|
|
825
|
+
if (projectSettingsPath && projectSettings.defaultThinking !== undefined) return projectSettings.defaultThinking;
|
|
826
|
+
return userSettings.defaultThinking;
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
function applySubagentDefaultThinking(agents: AgentConfig[], defaultThinking: string | undefined): AgentConfig[] {
|
|
830
|
+
if (defaultThinking === undefined) return agents;
|
|
831
|
+
return agents.map((agent) => {
|
|
832
|
+
if (agent.thinking !== undefined) return agent;
|
|
833
|
+
const next = { ...agent, thinking: defaultThinking };
|
|
834
|
+
const frontmatterFields = agentFrontmatterFields.get(agent);
|
|
835
|
+
if (frontmatterFields) agentFrontmatterFields.set(next, frontmatterFields);
|
|
836
|
+
return next;
|
|
837
|
+
});
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
function resolveSubagentDefaultExtensions(
|
|
841
|
+
userSettings: SubagentSettings,
|
|
842
|
+
projectSettings: SubagentSettings,
|
|
843
|
+
projectSettingsPath: string | null,
|
|
844
|
+
): string[] | undefined {
|
|
845
|
+
if (projectSettingsPath && projectSettings.defaultExtensions !== undefined) return projectSettings.defaultExtensions;
|
|
846
|
+
return userSettings.defaultExtensions;
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
function applySubagentDefaultExtensions(agents: AgentConfig[], defaultExtensions: string[] | undefined): AgentConfig[] {
|
|
850
|
+
if (defaultExtensions === undefined) return agents;
|
|
851
|
+
return agents.map((agent) => {
|
|
852
|
+
if (agent.extensions !== undefined) return agent;
|
|
853
|
+
const next = { ...agent, extensions: [...defaultExtensions], extensionsFromDefault: true };
|
|
854
|
+
const frontmatterFields = agentFrontmatterFields.get(agent);
|
|
855
|
+
if (frontmatterFields) agentFrontmatterFields.set(next, frontmatterFields);
|
|
856
|
+
return next;
|
|
857
|
+
});
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
function applySubagentDefaults(
|
|
861
|
+
agents: AgentConfig[],
|
|
862
|
+
defaultModel: AgentModelSourceInfo | undefined,
|
|
863
|
+
defaultThinking: string | undefined,
|
|
864
|
+
defaultExtensions: string[] | undefined,
|
|
865
|
+
): AgentConfig[] {
|
|
866
|
+
return applySubagentDefaultExtensions(
|
|
867
|
+
applySubagentDefaultThinking(applySubagentDefaultModel(agents, defaultModel), defaultThinking),
|
|
868
|
+
defaultExtensions,
|
|
869
|
+
);
|
|
870
|
+
}
|
|
871
|
+
|
|
816
872
|
function applyBuiltinOverride(
|
|
817
873
|
agent: AgentConfig,
|
|
818
874
|
override: BuiltinAgentOverrideConfig,
|
|
@@ -832,6 +888,7 @@ function applyBuiltinOverride(
|
|
|
832
888
|
if (override.inheritProjectContext !== undefined) next.inheritProjectContext = override.inheritProjectContext;
|
|
833
889
|
if (override.inheritSkills !== undefined) next.inheritSkills = override.inheritSkills;
|
|
834
890
|
if (override.defaultContext !== undefined) next.defaultContext = override.defaultContext === false ? undefined : override.defaultContext;
|
|
891
|
+
if (override.acceptanceRole !== undefined) next.acceptanceRole = override.acceptanceRole === false ? undefined : override.acceptanceRole;
|
|
835
892
|
if (override.disabled !== undefined) next.disabled = override.disabled;
|
|
836
893
|
if (override.systemPrompt !== undefined) next.systemPrompt = override.systemPrompt;
|
|
837
894
|
if (override.skills !== undefined) next.skills = override.skills === false ? undefined : [...override.skills];
|
|
@@ -840,6 +897,7 @@ function applyBuiltinOverride(
|
|
|
840
897
|
next.tools = tools;
|
|
841
898
|
next.mcpDirectTools = mcpDirectTools;
|
|
842
899
|
}
|
|
900
|
+
if (override.extensions !== undefined) next.extensions = override.extensions === false ? undefined : [...override.extensions];
|
|
843
901
|
if (override.subagentOnlyExtensions !== undefined) {
|
|
844
902
|
next.subagentOnlyExtensions = override.subagentOnlyExtensions === false ? undefined : [...override.subagentOnlyExtensions];
|
|
845
903
|
}
|
|
@@ -913,7 +971,7 @@ function applyBuiltinOverrides(
|
|
|
913
971
|
});
|
|
914
972
|
}
|
|
915
973
|
|
|
916
|
-
function
|
|
974
|
+
export function agentHasFrontmatterField(agent: AgentConfig, ...fields: string[]): boolean {
|
|
917
975
|
const frontmatterFields = agentFrontmatterFields.get(agent);
|
|
918
976
|
return frontmatterFields ? fields.some((field) => frontmatterFields.has(field)) : false;
|
|
919
977
|
}
|
|
@@ -936,7 +994,7 @@ function applyCustomAgentOverride(
|
|
|
936
994
|
frontmatterFields: string[],
|
|
937
995
|
value: AgentConfig[K],
|
|
938
996
|
): void => {
|
|
939
|
-
if (
|
|
997
|
+
if (agentHasFrontmatterField(agent, ...frontmatterFields)) return;
|
|
940
998
|
mutable()[field] = value;
|
|
941
999
|
anyFilled = true;
|
|
942
1000
|
};
|
|
@@ -966,6 +1024,9 @@ function applyCustomAgentOverride(
|
|
|
966
1024
|
if (override.defaultContext !== undefined) {
|
|
967
1025
|
fill("defaultContext", ["defaultContext"], override.defaultContext === false ? undefined : override.defaultContext);
|
|
968
1026
|
}
|
|
1027
|
+
if (override.acceptanceRole !== undefined) {
|
|
1028
|
+
fill("acceptanceRole", ["acceptanceRole"], override.acceptanceRole === false ? undefined : override.acceptanceRole);
|
|
1029
|
+
}
|
|
969
1030
|
if (override.disabled !== undefined && agent.disabled === undefined) {
|
|
970
1031
|
mutable().disabled = override.disabled;
|
|
971
1032
|
anyFilled = true;
|
|
@@ -973,13 +1034,16 @@ function applyCustomAgentOverride(
|
|
|
973
1034
|
if (override.skills !== undefined) {
|
|
974
1035
|
fill("skills", ["skill", "skills"], override.skills === false ? undefined : [...override.skills]);
|
|
975
1036
|
}
|
|
976
|
-
if (override.tools !== undefined && !
|
|
1037
|
+
if (override.tools !== undefined && !agentHasFrontmatterField(agent, "tools")) {
|
|
977
1038
|
const { tools, mcpDirectTools } = splitToolList(override.tools === false ? [] : override.tools);
|
|
978
1039
|
const target = mutable();
|
|
979
1040
|
target.tools = tools;
|
|
980
1041
|
target.mcpDirectTools = mcpDirectTools;
|
|
981
1042
|
anyFilled = true;
|
|
982
1043
|
}
|
|
1044
|
+
if (override.extensions !== undefined) {
|
|
1045
|
+
fill("extensions", ["extensions"], override.extensions === false ? undefined : [...override.extensions]);
|
|
1046
|
+
}
|
|
983
1047
|
if (override.subagentOnlyExtensions !== undefined) {
|
|
984
1048
|
fill(
|
|
985
1049
|
"subagentOnlyExtensions",
|
|
@@ -996,6 +1060,8 @@ function applyCustomAgentOverride(
|
|
|
996
1060
|
|
|
997
1061
|
if (!anyFilled || !next) return agent;
|
|
998
1062
|
next.override = { ...meta, base: cloneOverrideBase(agent) };
|
|
1063
|
+
const frontmatterFields = agentFrontmatterFields.get(agent);
|
|
1064
|
+
if (frontmatterFields) agentFrontmatterFields.set(next, frontmatterFields);
|
|
999
1065
|
return next;
|
|
1000
1066
|
}
|
|
1001
1067
|
|
|
@@ -1023,7 +1089,7 @@ function applyCustomAgentOverrides(
|
|
|
1023
1089
|
|
|
1024
1090
|
export function buildBuiltinOverrideConfig(
|
|
1025
1091
|
base: BuiltinAgentOverrideBase,
|
|
1026
|
-
draft: Pick<AgentConfig, "model" | "fallbackModels" | "thinking" | "systemPromptMode" | "inheritProjectContext" | "inheritSkills" | "defaultContext" | "disabled" | "systemPrompt" | "skills" | "tools" | "mcpDirectTools" | "subagentOnlyExtensions" | "completionGuard" | "toolBudget">,
|
|
1092
|
+
draft: Pick<AgentConfig, "model" | "fallbackModels" | "thinking" | "systemPromptMode" | "inheritProjectContext" | "inheritSkills" | "defaultContext" | "acceptanceRole" | "disabled" | "systemPrompt" | "skills" | "tools" | "mcpDirectTools" | "extensions" | "subagentOnlyExtensions" | "completionGuard" | "toolBudget">,
|
|
1027
1093
|
): BuiltinAgentOverrideConfig | undefined {
|
|
1028
1094
|
const override: BuiltinAgentOverrideConfig = {};
|
|
1029
1095
|
|
|
@@ -1034,6 +1100,7 @@ export function buildBuiltinOverrideConfig(
|
|
|
1034
1100
|
if (draft.inheritProjectContext !== base.inheritProjectContext) override.inheritProjectContext = draft.inheritProjectContext;
|
|
1035
1101
|
if (draft.inheritSkills !== base.inheritSkills) override.inheritSkills = draft.inheritSkills;
|
|
1036
1102
|
if (draft.defaultContext !== base.defaultContext) override.defaultContext = draft.defaultContext ?? false;
|
|
1103
|
+
if (draft.acceptanceRole !== base.acceptanceRole) override.acceptanceRole = draft.acceptanceRole ?? false;
|
|
1037
1104
|
if (draft.disabled !== base.disabled) override.disabled = draft.disabled ?? false;
|
|
1038
1105
|
if (draft.systemPrompt !== base.systemPrompt) override.systemPrompt = draft.systemPrompt;
|
|
1039
1106
|
if (!arraysEqual(draft.skills, base.skills)) override.skills = draft.skills ? [...draft.skills] : false;
|
|
@@ -1041,6 +1108,7 @@ export function buildBuiltinOverrideConfig(
|
|
|
1041
1108
|
const baseTools = joinToolList(base);
|
|
1042
1109
|
const draftTools = joinToolList(draft);
|
|
1043
1110
|
if (!arraysEqual(draftTools, baseTools)) override.tools = draftTools ? [...draftTools] : false;
|
|
1111
|
+
if (!arraysEqual(draft.extensions, base.extensions)) override.extensions = draft.extensions ? [...draft.extensions] : false;
|
|
1044
1112
|
if (!arraysEqual(draft.subagentOnlyExtensions, base.subagentOnlyExtensions)) {
|
|
1045
1113
|
override.subagentOnlyExtensions = draft.subagentOnlyExtensions ? [...draft.subagentOnlyExtensions] : false;
|
|
1046
1114
|
}
|
|
@@ -1173,7 +1241,19 @@ export function removeBuiltinAgentOverrideFields(
|
|
|
1173
1241
|
return { path: filePath, removed: true };
|
|
1174
1242
|
}
|
|
1175
1243
|
|
|
1176
|
-
|
|
1244
|
+
const DISCOVERY_PRUNED_DIR_NAMES = new Set([".git", "node_modules"]);
|
|
1245
|
+
|
|
1246
|
+
function isDiscoveryNestedProjectRoot(dir: string): boolean {
|
|
1247
|
+
return isDirectory(getProjectConfigDir(dir)) || isDirectory(path.join(dir, ".agents"));
|
|
1248
|
+
}
|
|
1249
|
+
|
|
1250
|
+
function shouldPruneDiscoveryDir(rootDir: string, dir: string, dirName: string): boolean {
|
|
1251
|
+
if (DISCOVERY_PRUNED_DIR_NAMES.has(dirName)) return true;
|
|
1252
|
+
if (fs.existsSync(path.join(dir, ".git"))) return true;
|
|
1253
|
+
return path.resolve(dir) !== path.resolve(rootDir) && isDiscoveryNestedProjectRoot(dir);
|
|
1254
|
+
}
|
|
1255
|
+
|
|
1256
|
+
function listFilesRecursive(dir: string, predicate: (fileName: string) => boolean, rootDir = dir): string[] {
|
|
1177
1257
|
const files: string[] = [];
|
|
1178
1258
|
if (!fs.existsSync(dir)) return files;
|
|
1179
1259
|
|
|
@@ -1187,7 +1267,9 @@ function listFilesRecursive(dir: string, predicate: (fileName: string) => boolea
|
|
|
1187
1267
|
for (const entry of entries) {
|
|
1188
1268
|
const filePath = path.join(dir, entry.name);
|
|
1189
1269
|
if (entry.isDirectory()) {
|
|
1190
|
-
|
|
1270
|
+
if (!shouldPruneDiscoveryDir(rootDir, filePath, entry.name)) {
|
|
1271
|
+
files.push(...listFilesRecursive(filePath, predicate, rootDir));
|
|
1272
|
+
}
|
|
1191
1273
|
continue;
|
|
1192
1274
|
}
|
|
1193
1275
|
if (!entry.isFile() && !entry.isSymbolicLink()) continue;
|
|
@@ -1206,6 +1288,19 @@ function isLegacyAgentSkillPath(rootDir: string, filePath: string): boolean {
|
|
|
1206
1288
|
return parts.some((part, index) => part === ".agents" && parts[index + 1] === "skills");
|
|
1207
1289
|
}
|
|
1208
1290
|
|
|
1291
|
+
function parseAgentAcceptanceFrontmatter(raw: string | undefined, agentName: string): AcceptanceInput | undefined {
|
|
1292
|
+
if (raw === undefined || !raw.trim()) return undefined;
|
|
1293
|
+
let parsed: unknown;
|
|
1294
|
+
try {
|
|
1295
|
+
parsed = parseYaml(raw);
|
|
1296
|
+
} catch (error) {
|
|
1297
|
+
throw new Error(`Agent '${agentName}' has invalid acceptance frontmatter: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
|
|
1298
|
+
}
|
|
1299
|
+
const errors = validateAcceptanceInput(parsed, `Agent '${agentName}' acceptance frontmatter`);
|
|
1300
|
+
if (errors.length > 0) throw new Error(errors.join(" "));
|
|
1301
|
+
return parsed as AcceptanceInput;
|
|
1302
|
+
}
|
|
1303
|
+
|
|
1209
1304
|
function loadAgentsFromDir(dir: string, source: AgentSource): AgentConfig[] {
|
|
1210
1305
|
const agents: AgentConfig[] = [];
|
|
1211
1306
|
|
|
@@ -1233,37 +1328,15 @@ function loadAgentsFromDir(dir: string, source: AgentSource): AgentConfig[] {
|
|
|
1233
1328
|
const packageName = parsedPackage.packageName;
|
|
1234
1329
|
const runtimeName = buildRuntimeName(localName, packageName);
|
|
1235
1330
|
|
|
1236
|
-
const rawTools = frontmatter.tools
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
const mcpDirectTools: string[] = [];
|
|
1242
|
-
const tools: string[] = [];
|
|
1243
|
-
if (rawTools) {
|
|
1244
|
-
for (const tool of rawTools) {
|
|
1245
|
-
if (tool.startsWith("mcp:")) {
|
|
1246
|
-
mcpDirectTools.push(tool.slice(4));
|
|
1247
|
-
} else {
|
|
1248
|
-
tools.push(tool);
|
|
1249
|
-
}
|
|
1250
|
-
}
|
|
1251
|
-
}
|
|
1252
|
-
|
|
1253
|
-
const defaultReads = frontmatter.defaultReads
|
|
1254
|
-
?.split(",")
|
|
1255
|
-
.map((f) => f.trim())
|
|
1256
|
-
.filter(Boolean);
|
|
1257
|
-
|
|
1331
|
+
const rawTools = parseFrontmatterList(frontmatter.tools);
|
|
1332
|
+
const parsedTools = splitToolList(rawTools);
|
|
1333
|
+
const tools = parsedTools.tools ?? [];
|
|
1334
|
+
const mcpDirectTools = parsedTools.mcpDirectTools ?? [];
|
|
1335
|
+
const defaultReads = parseFrontmatterList(frontmatter.defaultReads);
|
|
1258
1336
|
const skillStr = frontmatter.skill || frontmatter.skills;
|
|
1259
|
-
const skills = skillStr
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
.filter(Boolean);
|
|
1263
|
-
const fallbackModels = frontmatter.fallbackModels
|
|
1264
|
-
?.split(",")
|
|
1265
|
-
.map((model) => model.trim())
|
|
1266
|
-
.filter(Boolean);
|
|
1337
|
+
const skills = parseFrontmatterList(skillStr);
|
|
1338
|
+
const skillPath = parseFrontmatterList(frontmatter.skillPath);
|
|
1339
|
+
const fallbackModels = parseFrontmatterList(frontmatter.fallbackModels);
|
|
1267
1340
|
const systemPromptMode = frontmatter.systemPromptMode === "replace"
|
|
1268
1341
|
? "replace"
|
|
1269
1342
|
: frontmatter.systemPromptMode === "append"
|
|
@@ -1284,21 +1357,36 @@ function loadAgentsFromDir(dir: string, source: AgentSource): AgentConfig[] {
|
|
|
1284
1357
|
: frontmatter.defaultContext === "fresh"
|
|
1285
1358
|
? "fresh" as const
|
|
1286
1359
|
: undefined;
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
.map((e) => e.trim())
|
|
1293
|
-
.filter(Boolean);
|
|
1360
|
+
let defaultAsync: boolean | undefined;
|
|
1361
|
+
if (frontmatter.async !== undefined) {
|
|
1362
|
+
if (frontmatter.async === "true") defaultAsync = true;
|
|
1363
|
+
else if (frontmatter.async === "false") defaultAsync = false;
|
|
1364
|
+
else throw new Error(`Agent '${localName}' has invalid async frontmatter; expected true or false.`);
|
|
1294
1365
|
}
|
|
1295
|
-
let
|
|
1296
|
-
if (frontmatter.
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1366
|
+
let defaultTimeoutMs: number | undefined;
|
|
1367
|
+
if (frontmatter.timeoutMs !== undefined) {
|
|
1368
|
+
const parsed = Number(frontmatter.timeoutMs);
|
|
1369
|
+
if (!Number.isInteger(parsed) || parsed <= 0) {
|
|
1370
|
+
throw new Error(`Agent '${localName}' has invalid timeoutMs frontmatter; expected a positive integer.`);
|
|
1371
|
+
}
|
|
1372
|
+
defaultTimeoutMs = parsed;
|
|
1373
|
+
}
|
|
1374
|
+
let defaultTurnBudget: TurnBudgetConfig | undefined;
|
|
1375
|
+
if (frontmatter.turnBudget !== undefined && frontmatter.turnBudget.trim()) {
|
|
1376
|
+
const parsed = JSON.parse(frontmatter.turnBudget) as unknown;
|
|
1377
|
+
const resolved = resolveTurnBudgetConfig(parsed, `Agent '${localName}' turnBudget frontmatter`);
|
|
1378
|
+
if (resolved.error) throw new Error(resolved.error);
|
|
1379
|
+
defaultTurnBudget = resolved.turnBudget;
|
|
1301
1380
|
}
|
|
1381
|
+
const defaultAcceptance = parseAgentAcceptanceFrontmatter(frontmatter.acceptance, localName);
|
|
1382
|
+
let acceptanceRole: AcceptanceRole | undefined;
|
|
1383
|
+
if (frontmatter.acceptanceRole !== undefined && frontmatter.acceptanceRole.trim()) {
|
|
1384
|
+
if (frontmatter.acceptanceRole === "read-only" || frontmatter.acceptanceRole === "writer") acceptanceRole = frontmatter.acceptanceRole;
|
|
1385
|
+
else throw new Error(`Agent '${localName}' has invalid acceptanceRole frontmatter; expected 'read-only' or 'writer'.`);
|
|
1386
|
+
}
|
|
1387
|
+
|
|
1388
|
+
const extensions = parseFrontmatterList(frontmatter.extensions);
|
|
1389
|
+
const subagentOnlyExtensions = parseFrontmatterList(frontmatter.subagentOnlyExtensions);
|
|
1302
1390
|
|
|
1303
1391
|
const extraFields: Record<string, string> = {};
|
|
1304
1392
|
for (const [key, value] of Object.entries(frontmatter)) {
|
|
@@ -1325,19 +1413,25 @@ function loadAgentsFromDir(dir: string, source: AgentSource): AgentConfig[] {
|
|
|
1325
1413
|
localName,
|
|
1326
1414
|
packageName,
|
|
1327
1415
|
description: frontmatter.description,
|
|
1328
|
-
tools:
|
|
1416
|
+
tools: rawTools !== undefined ? tools : undefined,
|
|
1329
1417
|
mcpDirectTools: mcpDirectTools.length > 0 ? mcpDirectTools : undefined,
|
|
1330
1418
|
model: frontmatter.model,
|
|
1331
1419
|
fallbackModels: fallbackModels && fallbackModels.length > 0 ? fallbackModels : undefined,
|
|
1332
|
-
thinking: frontmatter.thinking,
|
|
1420
|
+
thinking: frontmatter.thinking === "false" ? false : frontmatter.thinking,
|
|
1333
1421
|
systemPromptMode,
|
|
1334
1422
|
inheritProjectContext,
|
|
1335
1423
|
inheritSkills,
|
|
1336
1424
|
defaultContext,
|
|
1425
|
+
defaultAsync,
|
|
1426
|
+
defaultTimeoutMs,
|
|
1427
|
+
defaultTurnBudget,
|
|
1428
|
+
defaultAcceptance,
|
|
1429
|
+
acceptanceRole,
|
|
1337
1430
|
systemPrompt: body,
|
|
1338
1431
|
source,
|
|
1339
1432
|
filePath,
|
|
1340
1433
|
skills: skills && skills.length > 0 ? skills : undefined,
|
|
1434
|
+
skillPath: skillPath && skillPath.length > 0 ? skillPath : undefined,
|
|
1341
1435
|
extensions,
|
|
1342
1436
|
subagentOnlyExtensions,
|
|
1343
1437
|
output: frontmatter.output,
|
|
@@ -1447,6 +1541,8 @@ export function discoverAgents(cwd: string, scope: AgentScope): AgentDiscoveryRe
|
|
|
1447
1541
|
const userSettings = scope === "project" ? EMPTY_SUBAGENT_SETTINGS : readSubagentSettings(userSettingsPath);
|
|
1448
1542
|
const projectSettings = scope === "user" ? EMPTY_SUBAGENT_SETTINGS : readSubagentSettings(projectSettingsPath);
|
|
1449
1543
|
const defaultModel = resolveSubagentDefaultModel(userSettings, projectSettings, userSettingsPath, projectSettingsPath);
|
|
1544
|
+
const defaultThinking = resolveSubagentDefaultThinking(userSettings, projectSettings, projectSettingsPath);
|
|
1545
|
+
const defaultExtensions = resolveSubagentDefaultExtensions(userSettings, projectSettings, projectSettingsPath);
|
|
1450
1546
|
const modelScope = projectSettings.modelScope ?? userSettings.modelScope;
|
|
1451
1547
|
const packageSubagentPaths = collectPackageSubagentPaths(cwd, {
|
|
1452
1548
|
includeUser: scope !== "project",
|
|
@@ -1454,7 +1550,7 @@ export function discoverAgents(cwd: string, scope: AgentScope): AgentDiscoveryRe
|
|
|
1454
1550
|
});
|
|
1455
1551
|
|
|
1456
1552
|
const builtinAgents = applyBuiltinOverrides(
|
|
1457
|
-
|
|
1553
|
+
applySubagentDefaults(loadAgentsFromDir(BUILTIN_AGENTS_DIR, "builtin"), defaultModel, defaultThinking, defaultExtensions),
|
|
1458
1554
|
userSettings,
|
|
1459
1555
|
projectSettings,
|
|
1460
1556
|
userSettingsPath,
|
|
@@ -1465,7 +1561,7 @@ export function discoverAgents(cwd: string, scope: AgentScope): AgentDiscoveryRe
|
|
|
1465
1561
|
const userAgentsOld = scope === "project" ? [] : loadAgentsFromDir(userDirOld, "user");
|
|
1466
1562
|
const userAgentsNew = scope === "project" ? [] : loadAgentsFromDir(userDirNew, "user");
|
|
1467
1563
|
const userAgents = applyCustomAgentOverrides(
|
|
1468
|
-
|
|
1564
|
+
applySubagentDefaults([...userAgentsExtra, ...userAgentsOld, ...userAgentsNew], defaultModel, defaultThinking, defaultExtensions),
|
|
1469
1565
|
userSettings,
|
|
1470
1566
|
projectSettings,
|
|
1471
1567
|
userSettingsPath,
|
|
@@ -1473,14 +1569,14 @@ export function discoverAgents(cwd: string, scope: AgentScope): AgentDiscoveryRe
|
|
|
1473
1569
|
);
|
|
1474
1570
|
|
|
1475
1571
|
const projectAgents = applyCustomAgentOverrides(
|
|
1476
|
-
|
|
1572
|
+
applySubagentDefaults(scope === "user" ? [] : projectAgentDirs.flatMap((dir) => loadAgentsFromDir(dir, "project")), defaultModel, defaultThinking, defaultExtensions),
|
|
1477
1573
|
userSettings,
|
|
1478
1574
|
projectSettings,
|
|
1479
1575
|
userSettingsPath,
|
|
1480
1576
|
projectSettingsPath,
|
|
1481
1577
|
);
|
|
1482
1578
|
const packageAgents = applyCustomAgentOverrides(
|
|
1483
|
-
|
|
1579
|
+
applySubagentDefaults(packageSubagentPaths.agents.flatMap((dir) => loadAgentsFromDir(dir, "package")), defaultModel, defaultThinking, defaultExtensions),
|
|
1484
1580
|
userSettings,
|
|
1485
1581
|
projectSettings,
|
|
1486
1582
|
userSettingsPath,
|
|
@@ -1516,21 +1612,23 @@ export function discoverAgentsAll(cwd: string): {
|
|
|
1516
1612
|
const userSettings = readSubagentSettings(userSettingsPath);
|
|
1517
1613
|
const projectSettings = readSubagentSettings(projectSettingsPath);
|
|
1518
1614
|
const defaultModel = resolveSubagentDefaultModel(userSettings, projectSettings, userSettingsPath, projectSettingsPath);
|
|
1615
|
+
const defaultThinking = resolveSubagentDefaultThinking(userSettings, projectSettings, projectSettingsPath);
|
|
1616
|
+
const defaultExtensions = resolveSubagentDefaultExtensions(userSettings, projectSettings, projectSettingsPath);
|
|
1519
1617
|
const packageSubagentPaths = collectPackageSubagentPaths(cwd);
|
|
1520
1618
|
|
|
1521
1619
|
const builtin = applyBuiltinOverrides(
|
|
1522
|
-
|
|
1620
|
+
applySubagentDefaults(loadAgentsFromDir(BUILTIN_AGENTS_DIR, "builtin"), defaultModel, defaultThinking, defaultExtensions),
|
|
1523
1621
|
userSettings,
|
|
1524
1622
|
projectSettings,
|
|
1525
1623
|
userSettingsPath,
|
|
1526
1624
|
projectSettingsPath,
|
|
1527
1625
|
);
|
|
1528
1626
|
const user = applyCustomAgentOverrides(
|
|
1529
|
-
|
|
1627
|
+
applySubagentDefaults([
|
|
1530
1628
|
...extraUserAgentDirs().flatMap((dir) => loadAgentsFromDir(dir, "user")),
|
|
1531
1629
|
...loadAgentsFromDir(userDirOld, "user"),
|
|
1532
1630
|
...loadAgentsFromDir(userDirNew, "user"),
|
|
1533
|
-
], defaultModel),
|
|
1631
|
+
], defaultModel, defaultThinking, defaultExtensions),
|
|
1534
1632
|
userSettings,
|
|
1535
1633
|
projectSettings,
|
|
1536
1634
|
userSettingsPath,
|
|
@@ -1543,7 +1641,7 @@ export function discoverAgentsAll(cwd: string): {
|
|
|
1543
1641
|
}
|
|
1544
1642
|
}
|
|
1545
1643
|
const packageAgents = applyCustomAgentOverrides(
|
|
1546
|
-
|
|
1644
|
+
applySubagentDefaults(Array.from(packageMap.values()), defaultModel, defaultThinking, defaultExtensions),
|
|
1547
1645
|
userSettings,
|
|
1548
1646
|
projectSettings,
|
|
1549
1647
|
userSettingsPath,
|
|
@@ -1556,7 +1654,7 @@ export function discoverAgentsAll(cwd: string): {
|
|
|
1556
1654
|
}
|
|
1557
1655
|
}
|
|
1558
1656
|
const project = applyCustomAgentOverrides(
|
|
1559
|
-
|
|
1657
|
+
applySubagentDefaults(Array.from(projectMap.values()), defaultModel, defaultThinking, defaultExtensions),
|
|
1560
1658
|
userSettings,
|
|
1561
1659
|
projectSettings,
|
|
1562
1660
|
userSettingsPath,
|