@selesai/code 0.13.15 → 0.13.18
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 +37 -0
- package/README.md +2 -14
- package/dist/bun/cli.d.ts +3 -1
- package/dist/bun/cli.js +3 -9
- package/dist/bun/{register-bedrock.js → runtime-setup.js} +5 -0
- package/dist/bun/sandbox-env-setup.d.ts +1 -0
- package/dist/bun/sandbox-env-setup.js +3 -0
- package/dist/cli/auth-command.d.ts +23 -0
- package/dist/cli/auth-command.js +102 -0
- package/dist/cli/config-selector.js +2 -1
- package/dist/cli/setup.d.ts +1 -0
- package/dist/cli/setup.js +11 -0
- package/dist/cli.js +2 -14
- package/dist/config.d.ts +3 -2
- package/dist/config.js +9 -4
- package/dist/core/agent-session-runtime.js +15 -7
- package/dist/core/agent-session.d.ts +2 -6
- package/dist/core/agent-session.js +15 -4
- package/dist/core/compaction/branch-summarization.d.ts +1 -1
- package/dist/core/compaction/branch-summarization.js +2 -1
- package/dist/core/extensions/loader.js +3 -0
- package/dist/core/extensions/types.d.ts +16 -2
- package/dist/core/http-dispatcher.js +2 -0
- package/dist/core/keybindings.d.ts +5 -0
- package/dist/core/keybindings.js +4 -0
- package/dist/core/messages.d.ts +1 -1
- package/dist/core/model-config.d.ts +15 -0
- package/dist/core/model-config.js +3 -0
- package/dist/core/model-runtime.d.ts +1 -0
- package/dist/core/model-runtime.js +5 -2
- package/dist/core/provider-composer.js +8 -2
- package/dist/core/session-export.d.ts +3 -0
- package/dist/core/session-export.js +31 -0
- package/dist/core/session-manager.d.ts +3 -2
- package/dist/core/session-manager.js +40 -13
- package/dist/core/skills.d.ts +1 -1
- package/dist/core/skills.js +4 -2
- package/dist/core/system-prompt.js +10 -10
- package/dist/core/tools/bash.js +3 -117
- package/dist/core/tools/edit.d.ts +1 -12
- package/dist/core/tools/edit.js +5 -163
- package/dist/core/tools/find.js +4 -55
- package/dist/core/tools/grep.js +4 -60
- package/dist/core/tools/ls.js +4 -49
- package/dist/core/tools/read.d.ts +4 -0
- package/dist/core/tools/read.js +10 -122
- package/dist/core/tools/renderers/bash.d.ts +11 -0
- package/dist/core/tools/renderers/bash.js +129 -0
- package/dist/core/tools/renderers/edit.d.ts +22 -0
- package/dist/core/tools/renderers/edit.js +166 -0
- package/dist/core/tools/renderers/find.d.ts +9 -0
- package/dist/core/tools/renderers/find.js +63 -0
- package/dist/core/tools/renderers/grep.d.ts +9 -0
- package/dist/core/tools/renderers/grep.js +68 -0
- package/dist/core/tools/renderers/index.d.ts +27 -0
- package/dist/core/tools/renderers/index.js +46 -0
- package/dist/core/tools/renderers/ls.d.ts +9 -0
- package/dist/core/tools/renderers/ls.js +57 -0
- package/dist/core/tools/renderers/read.d.ts +10 -0
- package/dist/core/tools/renderers/read.js +128 -0
- package/dist/core/tools/renderers/write.d.ts +9 -0
- package/dist/core/tools/renderers/write.js +152 -0
- package/dist/core/tools/write.js +5 -146
- package/dist/extensions/capability-gateway/index.ts +12 -1
- package/dist/extensions/capability-gateway/integration.test.ts +23 -0
- package/dist/extensions/pi-hermes-memory/CHANGELOG.md +18 -0
- package/dist/extensions/pi-hermes-memory/README.md +16 -12
- package/dist/extensions/pi-hermes-memory/docs/ROADMAP.md +1 -1
- package/dist/extensions/pi-hermes-memory/package-lock.json +587 -62
- package/dist/extensions/pi-hermes-memory/package.json +4 -4
- package/dist/extensions/pi-hermes-memory/src/config.ts +32 -0
- package/dist/extensions/pi-hermes-memory/src/constants.ts +12 -2
- package/dist/extensions/pi-hermes-memory/src/handlers/background-review.ts +109 -51
- package/dist/extensions/pi-hermes-memory/src/handlers/index-sessions.ts +9 -3
- package/dist/extensions/pi-hermes-memory/src/handlers/review-memory-ops.ts +257 -98
- package/dist/extensions/pi-hermes-memory/src/handlers/session-backfill.ts +9 -2
- package/dist/extensions/pi-hermes-memory/src/handlers/sync-markdown-memories.ts +5 -0
- package/dist/extensions/pi-hermes-memory/src/index.ts +22 -2
- package/dist/extensions/pi-hermes-memory/src/paths.ts +1 -1
- package/dist/extensions/pi-hermes-memory/src/store/db.ts +6 -0
- package/dist/extensions/pi-hermes-memory/src/store/fts-query.ts +58 -1
- package/dist/extensions/pi-hermes-memory/src/store/memory-store.ts +60 -8
- package/dist/extensions/pi-hermes-memory/src/store/session-indexer.ts +169 -7
- package/dist/extensions/pi-hermes-memory/src/store/session-search.ts +7 -21
- package/dist/extensions/pi-hermes-memory/src/store/sqlite-memory-store.ts +134 -15
- package/dist/extensions/pi-hermes-memory/src/tools/memory-search-tool.ts +4 -2
- package/dist/extensions/pi-hermes-memory/src/tools/memory-tool.ts +24 -9
- package/dist/extensions/pi-hermes-memory/src/types.ts +11 -0
- package/dist/extensions/pi-hermes-memory/tests/config.test.ts +42 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/background-review.test.ts +159 -3
- package/dist/extensions/pi-hermes-memory/tests/handlers/review-memory-ops.test.ts +452 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/session-backfill.test.ts +39 -0
- package/dist/extensions/pi-hermes-memory/tests/integration/corruption-recovery-integration.test.ts +91 -0
- package/dist/extensions/pi-hermes-memory/tests/store/db.test.ts +29 -0
- package/dist/extensions/pi-hermes-memory/tests/store/fts-query.test.ts +116 -0
- package/dist/extensions/pi-hermes-memory/tests/store/memory-store.test.ts +163 -0
- package/dist/extensions/pi-hermes-memory/tests/store/session-indexer.test.ts +233 -0
- package/dist/extensions/pi-hermes-memory/tests/store/session-search.test.ts +12 -0
- package/dist/extensions/pi-hermes-memory/tests/store/sqlite-memory-store.test.ts +175 -0
- package/dist/extensions/pi-hermes-memory/tests/store/sqlite-native.test.ts +2 -2
- package/dist/extensions/pi-hermes-memory/tests/tools/memory-search-tool.test.ts +22 -0
- package/dist/extensions/pi-hermes-memory/tests/tools/memory-tool.test.ts +37 -1
- package/dist/extensions/pi-intercom/CHANGELOG.md +13 -0
- package/dist/extensions/pi-intercom/README.md +16 -2
- package/dist/extensions/pi-intercom/broker/spawn.test.ts +19 -2
- package/dist/extensions/pi-intercom/broker/spawn.ts +4 -4
- package/dist/extensions/pi-intercom/index.ts +1 -1
- package/dist/extensions/pi-intercom/intercom.integration.test.ts +121 -2
- package/dist/extensions/pi-intercom/package.json +1 -1
- package/dist/extensions/pi-intercom/project-agent.test.ts +1 -1
- package/dist/extensions/pi-intercom/project-agent.ts +1 -6
- package/dist/extensions/pi-intercom/skills/pi-intercom/SKILL.md +7 -6
- package/dist/extensions/pi-rewind-hook/index.test.ts +7 -0
- package/dist/extensions/pi-subagents/.github/workflows/test.yml +36 -4
- package/dist/extensions/pi-subagents/CHANGELOG.md +120 -0
- package/dist/extensions/pi-subagents/README.md +3 -3
- package/dist/extensions/pi-subagents/agents/researcher.md +23 -13
- package/dist/extensions/pi-subagents/agents/reviewer.md +1 -1
- package/dist/extensions/pi-subagents/agents/scout.md +1 -1
- package/dist/extensions/pi-subagents/docs/agents.md +32 -16
- package/dist/extensions/pi-subagents/docs/configuration.md +41 -15
- package/dist/extensions/pi-subagents/docs/extension-api.md +109 -6
- package/dist/extensions/pi-subagents/docs/missions.md +2 -0
- package/dist/extensions/pi-subagents/docs/models.md +58 -1
- package/dist/extensions/pi-subagents/docs/observability.md +50 -12
- package/dist/extensions/pi-subagents/docs/tool-reference.md +17 -10
- package/dist/extensions/pi-subagents/docs/watchdog.md +1 -1
- package/dist/extensions/pi-subagents/docs/workflows.md +26 -9
- package/dist/extensions/pi-subagents/package-lock.json +747 -177
- package/dist/extensions/pi-subagents/package.json +6 -4
- package/dist/extensions/pi-subagents/runner-server-preload.mjs +13 -0
- package/dist/extensions/pi-subagents/skills/pi-subagents/SKILL.md +2 -1
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/constraints-and-recipes.md +1 -1
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/execution-controls.md +21 -4
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/management-authoring-rpc.md +2 -1
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/multi-lane-orchestration.md +2 -0
- package/dist/extensions/pi-subagents/src/agents/advertised-agent-prompt.ts +63 -0
- package/dist/extensions/pi-subagents/src/agents/agent-management.ts +61 -16
- package/dist/extensions/pi-subagents/src/agents/agent-serializer.ts +2 -0
- package/dist/extensions/pi-subagents/src/agents/agents.ts +8 -0
- package/dist/extensions/pi-subagents/src/api/capability-ceiling.ts +0 -1
- package/dist/extensions/pi-subagents/src/api/{pi-args.ts → child-tool-plan.ts} +1 -1
- package/dist/extensions/pi-subagents/src/api/preflight.ts +7 -4
- package/dist/extensions/pi-subagents/src/api/shared-types.ts +2 -2
- package/dist/extensions/pi-subagents/src/api/workflow-resources.ts +6 -0
- package/dist/extensions/pi-subagents/src/extension/config.ts +4 -2
- package/dist/extensions/pi-subagents/src/extension/doctor.ts +2 -10
- package/dist/extensions/pi-subagents/src/extension/fanout-child.ts +9 -11
- package/dist/extensions/pi-subagents/src/extension/index.ts +99 -10
- package/dist/extensions/pi-subagents/src/extension/public-execution.ts +13 -0
- package/dist/extensions/pi-subagents/src/extension/rpc.ts +7 -23
- package/dist/extensions/pi-subagents/src/extension/schemas.ts +11 -8
- package/dist/extensions/pi-subagents/src/extension/tool-description.ts +25 -7
- package/dist/extensions/pi-subagents/src/integrations/pi-web-session-liveness.ts +73 -0
- package/dist/extensions/pi-subagents/src/intercom/native-supervisor-channel.ts +228 -136
- package/dist/extensions/pi-subagents/src/intercom/supervisor-ui.ts +244 -0
- package/dist/extensions/pi-subagents/src/missions/workflow-state.ts +37 -16
- package/dist/extensions/pi-subagents/src/runs/background/active-async-capacity.ts +18 -18
- package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +51 -25
- package/dist/extensions/pi-subagents/src/runs/background/async-job-tracker.ts +46 -3
- package/dist/extensions/pi-subagents/src/runs/background/async-resume.ts +14 -3
- package/dist/extensions/pi-subagents/src/runs/background/async-retention.ts +9 -0
- package/dist/extensions/pi-subagents/src/runs/background/async-status-snapshot.ts +10 -12
- package/dist/extensions/pi-subagents/src/runs/background/async-status.ts +18 -15
- package/dist/extensions/pi-subagents/src/runs/background/auto-drain.ts +40 -29
- package/dist/extensions/pi-subagents/src/runs/background/chain-root-attachment.ts +8 -0
- package/dist/extensions/pi-subagents/src/runs/background/control-channel.ts +79 -247
- package/dist/extensions/pi-subagents/src/runs/background/notify.ts +88 -12
- package/dist/extensions/pi-subagents/src/runs/background/owned-process-tree.ts +6 -6
- package/dist/extensions/pi-subagents/src/runs/background/process-terminal.ts +24 -24
- package/dist/extensions/pi-subagents/src/runs/background/retained-nested-route-tracker.ts +96 -0
- package/dist/extensions/pi-subagents/src/runs/background/run-child-session.ts +642 -0
- package/dist/extensions/pi-subagents/src/runs/background/run-status.ts +75 -6
- package/dist/extensions/pi-subagents/src/runs/background/runner-aliases.ts +163 -0
- package/dist/extensions/pi-subagents/src/runs/background/runner-child-launch.ts +86 -0
- package/dist/extensions/pi-subagents/src/runs/background/runner-child-sessions.ts +31 -0
- package/dist/extensions/pi-subagents/src/runs/background/scheduled-runs.ts +18 -4
- package/dist/extensions/pi-subagents/src/runs/background/stale-run-reconciler.ts +3 -1
- package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +597 -1092
- package/dist/extensions/pi-subagents/src/runs/background/subagent-wait.ts +3 -0
- package/dist/extensions/pi-subagents/src/runs/background/wait-completions.ts +4 -0
- package/dist/extensions/pi-subagents/src/runs/foreground/async-steering-action.ts +20 -17
- package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +296 -394
- package/dist/extensions/pi-subagents/src/runs/foreground/foreground-control.ts +4 -0
- package/dist/extensions/pi-subagents/src/runs/foreground/foreground-history.ts +3 -1
- package/dist/extensions/pi-subagents/src/runs/foreground/prompt-audit.ts +9 -5
- package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +630 -283
- package/dist/extensions/pi-subagents/src/runs/foreground/workflow-detach-reconcile.ts +8 -5
- package/dist/extensions/pi-subagents/src/runs/foreground/workflow-foreground-steering.ts +78 -98
- package/dist/extensions/pi-subagents/src/runs/shared/abort-recovery.ts +3 -3
- package/dist/extensions/pi-subagents/src/runs/shared/acceptance.ts +16 -3
- package/dist/extensions/pi-subagents/src/runs/shared/agent-contract.ts +1 -1
- package/dist/extensions/pi-subagents/src/runs/shared/async-status-projection.ts +47 -47
- package/dist/extensions/pi-subagents/src/runs/shared/capability-ceiling.ts +1 -2
- package/dist/extensions/pi-subagents/src/runs/shared/child-hooks.ts +174 -0
- package/dist/extensions/pi-subagents/src/runs/shared/child-identity.ts +14 -3
- package/dist/extensions/pi-subagents/src/runs/shared/child-launch.ts +319 -0
- package/dist/extensions/pi-subagents/src/runs/shared/child-lifecycle.ts +25 -0
- package/dist/extensions/pi-subagents/src/runs/shared/child-runtime-config.ts +126 -0
- package/dist/extensions/pi-subagents/src/runs/shared/child-session.ts +373 -0
- package/dist/extensions/pi-subagents/src/runs/shared/child-tool-plan.ts +530 -0
- package/dist/extensions/pi-subagents/src/runs/shared/completion-evidence.ts +2 -2
- package/dist/extensions/pi-subagents/src/runs/shared/completion-guard.ts +2 -1
- package/dist/extensions/pi-subagents/src/runs/shared/external-cli-preflight.ts +16 -0
- package/dist/extensions/pi-subagents/src/runs/shared/host-step-status.ts +11 -11
- package/dist/extensions/pi-subagents/src/runs/shared/llm-intent-arbiter.ts +30 -20
- package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +5 -4
- package/dist/extensions/pi-subagents/src/runs/shared/model-exclusions.ts +84 -15
- package/dist/extensions/pi-subagents/src/runs/shared/model-fallback.ts +88 -12
- package/dist/extensions/pi-subagents/src/runs/shared/nested-events.ts +37 -53
- package/dist/extensions/pi-subagents/src/runs/shared/nested-path.ts +1 -1
- package/dist/extensions/pi-subagents/src/runs/shared/orca-progress-tabs.ts +18 -7
- package/dist/extensions/pi-subagents/src/runs/shared/parallel-handoff.ts +57 -12
- package/dist/extensions/pi-subagents/src/runs/shared/parallel-utils.ts +3 -4
- package/dist/extensions/pi-subagents/src/runs/shared/permissions.ts +0 -11
- package/dist/extensions/pi-subagents/src/runs/shared/process-signal.ts +4 -1
- package/dist/extensions/pi-subagents/src/runs/shared/readonly-drain-observation.ts +42 -0
- package/dist/extensions/pi-subagents/src/runs/shared/readonly-model-continuation.ts +69 -0
- package/dist/extensions/pi-subagents/src/runs/shared/readonly-session-evidence.ts +307 -0
- package/dist/extensions/pi-subagents/src/runs/shared/run-fanout-budget.ts +8 -21
- package/dist/extensions/pi-subagents/src/runs/shared/runtime-acknowledged-extensions.ts +3 -30
- package/dist/extensions/pi-subagents/src/runs/shared/structured-output.ts +17 -4
- package/dist/extensions/pi-subagents/src/runs/shared/subagent-control.ts +2 -0
- package/dist/extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.ts +99 -386
- package/dist/extensions/pi-subagents/src/runs/shared/tool-availability.ts +18 -62
- package/dist/extensions/pi-subagents/src/runs/shared/tool-budget.ts +0 -14
- package/dist/extensions/pi-subagents/src/runs/shared/worktree-cleanup-plan.ts +31 -9
- package/dist/extensions/pi-subagents/src/runs/shared/worktree-setup-command.ts +190 -0
- package/dist/extensions/pi-subagents/src/runs/shared/worktree.ts +506 -226
- package/dist/extensions/pi-subagents/src/shared/child-session-name.ts +1 -1
- package/dist/extensions/pi-subagents/src/shared/jsonl-writer.ts +11 -0
- package/dist/extensions/pi-subagents/src/shared/model-response-aliases.ts +13 -0
- package/dist/extensions/pi-subagents/src/shared/thinking-ceiling.ts +0 -6
- package/dist/extensions/pi-subagents/src/shared/types.ts +145 -89
- package/dist/extensions/pi-subagents/src/shared/utils.ts +13 -6
- package/dist/extensions/pi-subagents/src/shared/watch-strategy.ts +2 -0
- package/dist/extensions/pi-subagents/src/shared/workflow-child-permit.ts +18 -13
- package/dist/extensions/pi-subagents/src/slash/slash-commands.ts +0 -6
- package/dist/extensions/pi-subagents/src/tui/fleet-status.ts +1 -1
- package/dist/extensions/pi-subagents/src/tui/fleet.ts +11 -6
- package/dist/extensions/pi-subagents/src/tui/render.ts +277 -46
- package/dist/extensions/pi-subagents/src/watchdog/child-status.ts +0 -1
- package/dist/extensions/pi-subagents/src/watchdog/register-child.ts +12 -12
- package/dist/extensions/pi-subagents/src/workflows/chat-progress.ts +3 -3
- package/dist/extensions/pi-subagents/src/workflows/scripted-workflow.ts +116 -15
- package/dist/extensions/pi-subagents/src/workflows/workflow-checklist.ts +15 -18
- package/dist/extensions/pi-subagents/src/workflows/workflow-child-summary.ts +57 -8
- package/dist/extensions/pi-subagents/src/workflows/workflow-preflight.ts +19 -19
- package/dist/extensions/pi-subagents/src/workflows/workflow-receipt.ts +3 -3
- package/dist/extensions/pi-subagents/src/workflows/workflow-resources.ts +97 -22
- package/dist/extensions/pi-subagents/src/workflows/workflow-settlement.ts +3 -0
- package/dist/extensions/pi-subagents/test/integration/acceptance-file-report.test.ts +336 -21
- package/dist/extensions/pi-subagents/test/integration/async-execution.part-1.test.ts +1181 -0
- package/dist/extensions/pi-subagents/test/integration/async-execution.part-2.test.ts +2240 -0
- package/dist/extensions/pi-subagents/test/integration/async-execution.part-3.test.ts +2268 -0
- package/dist/extensions/pi-subagents/test/integration/async-execution.part-4.test.ts +1512 -0
- package/dist/extensions/pi-subagents/test/integration/async-job-tracker.test.ts +231 -16
- package/dist/extensions/pi-subagents/test/integration/error-handling.test.ts +4 -18
- package/dist/extensions/pi-subagents/test/integration/foreign-workflow-steering.test.ts +95 -0
- package/dist/extensions/pi-subagents/test/integration/fork-context-execution.test.ts +9 -15
- package/dist/extensions/pi-subagents/test/integration/in-process-child.test.ts +374 -0
- package/dist/extensions/pi-subagents/test/integration/intercom-result-delivery.test.ts +20 -10
- package/dist/extensions/pi-subagents/test/integration/orca-progress-tabs.test.ts +18 -6
- package/dist/extensions/pi-subagents/test/integration/recovered-assistant-error.test.ts +151 -0
- package/dist/extensions/pi-subagents/test/integration/render-fork-badge.test.ts +42 -1
- package/dist/extensions/pi-subagents/test/integration/render-widget.test.ts +150 -25
- package/dist/extensions/pi-subagents/test/integration/result-publication.test.ts +354 -0
- package/dist/extensions/pi-subagents/test/integration/shared-cwd-terminal-evidence.test.ts +117 -0
- package/dist/extensions/pi-subagents/test/integration/single-execution.part-1.test.ts +3678 -0
- package/dist/extensions/pi-subagents/test/integration/{single-execution.test.ts → single-execution.part-2.test.ts} +500 -4207
- package/dist/extensions/pi-subagents/test/integration/slash-commands.test.ts +1 -2
- package/dist/extensions/pi-subagents/test/integration/workflow-result-publication.test.ts +127 -0
- package/dist/extensions/pi-subagents/test/integration/workflow-steer-inbox.test.ts +365 -0
- package/dist/extensions/pi-subagents/test/smoke/pi085-child.ts +31 -0
- package/dist/extensions/pi-subagents/test/smoke/pi085-clean-install.mjs +74 -0
- package/dist/extensions/pi-subagents/test/smoke/pi085-extension.ts +16 -0
- package/dist/extensions/pi-subagents/test/support/async-execution-fixture.ts +699 -0
- package/dist/extensions/pi-subagents/test/support/fake-child-session.ts +418 -0
- package/dist/extensions/pi-subagents/test/support/foreign-workflow-steer-host.mjs +13 -0
- package/dist/extensions/pi-subagents/test/support/mock-pi.ts +30 -76
- package/dist/extensions/pi-subagents/test/support/notify-diagnostics-fixture.ts +84 -0
- package/dist/extensions/pi-subagents/test/support/result-publication-capacity-preload.mjs +70 -0
- package/dist/extensions/pi-subagents/test/support/runner-child-session-factory.ts +17 -0
- package/dist/extensions/pi-subagents/test/support/single-execution-fixture.ts +390 -0
- package/dist/extensions/pi-subagents/test/unit/acceptance-compaction.test.ts +120 -0
- package/dist/extensions/pi-subagents/test/unit/acceptance.test.ts +24 -3
- package/dist/extensions/pi-subagents/test/unit/advertised-agent-prompt.test.ts +87 -0
- package/dist/extensions/pi-subagents/test/unit/advertised-agent-refresh.test.ts +163 -0
- package/dist/extensions/pi-subagents/test/unit/agent-frontmatter.test.ts +70 -31
- package/dist/extensions/pi-subagents/test/unit/agent-management.test.ts +78 -3
- package/dist/extensions/pi-subagents/test/unit/agent-overrides.test.ts +2 -8
- package/dist/extensions/pi-subagents/test/unit/async-execution.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/async-interrupt-action.test.ts +73 -66
- package/dist/extensions/pi-subagents/test/unit/async-recovery-descriptor.test.ts +51 -1
- package/dist/extensions/pi-subagents/test/unit/async-retention.test.ts +49 -1
- package/dist/extensions/pi-subagents/test/unit/async-spawn-preload.test.ts +103 -0
- package/dist/extensions/pi-subagents/test/unit/async-status-projection.test.ts +3 -3
- package/dist/extensions/pi-subagents/test/unit/capability-ceiling-agent-allowlist.test.ts +9 -8
- package/dist/extensions/pi-subagents/test/unit/capability-ceiling.test.ts +10 -7
- package/dist/extensions/pi-subagents/test/unit/chain-root-attachment.test.ts +48 -6
- package/dist/extensions/pi-subagents/test/unit/child-runtime-config.test.ts +90 -0
- package/dist/extensions/pi-subagents/test/unit/{pi-args-permission-system.test.ts → child-tool-plan-permission-system.test.ts} +48 -86
- package/dist/extensions/pi-subagents/test/unit/child-tool-plan.test.ts +33 -0
- package/dist/extensions/pi-subagents/test/unit/compaction-resume.test.ts +18 -18
- package/dist/extensions/pi-subagents/test/unit/completion-evidence.test.ts +9 -9
- package/dist/extensions/pi-subagents/test/unit/completion-guard.test.ts +8 -7
- package/dist/extensions/pi-subagents/test/unit/control-channel.test.ts +225 -65
- package/dist/extensions/pi-subagents/test/unit/extension-bindings.test.ts +17 -22
- package/dist/extensions/pi-subagents/test/unit/fleet-status.test.ts +11 -1
- package/dist/extensions/pi-subagents/test/unit/fleet.test.ts +47 -3
- package/dist/extensions/pi-subagents/test/unit/foreign-workflow-steering.test.ts +74 -0
- package/dist/extensions/pi-subagents/test/unit/fork-cache-key.test.ts +23 -29
- package/dist/extensions/pi-subagents/test/unit/host-peer-runtime-imports.test.ts +96 -4
- package/dist/extensions/pi-subagents/test/unit/host-step-status.test.ts +4 -4
- package/dist/extensions/pi-subagents/test/unit/index-child-registration.test.ts +116 -55
- package/dist/extensions/pi-subagents/test/unit/index-segment.test.ts +58 -1
- package/dist/extensions/pi-subagents/test/unit/llm-intent-arbiter.test.ts +104 -3
- package/dist/extensions/pi-subagents/test/unit/mission-lifecycle.test.ts +10 -1
- package/dist/extensions/pi-subagents/test/unit/mission-store.test.ts +31 -1
- package/dist/extensions/pi-subagents/test/unit/model-exclusions.test.ts +102 -51
- package/dist/extensions/pi-subagents/test/unit/model-fallback.test.ts +196 -6
- package/dist/extensions/pi-subagents/test/unit/native-supervisor-channel.test.ts +181 -38
- package/dist/extensions/pi-subagents/test/unit/nested-control.test.ts +62 -70
- package/dist/extensions/pi-subagents/test/unit/nested-events.test.ts +58 -53
- package/dist/extensions/pi-subagents/test/unit/notify-diagnostics.test.ts +42 -0
- package/dist/extensions/pi-subagents/test/unit/notify.test.ts +84 -0
- package/dist/extensions/pi-subagents/test/unit/orca-progress-tabs.test.ts +13 -5
- package/dist/extensions/pi-subagents/test/unit/package-manifest.test.ts +21 -5
- package/dist/extensions/pi-subagents/test/unit/parallel-handoff.test.ts +5 -4
- package/dist/extensions/pi-subagents/test/unit/permissions.test.ts +2 -6
- package/dist/extensions/pi-subagents/test/unit/pi-coding-agent-dir.test.ts +28 -2
- package/dist/extensions/pi-subagents/test/unit/pi-web-session-liveness.test.ts +209 -0
- package/dist/extensions/pi-subagents/test/unit/preflight.test.ts +38 -1
- package/dist/extensions/pi-subagents/test/unit/prompt-audit-optional-peers.test.ts +43 -0
- package/dist/extensions/pi-subagents/test/unit/public-execution.test.ts +24 -2
- package/dist/extensions/pi-subagents/test/unit/readonly-drain-observation.test.ts +174 -0
- package/dist/extensions/pi-subagents/test/unit/readonly-model-continuation.test.ts +94 -0
- package/dist/extensions/pi-subagents/test/unit/readonly-session-evidence.test.ts +1329 -0
- package/dist/extensions/pi-subagents/test/unit/recursion-guard.test.ts +29 -80
- package/dist/extensions/pi-subagents/test/unit/render-helpers.test.ts +11 -8
- package/dist/extensions/pi-subagents/test/unit/result-files.test.ts +2 -2
- package/dist/extensions/pi-subagents/test/unit/retained-nested-route-tracker.test.ts +175 -0
- package/dist/extensions/pi-subagents/test/unit/rpc.test.ts +38 -12
- package/dist/extensions/pi-subagents/test/unit/run-fanout-budget.test.ts +2 -5
- package/dist/extensions/pi-subagents/test/unit/run-status.test.ts +89 -1
- package/dist/extensions/pi-subagents/test/unit/runtime-acknowledged-extensions.test.ts +2 -16
- package/dist/extensions/pi-subagents/test/unit/scheduled-runs.test.ts +27 -3
- package/dist/extensions/pi-subagents/test/unit/scheduled-supervisor-demand.test.ts +215 -0
- package/dist/extensions/pi-subagents/test/unit/schemas.test.ts +15 -11
- package/dist/extensions/pi-subagents/test/unit/scripted-workflow.test.ts +237 -1
- package/dist/extensions/pi-subagents/test/unit/steering-action.test.ts +2 -5
- package/dist/extensions/pi-subagents/test/unit/streamed-progress-bounds.test.ts +2 -2
- package/dist/extensions/pi-subagents/test/unit/subagent-guide.test.ts +14 -1
- package/dist/extensions/pi-subagents/test/unit/subagent-prompt-runtime.test.ts +130 -739
- package/dist/extensions/pi-subagents/test/unit/supervisor-ask-registration.test.ts +682 -0
- package/dist/extensions/pi-subagents/test/unit/supervisor-ui.test.ts +137 -0
- package/dist/extensions/pi-subagents/test/unit/tool-budget.test.ts +1 -11
- package/dist/extensions/pi-subagents/test/unit/tool-description.test.ts +23 -3
- package/dist/extensions/pi-subagents/test/unit/wait-completions.test.ts +8 -1
- package/dist/extensions/pi-subagents/test/unit/watchdog-tool-actions.test.ts +19 -1
- package/dist/extensions/pi-subagents/test/unit/workflow-chat-progress.test.ts +72 -4
- package/dist/extensions/pi-subagents/test/unit/workflow-checklist.test.ts +17 -3
- package/dist/extensions/pi-subagents/test/unit/workflow-child-summary.test.ts +34 -0
- package/dist/extensions/pi-subagents/test/unit/workflow-detach-reconcile.test.ts +12 -2
- package/dist/extensions/pi-subagents/test/unit/workflow-launch-params.test.ts +46 -6
- package/dist/extensions/pi-subagents/test/unit/workflow-receipt.test.ts +3 -3
- package/dist/extensions/pi-subagents/test/unit/workflow-resources.test.ts +133 -1
- package/dist/extensions/pi-subagents/test/unit/workflow-resume-hint.test.ts +53 -2
- package/dist/extensions/pi-subagents/test/unit/worktree-cleanup-plan.test.ts +222 -14
- package/dist/extensions/pi-subagents/test/unit/worktree.test.ts +526 -85
- package/dist/extensions/pi-web-agent/src/backends/config.ts +1 -0
- package/dist/extensions/pi-web-agent/src/backends/settings-reader.ts +5 -3
- package/dist/extensions/pi-web-agent/src/search/tokenin.ts +7 -3
- package/dist/extensions/pi-web-agent/src/types.ts +1 -1
- package/dist/extensions/pi-zentui/README.md +17 -0
- package/dist/extensions/pi-zentui/assets/screenshots/footer-status-hyperlink.png +0 -0
- package/dist/extensions/pi-zentui/docs/configuration.md +71 -2
- package/dist/extensions/pi-zentui/extensions/zentui/config.ts +11 -0
- package/dist/extensions/pi-zentui/extensions/zentui/editor-transfer.ts +14 -0
- package/dist/extensions/pi-zentui/extensions/zentui/extension-status.ts +29 -13
- package/dist/extensions/pi-zentui/extensions/zentui/footer-layout.ts +5 -4
- package/dist/extensions/pi-zentui/extensions/zentui/footer-text.ts +11 -0
- package/dist/extensions/pi-zentui/extensions/zentui/footer.ts +11 -10
- package/dist/extensions/pi-zentui/extensions/zentui/index.ts +77 -3
- package/dist/extensions/pi-zentui/extensions/zentui/presets.ts +77 -0
- package/dist/extensions/pi-zentui/extensions/zentui/settings-command.ts +103 -2
- package/dist/extensions/pi-zentui/extensions/zentui/working-line-extension-segments.ts +115 -0
- package/dist/extensions/pi-zentui/extensions/zentui/working-line.ts +87 -5
- package/dist/extensions/pi-zentui/package-lock.json +277 -517
- package/dist/extensions/pi-zentui/package.json +7 -4
- package/dist/extensions/pi-zentui/test/config-presets.test.ts +238 -0
- package/dist/extensions/pi-zentui/test/editor-transfer.test.ts +24 -1
- package/dist/extensions/pi-zentui/test/extension-compliance.test.ts +570 -2
- package/dist/extensions/pi-zentui/test/extension-status.test.ts +90 -0
- package/dist/extensions/pi-zentui/test/footer-hyperlink.test.ts +243 -0
- package/dist/extensions/pi-zentui/test/package-contents.mjs +1 -0
- package/dist/extensions/pi-zentui/test/presets.test.ts +121 -0
- package/dist/extensions/pi-zentui/test/settings-command.test.ts +205 -1
- package/dist/extensions/pi-zentui/test/working-line-extension-segments.test.ts +139 -0
- package/dist/extensions/pi-zentui/test/working-line-lifecycle.integration.test.ts +237 -3
- package/dist/extensions/pi-zentui/test/working-line.test.ts +94 -2
- package/dist/index.d.ts +1 -1
- package/dist/main.js +4 -1
- package/dist/modes/interactive/chat-viewport.d.ts +19 -0
- package/dist/modes/interactive/chat-viewport.js +27 -0
- package/dist/modes/interactive/components/assistant-message.d.ts +6 -2
- package/dist/modes/interactive/components/assistant-message.js +30 -13
- package/dist/modes/interactive/components/custom-editor.d.ts +10 -1
- package/dist/modes/interactive/components/custom-editor.js +39 -1
- package/dist/modes/interactive/components/first-time-setup.js +1 -1
- package/dist/modes/interactive/components/index.d.ts +1 -1
- package/dist/modes/interactive/components/markdown-transform.d.ts +2 -0
- package/dist/modes/interactive/components/markdown-transform.js +18 -0
- package/dist/modes/interactive/components/model-selector.js +19 -17
- package/dist/modes/interactive/components/scoped-models-selector.js +21 -23
- package/dist/modes/interactive/components/settings-selector.d.ts +7 -1
- package/dist/modes/interactive/components/settings-selector.js +128 -20
- package/dist/modes/interactive/components/settings-submenu.d.ts +71 -0
- package/dist/modes/interactive/components/settings-submenu.js +164 -0
- package/dist/modes/interactive/components/status-indicator.d.ts +3 -1
- package/dist/modes/interactive/components/status-indicator.js +10 -3
- package/dist/modes/interactive/components/thinking-selector.d.ts +15 -3
- package/dist/modes/interactive/components/thinking-selector.js +75 -18
- package/dist/modes/interactive/components/tool-execution.d.ts +21 -4
- package/dist/modes/interactive/components/tool-execution.js +35 -33
- package/dist/modes/interactive/components/trust-selector.js +2 -2
- package/dist/modes/interactive/interactive-mode.d.ts +13 -15
- package/dist/modes/interactive/interactive-mode.js +144 -80
- package/dist/modes/interactive/session-share.d.ts +15 -0
- package/dist/modes/interactive/session-share.js +183 -0
- package/dist/modes/interactive/theme/dark.json +2 -1
- package/dist/modes/interactive/theme/light.json +2 -1
- package/dist/modes/interactive/theme/theme-controller.d.ts +1 -0
- package/dist/modes/interactive/theme/theme-controller.js +5 -0
- package/dist/modes/interactive/theme/theme-json.d.ts +83 -0
- package/dist/modes/interactive/theme/theme-json.js +129 -0
- package/dist/modes/interactive/theme/theme-schema.json +9 -1
- package/dist/modes/interactive/theme/theme.d.ts +14 -5
- package/dist/modes/interactive/theme/theme.js +18 -119
- package/dist/modes/interactive/tui-renderer.d.ts +20 -0
- package/dist/modes/interactive/tui-renderer.js +65 -0
- package/dist/utils/exif-orientation.js +2 -3
- package/dist/utils/management-http.d.ts +24 -0
- package/dist/utils/management-http.js +53 -0
- package/dist/utils/text.d.ts +7 -0
- package/dist/utils/text.js +8 -0
- package/dist/utils/tools-manager.d.ts +1 -0
- package/dist/utils/tools-manager.js +43 -21
- package/docs/docs.json +0 -4
- package/package.json +4 -4
- package/dist/extensions/pi-subagents/src/runs/shared/child-protocol.ts +0 -415
- package/dist/extensions/pi-subagents/src/runs/shared/pi-args.ts +0 -1059
- package/dist/extensions/pi-subagents/src/runs/shared/subagent-startup-retry.ts +0 -116
- package/dist/extensions/pi-subagents/src/shared/post-exit-stdio-guard.ts +0 -85
- package/dist/extensions/pi-subagents/test/e2e/real-session-subagent.test.ts +0 -224
- package/dist/extensions/pi-subagents/test/integration/async-execution.test.ts +0 -6986
- package/dist/extensions/pi-subagents/test/support/mock-pi-script.mjs +0 -447
- package/dist/extensions/pi-subagents/test/support/real-session-child-cli.mjs +0 -185
- package/dist/extensions/pi-subagents/test/support/real-session-runner.ts +0 -311
- package/dist/extensions/pi-subagents/test/unit/capability-ceiling-pi-args.test.ts +0 -84
- package/dist/extensions/pi-subagents/test/unit/child-protocol.test.ts +0 -202
- package/dist/extensions/pi-subagents/test/unit/close-grace-timer.test.ts +0 -101
- package/dist/extensions/pi-subagents/test/unit/pi-args.test.ts +0 -2347
- package/dist/extensions/pi-subagents/test/unit/subagent-startup-retry.test.ts +0 -104
- package/dist/extensions/pi-subagents/test/unit/windows-hide-spawn.test.ts +0 -49
- package/dist/skills/imagegen-frontend-mobile/SKILL.md +0 -1465
- package/dist/skills/imagegen-frontend-web/SKILL.md +0 -987
- package/dist/skills/implanger/SKILL.md +0 -70
- package/dist/skills/output/SKILL.md +0 -49
- package/dist/skills/planger/SKILL.md +0 -167
- package/dist/skills/workflow/SKILL.md +0 -95
- package/docs/workflows.md +0 -18
- /package/dist/bun/{register-bedrock.d.ts → runtime-setup.d.ts} +0 -0
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { describe, it } from "node:test";
|
|
3
|
+
import { appendAdvertisedAgentPrompt, buildAdvertisedAgentPrompt } from "../../src/agents/advertised-agent-prompt.ts";
|
|
4
|
+
import type { AgentConfig } from "../../src/agents/agents.ts";
|
|
5
|
+
|
|
6
|
+
function agent(name: string, overrides: Partial<AgentConfig> = {}): AgentConfig {
|
|
7
|
+
return {
|
|
8
|
+
name,
|
|
9
|
+
description: `${name} agent`,
|
|
10
|
+
systemPrompt: `${name} prompt`,
|
|
11
|
+
systemPromptMode: "replace",
|
|
12
|
+
inheritProjectContext: false,
|
|
13
|
+
inheritSkills: false,
|
|
14
|
+
source: "project",
|
|
15
|
+
filePath: `/tmp/${name}.md`,
|
|
16
|
+
...overrides,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
describe("advertised agent prompt", () => {
|
|
21
|
+
it("includes only opted-in, capability-permitted agents in stable order", () => {
|
|
22
|
+
const prompt = buildAdvertisedAgentPrompt([
|
|
23
|
+
agent("zeta", { advertise: true }),
|
|
24
|
+
agent("hidden"),
|
|
25
|
+
agent("disabled", { advertise: true, disabled: true }),
|
|
26
|
+
agent("alpha", { advertise: true }),
|
|
27
|
+
], {
|
|
28
|
+
version: 1,
|
|
29
|
+
allowedAgents: ["alpha", "hidden", "zeta"],
|
|
30
|
+
denyExtensions: false,
|
|
31
|
+
sources: ["test"],
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
assert.ok(prompt);
|
|
35
|
+
assert.match(prompt, /<name>alpha<\/name>/);
|
|
36
|
+
assert.match(prompt, /<name>zeta<\/name>/);
|
|
37
|
+
assert.doesNotMatch(prompt, /hidden|disabled/);
|
|
38
|
+
assert.ok(prompt.indexOf("alpha") < prompt.indexOf("zeta"));
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it("escapes agent-owned metadata and bounds the catalog", () => {
|
|
42
|
+
const agents = Array.from({ length: 18 }, (_, index) => agent(`agent-${String(index).padStart(2, "0")}`, {
|
|
43
|
+
advertise: true,
|
|
44
|
+
description: index === 0 ? `<route>&${"x".repeat(700)}` : `agent ${index}`,
|
|
45
|
+
}));
|
|
46
|
+
const prompt = buildAdvertisedAgentPrompt(agents);
|
|
47
|
+
|
|
48
|
+
assert.ok(prompt);
|
|
49
|
+
assert.match(prompt, /<route>&/);
|
|
50
|
+
assert.doesNotMatch(prompt, /<route>/);
|
|
51
|
+
assert.match(prompt, /…<\/description>/);
|
|
52
|
+
assert.match(prompt, /<omitted count="2" \/>/);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it("replaces an existing catalog instead of duplicating it", () => {
|
|
56
|
+
const first = buildAdvertisedAgentPrompt([agent("alpha", { advertise: true })]);
|
|
57
|
+
const second = buildAdvertisedAgentPrompt([agent("beta", { advertise: true })]);
|
|
58
|
+
assert.ok(first);
|
|
59
|
+
assert.ok(second);
|
|
60
|
+
|
|
61
|
+
const systemPrompt = appendAdvertisedAgentPrompt(appendAdvertisedAgentPrompt("base prompt", first), second);
|
|
62
|
+
assert.equal(systemPrompt.match(/<advertised_subagents>/gu)?.length, 1);
|
|
63
|
+
assert.doesNotMatch(systemPrompt, /<name>alpha<\/name>/);
|
|
64
|
+
assert.match(systemPrompt, /<name>beta<\/name>/);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it("returns no catalog when no agent opts in", () => {
|
|
68
|
+
assert.equal(buildAdvertisedAgentPrompt([agent("hidden")]), undefined);
|
|
69
|
+
assert.equal(appendAdvertisedAgentPrompt("base prompt\n\n", undefined), "base prompt\n\n");
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("admits an exact-budget canonical name and omits it one byte over", () => {
|
|
73
|
+
const emptyName = buildAdvertisedAgentPrompt([agent("", { advertise: true, description: "small" })])!;
|
|
74
|
+
const name = "x".repeat(12_288 - Buffer.byteLength(emptyName));
|
|
75
|
+
const exact = buildAdvertisedAgentPrompt([agent(name, { advertise: true, description: "small" })])!;
|
|
76
|
+
assert.equal(Buffer.byteLength(exact), 12_288);
|
|
77
|
+
assert.ok(exact.includes(`<name>${name}</name>`));
|
|
78
|
+
const over = buildAdvertisedAgentPrompt([agent(`${name}x`, { advertise: true, description: "small" })])!;
|
|
79
|
+
assert.doesNotMatch(over, /<name>/);
|
|
80
|
+
assert.match(over, /<omitted count="1"/);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it("withdraws a reused catalog when the last advertised agent disappears", () => {
|
|
84
|
+
const prior = appendAdvertisedAgentPrompt("base prompt", buildAdvertisedAgentPrompt([agent("alpha", { advertise: true })]));
|
|
85
|
+
assert.equal(appendAdvertisedAgentPrompt(prior, buildAdvertisedAgentPrompt([])), "base prompt");
|
|
86
|
+
});
|
|
87
|
+
});
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { execFileSync } from "node:child_process";
|
|
3
|
+
import * as fs from "node:fs";
|
|
4
|
+
import * as os from "node:os";
|
|
5
|
+
import * as path from "node:path";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
import { it } from "node:test";
|
|
8
|
+
import { SUBAGENT_CHILD_ENV } from "../../src/runs/shared/child-runtime-config.ts";
|
|
9
|
+
|
|
10
|
+
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
|
|
11
|
+
|
|
12
|
+
it("emits bounded file-only snapshots, refreshes through management, and performs zero prompt-time filesystem calls", () => {
|
|
13
|
+
const home = fs.mkdtempSync(path.join(os.tmpdir(), "advertised-refresh-"));
|
|
14
|
+
const env = { ...process.env, SELESAI_CODING_AGENT_DIR: home };
|
|
15
|
+
delete env[SUBAGENT_CHILD_ENV];
|
|
16
|
+
try {
|
|
17
|
+
const output = execFileSync(process.execPath, ["--experimental-strip-types", "--import", "./test/support/register-loader.mjs", "--input-type=module", "--eval", String.raw`
|
|
18
|
+
import assert from "node:assert/strict";
|
|
19
|
+
import fs from "node:fs";
|
|
20
|
+
import path from "node:path";
|
|
21
|
+
import { syncBuiltinESMExports } from "node:module";
|
|
22
|
+
import register from "./src/extension/index.ts";
|
|
23
|
+
import { registerSubagentCapabilityCeiling } from "./src/runs/shared/capability-ceiling.ts";
|
|
24
|
+
const home = process.env.SELESAI_CODING_AGENT_DIR;
|
|
25
|
+
const cwd = path.join(home, "project");
|
|
26
|
+
fs.mkdirSync(path.join(cwd, ".selesai"), { recursive: true });
|
|
27
|
+
const dir = path.join(home, "agents");
|
|
28
|
+
fs.mkdirSync(dir);
|
|
29
|
+
const write = (file, name, description, advertise = true) => fs.writeFileSync(path.join(dir, file + ".md"),
|
|
30
|
+
"---\nname: " + name + "\ndescription: " + description + "\nadvertise: " + advertise + "\n---\nAct narrowly.\n");
|
|
31
|
+
const handlers = new Map();
|
|
32
|
+
let tool;
|
|
33
|
+
let activeTools = ["subagent"];
|
|
34
|
+
const pi = new Proxy({
|
|
35
|
+
events: { on() { return () => {}; }, emit() {} },
|
|
36
|
+
on(event, handler) { handlers.set(event, [...(handlers.get(event) ?? []), handler]); },
|
|
37
|
+
registerTool(value) { if (value.name === "subagent") tool = value; },
|
|
38
|
+
getActiveTools() { return activeTools; },
|
|
39
|
+
}, { get(target, key) { return key in target ? target[key] : () => undefined; } });
|
|
40
|
+
register(pi);
|
|
41
|
+
const ctx = {
|
|
42
|
+
cwd, hasUI: false, model: { provider: "test", id: "test" },
|
|
43
|
+
modelRegistry: { getAvailable() { return []; }, getAll() { return []; } },
|
|
44
|
+
sessionManager: { getSessionId() { return "advertised-test"; }, getSessionFile() { return undefined; }, getBranch() { return []; } },
|
|
45
|
+
};
|
|
46
|
+
// Invoke the registered catalog lifecycle hook; unrelated host services are not started by this harness.
|
|
47
|
+
const refresh = (reason = "reload") => handlers.get("session_start").at(-1)({ reason }, ctx);
|
|
48
|
+
const emit = (systemPrompt = "base", selectedTools = activeTools) => {
|
|
49
|
+
const result = handlers.get("before_agent_start").at(-1)({ systemPrompt, systemPromptOptions: { selectedTools: selectedTools ?? undefined } }, ctx);
|
|
50
|
+
return result?.systemPrompt ?? systemPrompt;
|
|
51
|
+
};
|
|
52
|
+
const io = { statSync: 0, readdirSync: 0, readFileSync: 0 };
|
|
53
|
+
const originals = {};
|
|
54
|
+
for (const key of Object.keys(io)) {
|
|
55
|
+
originals[key] = fs[key];
|
|
56
|
+
fs[key] = (...args) => { io[key]++; return originals[key](...args); };
|
|
57
|
+
}
|
|
58
|
+
syncBuiltinESMExports();
|
|
59
|
+
const noIo = (fn) => {
|
|
60
|
+
const before = { ...io };
|
|
61
|
+
const result = fn();
|
|
62
|
+
assert.deepEqual(io, before, "prompt emission must not stat, readdir, or read files");
|
|
63
|
+
return result;
|
|
64
|
+
};
|
|
65
|
+
refresh("startup");
|
|
66
|
+
noIo(() => { for (let i = 0; i < 20; i++) assert.equal(emit(), "base"); });
|
|
67
|
+
for (let i = 0; i < 250; i++) write("hidden-" + i, "hidden-" + i, "hidden", false);
|
|
68
|
+
refresh();
|
|
69
|
+
noIo(() => { for (let i = 0; i < 20; i++) assert.equal(emit(), "base"); });
|
|
70
|
+
write("specialist", "specialist", "Original specialist");
|
|
71
|
+
assert.equal(noIo(() => emit()), "base", "external edits wait for reload");
|
|
72
|
+
refresh();
|
|
73
|
+
let prompt = noIo(() => emit());
|
|
74
|
+
assert.match(prompt, /<name>specialist<\/name>/);
|
|
75
|
+
assert.doesNotMatch(prompt, /hidden-/);
|
|
76
|
+
assert.match(prompt, /Before execution.*action: "list", capabilities: true/);
|
|
77
|
+
assert.equal(noIo(() => emit(prompt, ["read"])), "base");
|
|
78
|
+
activeTools = ["read"];
|
|
79
|
+
assert.equal(noIo(() => emit(prompt, null)), "base");
|
|
80
|
+
activeTools = ["subagent"];
|
|
81
|
+
const ceiling = registerSubagentCapabilityCeiling({ sessionId: "advertised-test", source: "test", ceiling: { allowedAgents: [] } });
|
|
82
|
+
assert.equal(noIo(() => emit(prompt)), "base");
|
|
83
|
+
ceiling.dispose();
|
|
84
|
+
assert.match(noIo(() => emit()), /Original specialist/);
|
|
85
|
+
const manage = async (params) => tool.execute("manage", params, new AbortController().signal, undefined, ctx);
|
|
86
|
+
write("pending", "pending", "External change awaiting refresh");
|
|
87
|
+
await manage({ action: "get", agent: "specialist" });
|
|
88
|
+
assert.doesNotMatch(noIo(() => emit()), /<name>pending<\/name>/, "reads must not refresh");
|
|
89
|
+
await assert.rejects(manage({ action: "update", agent: "specialist", config: { advertise: "invalid" } }), /config.advertise must be a boolean/);
|
|
90
|
+
assert.doesNotMatch(noIo(() => emit()), /<name>pending<\/name>/, "failed mutations must not refresh");
|
|
91
|
+
fs.unlinkSync(path.join(dir, "pending.md"));
|
|
92
|
+
let result = await manage({ action: "update", agent: "specialist", config: { description: "Updated specialist" } });
|
|
93
|
+
assert.notEqual(result.isError, true, JSON.stringify(result));
|
|
94
|
+
assert.match(noIo(() => emit(prompt)), /Updated specialist/);
|
|
95
|
+
assert.match(fs.readFileSync(path.join(dir, "specialist.md"), "utf8"), /advertise: true/);
|
|
96
|
+
result = await manage({ action: "disable", agent: "specialist", agentScope: "user" });
|
|
97
|
+
assert.notEqual(result.isError, true, JSON.stringify(result));
|
|
98
|
+
assert.equal(noIo(() => emit(prompt)), "base");
|
|
99
|
+
result = await manage({ action: "enable", agent: "specialist", agentScope: "user" });
|
|
100
|
+
assert.notEqual(result.isError, true, JSON.stringify(result));
|
|
101
|
+
prompt = noIo(() => emit());
|
|
102
|
+
assert.match(prompt, /Updated specialist/);
|
|
103
|
+
result = await manage({ action: "delete", agent: "specialist", agentScope: "user" });
|
|
104
|
+
assert.notEqual(result.isError, true, JSON.stringify(result));
|
|
105
|
+
assert.equal(noIo(() => emit(prompt)), "base");
|
|
106
|
+
result = await manage({ action: "create", config: { name: "created", description: "Created specialist", systemPrompt: "Act narrowly.", scope: "user", advertise: true } });
|
|
107
|
+
assert.notEqual(result.isError, true, JSON.stringify(result));
|
|
108
|
+
assert.match(noIo(() => emit()), /<name>created<\/name>/);
|
|
109
|
+
result = await manage({ action: "update", agent: "created", config: { name: "renamed" } });
|
|
110
|
+
assert.notEqual(result.isError, true, JSON.stringify(result));
|
|
111
|
+
prompt = noIo(() => emit());
|
|
112
|
+
assert.match(prompt, /<name>renamed<\/name>/);
|
|
113
|
+
assert.doesNotMatch(prompt, /<name>created<\/name>/);
|
|
114
|
+
result = await manage({ action: "update", agent: "renamed", config: { advertise: false } });
|
|
115
|
+
assert.notEqual(result.isError, true, JSON.stringify(result));
|
|
116
|
+
assert.equal(noIo(() => emit(prompt)), "base");
|
|
117
|
+
// Inject a refresh-only read failure after the management file write has succeeded.
|
|
118
|
+
await manage({ action: "update", agent: "renamed", config: { advertise: true } });
|
|
119
|
+
prompt = noIo(() => emit());
|
|
120
|
+
assert.match(prompt, /<name>renamed<\/name>/);
|
|
121
|
+
const writeFile = fs.writeFileSync;
|
|
122
|
+
fs.writeFileSync = (file, ...args) => {
|
|
123
|
+
const result = writeFile(file, ...args);
|
|
124
|
+
if (String(file).endsWith("renamed.md")) writeFile(path.join(home, "settings.json"), "{");
|
|
125
|
+
return result;
|
|
126
|
+
};
|
|
127
|
+
syncBuiltinESMExports();
|
|
128
|
+
result = await manage({ action: "update", agent: "renamed", config: { description: "Persisted despite refresh failure" } });
|
|
129
|
+
assert.notEqual(result.isError, true, "refresh failure must not change the persisted mutation result");
|
|
130
|
+
assert.match(fs.readFileSync(path.join(dir, "renamed.md"), "utf8"), /advertise: true/);
|
|
131
|
+
assert.equal(noIo(() => emit(prompt)), "base", "failed refresh withdraws stale guidance");
|
|
132
|
+
assert.throws(() => refresh(), /Failed to parse settings file/, "reload discovery errors must reach the host");
|
|
133
|
+
fs.writeFileSync = writeFile;
|
|
134
|
+
syncBuiltinESMExports();
|
|
135
|
+
fs.unlinkSync(path.join(home, "settings.json"));
|
|
136
|
+
refresh();
|
|
137
|
+
assert.match(noIo(() => emit()), /<name>renamed<\/name>/);
|
|
138
|
+
await manage({ action: "delete", agent: "renamed", agentScope: "user" });
|
|
139
|
+
write("huge", "a".repeat(100000), "huge name");
|
|
140
|
+
write("escaped-name", "b" + "&".repeat(4000), "escaped huge name");
|
|
141
|
+
for (let i = 0; i < 25; i++) write("opt-" + i, "pkg.opt-" + i, i % 2 ? '<>&"'.repeat(300) : "🦜界".repeat(300));
|
|
142
|
+
refresh();
|
|
143
|
+
prompt = noIo(() => { let result; for (let i = 0; i < 20; i++) result = emit(); return result; });
|
|
144
|
+
const catalog = prompt.slice(prompt.indexOf("<advertised_subagents>"));
|
|
145
|
+
assert.ok(Buffer.byteLength(catalog) <= 12288);
|
|
146
|
+
assert.doesNotMatch(catalog, /<name>[ab]/);
|
|
147
|
+
assert.match(catalog, /<>&"/);
|
|
148
|
+
assert.match(catalog, /not instructions to delegate/);
|
|
149
|
+
assert.match(catalog, /🦜界/);
|
|
150
|
+
assert.doesNotMatch(catalog, /�/);
|
|
151
|
+
assert.match(catalog, /<name>pkg\.opt-\d+<\/name>/);
|
|
152
|
+
assert.match(catalog, /<omitted count="\d+"/);
|
|
153
|
+
for (const file of fs.readdirSync(dir)) fs.unlinkSync(path.join(dir, file));
|
|
154
|
+
assert.equal(noIo(() => emit()), prompt, "external removal waits for reload");
|
|
155
|
+
refresh();
|
|
156
|
+
assert.equal(noIo(() => emit(prompt)), "base");
|
|
157
|
+
process.stdout.write("prompt contracts passed; zero prompt-time stat/readdir/readFile calls at 0, 250, and 277 definitions");
|
|
158
|
+
`], { cwd: root, env, encoding: "utf8", timeout: 60_000 });
|
|
159
|
+
assert.match(output, /prompt contracts passed/);
|
|
160
|
+
} finally {
|
|
161
|
+
fs.rmSync(home, { recursive: true, force: true });
|
|
162
|
+
}
|
|
163
|
+
});
|
|
@@ -9,7 +9,8 @@ import { serializeAgent } from "../../src/agents/agent-serializer.ts";
|
|
|
9
9
|
import { parseChain, serializeChain } from "../../src/agents/chain-serializer.ts";
|
|
10
10
|
import { discoverAgents, discoverAgentsAll, inspectAgentDefinitionDirectory, type AgentConfig } from "../../src/agents/agents.ts";
|
|
11
11
|
import { parseFrontmatter } from "../../src/agents/frontmatter.ts";
|
|
12
|
-
import {
|
|
12
|
+
import { buildInProcessChildLaunch } from "../../src/runs/shared/child-launch.ts";
|
|
13
|
+
import { applyThinkingSuffix } from "../../src/runs/shared/child-tool-plan.ts";
|
|
13
14
|
import { THINKING_LEVELS } from "../../src/shared/model-info.ts";
|
|
14
15
|
|
|
15
16
|
const tempDirs: string[] = [];
|
|
@@ -384,6 +385,31 @@ body`);
|
|
|
384
385
|
}));
|
|
385
386
|
});
|
|
386
387
|
|
|
388
|
+
describe("agent advertise frontmatter", () => {
|
|
389
|
+
it("parses and serializes explicit prompt advertisement", () => withTempHome(() => {
|
|
390
|
+
const project = fs.mkdtempSync(path.join(os.tmpdir(), "pi-subagents-advertised-agent-"));
|
|
391
|
+
tempDirs.push(project);
|
|
392
|
+
writeAgent(path.join(project, ".selesai", "agents", "worker.md"), `---
|
|
393
|
+
name: worker
|
|
394
|
+
description: Worker
|
|
395
|
+
advertise: true
|
|
396
|
+
---
|
|
397
|
+
body`);
|
|
398
|
+
|
|
399
|
+
const worker = discoverAgents(project, "both").agents.find((agent) => agent.name === "worker")!;
|
|
400
|
+
assert.equal(worker.advertise, true);
|
|
401
|
+
assert.match(serializeAgent(worker), /^advertise: true$/m);
|
|
402
|
+
}));
|
|
403
|
+
|
|
404
|
+
it("rejects non-boolean advertise values", () => withTempHome(() => {
|
|
405
|
+
const project = fs.mkdtempSync(path.join(os.tmpdir(), "pi-subagents-invalid-advertise-"));
|
|
406
|
+
tempDirs.push(project);
|
|
407
|
+
writeAgent(path.join(project, ".selesai", "agents", "worker.md"), "---\nname: worker\ndescription: Worker\nadvertise: yes\n---\nbody");
|
|
408
|
+
|
|
409
|
+
assert.match(discoverAgents(project, "project").agentDiagnostics?.[0]?.error ?? "", /invalid advertise frontmatter; expected true or false/);
|
|
410
|
+
}));
|
|
411
|
+
});
|
|
412
|
+
|
|
387
413
|
describe("agent aliases", () => {
|
|
388
414
|
it("parses and serializes agent aliases", () => withTempHome(() => {
|
|
389
415
|
const project = fs.mkdtempSync(path.join(os.tmpdir(), "pi-subagents-alias-agent-"));
|
|
@@ -1037,7 +1063,7 @@ Review nested project work.
|
|
|
1037
1063
|
assert.equal(agent.filePath, path.join(packageRoot, "agents", "reviewer.md"));
|
|
1038
1064
|
}));
|
|
1039
1065
|
|
|
1040
|
-
it("keeps nearest project root discovery by default when a nested .
|
|
1066
|
+
it("keeps nearest project root discovery by default when a nested .pi exists", () => withTempHome(() => {
|
|
1041
1067
|
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-subagents-nearest-root-default-"));
|
|
1042
1068
|
tempDirs.push(dir);
|
|
1043
1069
|
const nested = path.join(dir, "packages", "app", "src");
|
|
@@ -1103,7 +1129,7 @@ Plan outer project work.
|
|
|
1103
1129
|
assert.equal(reviewer?.override?.path, path.join(dir, ".selesai", "settings.json"));
|
|
1104
1130
|
}));
|
|
1105
1131
|
|
|
1106
|
-
it("keeps git-root discovery stable when a nested linked worktree creates incidental .
|
|
1132
|
+
it("keeps git-root discovery stable when a nested linked worktree creates incidental .pi state", () => withTempHome(() => {
|
|
1107
1133
|
const { repo, worktree } = createNestedLinkedWorktree();
|
|
1108
1134
|
const { packageAgentName, packageAgentPath, settingsPath } = writeLinkedWorktreePackage(repo);
|
|
1109
1135
|
|
|
@@ -1514,19 +1540,19 @@ Do work
|
|
|
1514
1540
|
assert.ok(agent);
|
|
1515
1541
|
assert.equal(agent.thinking, false);
|
|
1516
1542
|
|
|
1517
|
-
const {
|
|
1518
|
-
|
|
1519
|
-
|
|
1543
|
+
const { session } = buildInProcessChildLaunch({
|
|
1544
|
+
host: "parent",
|
|
1545
|
+
cwd: dir,
|
|
1520
1546
|
sessionEnabled: false,
|
|
1521
|
-
model: agent.model,
|
|
1522
|
-
thinking: agent.thinking,
|
|
1547
|
+
model: applyThinkingSuffix(agent.model, agent.thinking),
|
|
1523
1548
|
inheritProjectContext: agent.inheritProjectContext,
|
|
1549
|
+
inheritGlobalContext: agent.inheritGlobalContext,
|
|
1524
1550
|
inheritSkills: agent.inheritSkills,
|
|
1551
|
+
childAgentName: agent.name,
|
|
1552
|
+
childIndex: 0,
|
|
1525
1553
|
});
|
|
1526
1554
|
|
|
1527
|
-
assert.
|
|
1528
|
-
assert.ok(args.includes("glm-5.2-short-fast"));
|
|
1529
|
-
assert.ok(!args.some((arg) => arg.includes(":false")));
|
|
1555
|
+
assert.equal(session.model, "glm-5.2-short-fast");
|
|
1530
1556
|
}
|
|
1531
1557
|
});
|
|
1532
1558
|
|
|
@@ -1769,26 +1795,22 @@ Do work
|
|
|
1769
1795
|
});
|
|
1770
1796
|
|
|
1771
1797
|
it("adds the fast extension only for allowlisted native models", () => {
|
|
1772
|
-
const
|
|
1773
|
-
|
|
1774
|
-
|
|
1798
|
+
const launch = {
|
|
1799
|
+
host: "parent" as const,
|
|
1800
|
+
cwd: process.cwd(),
|
|
1775
1801
|
sessionEnabled: false,
|
|
1776
|
-
model: "openai-codex/gpt-5.6-luna:low",
|
|
1777
|
-
fast: true,
|
|
1778
1802
|
inheritProjectContext: false,
|
|
1803
|
+
inheritGlobalContext: false,
|
|
1779
1804
|
inheritSkills: false,
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
assert.ok(allowed.args.some((arg) => arg.endsWith("fast-mode-extension.ts")));
|
|
1783
|
-
assert.throws(() => buildPiArgs({
|
|
1784
|
-
baseArgs: ["-p"],
|
|
1785
|
-
task: "hello",
|
|
1786
|
-
sessionEnabled: false,
|
|
1787
|
-
model: "anthropic/claude-sonnet-4",
|
|
1805
|
+
childAgentName: "worker",
|
|
1806
|
+
childIndex: 0,
|
|
1788
1807
|
fast: true,
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1808
|
+
};
|
|
1809
|
+
const allowed = buildInProcessChildLaunch({ ...launch, model: "openai-codex/gpt-5.6-luna:low" });
|
|
1810
|
+
|
|
1811
|
+
assert.ok(allowed.toolPlan.runtimeExtensions.some((extensionPath) => extensionPath.endsWith("fast-mode-extension.ts")));
|
|
1812
|
+
assert.deepEqual(allowed.session.hooks.map((hook) => hook.name), ["pi-subagents:prompt-runtime", "pi-subagents:fast-mode"]);
|
|
1813
|
+
assert.throws(() => buildInProcessChildLaunch({ ...launch, model: "anthropic/claude-sonnet-4" }), /fast mode supports only/);
|
|
1792
1814
|
});
|
|
1793
1815
|
});
|
|
1794
1816
|
|
|
@@ -1865,7 +1887,7 @@ Do work
|
|
|
1865
1887
|
}
|
|
1866
1888
|
});
|
|
1867
1889
|
|
|
1868
|
-
it("
|
|
1890
|
+
it("bundled standard agents keep bounded tool allowlists", () => {
|
|
1869
1891
|
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-subagents-builtin-supervisor-tool-"));
|
|
1870
1892
|
const homeDir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-subagents-builtin-supervisor-tool-home-"));
|
|
1871
1893
|
tempDirs.push(dir);
|
|
@@ -1877,11 +1899,28 @@ Do work
|
|
|
1877
1899
|
process.env.HOME = homeDir;
|
|
1878
1900
|
process.env.USERPROFILE = homeDir;
|
|
1879
1901
|
const agents = discoverAgentsAll(dir).builtin;
|
|
1880
|
-
|
|
1902
|
+
const expectedTools = {
|
|
1903
|
+
worker: ["read", "grep", "find", "ls", "bash", "edit", "write", "contact_supervisor"],
|
|
1904
|
+
delegate: ["read", "grep", "find", "ls", "bash", "edit", "write", "contact_supervisor"],
|
|
1905
|
+
reviewer: ["read", "grep", "find", "ls", "contact_supervisor"],
|
|
1906
|
+
scout: ["read", "grep", "find", "ls", "bash", "write", "contact_supervisor"],
|
|
1907
|
+
researcher: ["read", "write", "web_search", "fetch_content", "get_search_content", "source_check"],
|
|
1908
|
+
};
|
|
1909
|
+
for (const [name, tools] of Object.entries(expectedTools)) {
|
|
1881
1910
|
const agent = agents.find((candidate) => candidate.name === name);
|
|
1882
1911
|
assert.ok(agent, `${name} builtin should be discovered`);
|
|
1883
|
-
assert.deepEqual(agent?.tools,
|
|
1912
|
+
assert.deepEqual(agent?.tools, tools);
|
|
1884
1913
|
}
|
|
1914
|
+
|
|
1915
|
+
const researcherPrompt = agents.find((candidate) => candidate.name === "researcher")?.systemPrompt ?? "";
|
|
1916
|
+
assert.match(researcherPrompt, /search-result summaries as discovery aids, not final evidence/);
|
|
1917
|
+
assert.match(researcherPrompt, /source_check.*decision-critical or disputed claims/);
|
|
1918
|
+
assert.match(researcherPrompt, /direct evidence, source interpretation, and researcher inference distinctly/);
|
|
1919
|
+
assert.match(researcherPrompt, /Record contradictions.*Record missing evidence/);
|
|
1920
|
+
assert.match(researcherPrompt, /Never invent dates, quotations, citations, or unsupported precision/);
|
|
1921
|
+
assert.match(researcherPrompt, /`source_check` must be registered by the loaded provider before launch/);
|
|
1922
|
+
assert.match(researcherPrompt, /If a registered `source_check` call fails, continue/);
|
|
1923
|
+
assert.match(researcherPrompt, /\*\*Support:\*\* direct evidence \| interpretation\. \*\*Confidence:\*\* high \| medium \| low/);
|
|
1885
1924
|
} finally {
|
|
1886
1925
|
if (previousHome === undefined) delete process.env.HOME;
|
|
1887
1926
|
else process.env.HOME = previousHome;
|
|
@@ -2321,4 +2360,4 @@ Inspect project
|
|
|
2321
2360
|
else process.env.USERPROFILE = oldUserProfile;
|
|
2322
2361
|
}
|
|
2323
2362
|
});
|
|
2324
|
-
});
|
|
2363
|
+
});
|
|
@@ -109,6 +109,81 @@ describe("agent management config parsing", () => {
|
|
|
109
109
|
assert.equal(JSON.stringify(capabilities).includes("SYSTEM_PROMPT_SENTINEL"), false);
|
|
110
110
|
});
|
|
111
111
|
|
|
112
|
+
it("reports bundled reviewer supervisor contact without mutation tools in capabilities", () => {
|
|
113
|
+
const listed = handleManagementAction("list", { agentScope: "project", capabilities: true }, {
|
|
114
|
+
cwd: tempDir,
|
|
115
|
+
modelRegistry: { getAvailable: () => [] },
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
assert.equal(listed.isError, false);
|
|
119
|
+
const capabilities = listed.details?.agentCapabilities;
|
|
120
|
+
assert.ok(capabilities);
|
|
121
|
+
const reviewer = capabilities.agents.find((agent) => agent.name === "reviewer");
|
|
122
|
+
assert.ok(reviewer, "reviewer builtin should be present in capability output");
|
|
123
|
+
assert.deepEqual(reviewer.tools.names, ["read", "grep", "find", "ls", "contact_supervisor"]);
|
|
124
|
+
assert.match(readText(listed), /Tools: read, grep, find, ls, contact_supervisor/);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it("reports passive external CLI availability for present and absent commands", () => {
|
|
128
|
+
const agentsDir = path.join(tempDir, ".selesai", "agents");
|
|
129
|
+
fs.mkdirSync(agentsDir, { recursive: true });
|
|
130
|
+
const presentCommand = path.basename(process.execPath, path.extname(process.execPath));
|
|
131
|
+
fs.writeFileSync(path.join(agentsDir, "present-external.md"), `---
|
|
132
|
+
name: present-external
|
|
133
|
+
description: Present external CLI
|
|
134
|
+
runner:
|
|
135
|
+
type: external-cli
|
|
136
|
+
command: ${presentCommand}
|
|
137
|
+
---
|
|
138
|
+
Present.
|
|
139
|
+
`);
|
|
140
|
+
fs.writeFileSync(path.join(agentsDir, "missing-external.md"), `---
|
|
141
|
+
name: missing-external
|
|
142
|
+
description: Missing external CLI
|
|
143
|
+
runner:
|
|
144
|
+
type: external-cli
|
|
145
|
+
command: missing-external-cli
|
|
146
|
+
---
|
|
147
|
+
Missing.
|
|
148
|
+
`);
|
|
149
|
+
const previousPath = process.env.PATH;
|
|
150
|
+
try {
|
|
151
|
+
process.env.PATH = path.dirname(process.execPath);
|
|
152
|
+
const listed = handleManagementAction("list", { agentScope: "project", capabilities: true }, {
|
|
153
|
+
cwd: tempDir,
|
|
154
|
+
modelRegistry: { getAvailable: () => [] },
|
|
155
|
+
});
|
|
156
|
+
assert.equal(listed.isError, false);
|
|
157
|
+
const text = readText(listed);
|
|
158
|
+
assert.match(text, new RegExp(`external-cli:${presentCommand} ✓`));
|
|
159
|
+
assert.match(text, /external-cli:missing-external-cli missing/);
|
|
160
|
+
|
|
161
|
+
const rows = listed.details?.agentCapabilities?.agents;
|
|
162
|
+
assert.ok(rows);
|
|
163
|
+
const present = rows.find((agent) => agent.name === "present-external");
|
|
164
|
+
const missing = rows.find((agent) => agent.name === "missing-external");
|
|
165
|
+
assert.ok(present);
|
|
166
|
+
assert.ok(missing);
|
|
167
|
+
assert.equal(present.executable, true);
|
|
168
|
+
assert.equal(missing.executable, true);
|
|
169
|
+
assert.equal(present.runner.type, "external-cli");
|
|
170
|
+
assert.equal(missing.runner.type, "external-cli");
|
|
171
|
+
if (present.runner.type !== "external-cli" || missing.runner.type !== "external-cli") return;
|
|
172
|
+
assert.equal(present.runner.command, presentCommand);
|
|
173
|
+
assert.equal(present.runner.available, true);
|
|
174
|
+
assert.equal("unavailableReason" in present.runner, false);
|
|
175
|
+
assert.equal(missing.runner.command, "missing-external-cli");
|
|
176
|
+
assert.equal(missing.runner.available, false);
|
|
177
|
+
assert.match(missing.runner.unavailableReason ?? "", /External CLI binary 'missing-external-cli' was not found on PATH\./);
|
|
178
|
+
assert.ok((missing.runner.unavailableReason ?? "").length <= 256);
|
|
179
|
+
} finally {
|
|
180
|
+
if (previousPath === undefined) delete process.env.PATH;
|
|
181
|
+
else process.env.PATH = previousPath;
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
|
|
112
187
|
it("lists valid agents and diagnoses malformed agent definitions", () => {
|
|
113
188
|
const agentsDir = path.join(tempDir, ".selesai", "agents");
|
|
114
189
|
fs.mkdirSync(agentsDir, { recursive: true });
|
|
@@ -343,7 +418,7 @@ Advise only.
|
|
|
343
418
|
assert.match(readText(result), /Agent 'foo' has invalid configuration: Agent 'foo' package is invalid after sanitization/);
|
|
344
419
|
});
|
|
345
420
|
|
|
346
|
-
it("blocks a malformed .
|
|
421
|
+
it("blocks a malformed .pi agent from falling back to a legacy project agent", () => {
|
|
347
422
|
const canonicalAgentsDir = path.join(tempDir, ".selesai", "agents");
|
|
348
423
|
const legacyAgentsDir = path.join(tempDir, ".agents");
|
|
349
424
|
fs.mkdirSync(canonicalAgentsDir, { recursive: true });
|
|
@@ -1326,7 +1401,7 @@ Drive the failing test first.
|
|
|
1326
1401
|
assert.match(text, /Source: project override/);
|
|
1327
1402
|
assert.match(text, /Requested model setting:\n claude-sonnet-4/);
|
|
1328
1403
|
assert.match(text, /Disabled: true/);
|
|
1329
|
-
assert.match(text.replaceAll("\\", "/"), /Override file:\n .*\.selesai
|
|
1404
|
+
assert.match(text.replaceAll("\\", "/"), /Override file:\n .*\.selesai\/settings\.json/);
|
|
1330
1405
|
});
|
|
1331
1406
|
|
|
1332
1407
|
it("rejects unknown agents for runtime model mappings", () => {
|
|
@@ -1405,4 +1480,4 @@ Inspect cleanup.
|
|
|
1405
1480
|
assert.doesNotMatch(readText(listed), /Proactive skill subagent suggestions:/);
|
|
1406
1481
|
});
|
|
1407
1482
|
|
|
1408
|
-
});
|
|
1483
|
+
});
|
|
@@ -113,7 +113,7 @@ describe("builtin agent overrides", () => {
|
|
|
113
113
|
|
|
114
114
|
const builtins = discoverAgentsAll(tempProject).builtin;
|
|
115
115
|
assert.equal(builtins.find((agent) => agent.name === "researcher")?.tools, undefined);
|
|
116
|
-
assert.deepEqual(builtins.find((agent) => agent.name === "reviewer")?.tools, ["read", "grep", "find", "ls"]);
|
|
116
|
+
assert.deepEqual(builtins.find((agent) => agent.name === "reviewer")?.tools, ["read", "grep", "find", "ls", "contact_supervisor"]);
|
|
117
117
|
});
|
|
118
118
|
|
|
119
119
|
it("keeps explicit empty builtin tool allowlists distinct from inherited tools", () => {
|
|
@@ -719,7 +719,6 @@ describe("builtin agent overrides", () => {
|
|
|
719
719
|
it("agentOverrides replace frontmatter for a shadowing project agent", () => {
|
|
720
720
|
fs.mkdirSync(path.join(tempProject, ".selesai"), { recursive: true });
|
|
721
721
|
writeJson(path.join(tempProject, ".selesai", "settings.json"), {
|
|
722
|
-
|
|
723
722
|
subagents: { agentOverrides: { reviewer: { model: "openai/gpt-5.4" } } },
|
|
724
723
|
});
|
|
725
724
|
writeProjectAgent(tempProject, "reviewer", `---\nname: reviewer\ndescription: Project reviewer\nmodel: google/gemini-3-pro\n---\n\nUse the project reviewer.\n`);
|
|
@@ -734,7 +733,6 @@ describe("builtin agent overrides", () => {
|
|
|
734
733
|
it("applies project agentOverrides to a custom project agent", () => {
|
|
735
734
|
fs.mkdirSync(path.join(tempProject, ".selesai"), { recursive: true });
|
|
736
735
|
writeJson(path.join(tempProject, ".selesai", "settings.json"), {
|
|
737
|
-
|
|
738
736
|
subagents: {
|
|
739
737
|
agentOverrides: {
|
|
740
738
|
implementer: {
|
|
@@ -786,7 +784,6 @@ describe("builtin agent overrides", () => {
|
|
|
786
784
|
|
|
787
785
|
it("applies user agentOverrides to a custom user agent", () => {
|
|
788
786
|
writeJson(path.join(tempHome, ".selesai", "agent", "settings.json"), {
|
|
789
|
-
|
|
790
787
|
subagents: { agentOverrides: { implementer: { model: "anthropic/claude-sonnet-4-6" } } },
|
|
791
788
|
});
|
|
792
789
|
writeUserAgent(tempHome, "implementer", `---\nname: implementer\ndescription: TDD implementer\n---\n\nDrive the failing test first.\n`);
|
|
@@ -832,7 +829,6 @@ describe("builtin agent overrides", () => {
|
|
|
832
829
|
it("agentOverrides replace explicit custom frontmatter fields", () => {
|
|
833
830
|
fs.mkdirSync(path.join(tempProject, ".selesai"), { recursive: true });
|
|
834
831
|
writeJson(path.join(tempProject, ".selesai", "settings.json"), {
|
|
835
|
-
|
|
836
832
|
subagents: {
|
|
837
833
|
agentOverrides: {
|
|
838
834
|
implementer: {
|
|
@@ -877,7 +873,6 @@ describe("builtin agent overrides", () => {
|
|
|
877
873
|
it("lets false overrides clear explicit output and defaultReads frontmatter", () => {
|
|
878
874
|
fs.mkdirSync(path.join(tempProject, ".selesai"), { recursive: true });
|
|
879
875
|
writeJson(path.join(tempProject, ".selesai", "settings.json"), {
|
|
880
|
-
|
|
881
876
|
subagents: { agentOverrides: { implementer: { output: false, defaultReads: false } } },
|
|
882
877
|
});
|
|
883
878
|
writeProjectAgent(tempProject, "implementer", `---\nname: implementer\ndescription: TDD implementer\noutput: explicit.md\ndefaultReads: explicit.md\n---\n\nDrive the failing test first.\n`);
|
|
@@ -1058,7 +1053,6 @@ describe("builtin agent overrides", () => {
|
|
|
1058
1053
|
writeJson(path.join(packageRoot, "package.json"), { "pi-subagents": { agents: ["agents"] } });
|
|
1059
1054
|
fs.writeFileSync(path.join(packageRoot, "agents", "package-scout.md"), `---\nname: package-scout\ndescription: Package scout\noutput: package-frontmatter.md\ndefaultReads: PACKAGE-FRONTMATTER.md\n---\n\nScout the package.\n`, "utf-8");
|
|
1060
1055
|
writeJson(path.join(tempProject, ".selesai", "settings.json"), {
|
|
1061
|
-
|
|
1062
1056
|
packages: [packageRoot],
|
|
1063
1057
|
subagents: { agentOverrides: { "package-scout": { output: "package.md", defaultReads: ["PACKAGE.md"] } } },
|
|
1064
1058
|
});
|
|
@@ -1171,4 +1165,4 @@ describe("builtin agent overrides", () => {
|
|
|
1171
1165
|
);
|
|
1172
1166
|
assert.equal(whitespaceDescription, undefined);
|
|
1173
1167
|
});
|
|
1174
|
-
});
|
|
1168
|
+
});
|
|
@@ -77,7 +77,7 @@ describe("async runner execution", () => {
|
|
|
77
77
|
agents: [{ ...agent("worker"), model: "mock/denied" }],
|
|
78
78
|
ctx: { ...ctx, cwd: repo },
|
|
79
79
|
cwd: repo,
|
|
80
|
-
asyncDir: path.join(repo, ".
|
|
80
|
+
asyncDir: path.join(repo, ".pi-subagents", "async-step-rules"),
|
|
81
81
|
maxSubagentDepth: 1,
|
|
82
82
|
});
|
|
83
83
|
|