@selesai/code 0.5.28 → 0.6.1
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/CHANGELOG.md +24 -0
- package/README.md +1 -1
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +9 -1
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/config-selector.d.ts.map +1 -1
- package/dist/cli/config-selector.js +1 -1
- package/dist/cli/config-selector.js.map +1 -1
- package/dist/cli/credential-print.d.ts +23 -0
- package/dist/cli/credential-print.d.ts.map +1 -0
- package/dist/cli/credential-print.js +117 -0
- package/dist/cli/credential-print.js.map +1 -0
- package/dist/cli/startup-ui.d.ts.map +1 -1
- package/dist/cli/startup-ui.js +1 -1
- package/dist/cli/startup-ui.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +3 -0
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session.d.ts +12 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +20 -14
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +11 -3
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +1 -0
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +11 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +14 -1
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/footer-data-provider.d.ts +10 -0
- package/dist/core/footer-data-provider.d.ts.map +1 -1
- package/dist/core/footer-data-provider.js +1 -1
- package/dist/core/footer-data-provider.js.map +1 -1
- package/dist/core/llama/provider.d.ts.map +1 -1
- package/dist/core/llama/provider.js +8 -3
- package/dist/core/llama/provider.js.map +1 -1
- package/dist/core/model-config.d.ts +30 -0
- package/dist/core/model-config.d.ts.map +1 -1
- package/dist/core/model-config.js +6 -0
- package/dist/core/model-config.js.map +1 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +2 -2
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts +1 -0
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +20 -3
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/model-runtime.d.ts +2 -0
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +5 -4
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +13 -6
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/remote-catalog-provider.d.ts +1 -1
- package/dist/core/remote-catalog-provider.d.ts.map +1 -1
- package/dist/core/remote-catalog-provider.js +24 -11
- package/dist/core/remote-catalog-provider.js.map +1 -1
- package/dist/core/resource-loader.d.ts +15 -0
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +66 -9
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/settings-manager.d.ts +1 -1
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +19 -1
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/system-prompt.test.d.ts +2 -0
- package/dist/core/system-prompt.test.d.ts.map +1 -0
- package/dist/core/system-prompt.test.js +89 -0
- package/dist/core/system-prompt.test.js.map +1 -0
- package/dist/core/tools/bash.d.ts +2 -0
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +34 -5
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.js +3 -1
- package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
- package/dist/defaults/models.json +13 -45
- package/dist/defaults/settings.json +1 -2
- package/dist/extensions/copy-turn.test.ts +131 -0
- package/dist/extensions/copy-turn.ts +6 -1
- package/dist/extensions/package.json +0 -1
- package/dist/extensions/pi-intercom/CHANGELOG.md +249 -0
- package/dist/extensions/pi-intercom/README.md +102 -39
- package/dist/extensions/pi-intercom/broker/broker.ts +1233 -36
- package/dist/extensions/pi-intercom/broker/client.test.ts +83 -0
- package/dist/extensions/pi-intercom/broker/client.ts +315 -12
- package/dist/extensions/pi-intercom/broker/extension-state.ts +186 -0
- package/dist/extensions/pi-intercom/broker/extension.test.ts +387 -0
- package/dist/extensions/pi-intercom/broker/framing.test.ts +114 -0
- package/dist/extensions/pi-intercom/broker/framing.ts +82 -24
- package/dist/extensions/pi-intercom/broker/paths.test.ts +153 -0
- package/dist/extensions/pi-intercom/broker/paths.ts +117 -8
- package/dist/extensions/pi-intercom/broker/runtime-claim.test.ts +34 -0
- package/dist/extensions/pi-intercom/broker/runtime-claim.ts +21 -0
- package/dist/extensions/pi-intercom/broker/spawn.test.ts +160 -23
- package/dist/extensions/pi-intercom/broker/spawn.ts +113 -27
- package/dist/extensions/pi-intercom/config.test.ts +93 -0
- package/dist/extensions/pi-intercom/config.ts +55 -6
- package/dist/extensions/pi-intercom/cwd.test.ts +40 -0
- package/dist/extensions/pi-intercom/cwd.ts +31 -0
- package/dist/extensions/pi-intercom/extension-api.ts +44 -0
- package/dist/extensions/pi-intercom/format-context.test.ts +31 -0
- package/dist/extensions/pi-intercom/format-context.ts +32 -0
- package/dist/extensions/pi-intercom/index.ts +742 -145
- package/dist/extensions/pi-intercom/intercom.integration.test.ts +2646 -0
- package/dist/extensions/pi-intercom/package.json +15 -5
- package/dist/extensions/pi-intercom/reply-tracker.test.ts +134 -0
- package/dist/extensions/pi-intercom/reply-tracker.ts +31 -13
- package/dist/extensions/pi-intercom/skills/pi-intercom/SKILL.md +13 -11
- package/dist/extensions/pi-intercom/test/inline-message.test.ts +184 -0
- package/dist/extensions/pi-intercom/test/overlay-width.test.ts +66 -0
- package/dist/extensions/pi-intercom/types.ts +94 -4
- package/dist/extensions/pi-intercom/ui/compose.ts +8 -4
- package/dist/extensions/pi-intercom/ui/inline-message.ts +61 -25
- package/dist/extensions/pi-intercom/ui/session-list.ts +7 -3
- package/dist/extensions/pi-subagents/CHANGELOG.md +88 -0
- package/dist/extensions/pi-subagents/LICENSE +21 -0
- package/dist/extensions/pi-subagents/README.md +158 -69
- package/dist/extensions/pi-subagents/agents/architect.md +5 -4
- package/dist/extensions/pi-subagents/agents/builder.md +6 -4
- package/dist/extensions/pi-subagents/agents/commentator.md +3 -2
- package/dist/extensions/pi-subagents/agents/explorer.md +3 -2
- package/dist/extensions/pi-subagents/agents/recapper.md +3 -2
- package/dist/extensions/pi-subagents/agents/researcher.md +4 -3
- package/dist/extensions/pi-subagents/package-lock.json +2 -2
- package/dist/extensions/pi-subagents/package.json +3 -3
- package/dist/extensions/pi-subagents/prompts/review-loop.md +1 -1
- package/dist/extensions/pi-subagents/skills/pi-subagents/SKILL.md +22 -988
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/constraints-and-recipes.md +257 -0
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/execution-controls.md +431 -0
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/management-authoring-rpc.md +144 -0
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/prompting-and-roles.md +281 -0
- package/dist/extensions/pi-subagents/src/agents/agent-management.ts +125 -37
- package/dist/extensions/pi-subagents/src/agents/agent-serializer.ts +4 -0
- package/dist/extensions/pi-subagents/src/agents/agents.ts +118 -9
- package/dist/extensions/pi-subagents/src/agents/skills.ts +14 -12
- package/dist/extensions/pi-subagents/src/agents/task-aware-routing.ts +125 -0
- package/dist/extensions/pi-subagents/src/api/delegation.ts +3 -0
- package/dist/extensions/pi-subagents/src/api/preflight.ts +17 -13
- package/dist/extensions/pi-subagents/src/extension/chain-validation.ts +17 -1
- package/dist/extensions/pi-subagents/src/extension/index.ts +22 -8
- package/dist/extensions/pi-subagents/src/extension/rpc.ts +248 -6
- package/dist/extensions/pi-subagents/src/extension/schemas.ts +33 -8
- package/dist/extensions/pi-subagents/src/extension/tool-description.ts +32 -14
- package/dist/extensions/pi-subagents/src/intercom/intercom-bridge.ts +9 -4
- package/dist/extensions/pi-subagents/src/intercom/result-intercom.ts +33 -4
- package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +86 -21
- package/dist/extensions/pi-subagents/src/runs/background/async-job-tracker.ts +24 -13
- package/dist/extensions/pi-subagents/src/runs/background/async-resume.ts +7 -5
- package/dist/extensions/pi-subagents/src/runs/background/async-status.ts +18 -2
- package/dist/extensions/pi-subagents/src/runs/background/chain-append.ts +48 -5
- package/dist/extensions/pi-subagents/src/runs/background/control-channel.ts +68 -1
- package/dist/extensions/pi-subagents/src/runs/background/notify.ts +56 -5
- package/dist/extensions/pi-subagents/src/runs/background/result-watcher.ts +92 -11
- package/dist/extensions/pi-subagents/src/runs/background/run-status.ts +29 -3
- package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +388 -29
- package/dist/extensions/pi-subagents/src/runs/foreground/async-stop-action.ts +65 -0
- package/dist/extensions/pi-subagents/src/runs/foreground/chain-clarify.ts +3 -3
- package/dist/extensions/pi-subagents/src/runs/foreground/chain-execution.ts +214 -60
- package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +546 -252
- package/dist/extensions/pi-subagents/src/runs/foreground/foreground-control.ts +42 -0
- package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +553 -154
- package/dist/extensions/pi-subagents/src/runs/shared/acceptance.ts +19 -13
- package/dist/extensions/pi-subagents/src/runs/shared/capability-ceiling.ts +51 -19
- package/dist/extensions/pi-subagents/src/runs/shared/chain-outputs.ts +3 -1
- package/dist/extensions/pi-subagents/src/runs/shared/dynamic-fanout.ts +1 -1
- package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +44 -11
- package/dist/extensions/pi-subagents/src/runs/shared/model-fallback.ts +8 -0
- package/dist/extensions/pi-subagents/src/runs/shared/nested-events.ts +97 -20
- package/dist/extensions/pi-subagents/src/runs/shared/parallel-utils.ts +43 -12
- package/dist/extensions/pi-subagents/src/runs/shared/pi-args.ts +52 -4
- package/dist/extensions/pi-subagents/src/runs/shared/process-signal.ts +19 -0
- package/dist/extensions/pi-subagents/src/runs/shared/run-history.ts +45 -9
- package/dist/extensions/pi-subagents/src/runs/shared/runtime-acknowledged-extensions.ts +71 -0
- package/dist/extensions/pi-subagents/src/runs/shared/single-output.ts +63 -9
- package/dist/extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.ts +31 -1
- package/dist/extensions/pi-subagents/src/runs/shared/subagent-startup-retry.ts +101 -0
- package/dist/extensions/pi-subagents/src/runs/shared/task-intent.ts +22 -1
- package/dist/extensions/pi-subagents/src/runs/shared/usage-budget.ts +65 -0
- package/dist/extensions/pi-subagents/src/runs/shared/workflow-graph.ts +26 -1
- package/dist/extensions/pi-subagents/src/shared/settings.ts +17 -1
- package/dist/extensions/pi-subagents/src/shared/types.ts +196 -12
- package/dist/extensions/pi-subagents/src/shared/utils.ts +102 -5
- package/dist/extensions/pi-subagents/src/slash/delegation-adapters.ts +10 -1
- package/dist/extensions/pi-subagents/src/slash/slash-commands.ts +46 -4
- package/dist/extensions/pi-subagents/src/slash/slash-live-state.ts +5 -3
- package/dist/extensions/pi-subagents/src/tui/fleet-status.ts +87 -24
- package/dist/extensions/pi-subagents/src/tui/fleet.ts +182 -9
- package/dist/extensions/pi-subagents/src/tui/render.ts +55 -34
- package/dist/extensions/pi-subagents/src/watchdog/register-main.ts +14 -7
- package/dist/extensions/pi-subagents/src/watchdog/review.ts +5 -4
- package/dist/extensions/pi-subagents/src/watchdog/runtime.ts +170 -17
- package/dist/extensions/pi-subagents/src/watchdog/scope.ts +62 -0
- package/dist/extensions/pi-subagents/src/watchdog/settings.ts +41 -1
- package/dist/extensions/pi-subagents/src/watchdog/types.ts +10 -0
- package/dist/extensions/pi-subagents/test/e2e/real-session-subagent.test.ts +113 -8
- package/dist/extensions/pi-subagents/test/integration/async-execution.test.ts +419 -47
- package/dist/extensions/pi-subagents/test/integration/async-job-tracker.test.ts +84 -0
- package/dist/extensions/pi-subagents/test/integration/async-status.test.ts +4 -2
- package/dist/extensions/pi-subagents/test/integration/chain-clarify.test.ts +51 -2
- package/dist/extensions/pi-subagents/test/integration/chain-execution.test.ts +62 -22
- package/dist/extensions/pi-subagents/test/integration/detect-error.test.ts +48 -0
- package/dist/extensions/pi-subagents/test/integration/fork-context-execution.test.ts +8 -6
- package/dist/extensions/pi-subagents/test/integration/intercom-result-delivery.test.ts +231 -19
- package/dist/extensions/pi-subagents/test/integration/parallel-execution.test.ts +48 -7
- package/dist/extensions/pi-subagents/test/integration/render-fork-badge.test.ts +44 -0
- package/dist/extensions/pi-subagents/test/integration/result-watcher.test.ts +199 -17
- package/dist/extensions/pi-subagents/test/integration/single-execution.test.ts +898 -16
- package/dist/extensions/pi-subagents/test/integration/slash-commands.test.ts +112 -23
- package/dist/extensions/pi-subagents/test/support/mock-pi-script.mjs +17 -5
- package/dist/extensions/pi-subagents/test/support/mock-pi.ts +2 -0
- package/dist/extensions/pi-subagents/test/support/real-session-runner.ts +18 -2
- package/dist/extensions/pi-subagents/test/support/register-loader.mjs +3 -3
- package/dist/extensions/pi-subagents/test/unit/acceptance.test.ts +3 -1
- package/dist/extensions/pi-subagents/test/unit/agent-disabled.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/agent-frontmatter.test.ts +198 -6
- package/dist/extensions/pi-subagents/test/unit/agent-management.test.ts +161 -1
- package/dist/extensions/pi-subagents/test/unit/agent-overrides.test.ts +47 -2
- package/dist/extensions/pi-subagents/test/unit/async-recovery-descriptor.test.ts +60 -0
- package/dist/extensions/pi-subagents/test/unit/async-resume.test.ts +8 -0
- package/dist/extensions/pi-subagents/test/unit/builtin-agent-documentation.test.ts +63 -0
- package/dist/extensions/pi-subagents/test/unit/capability-ceiling-agent-allowlist.test.ts +136 -0
- package/dist/extensions/pi-subagents/test/unit/capability-ceiling.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/chain-append.test.ts +6 -0
- package/dist/extensions/pi-subagents/test/unit/chain-validation.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/completion-guard.test.ts +48 -48
- package/dist/extensions/pi-subagents/test/unit/config-dir-runtime.test.ts +23 -0
- package/dist/extensions/pi-subagents/test/unit/control-channel.test.ts +27 -0
- package/dist/extensions/pi-subagents/test/unit/delegation-api.test.ts +28 -2
- package/dist/extensions/pi-subagents/test/unit/dynamic-fanout.test.ts +1 -0
- package/dist/extensions/pi-subagents/test/unit/fleet-status.test.ts +176 -8
- package/dist/extensions/pi-subagents/test/unit/fleet.test.ts +164 -5
- package/dist/extensions/pi-subagents/test/unit/foreground-control.test.ts +41 -1
- package/dist/extensions/pi-subagents/test/unit/index-child-registration.test.ts +17 -12
- package/dist/extensions/pi-subagents/test/unit/intercom-bridge.test.ts +18 -2
- package/dist/extensions/pi-subagents/test/unit/nested-control.test.ts +20 -1
- package/dist/extensions/pi-subagents/test/unit/nested-events.test.ts +30 -2
- package/dist/extensions/pi-subagents/test/unit/notify.test.ts +39 -2
- package/dist/extensions/pi-subagents/test/unit/parallel-utils.test.ts +22 -0
- package/dist/extensions/pi-subagents/test/unit/pi-args.test.ts +103 -0
- package/dist/extensions/pi-subagents/test/unit/pi-coding-agent-dir.test.ts +18 -0
- package/dist/extensions/pi-subagents/test/unit/preflight.test.ts +48 -0
- package/dist/extensions/pi-subagents/test/unit/render-helpers.test.ts +13 -1
- package/dist/extensions/pi-subagents/test/unit/result-intercom.test.ts +29 -4
- package/dist/extensions/pi-subagents/test/unit/rpc.test.ts +223 -4
- package/dist/extensions/pi-subagents/test/unit/run-status.test.ts +30 -0
- package/dist/extensions/pi-subagents/test/unit/runtime-acknowledged-extensions.test.ts +52 -0
- package/dist/extensions/pi-subagents/test/unit/schemas.test.ts +46 -2
- package/dist/extensions/pi-subagents/test/unit/single-output.test.ts +91 -1
- package/dist/extensions/pi-subagents/test/unit/skills-fallback.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/steering-action.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/streamed-progress-bounds.test.ts +78 -0
- package/dist/extensions/pi-subagents/test/unit/subagent-prompt-runtime.test.ts +41 -0
- package/dist/extensions/pi-subagents/test/unit/subagent-startup-retry.test.ts +77 -0
- package/dist/extensions/pi-subagents/test/unit/task-aware-routing.test.ts +213 -0
- package/dist/extensions/pi-subagents/test/unit/task-intent.test.ts +26 -1
- package/dist/extensions/pi-subagents/test/unit/tool-description.test.ts +61 -10
- package/dist/extensions/pi-subagents/test/unit/total-cost.test.ts +1 -0
- package/dist/extensions/pi-subagents/test/unit/watchdog-runtime.test.ts +210 -1
- package/dist/extensions/pi-subagents/test/unit/watchdog-scope.test.ts +33 -0
- package/dist/extensions/pi-subagents/test/unit/watchdog-settings.test.ts +32 -0
- package/dist/extensions/pi-subagents/test/unit/writer-budget-guidance.test.ts +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +43 -0
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/custom-message.d.ts +3 -1
- package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-message.js +10 -2
- package/dist/modes/interactive/components/custom-message.js.map +1 -1
- package/dist/modes/interactive/components/extension-editor.d.ts +1 -2
- package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-editor.js +16 -46
- package/dist/modes/interactive/components/extension-editor.js.map +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +4 -1
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.js +22 -13
- package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
- package/dist/modes/interactive/external-editor.d.ts +12 -0
- package/dist/modes/interactive/external-editor.d.ts.map +1 -0
- package/dist/modes/interactive/external-editor.js +37 -0
- package/dist/modes/interactive/external-editor.js.map +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +72 -64
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +14 -0
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/skills/ponytail/SKILL.md +1 -3
- package/dist/utils/clipboard.d.ts.map +1 -1
- package/dist/utils/clipboard.js +19 -8
- package/dist/utils/clipboard.js.map +1 -1
- package/dist/utils/version-check.d.ts.map +1 -1
- package/dist/utils/version-check.js +1 -1
- package/dist/utils/version-check.js.map +1 -1
- package/docs/compaction.md +1 -1
- package/docs/custom-provider.md +14 -5
- package/docs/environment-variables.md +86 -0
- package/docs/extensions.md +15 -5
- package/docs/index.md +1 -0
- package/docs/models.md +9 -2
- package/docs/plans/subagent-delegation/phase-0-correctness.md +265 -0
- package/docs/plans/subagent-delegation/phase-1-behavioral-contract.md +486 -0
- package/docs/plans/subagent-delegation/phase-2-context-controls.md +282 -0
- package/docs/plans/subagent-delegation/phase-3-advisory-routing.md +362 -0
- package/docs/plans/subagent-delegation/phase-4-optional-enforcement.md +381 -0
- package/docs/providers.md +21 -2
- package/docs/rpc.md +23 -6
- package/docs/session-format.md +2 -0
- package/docs/settings.md +1 -1
- package/docs/usage.md +0 -13
- package/examples/extensions/custom-compaction.ts +5 -2
- package/examples/extensions/custom-provider-anthropic/index.ts +9 -3
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/handoff.ts +11 -3
- package/examples/extensions/message-renderer.ts +3 -3
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/summarize.ts +5 -2
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/examples/sdk/12-full-control.ts +3 -1
- package/package.json +16 -7
- package/dist/extensions/caveman/caveman-instructions.cjs +0 -11
- package/dist/extensions/caveman/index.js +0 -118
- package/dist/extensions/caveman/package.json +0 -8
- package/dist/extensions/caveman/test/extension.test.js +0 -203
- package/dist/extensions/caveman/test/helpers.test.js +0 -58
- package/dist/skills/caveman/SKILL.md +0 -50
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { describe, it } from "node:test";
|
|
3
|
+
import {
|
|
4
|
+
formatTaskAwareAgentRecommendation,
|
|
5
|
+
recommendTaskAwareAgent,
|
|
6
|
+
} from "../../src/agents/task-aware-routing.ts";
|
|
7
|
+
import type { AgentConfig } from "../../src/agents/agents.ts";
|
|
8
|
+
|
|
9
|
+
function agent(name: string, overrides: Partial<AgentConfig> = {}): AgentConfig {
|
|
10
|
+
return {
|
|
11
|
+
name,
|
|
12
|
+
description: `${name} agent`,
|
|
13
|
+
systemPrompt: `${name} prompt`,
|
|
14
|
+
systemPromptMode: "append",
|
|
15
|
+
inheritProjectContext: false,
|
|
16
|
+
inheritSkills: false,
|
|
17
|
+
source: "builtin",
|
|
18
|
+
filePath: `/tmp/${name}.md`,
|
|
19
|
+
...overrides,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
describe("recommendTaskAwareAgent", () => {
|
|
24
|
+
it("no-ops for empty or whitespace-only tasks", () => {
|
|
25
|
+
assert.equal(recommendTaskAwareAgent({ task: "", agents: [] }), undefined);
|
|
26
|
+
assert.equal(recommendTaskAwareAgent({ task: " \n\t ", agents: [] }), undefined);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it("recommends a canonical writer for an implementation task, never a read-only agent", () => {
|
|
30
|
+
const recommendation = recommendTaskAwareAgent({
|
|
31
|
+
task: "Implement the fix",
|
|
32
|
+
agents: [
|
|
33
|
+
agent("commentator", { tools: ["read", "grep"] }),
|
|
34
|
+
agent("builder"),
|
|
35
|
+
],
|
|
36
|
+
});
|
|
37
|
+
assert.ok(recommendation);
|
|
38
|
+
assert.equal(recommendation.intent, "implementation");
|
|
39
|
+
assert.equal(recommendation.agent?.name, "builder");
|
|
40
|
+
assert.equal(recommendation.agent?.role, "writer");
|
|
41
|
+
assert.equal(recommendation.agent?.roleBasis, "inferred");
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("recommends a read-only agent without known write tools, never a writer", () => {
|
|
45
|
+
const recommendation = recommendTaskAwareAgent({
|
|
46
|
+
task: "Review only; do not edit files",
|
|
47
|
+
agents: [
|
|
48
|
+
agent("builder"),
|
|
49
|
+
agent("commentator", { tools: ["read", "grep", "find", "ls"] }),
|
|
50
|
+
],
|
|
51
|
+
});
|
|
52
|
+
assert.ok(recommendation);
|
|
53
|
+
assert.equal(recommendation.intent, "read-only");
|
|
54
|
+
assert.equal(recommendation.agent?.name, "commentator");
|
|
55
|
+
assert.equal(recommendation.agent?.role, "read-only");
|
|
56
|
+
assert.equal(recommendation.agent?.roleBasis, "inferred");
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("never recommends a read-only agent whose tools are unset or include bash", () => {
|
|
60
|
+
for (const candidate of [
|
|
61
|
+
agent("commentator"),
|
|
62
|
+
agent("commentator", { tools: ["read", "bash"] }),
|
|
63
|
+
]) {
|
|
64
|
+
const recommendation = recommendTaskAwareAgent({
|
|
65
|
+
task: "Review only; do not edit files",
|
|
66
|
+
agents: [candidate],
|
|
67
|
+
});
|
|
68
|
+
assert.ok(recommendation);
|
|
69
|
+
assert.equal(recommendation.agent, undefined);
|
|
70
|
+
assert.match(recommendation.next ?? "", /read-only role without known write tools/);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it("gives recovery guidance, not a guess, for unknown intent", () => {
|
|
75
|
+
const recommendation = recommendTaskAwareAgent({
|
|
76
|
+
task: "Look into this",
|
|
77
|
+
agents: [agent("builder"), agent("commentator", { tools: ["read", "grep"] })],
|
|
78
|
+
});
|
|
79
|
+
assert.ok(recommendation);
|
|
80
|
+
assert.equal(recommendation.intent, "unknown");
|
|
81
|
+
assert.equal(recommendation.agent, undefined);
|
|
82
|
+
assert.match(recommendation.next ?? "", /Clarify whether the task is read-only analysis\/review or implementation allowed to edit files/);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it("excludes disabled agents even when they match the task role", () => {
|
|
86
|
+
const recommendation = recommendTaskAwareAgent({
|
|
87
|
+
task: "Implement the fix",
|
|
88
|
+
agents: [
|
|
89
|
+
agent("builder", { disabled: true }),
|
|
90
|
+
agent("fixer", { source: "project", acceptanceRole: "writer", tools: ["edit"] }),
|
|
91
|
+
],
|
|
92
|
+
});
|
|
93
|
+
assert.ok(recommendation);
|
|
94
|
+
assert.equal(recommendation.agent?.name, "fixer");
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it("excludes agents denied by the capability ceiling allowedAgents", () => {
|
|
98
|
+
const recommendation = recommendTaskAwareAgent({
|
|
99
|
+
task: "Implement the fix",
|
|
100
|
+
agents: [agent("builder"), agent("fixer", { source: "project", acceptanceRole: "writer", tools: ["edit"] })],
|
|
101
|
+
capabilityCeiling: { version: 1, allowedAgents: ["builder"], denyExtensions: false, sources: ["plan"] },
|
|
102
|
+
});
|
|
103
|
+
assert.ok(recommendation);
|
|
104
|
+
assert.equal(recommendation.agent?.name, "builder");
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it("refuses a writer recommendation when allowedTools has no writer tool", () => {
|
|
108
|
+
const recommendation = recommendTaskAwareAgent({
|
|
109
|
+
task: "Implement the fix",
|
|
110
|
+
agents: [agent("builder")],
|
|
111
|
+
capabilityCeiling: { version: 1, allowedTools: ["read", "grep"], denyExtensions: false, sources: ["plan"] },
|
|
112
|
+
});
|
|
113
|
+
assert.ok(recommendation);
|
|
114
|
+
assert.equal(recommendation.intent, "implementation");
|
|
115
|
+
assert.equal(recommendation.agent, undefined);
|
|
116
|
+
assert.match(recommendation.next ?? "", /capability ceiling/);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it("recommends a writer when allowedTools includes a writer tool", () => {
|
|
120
|
+
const recommendation = recommendTaskAwareAgent({
|
|
121
|
+
task: "Implement the fix",
|
|
122
|
+
agents: [agent("builder")],
|
|
123
|
+
capabilityCeiling: { version: 1, allowedTools: ["read", "edit"], denyExtensions: false, sources: ["plan"] },
|
|
124
|
+
});
|
|
125
|
+
assert.ok(recommendation);
|
|
126
|
+
assert.equal(recommendation.agent?.name, "builder");
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it("prefers project over user, package, and builtin candidates", () => {
|
|
130
|
+
const recommendation = recommendTaskAwareAgent({
|
|
131
|
+
task: "Implement the fix",
|
|
132
|
+
agents: [
|
|
133
|
+
agent("builder", { source: "builtin" }),
|
|
134
|
+
agent("builder", { source: "package" }),
|
|
135
|
+
agent("builder", { source: "user" }),
|
|
136
|
+
agent("builder", { source: "project" }),
|
|
137
|
+
],
|
|
138
|
+
});
|
|
139
|
+
assert.ok(recommendation);
|
|
140
|
+
assert.equal(recommendation.agent?.name, "builder");
|
|
141
|
+
assert.equal(recommendation.agent?.source, "project");
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it("sorts equal candidates by canonical name", () => {
|
|
145
|
+
const recommendation = recommendTaskAwareAgent({
|
|
146
|
+
task: "Implement the fix",
|
|
147
|
+
agents: [
|
|
148
|
+
agent("zeta-builder", { source: "user", acceptanceRole: "writer", tools: ["edit"] }),
|
|
149
|
+
agent("alpha-builder", { source: "user", acceptanceRole: "writer", tools: ["edit"] }),
|
|
150
|
+
],
|
|
151
|
+
});
|
|
152
|
+
assert.ok(recommendation);
|
|
153
|
+
assert.equal(recommendation.agent?.name, "alpha-builder");
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it("prefers a declared role over an inferred role at the same source", () => {
|
|
157
|
+
const recommendation = recommendTaskAwareAgent({
|
|
158
|
+
task: "Implement the fix",
|
|
159
|
+
agents: [
|
|
160
|
+
agent("builder", { source: "user" }),
|
|
161
|
+
agent("fixer", { source: "user", acceptanceRole: "writer", tools: ["edit"] }),
|
|
162
|
+
],
|
|
163
|
+
});
|
|
164
|
+
assert.ok(recommendation);
|
|
165
|
+
assert.equal(recommendation.agent?.name, "fixer");
|
|
166
|
+
assert.equal(recommendation.agent?.roleBasis, "declared");
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it("never emits an alias as the recommended launch name", () => {
|
|
170
|
+
const recommendation = recommendTaskAwareAgent({
|
|
171
|
+
task: "Implement the fix",
|
|
172
|
+
agents: [
|
|
173
|
+
agent("canonical-builder", { aliases: ["developer"], source: "user", acceptanceRole: "writer", tools: ["edit"] }),
|
|
174
|
+
],
|
|
175
|
+
});
|
|
176
|
+
assert.ok(recommendation);
|
|
177
|
+
assert.equal(recommendation.agent?.name, "canonical-builder");
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
describe("formatTaskAwareAgentRecommendation", () => {
|
|
182
|
+
it("renders nothing for an empty-task no-op", () => {
|
|
183
|
+
assert.deepEqual(formatTaskAwareAgentRecommendation(undefined), []);
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
it("renders a safe recommendation with the canonical agent and explicit-launch note", () => {
|
|
187
|
+
const lines = formatTaskAwareAgentRecommendation({
|
|
188
|
+
intent: "implementation",
|
|
189
|
+
agent: { name: "builder", source: "project", role: "writer", roleBasis: "declared", reason: "declared writer role with write tools" },
|
|
190
|
+
});
|
|
191
|
+
assert.deepEqual(lines, [
|
|
192
|
+
"Task-aware advisory routing:",
|
|
193
|
+
"- Intent: implementation",
|
|
194
|
+
"- Recommended: builder (project)",
|
|
195
|
+
"- Reason: declared writer role with write tools",
|
|
196
|
+
"- Advisory only: no subagent was launched. To proceed, explicitly call subagent with this canonical agent name and the task.",
|
|
197
|
+
]);
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
it("renders recovery guidance without an agent name", () => {
|
|
201
|
+
const lines = formatTaskAwareAgentRecommendation({
|
|
202
|
+
intent: "unknown",
|
|
203
|
+
next: "Clarify whether the task is read-only analysis/review or implementation allowed to edit files.",
|
|
204
|
+
});
|
|
205
|
+
assert.deepEqual(lines, [
|
|
206
|
+
"Task-aware advisory routing:",
|
|
207
|
+
"- Intent: unknown",
|
|
208
|
+
"- Recommendation: none",
|
|
209
|
+
"- Next: Clarify whether the task is read-only analysis/review or implementation allowed to edit files.",
|
|
210
|
+
"- Advisory only: no subagent was launched.",
|
|
211
|
+
]);
|
|
212
|
+
});
|
|
213
|
+
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import assert from "node:assert/strict";
|
|
2
2
|
import { describe, it } from "node:test";
|
|
3
|
-
import { classifyTaskMutationIntent, expectsImplementationMutation, taskMayMutate } from "../../src/runs/shared/task-intent.ts";
|
|
3
|
+
import { classifyTaskMutationIntent, expectsImplementationMutation, resolveAgentRoutingRole, taskMayMutate } from "../../src/runs/shared/task-intent.ts";
|
|
4
4
|
|
|
5
5
|
describe("classifyTaskMutationIntent", () => {
|
|
6
6
|
it("keeps write imperatives despite investigative wording", () => {
|
|
@@ -38,6 +38,9 @@ describe("classifyTaskMutationIntent", () => {
|
|
|
38
38
|
assert.equal(classifyTaskMutationIntent("builder", "Do not edit files. Tell me how to fix the bug.").kind, "read-only");
|
|
39
39
|
assert.equal(classifyTaskMutationIntent("builder", "Report on the extraction pipeline. Do not modify project/source files.").kind, "read-only");
|
|
40
40
|
assert.equal(classifyTaskMutationIntent("commentator", "Final correctness review after prior fixes. Inspect all changed files and tests. Do not modify project/source files. Report findings.").kind, "read-only");
|
|
41
|
+
assert.equal(classifyTaskMutationIntent("builder", `Verification-only task. Do not edit product/source/config files.
|
|
42
|
+
Run a disposable check, delete its temporary harness, and retain only
|
|
43
|
+
a sanitized report at an explicitly named artifact path.`).kind, "read-only");
|
|
41
44
|
});
|
|
42
45
|
|
|
43
46
|
it("strips repeated prohibition phrases before testing write intent", () => {
|
|
@@ -66,6 +69,28 @@ describe("classifyTaskMutationIntent", () => {
|
|
|
66
69
|
});
|
|
67
70
|
});
|
|
68
71
|
|
|
72
|
+
describe("resolveAgentRoutingRole", () => {
|
|
73
|
+
it("lets a declared acceptanceRole override name heuristics", () => {
|
|
74
|
+
assert.equal(resolveAgentRoutingRole("commentator", "writer"), "writer");
|
|
75
|
+
assert.equal(resolveAgentRoutingRole("builder", "read-only"), "read-only");
|
|
76
|
+
assert.equal(resolveAgentRoutingRole("custom-agent", "writer"), "writer");
|
|
77
|
+
assert.equal(resolveAgentRoutingRole("custom-agent", "read-only"), "read-only");
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it("infers writer for builder-named agents and read-only for reviewer-style names", () => {
|
|
81
|
+
assert.equal(resolveAgentRoutingRole("builder"), "writer");
|
|
82
|
+
assert.equal(resolveAgentRoutingRole("package.builder"), "writer");
|
|
83
|
+
for (const name of ["architect", "commentator", "explorer", "recapper", "researcher", "analyst"]) {
|
|
84
|
+
assert.equal(resolveAgentRoutingRole(name), "read-only", name);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it("returns undefined for names without an established role", () => {
|
|
89
|
+
assert.equal(resolveAgentRoutingRole("custom-agent"), undefined);
|
|
90
|
+
assert.equal(resolveAgentRoutingRole("reviewer"), undefined);
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
|
|
69
94
|
describe("taskMayMutate", () => {
|
|
70
95
|
it("treats any bare write verb as write-capable", () => {
|
|
71
96
|
for (const task of ["Write the code", "Commit the changes", "Delete temporary data", "Remove obsolete assets", "Update dependencies"]) {
|
|
@@ -9,8 +9,10 @@ import {
|
|
|
9
9
|
buildSubagentToolDescription,
|
|
10
10
|
COMPACT_SUBAGENT_TOOL_DESCRIPTION,
|
|
11
11
|
FULL_SUBAGENT_TOOL_DESCRIPTION,
|
|
12
|
+
SUBAGENT_PARENT_ROUTING_GUIDANCE,
|
|
12
13
|
SUBAGENT_SAFETY_GUIDANCE,
|
|
13
14
|
} from "../../src/extension/tool-description.ts";
|
|
15
|
+
import { BUILTIN_AGENT_NAMES } from "../../src/agents/agents.ts";
|
|
14
16
|
import { SUBAGENT_CHILD_ENV, SUBAGENT_FANOUT_CHILD_ENV } from "../../src/runs/shared/pi-args.ts";
|
|
15
17
|
|
|
16
18
|
const projectRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..", "..");
|
|
@@ -31,9 +33,12 @@ describe("registered subagent tool description", () => {
|
|
|
31
33
|
it("keeps full mode safe and free of hardcoded builtin agent names", () => {
|
|
32
34
|
const description = buildSubagentToolDescription();
|
|
33
35
|
|
|
34
|
-
for (const builtinName of
|
|
36
|
+
for (const builtinName of BUILTIN_AGENT_NAMES) {
|
|
35
37
|
assert.doesNotMatch(description, new RegExp(`\\b${builtinName}\\b`));
|
|
36
38
|
}
|
|
39
|
+
for (const legacyName of ["scout", "worker", "planner"]) {
|
|
40
|
+
assert.doesNotMatch(description, new RegExp(`\\b${legacyName}\\b`));
|
|
41
|
+
}
|
|
37
42
|
assert.match(description, /^To delegate work, call with \{ agent, task \}, \{ tasks \}, or \{ chain \}; omit action\./i);
|
|
38
43
|
assert.match(description, /Use action only for management\/control actions listed below/i);
|
|
39
44
|
assert.match(description, /use \{ action: "list" \} to inspect configured agents\/chains/i);
|
|
@@ -50,6 +55,11 @@ describe("registered subagent tool description", () => {
|
|
|
50
55
|
assert.doesNotMatch(description, /only for foreground runs/i);
|
|
51
56
|
assert.doesNotMatch(description, /omit for async\/background runs/i);
|
|
52
57
|
assert.match(description, /SAFETY-CRITICAL SUBAGENT GUIDANCE/);
|
|
58
|
+
assert.match(description, /PARENT-ONLY SUBAGENT ROUTING/);
|
|
59
|
+
assert.match(description, /call \{ action: "list" \} and select only an executable entry using its current role, context, and tool metadata/i);
|
|
60
|
+
assert.match(description, /Keep tiny targeted reads and simple answers local/i);
|
|
61
|
+
assert.match(description, /broad local investigation, external research, and mutation\/implementation work/i);
|
|
62
|
+
assert.match(description, /parent remains the decision-maker and normally the sole writer/i);
|
|
53
63
|
assert.match(description, /Do not sleep or poll status just to wait/i);
|
|
54
64
|
assert.match(description, /use subagent_wait/i);
|
|
55
65
|
assert.match(description, /interactive session.*normally return control/i);
|
|
@@ -62,6 +72,10 @@ describe("registered subagent tool description", () => {
|
|
|
62
72
|
assert.match(description, /action: "steer"/);
|
|
63
73
|
assert.match(description, /schedule-list/);
|
|
64
74
|
assert.match(description, /action: "eject"/);
|
|
75
|
+
assert.match(description, /action: "eject", agent: "agent-name"/);
|
|
76
|
+
assert.match(description, /action: "disable", agent: "agent-name"/);
|
|
77
|
+
assert.match(description, /action: "enable", agent: "agent-name"/);
|
|
78
|
+
assert.match(description, /action: "reset", agent: "agent-name"/);
|
|
65
79
|
assert.match(description, /action: "disable"/);
|
|
66
80
|
assert.match(description, /action: "grant-spawn-budget"/);
|
|
67
81
|
assert.match(description, /root interactive parent/i);
|
|
@@ -97,6 +111,14 @@ describe("registered subagent tool description", () => {
|
|
|
97
111
|
assert.match(description, /PARALLEL/);
|
|
98
112
|
assert.match(description, /CHAIN/);
|
|
99
113
|
assert.match(description, /action without execution fields/i);
|
|
114
|
+
assert.match(description, /Parent-only routing/);
|
|
115
|
+
assert.match(description, /select only an executable entry using its current role, context, and tool metadata/i);
|
|
116
|
+
assert.match(description, /Keep tiny targeted reads and simple answers local/i);
|
|
117
|
+
assert.match(description, /broad local investigation, external research, and mutation\/implementation work/i);
|
|
118
|
+
assert.match(description, /parent remains the decision-maker and normally the sole writer/i);
|
|
119
|
+
for (const builtinName of BUILTIN_AGENT_NAMES) {
|
|
120
|
+
assert.doesNotMatch(description, new RegExp(`\\b${builtinName}\\b`));
|
|
121
|
+
}
|
|
100
122
|
assert.match(description, /subagent_wait/i);
|
|
101
123
|
assert.match(description, /interactive session.*normally return control/i);
|
|
102
124
|
assert.match(description, /Non-interactive runs.*auto-drain current-session work at agent_end/i);
|
|
@@ -127,6 +149,15 @@ describe("registered subagent tool description", () => {
|
|
|
127
149
|
assert.match(description, /count:/);
|
|
128
150
|
});
|
|
129
151
|
|
|
152
|
+
it("documents task-aware list advice as explicit-only in both modes", () => {
|
|
153
|
+
for (const description of [FULL_SUBAGENT_TOOL_DESCRIPTION, COMPACT_SUBAGENT_TOOL_DESCRIPTION]) {
|
|
154
|
+
assert.match(description, /\{ action: "list", task: "\.\.\." \}/);
|
|
155
|
+
assert.match(description, /advisory/i);
|
|
156
|
+
assert.match(description, /never launches/i);
|
|
157
|
+
assert.match(description, /explicitly call subagent|execute the recommended agent explicitly/i);
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
|
|
130
161
|
it("renders a custom project description with placeholders and mandatory safety guidance", () => {
|
|
131
162
|
const cwd = fs.mkdtempSync(path.join(os.tmpdir(), "pi-subagents-tool-desc-project-"));
|
|
132
163
|
const agentDir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-subagents-tool-desc-agent-"));
|
|
@@ -148,6 +179,8 @@ describe("registered subagent tool description", () => {
|
|
|
148
179
|
assert.match(description, new RegExp(escapeRegex(agentDir)));
|
|
149
180
|
assert.match(description, new RegExp(escapeRegex(projectConfigDir)));
|
|
150
181
|
assert.match(description, /SAFETY-CRITICAL SUBAGENT GUIDANCE/);
|
|
182
|
+
assert.match(description, /PARENT-ONLY SUBAGENT ROUTING/);
|
|
183
|
+
assert.match(description, /select only an executable entry using its current role, context, and tool metadata/i);
|
|
151
184
|
assert.equal(warnings.length, 0);
|
|
152
185
|
});
|
|
153
186
|
|
|
@@ -213,7 +246,7 @@ describe("registered subagent tool description", () => {
|
|
|
213
246
|
assert.ok(warnings.some((message) => message.includes("Ignoring invalid toolDescriptionMode")));
|
|
214
247
|
});
|
|
215
248
|
|
|
216
|
-
function
|
|
249
|
+
function readRegisteredTool(agentDir: string): { description: string; promptGuidelines?: string[] } {
|
|
217
250
|
const script = String.raw`
|
|
218
251
|
import registerSubagentExtension from "./src/extension/index.ts";
|
|
219
252
|
const events = { on() { return () => {}; }, emit() {} };
|
|
@@ -234,12 +267,15 @@ describe("registered subagent tool description", () => {
|
|
|
234
267
|
});
|
|
235
268
|
registerSubagentExtension(fakePi);
|
|
236
269
|
if (!registeredTool) throw new Error("tool not registered");
|
|
237
|
-
process.stdout.write(JSON.stringify(
|
|
270
|
+
process.stdout.write(JSON.stringify({
|
|
271
|
+
description: registeredTool.description,
|
|
272
|
+
promptGuidelines: registeredTool.promptGuidelines ?? null,
|
|
273
|
+
}));
|
|
238
274
|
`;
|
|
239
275
|
const output = execFileSync(
|
|
240
276
|
process.execPath,
|
|
241
277
|
[
|
|
242
|
-
"--experimental-
|
|
278
|
+
"--experimental-strip-types",
|
|
243
279
|
"--import",
|
|
244
280
|
"./test/support/register-loader.mjs",
|
|
245
281
|
"--input-type=module",
|
|
@@ -248,7 +284,7 @@ describe("registered subagent tool description", () => {
|
|
|
248
284
|
],
|
|
249
285
|
{ cwd: projectRoot, env: parentToolEnv(agentDir), encoding: "utf-8" },
|
|
250
286
|
);
|
|
251
|
-
return JSON.parse(output) as string;
|
|
287
|
+
return JSON.parse(output) as { description: string; promptGuidelines?: string[] };
|
|
252
288
|
}
|
|
253
289
|
|
|
254
290
|
function writeExtensionConfig(agentDir: string, config: Record<string, unknown>): void {
|
|
@@ -259,25 +295,40 @@ describe("registered subagent tool description", () => {
|
|
|
259
295
|
|
|
260
296
|
it("registers full, compact, custom, and fallback descriptions from extension config", () => {
|
|
261
297
|
const defaultAgentDir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-subagents-tool-desc-default-"));
|
|
262
|
-
assert.equal(
|
|
298
|
+
assert.equal(readRegisteredTool(defaultAgentDir).description, FULL_SUBAGENT_TOOL_DESCRIPTION);
|
|
263
299
|
|
|
264
300
|
const compactAgentDir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-subagents-tool-desc-compact-"));
|
|
265
301
|
writeExtensionConfig(compactAgentDir, { toolDescriptionMode: "compact" });
|
|
266
|
-
assert.equal(
|
|
302
|
+
assert.equal(readRegisteredTool(compactAgentDir).description, COMPACT_SUBAGENT_TOOL_DESCRIPTION);
|
|
267
303
|
|
|
268
304
|
const customAgentDir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-subagents-tool-desc-custom-"));
|
|
269
305
|
writeExtensionConfig(customAgentDir, { toolDescriptionMode: "custom" });
|
|
270
306
|
fs.writeFileSync(path.join(customAgentDir, "subagent-tool-description.md"), "Registered custom description.", "utf-8");
|
|
271
|
-
const customDescription =
|
|
307
|
+
const customDescription = readRegisteredTool(customAgentDir).description;
|
|
272
308
|
assert.match(customDescription, /Registered custom description/);
|
|
273
309
|
assert.match(customDescription, /SAFETY-CRITICAL SUBAGENT GUIDANCE/);
|
|
274
310
|
|
|
275
311
|
const missingCustomAgentDir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-subagents-tool-desc-missing-"));
|
|
276
312
|
writeExtensionConfig(missingCustomAgentDir, { toolDescriptionMode: "custom" });
|
|
277
|
-
assert.equal(
|
|
313
|
+
assert.equal(readRegisteredTool(missingCustomAgentDir).description, FULL_SUBAGENT_TOOL_DESCRIPTION);
|
|
278
314
|
|
|
279
315
|
const invalidAgentDir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-subagents-tool-desc-invalid-"));
|
|
280
316
|
writeExtensionConfig(invalidAgentDir, { toolDescriptionMode: "tiny" });
|
|
281
|
-
assert.equal(
|
|
317
|
+
assert.equal(readRegisteredTool(invalidAgentDir).description, FULL_SUBAGENT_TOOL_DESCRIPTION);
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
it("registers parent-only routing guidance as promptGuidelines on the parent tool", () => {
|
|
321
|
+
const defaultAgentDir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-subagents-tool-desc-guidelines-"));
|
|
322
|
+
const registered = readRegisteredTool(defaultAgentDir);
|
|
323
|
+
|
|
324
|
+
assert.ok(Array.isArray(registered.promptGuidelines), "parent subagent tool must expose promptGuidelines");
|
|
325
|
+
assert.equal(registered.promptGuidelines!.length, 1);
|
|
326
|
+
assert.equal(registered.promptGuidelines![0], SUBAGENT_PARENT_ROUTING_GUIDANCE);
|
|
327
|
+
assert.doesNotMatch(SUBAGENT_PARENT_ROUTING_GUIDANCE, new RegExp(BUILTIN_AGENT_NAMES.join("|")));
|
|
328
|
+
assert.match(SUBAGENT_PARENT_ROUTING_GUIDANCE, /\{ action: "list" \}/);
|
|
329
|
+
assert.match(SUBAGENT_PARENT_ROUTING_GUIDANCE, /executable entry/i);
|
|
330
|
+
assert.match(SUBAGENT_PARENT_ROUTING_GUIDANCE, /tiny targeted reads and simple answers local/i);
|
|
331
|
+
assert.match(SUBAGENT_PARENT_ROUTING_GUIDANCE, /broad local investigation, external research, and mutation\/implementation work/i);
|
|
332
|
+
assert.match(SUBAGENT_PARENT_ROUTING_GUIDANCE, /decision-maker and normally the sole writer/i);
|
|
282
333
|
});
|
|
283
334
|
});
|