@selesai/code 0.13.0 → 0.13.2
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 +22 -0
- package/dist/core/agent-session.d.ts +1 -1
- package/dist/core/agent-session.js +1 -1
- package/dist/core/sdk.d.ts +2 -2
- package/dist/core/sdk.js +1 -1
- package/dist/core/system-prompt.d.ts +1 -1
- package/dist/core/system-prompt.js +1 -1
- package/dist/extensions/package.json +1 -2
- package/dist/extensions/pi-hermes-memory/CHANGELOG.md +371 -0
- package/dist/extensions/pi-hermes-memory/LICENSE +21 -0
- package/dist/extensions/pi-hermes-memory/README.md +643 -0
- package/dist/extensions/pi-hermes-memory/docs/0.1/TASKS.md +197 -0
- package/dist/extensions/pi-hermes-memory/docs/0.2/PLAN.md +290 -0
- package/dist/extensions/pi-hermes-memory/docs/0.2/TASKS.md +134 -0
- package/dist/extensions/pi-hermes-memory/docs/0.2/TEST-PLAN.md +216 -0
- package/dist/extensions/pi-hermes-memory/docs/0.3/PLAN.md +330 -0
- package/dist/extensions/pi-hermes-memory/docs/0.3/TASKS.md +125 -0
- package/dist/extensions/pi-hermes-memory/docs/0.4/PLAN.md +160 -0
- package/dist/extensions/pi-hermes-memory/docs/0.4/TASKS.md +113 -0
- package/dist/extensions/pi-hermes-memory/docs/0.6/CHANGELOG.md +57 -0
- package/dist/extensions/pi-hermes-memory/docs/0.6/PLAN.md +202 -0
- package/dist/extensions/pi-hermes-memory/docs/0.6/TASKS.md +144 -0
- package/dist/extensions/pi-hermes-memory/docs/0.7/PLAN.md +349 -0
- package/dist/extensions/pi-hermes-memory/docs/0.7/TASKS.md +110 -0
- package/dist/extensions/pi-hermes-memory/docs/PUBLISHING.md +149 -0
- package/dist/extensions/pi-hermes-memory/docs/ROADMAP.md +468 -0
- package/dist/extensions/pi-hermes-memory/docs/images/memory-architecture.svg +1 -0
- package/dist/extensions/pi-hermes-memory/docs/images/pi-logo.svg +22 -0
- package/dist/extensions/pi-hermes-memory/docs/images/pi_memory.png +0 -0
- package/dist/extensions/pi-hermes-memory/docs/images/pi_memory.svg +19 -0
- package/dist/extensions/pi-hermes-memory/docs/images/security-flow.svg +1 -0
- package/dist/extensions/pi-hermes-memory/docs/images/session-lifecycle.svg +1 -0
- package/dist/extensions/pi-hermes-memory/docs/images/source-architecture.svg +1 -0
- package/dist/extensions/pi-hermes-memory/docs/mermaid/memory-architecture.mmd +49 -0
- package/dist/extensions/pi-hermes-memory/docs/mermaid/security-flow.mmd +40 -0
- package/dist/extensions/pi-hermes-memory/docs/mermaid/session-lifecycle.mmd +56 -0
- package/dist/extensions/pi-hermes-memory/docs/mermaid/source-architecture.mmd +54 -0
- package/dist/extensions/pi-hermes-memory/package-lock.json +3799 -0
- package/dist/extensions/pi-hermes-memory/package.json +66 -0
- package/dist/extensions/pi-hermes-memory/scripts/check-min-sdk.mjs +99 -0
- package/dist/extensions/pi-hermes-memory/scripts/ensure-dev.mjs +57 -0
- package/dist/extensions/pi-hermes-memory/src/auto-consolidation-warning.ts +6 -0
- package/dist/extensions/pi-hermes-memory/src/config.ts +178 -0
- package/dist/extensions/pi-hermes-memory/src/constants.ts +424 -0
- package/dist/extensions/pi-hermes-memory/src/extension-root-migration.ts +639 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/auto-consolidate.ts +401 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/background-review.ts +297 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/child-process-watchdog.mjs +90 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/correction-detector.ts +300 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/index-sessions.ts +86 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/insights.ts +78 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/interview.ts +37 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/learn-memory.ts +186 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/message-parts.ts +27 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/pi-child-process.ts +485 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/preview-context.ts +105 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/review-memory-ops.ts +506 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/session-backfill.ts +145 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/session-flush.ts +151 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/session-live-index.ts +94 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/skills-command.ts +1334 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/standing-pin.ts +111 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/switch-project.ts +75 -0
- package/dist/extensions/pi-hermes-memory/src/handlers/sync-markdown-memories.ts +266 -0
- package/dist/extensions/pi-hermes-memory/src/index.ts +378 -0
- package/dist/extensions/pi-hermes-memory/src/lifecycle-timing.ts +54 -0
- package/dist/extensions/pi-hermes-memory/src/paths.ts +61 -0
- package/dist/extensions/pi-hermes-memory/src/project-context.ts +13 -0
- package/dist/extensions/pi-hermes-memory/src/project-memory-migration.ts +93 -0
- package/dist/extensions/pi-hermes-memory/src/project.ts +157 -0
- package/dist/extensions/pi-hermes-memory/src/prompt-context.ts +55 -0
- package/dist/extensions/pi-hermes-memory/src/store/atomic-lock-coordinator.ts +375 -0
- package/dist/extensions/pi-hermes-memory/src/store/canonical-storage-path.ts +54 -0
- package/dist/extensions/pi-hermes-memory/src/store/content-scanner.ts +101 -0
- package/dist/extensions/pi-hermes-memory/src/store/db.ts +1180 -0
- package/dist/extensions/pi-hermes-memory/src/store/fts-query.ts +101 -0
- package/dist/extensions/pi-hermes-memory/src/store/markdown-mutation-lock.ts +38 -0
- package/dist/extensions/pi-hermes-memory/src/store/memory-lookup.ts +24 -0
- package/dist/extensions/pi-hermes-memory/src/store/memory-store.ts +1191 -0
- package/dist/extensions/pi-hermes-memory/src/store/recovery-maintenance.ts +66 -0
- package/dist/extensions/pi-hermes-memory/src/store/schema.ts +118 -0
- package/dist/extensions/pi-hermes-memory/src/store/session-anchor-search.ts +472 -0
- package/dist/extensions/pi-hermes-memory/src/store/session-indexer.ts +511 -0
- package/dist/extensions/pi-hermes-memory/src/store/session-parser.ts +213 -0
- package/dist/extensions/pi-hermes-memory/src/store/session-search.ts +234 -0
- package/dist/extensions/pi-hermes-memory/src/store/skill-store.ts +950 -0
- package/dist/extensions/pi-hermes-memory/src/store/skill-utils.ts +133 -0
- package/dist/extensions/pi-hermes-memory/src/store/sqlite-memory-store.ts +1002 -0
- package/dist/extensions/pi-hermes-memory/src/store/sqlite-native.ts +241 -0
- package/dist/extensions/pi-hermes-memory/src/store/standing-instructions.ts +247 -0
- package/dist/extensions/pi-hermes-memory/src/tools/memory-search-tool.ts +95 -0
- package/dist/extensions/pi-hermes-memory/src/tools/memory-tool.ts +469 -0
- package/dist/extensions/pi-hermes-memory/src/tools/session-search-tool.ts +246 -0
- package/dist/extensions/pi-hermes-memory/src/tools/shared-output-view.ts +170 -0
- package/dist/extensions/pi-hermes-memory/src/tools/skill-tool.ts +333 -0
- package/dist/extensions/pi-hermes-memory/src/tools/tool-result-views.ts +105 -0
- package/dist/extensions/pi-hermes-memory/src/types.ts +214 -0
- package/dist/extensions/pi-hermes-memory/tests/config.test.ts +434 -0
- package/dist/extensions/pi-hermes-memory/tests/extension-root-migration.test.ts +368 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/auto-consolidate.test.ts +984 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/background-review.test.ts +950 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/correction-detector.test.ts +671 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/insights.test.ts +157 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/interview.test.ts +127 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/pi-child-process.test.ts +905 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/preview-context.test.ts +152 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/prompt-context.test.ts +166 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/resources-discover.test.ts +71 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/review-memory-ops.test.ts +614 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/session-backfill.test.ts +192 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/session-flush.test.ts +677 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/session-live-index.test.ts +225 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/skills-command.test.ts +827 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/standing-pin.test.ts +134 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/sync-markdown-memories.test.ts +491 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/system-prompt.test.ts +199 -0
- package/dist/extensions/pi-hermes-memory/tests/handlers/thinking-max.test.ts +64 -0
- package/dist/extensions/pi-hermes-memory/tests/index.test.ts +30 -0
- package/dist/extensions/pi-hermes-memory/tests/integration/flow.test.ts +126 -0
- package/dist/extensions/pi-hermes-memory/tests/lifecycle-timing.test.ts +76 -0
- package/dist/extensions/pi-hermes-memory/tests/paths.test.ts +23 -0
- package/dist/extensions/pi-hermes-memory/tests/project-memory-migration.test.ts +80 -0
- package/dist/extensions/pi-hermes-memory/tests/project-rebinding.test.ts +115 -0
- package/dist/extensions/pi-hermes-memory/tests/project.test.ts +120 -0
- package/dist/extensions/pi-hermes-memory/tests/run-all-timeout.test.ts +107 -0
- package/dist/extensions/pi-hermes-memory/tests/run-all.sh +45 -0
- package/dist/extensions/pi-hermes-memory/tests/store/atomic-lock-coordinator.test.ts +381 -0
- package/dist/extensions/pi-hermes-memory/tests/store/content-scanner.test.ts +388 -0
- package/dist/extensions/pi-hermes-memory/tests/store/db.test.ts +1046 -0
- package/dist/extensions/pi-hermes-memory/tests/store/markdown-mutation-lock.test.ts +34 -0
- package/dist/extensions/pi-hermes-memory/tests/store/memory-store.test.ts +2150 -0
- package/dist/extensions/pi-hermes-memory/tests/store/recovery-maintenance.test.ts +170 -0
- package/dist/extensions/pi-hermes-memory/tests/store/session-anchor-search.test.ts +210 -0
- package/dist/extensions/pi-hermes-memory/tests/store/session-indexer.test.ts +643 -0
- package/dist/extensions/pi-hermes-memory/tests/store/session-parser.test.ts +282 -0
- package/dist/extensions/pi-hermes-memory/tests/store/session-search.test.ts +287 -0
- package/dist/extensions/pi-hermes-memory/tests/store/skill-store.test.ts +678 -0
- package/dist/extensions/pi-hermes-memory/tests/store/skill-utils.test.ts +21 -0
- package/dist/extensions/pi-hermes-memory/tests/store/sqlite-lazy-load.test.ts +78 -0
- package/dist/extensions/pi-hermes-memory/tests/store/sqlite-memory-store.test.ts +543 -0
- package/dist/extensions/pi-hermes-memory/tests/store/sqlite-native.test.ts +164 -0
- package/dist/extensions/pi-hermes-memory/tests/store/standing-instructions.test.ts +171 -0
- package/dist/extensions/pi-hermes-memory/tests/tools/memory-search-tool.test.ts +84 -0
- package/dist/extensions/pi-hermes-memory/tests/tools/memory-tool.test.ts +709 -0
- package/dist/extensions/pi-hermes-memory/tests/tools/session-search-tool.test.ts +345 -0
- package/dist/extensions/pi-hermes-memory/tests/tools/shared-output-view.test.ts +362 -0
- package/dist/extensions/pi-hermes-memory/tests/tools/skill-tool.test.ts +478 -0
- package/dist/extensions/pi-hermes-memory/tests/tools/tool-result-renderer-wiring.test.ts +40 -0
- package/dist/extensions/pi-hermes-memory/tsconfig.json +19 -0
- package/dist/extensions/pi-rewind-hook/README.md +4 -1
- package/dist/extensions/pi-rewind-hook/index.ts +151 -21
- package/dist/extensions/pi-rewind-hook/package.json +5 -3
- package/dist/extensions/pi-subagents/.oxlintrc.json +43 -0
- package/dist/extensions/pi-subagents/AGENTS.md +5 -0
- package/dist/extensions/pi-subagents/CHANGELOG.md +157 -0
- package/dist/extensions/pi-subagents/README.md +12 -6
- package/dist/extensions/pi-subagents/VISION.md +81 -0
- package/dist/extensions/pi-subagents/agents/claude-code-writer.md +15 -0
- package/dist/extensions/pi-subagents/agents/claude-code.md +15 -0
- package/dist/extensions/pi-subagents/agents/codex-exec-writer.md +15 -0
- package/dist/extensions/pi-subagents/agents/codex-exec.md +15 -0
- package/dist/extensions/pi-subagents/agents/cursor-agent-writer.md +14 -0
- package/dist/extensions/pi-subagents/agents/cursor-agent.md +14 -0
- package/dist/extensions/pi-subagents/agents/reviewer.md +1 -3
- package/dist/extensions/pi-subagents/docs/agents.md +488 -0
- package/dist/extensions/pi-subagents/docs/configuration.md +46 -9
- package/dist/extensions/pi-subagents/docs/extension-api.md +42 -3
- package/dist/extensions/pi-subagents/docs/models.md +27 -4
- package/dist/extensions/pi-subagents/docs/observability.md +10 -9
- package/dist/extensions/pi-subagents/docs/tool-reference.md +102 -6
- package/dist/extensions/pi-subagents/docs/workflows.md +135 -0
- package/dist/extensions/pi-subagents/package-lock.json +389 -2
- package/dist/extensions/pi-subagents/package.json +3 -1
- package/dist/extensions/pi-subagents/prompts/review-loop.md +2 -2
- package/dist/extensions/pi-subagents/skills/council-mode/SKILL.md +1 -1
- package/dist/extensions/pi-subagents/skills/pi-subagents/SKILL.md +3 -1
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/execution-controls.md +7 -3
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/management-authoring-rpc.md +2 -2
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/prompting-and-roles.md +26 -5
- package/dist/extensions/pi-subagents/src/agents/agent-management.ts +41 -22
- package/dist/extensions/pi-subagents/src/agents/agent-refinements.ts +4 -4
- package/dist/extensions/pi-subagents/src/agents/agent-serializer.ts +9 -2
- package/dist/extensions/pi-subagents/src/agents/agents.ts +322 -75
- package/dist/extensions/pi-subagents/src/agents/builtin-names.ts +6 -0
- package/dist/extensions/pi-subagents/src/agents/runtime-agent-events.ts +70 -0
- package/dist/extensions/pi-subagents/src/agents/runtime-agent-registry.ts +27 -20
- package/dist/extensions/pi-subagents/src/api/agents.ts +10 -5
- package/dist/extensions/pi-subagents/src/api/background-work.ts +5 -1
- package/dist/extensions/pi-subagents/src/api/delegation.ts +0 -7
- package/dist/extensions/pi-subagents/src/api/preflight.ts +34 -12
- package/dist/extensions/pi-subagents/src/extension/config.ts +70 -0
- package/dist/extensions/pi-subagents/src/extension/doctor.ts +3 -3
- package/dist/extensions/pi-subagents/src/extension/fanout-child.ts +5 -3
- package/dist/extensions/pi-subagents/src/extension/index.ts +83 -30
- package/dist/extensions/pi-subagents/src/extension/public-execution.ts +44 -15
- package/dist/extensions/pi-subagents/src/extension/rpc.ts +55 -19
- package/dist/extensions/pi-subagents/src/extension/schemas.ts +41 -15
- package/dist/extensions/pi-subagents/src/extension/tool-description.ts +28 -31
- package/dist/extensions/pi-subagents/src/inspectors/herdr/actions.ts +2 -1
- package/dist/extensions/pi-subagents/src/inspectors/herdr/inspector-runner.ts +2 -10
- package/dist/extensions/pi-subagents/src/inspectors/herdr/session-roots-codec.ts +42 -0
- package/dist/extensions/pi-subagents/src/integrations/herdr-status.ts +51 -7
- package/dist/extensions/pi-subagents/src/intercom/result-intercom.ts +2 -0
- package/dist/extensions/pi-subagents/src/profiles/profiles.ts +5 -6
- package/dist/extensions/pi-subagents/src/runs/background/active-async-capacity.ts +77 -10
- package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +176 -53
- package/dist/extensions/pi-subagents/src/runs/background/async-job-tracker.ts +19 -12
- package/dist/extensions/pi-subagents/src/runs/background/async-resume.ts +29 -27
- package/dist/extensions/pi-subagents/src/runs/background/async-retention.ts +20 -3
- package/dist/extensions/pi-subagents/src/runs/background/async-status-snapshot.ts +23 -261
- package/dist/extensions/pi-subagents/src/runs/background/async-status.ts +73 -7
- package/dist/extensions/pi-subagents/src/runs/background/chain-append.ts +8 -3
- package/dist/extensions/pi-subagents/src/runs/background/chain-root-attachment.ts +74 -8
- package/dist/extensions/pi-subagents/src/runs/background/fleet-view.ts +37 -21
- package/dist/extensions/pi-subagents/src/runs/background/inspect-rpc.ts +8 -8
- package/dist/extensions/pi-subagents/src/runs/background/notify.ts +184 -9
- package/dist/extensions/pi-subagents/src/runs/background/result-delivery-ownership.ts +45 -0
- package/dist/extensions/pi-subagents/src/runs/background/result-files.ts +28 -14
- package/dist/extensions/pi-subagents/src/runs/background/result-watcher.ts +38 -15
- package/dist/extensions/pi-subagents/src/runs/background/resume-guidance.ts +1 -1
- package/dist/extensions/pi-subagents/src/runs/background/retained-children.ts +1 -1
- package/dist/extensions/pi-subagents/src/runs/background/run-status.ts +50 -13
- package/dist/extensions/pi-subagents/src/runs/background/scheduled-runs.ts +93 -8
- package/dist/extensions/pi-subagents/src/runs/background/stale-run-reconciler.ts +10 -4
- package/dist/extensions/pi-subagents/src/runs/background/steering.ts +4 -14
- package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +549 -377
- package/dist/extensions/pi-subagents/src/runs/background/subagent-wait.ts +58 -10
- package/dist/extensions/pi-subagents/src/runs/background/terminal-run-index.ts +1 -1
- package/dist/extensions/pi-subagents/src/runs/background/wait-completions.ts +26 -1
- package/dist/extensions/pi-subagents/src/runs/background/wait-config.ts +23 -9
- package/dist/extensions/pi-subagents/src/runs/background/wait-tool.ts +9 -2
- package/dist/extensions/pi-subagents/src/runs/foreground/async-steering-action.ts +2 -2
- package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +204 -129
- package/dist/extensions/pi-subagents/src/runs/foreground/foreground-control.ts +9 -0
- package/dist/extensions/pi-subagents/src/runs/foreground/foreground-history.ts +23 -1
- package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +773 -311
- package/dist/extensions/pi-subagents/src/runs/foreground/workflow-detach-reconcile.ts +140 -115
- package/dist/extensions/pi-subagents/src/runs/shared/abort-recovery.ts +119 -0
- package/dist/extensions/pi-subagents/src/runs/shared/async-status-projection.ts +463 -0
- package/dist/extensions/pi-subagents/src/runs/shared/child-identity.ts +19 -4
- package/dist/extensions/pi-subagents/src/runs/shared/child-launch-plan.ts +151 -0
- package/dist/extensions/pi-subagents/src/runs/shared/child-protocol.ts +21 -7
- package/dist/extensions/pi-subagents/src/runs/shared/claude-code-adapter.ts +129 -0
- package/dist/extensions/pi-subagents/src/runs/shared/codex-exec-adapter.ts +129 -0
- package/dist/extensions/pi-subagents/src/runs/shared/completion-evidence.ts +89 -0
- package/dist/extensions/pi-subagents/src/runs/shared/completion-guard.ts +5 -4
- package/dist/extensions/pi-subagents/src/runs/shared/cursor-agent-adapter.ts +114 -0
- package/dist/extensions/pi-subagents/src/runs/shared/dynamic-fanout.ts +3 -3
- package/dist/extensions/pi-subagents/src/runs/shared/external-cli-contract.ts +167 -0
- package/dist/extensions/pi-subagents/src/runs/shared/external-cli-preflight.ts +122 -0
- package/dist/extensions/pi-subagents/src/runs/shared/external-cli-runner.ts +348 -55
- package/dist/extensions/pi-subagents/src/runs/shared/fast-mode-extension.ts +5 -5
- package/dist/extensions/pi-subagents/src/runs/shared/host-step-status.ts +230 -0
- package/dist/extensions/pi-subagents/src/runs/shared/lane-metadata.ts +105 -0
- package/dist/extensions/pi-subagents/src/runs/shared/launch-cwd.ts +16 -0
- package/dist/extensions/pi-subagents/src/runs/shared/long-running-guard.ts +2 -1
- package/dist/extensions/pi-subagents/src/runs/shared/mcp-config-sources.ts +422 -0
- package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-allowlist.ts +221 -158
- package/dist/extensions/pi-subagents/src/runs/shared/mcp-direct-tool-grant.ts +197 -0
- package/dist/extensions/pi-subagents/src/runs/shared/model-exclusions.ts +69 -7
- package/dist/extensions/pi-subagents/src/runs/shared/model-fallback.ts +47 -6
- package/dist/extensions/pi-subagents/src/runs/shared/mutation-evidence.ts +7 -2
- package/dist/extensions/pi-subagents/src/runs/shared/nested-events.ts +9 -3
- package/dist/extensions/pi-subagents/src/runs/shared/nested-render.ts +9 -5
- package/dist/extensions/pi-subagents/src/runs/shared/parallel-handoff.ts +419 -7
- package/dist/extensions/pi-subagents/src/runs/shared/parallel-utils.ts +15 -1
- package/dist/extensions/pi-subagents/src/runs/shared/pi-args.ts +81 -8
- package/dist/extensions/pi-subagents/src/runs/shared/process-signal.ts +13 -0
- package/dist/extensions/pi-subagents/src/runs/shared/run-history.ts +21 -1
- package/dist/extensions/pi-subagents/src/runs/shared/single-output.ts +44 -4
- package/dist/extensions/pi-subagents/src/runs/shared/subagent-prompt-runtime.ts +98 -13
- package/dist/extensions/pi-subagents/src/runs/shared/subagent-startup-retry.ts +1 -1
- package/dist/extensions/pi-subagents/src/runs/shared/worktree-cleanup-plan.ts +847 -0
- package/dist/extensions/pi-subagents/src/runs/shared/worktree.ts +18 -0
- package/dist/extensions/pi-subagents/src/shared/child-session-name.ts +46 -0
- package/dist/extensions/pi-subagents/src/shared/extension-context.ts +24 -0
- package/dist/extensions/pi-subagents/src/shared/fork-context.ts +21 -0
- package/dist/extensions/pi-subagents/src/shared/formatters.ts +18 -3
- package/dist/extensions/pi-subagents/src/shared/launch-contract.ts +5 -1
- package/dist/extensions/pi-subagents/src/shared/pruned-fork.ts +450 -0
- package/dist/extensions/pi-subagents/src/shared/session-file-trust.ts +19 -0
- package/dist/extensions/pi-subagents/src/shared/session-tokens.ts +14 -3
- package/dist/extensions/pi-subagents/src/shared/settings.ts +19 -105
- package/dist/extensions/pi-subagents/src/shared/shortcuts.ts +17 -0
- package/dist/extensions/pi-subagents/src/shared/types.ts +359 -40
- package/dist/extensions/pi-subagents/src/shared/utils.ts +41 -84
- package/dist/extensions/pi-subagents/src/shared/workflow-child-permit.ts +116 -0
- package/dist/extensions/pi-subagents/src/slash/delegation-adapters.ts +1 -9
- package/dist/extensions/pi-subagents/src/slash/delegation-request.ts +0 -4
- package/dist/extensions/pi-subagents/src/slash/slash-bridge.ts +1 -2
- package/dist/extensions/pi-subagents/src/slash/slash-commands.ts +378 -88
- package/dist/extensions/pi-subagents/src/slash/slash-live-state.ts +22 -11
- package/dist/extensions/pi-subagents/src/slash/subagents-admin.ts +3 -0
- package/dist/extensions/pi-subagents/src/tui/fleet-status.ts +147 -79
- package/dist/extensions/pi-subagents/src/tui/fleet-transcript.ts +11 -5
- package/dist/extensions/pi-subagents/src/tui/fleet.ts +39 -18
- package/dist/extensions/pi-subagents/src/tui/render.ts +369 -46
- package/dist/extensions/pi-subagents/src/watchdog/turn-delta.ts +1 -1
- package/dist/extensions/pi-subagents/src/workflows/chat-progress.ts +6 -3
- package/dist/extensions/pi-subagents/src/workflows/host-command.ts +230 -0
- package/dist/extensions/pi-subagents/src/workflows/scripted-workflow.ts +740 -58
- package/dist/extensions/pi-subagents/src/workflows/workflow-child-summary.ts +121 -0
- package/dist/extensions/pi-subagents/src/workflows/workflow-preflight.ts +270 -0
- package/dist/extensions/pi-subagents/src/workflows/workflow-receipt.ts +195 -6
- package/dist/extensions/pi-subagents/src/workflows/workflow-settlement.ts +246 -0
- package/dist/extensions/pi-subagents/test/e2e/real-session-subagent.test.ts +2 -2
- package/dist/extensions/pi-subagents/test/integration/async-execution.test.ts +1114 -260
- package/dist/extensions/pi-subagents/test/integration/async-job-tracker.test.ts +34 -0
- package/dist/extensions/pi-subagents/test/integration/async-status.test.ts +150 -3
- package/dist/extensions/pi-subagents/test/integration/claude-code-smoke.test.ts +52 -0
- package/dist/extensions/pi-subagents/test/integration/claude-code-writer-smoke.test.ts +55 -0
- package/dist/extensions/pi-subagents/test/integration/codex-exec-smoke.test.ts +53 -0
- package/dist/extensions/pi-subagents/test/integration/codex-exec-writer-smoke.test.ts +57 -0
- package/dist/extensions/pi-subagents/test/integration/cursor-agent-smoke.test.ts +59 -0
- package/dist/extensions/pi-subagents/test/integration/cursor-agent-writer-smoke.test.ts +62 -0
- package/dist/extensions/pi-subagents/test/integration/error-handling.test.ts +57 -1
- package/dist/extensions/pi-subagents/test/integration/external-cli-runner.test.ts +1 -0
- package/dist/extensions/pi-subagents/test/integration/fork-context-execution.test.ts +20 -0
- package/dist/extensions/pi-subagents/test/integration/intercom-result-delivery.test.ts +4 -3
- package/dist/extensions/pi-subagents/test/integration/orca-progress-tabs.test.ts +2 -2
- package/dist/extensions/pi-subagents/test/integration/render-fork-badge.test.ts +54 -4
- package/dist/extensions/pi-subagents/test/integration/render-widget.test.ts +482 -4
- package/dist/extensions/pi-subagents/test/integration/result-watcher.test.ts +157 -9
- package/dist/extensions/pi-subagents/test/integration/session-tokens.test.ts +5 -5
- package/dist/extensions/pi-subagents/test/integration/single-execution.test.ts +1508 -291
- package/dist/extensions/pi-subagents/test/integration/slash-commands.test.ts +423 -1
- package/dist/extensions/pi-subagents/test/integration/template-resolution.test.ts +8 -0
- package/dist/extensions/pi-subagents/test/support/cursor-smoke-inputs.ts +51 -0
- package/dist/extensions/pi-subagents/test/support/helpers.ts +2 -0
- package/dist/extensions/pi-subagents/test/support/mock-pi.ts +5 -5
- package/dist/extensions/pi-subagents/test/support/real-session-runner.ts +6 -6
- package/dist/extensions/pi-subagents/test/unit/abort-recovery.test.ts +152 -0
- package/dist/extensions/pi-subagents/test/unit/active-async-capacity.test.ts +48 -0
- package/dist/extensions/pi-subagents/test/unit/agent-frontmatter.test.ts +184 -6
- package/dist/extensions/pi-subagents/test/unit/agent-management.test.ts +66 -6
- package/dist/extensions/pi-subagents/test/unit/agent-overrides.test.ts +77 -0
- package/dist/extensions/pi-subagents/test/unit/agent-refinements.test.ts +18 -0
- package/dist/extensions/pi-subagents/test/unit/anti-slop-oxlint.test.ts +86 -0
- package/dist/extensions/pi-subagents/test/unit/artifacts.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/async-execution.test.ts +101 -1
- package/dist/extensions/pi-subagents/test/unit/async-interrupt-action.test.ts +121 -0
- package/dist/extensions/pi-subagents/test/unit/async-recovery-descriptor.test.ts +28 -0
- package/dist/extensions/pi-subagents/test/unit/async-resume.test.ts +14 -7
- package/dist/extensions/pi-subagents/test/unit/async-retention.test.ts +53 -0
- package/dist/extensions/pi-subagents/test/unit/async-status-projection.test.ts +190 -0
- package/dist/extensions/pi-subagents/test/unit/async-status-snapshot.test.ts +42 -0
- package/dist/extensions/pi-subagents/test/unit/auto-drain.test.ts +8 -4
- package/dist/extensions/pi-subagents/test/unit/background-work.test.ts +23 -0
- package/dist/extensions/pi-subagents/test/unit/chain-root-attachment.test.ts +78 -1
- package/dist/extensions/pi-subagents/test/unit/child-launch-plan.test.ts +94 -0
- package/dist/extensions/pi-subagents/test/unit/child-protocol.test.ts +21 -0
- package/dist/extensions/pi-subagents/test/unit/child-session-name.test.ts +50 -0
- package/dist/extensions/pi-subagents/test/unit/claude-code-adapter.test.ts +245 -0
- package/dist/extensions/pi-subagents/test/unit/codex-exec-adapter.test.ts +192 -0
- package/dist/extensions/pi-subagents/test/unit/compaction-resume.test.ts +27 -0
- package/dist/extensions/pi-subagents/test/unit/completion-evidence.test.ts +150 -0
- package/dist/extensions/pi-subagents/test/unit/completion-guard.test.ts +21 -0
- package/dist/extensions/pi-subagents/test/unit/cursor-agent-adapter.test.ts +259 -0
- package/dist/extensions/pi-subagents/test/unit/cursor-smoke-inputs.test.ts +77 -0
- package/dist/extensions/pi-subagents/test/unit/delegation-api.test.ts +1 -4
- package/dist/extensions/pi-subagents/test/unit/doctor.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/extension-context.test.ts +27 -0
- package/dist/extensions/pi-subagents/test/unit/external-cli-runner.test.ts +223 -0
- package/dist/extensions/pi-subagents/test/unit/fast-mode-extension.test.ts +27 -0
- package/dist/extensions/pi-subagents/test/unit/fleet-status.test.ts +208 -2
- package/dist/extensions/pi-subagents/test/unit/fleet-transcript.test.ts +29 -1
- package/dist/extensions/pi-subagents/test/unit/fleet.test.ts +110 -1
- package/dist/extensions/pi-subagents/test/unit/foreground-control.test.ts +10 -0
- package/dist/extensions/pi-subagents/test/unit/formatters.test.ts +14 -0
- package/dist/extensions/pi-subagents/test/unit/herdr-inspector.test.ts +18 -9
- package/dist/extensions/pi-subagents/test/unit/herdr-session-roots-codec.test.ts +63 -0
- package/dist/extensions/pi-subagents/test/unit/herdr-shell-command.test.ts +2 -2
- package/dist/extensions/pi-subagents/test/unit/herdr-status-bridge.test.ts +136 -6
- package/dist/extensions/pi-subagents/test/unit/host-command.test.ts +156 -0
- package/dist/extensions/pi-subagents/test/unit/host-step-status.test.ts +98 -0
- package/dist/extensions/pi-subagents/test/unit/index-child-registration.test.ts +178 -26
- package/dist/extensions/pi-subagents/test/unit/index-segment.test.ts +2 -1
- package/dist/extensions/pi-subagents/test/unit/inspect-rpc.test.ts +21 -0
- package/dist/extensions/pi-subagents/test/unit/mcp-direct-tool-grant.test.ts +138 -0
- package/dist/extensions/pi-subagents/test/unit/mission-lifecycle.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/model-exclusions.test.ts +91 -0
- package/dist/extensions/pi-subagents/test/unit/model-fallback.test.ts +72 -7
- package/dist/extensions/pi-subagents/test/unit/mutation-evidence.test.ts +21 -0
- package/dist/extensions/pi-subagents/test/unit/nested-control.test.ts +1 -0
- package/dist/extensions/pi-subagents/test/unit/nested-events.test.ts +20 -2
- package/dist/extensions/pi-subagents/test/unit/notify.test.ts +129 -1
- package/dist/extensions/pi-subagents/test/unit/orca-progress-tabs.test.ts +2 -2
- package/dist/extensions/pi-subagents/test/unit/package-manifest.test.ts +4 -0
- package/dist/extensions/pi-subagents/test/unit/parallel-handoff.test.ts +358 -0
- package/dist/extensions/pi-subagents/test/unit/pi-args.test.ts +574 -21
- package/dist/extensions/pi-subagents/test/unit/pi-coding-agent-dir.test.ts +109 -1
- package/dist/extensions/pi-subagents/test/unit/preflight.test.ts +71 -1
- package/dist/extensions/pi-subagents/test/unit/profiles.test.ts +7 -7
- package/dist/extensions/pi-subagents/test/unit/pruned-fork.test.ts +214 -0
- package/dist/extensions/pi-subagents/test/unit/public-execution.test.ts +29 -8
- package/dist/extensions/pi-subagents/test/unit/render-helpers.test.ts +53 -0
- package/dist/extensions/pi-subagents/test/unit/result-delivery-ownership.test.ts +34 -0
- package/dist/extensions/pi-subagents/test/unit/result-files.test.ts +101 -3
- package/dist/extensions/pi-subagents/test/unit/retained-children.test.ts +1 -0
- package/dist/extensions/pi-subagents/test/unit/rpc.test.ts +10 -8
- package/dist/extensions/pi-subagents/test/unit/run-fanout-budget.test.ts +71 -1
- package/dist/extensions/pi-subagents/test/unit/run-status.test.ts +41 -7
- package/dist/extensions/pi-subagents/test/unit/runtime-agent-registration.test.ts +136 -2
- package/dist/extensions/pi-subagents/test/unit/scheduled-runs.test.ts +137 -0
- package/dist/extensions/pi-subagents/test/unit/schemas.test.ts +33 -12
- package/dist/extensions/pi-subagents/test/unit/scripted-workflow.test.ts +504 -1
- package/dist/extensions/pi-subagents/test/unit/single-output.test.ts +8 -0
- package/dist/extensions/pi-subagents/test/unit/skills-fallback.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/stale-run-reconciler.test.ts +12 -1
- package/dist/extensions/pi-subagents/test/unit/steering-action.test.ts +3 -5
- package/dist/extensions/pi-subagents/test/unit/steering.test.ts +5 -6
- package/dist/extensions/pi-subagents/test/unit/subagent-action-recovery.test.ts +0 -8
- package/dist/extensions/pi-subagents/test/unit/subagent-guide.test.ts +5 -0
- package/dist/extensions/pi-subagents/test/unit/subagent-prompt-runtime.test.ts +157 -2
- package/dist/extensions/pi-subagents/test/unit/subagent-startup-retry.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/subagent-wait.test.ts +63 -4
- package/dist/extensions/pi-subagents/test/unit/tool-description.test.ts +27 -23
- package/dist/extensions/pi-subagents/test/unit/wait-completions.test.ts +44 -0
- package/dist/extensions/pi-subagents/test/unit/wait-subscriptions.test.ts +1 -0
- package/dist/extensions/pi-subagents/test/unit/widget-nested-render.test.ts +7 -5
- package/dist/extensions/pi-subagents/test/unit/workflow-chat-progress.test.ts +106 -0
- package/dist/extensions/pi-subagents/test/unit/workflow-detach-reconcile.test.ts +484 -9
- package/dist/extensions/pi-subagents/test/unit/workflow-launch-params.test.ts +38 -4
- package/dist/extensions/pi-subagents/test/unit/workflow-preflight.test.ts +155 -0
- package/dist/extensions/pi-subagents/test/unit/workflow-receipt.test.ts +318 -0
- package/dist/extensions/pi-subagents/test/unit/workflow-resume-hint.test.ts +365 -0
- package/dist/extensions/pi-subagents/test/unit/worktree-cleanup-plan.test.ts +349 -0
- package/dist/extensions/pi-subagents/test/unit/worktree.test.ts +21 -0
- package/dist/extensions/pi-subagents/test/unit/writer-budget-guidance.test.ts +2 -7
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/effect/index.ts +13 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/effect/rules/no-service-constructor-imports.ts +52 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/index.ts +41 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-chained-type-assertions.ts +77 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-conditional-empty-object-spread.ts +49 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-known-value-widening.ts +247 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-module-mocking.ts +91 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-object-parameters.ts +126 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-reflect-apply.ts +28 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-reflect-get.ts +28 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-runtime-typeof.ts +67 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-shape-in-symbol-names.ts +39 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-unknown-parameters.ts +83 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-unknown-returns.ts +115 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-unknown-type-aliases.ts +72 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-unsafe-dictionary-type.ts +134 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/no-widen-then-assert.ts +366 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/rules/require-safety-comment-for-type-assertion.ts +62 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/shared/dictionary-types.ts +502 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/shared/lexical-type-parameters.ts +60 -0
- package/dist/extensions/pi-subagents/tools/oxlint/anti-slop/shared/reflect-method.ts +35 -0
- package/dist/extensions/pi-tool-display/tests/capabilities.test.ts +1 -1
- package/dist/extensions/pi-tool-display/tests/settings-inspector.test.ts +2 -2
- package/dist/extensions/pi-tool-display/tests/tool-overrides-mcp.test.ts +1 -1
- package/dist/modes/interactive/interactive-mode.js +7 -7
- package/dist/skills/workflow/SKILL.md +65 -50
- package/package.json +112 -110
- package/dist/extensions/enable-readonly-tools.test.ts +0 -63
- package/dist/extensions/enable-readonly-tools.ts +0 -24
- package/dist/extensions/model-prompt-injector/config.json +0 -16
- package/dist/extensions/model-prompt-injector/index.test.ts +0 -102
- package/dist/extensions/model-prompt-injector/index.ts +0 -148
- package/dist/extensions/pi-subagents/src/runs/shared/turn-budget.ts +0 -98
- package/dist/extensions/pi-subagents/test/unit/turn-budget.test.ts +0 -250
|
@@ -106,18 +106,15 @@ describe("steering lifecycle ledger", () => {
|
|
|
106
106
|
assert.equal(result?.targets[0]?.lateDeliveredAt, 5);
|
|
107
107
|
});
|
|
108
108
|
|
|
109
|
-
it("preserves only remaining deadline
|
|
109
|
+
it("preserves only remaining deadline and tool budgets", () => {
|
|
110
110
|
assert.deepEqual(remainingSteeringRecoveryLimits({
|
|
111
111
|
absoluteDeadlineAt: 10_000,
|
|
112
|
-
initialTurnBudget: { maxTurns: 20, graceTurns: 3 },
|
|
113
112
|
initialToolBudget: { soft: 45, hard: 65, block: ["read"] },
|
|
114
113
|
}, {
|
|
115
|
-
turnBudget: { maxTurns: 20, graceTurns: 3, turnCount: 21, outcome: "wrap-up-requested" },
|
|
116
114
|
toolBudget: { soft: 45, hard: 65, block: ["read"], toolCount: 50, outcome: "soft-reached" },
|
|
117
115
|
}, 4_000), {
|
|
118
116
|
timeoutMs: 6_000,
|
|
119
117
|
absoluteDeadlineAt: 10_000,
|
|
120
|
-
turnBudget: { maxTurns: 1, graceTurns: 1 },
|
|
121
118
|
toolBudget: { hard: 15, block: ["read"] },
|
|
122
119
|
});
|
|
123
120
|
});
|
|
@@ -130,6 +127,7 @@ describe("steering lifecycle ledger", () => {
|
|
|
130
127
|
fallbackModels: ["current/fallback"],
|
|
131
128
|
thinking: "high",
|
|
132
129
|
tools: ["write"],
|
|
130
|
+
allowNestedSubagents: true,
|
|
133
131
|
extensions: ["current-extension"],
|
|
134
132
|
subagentOnlyExtensions: ["current-child-extension"],
|
|
135
133
|
mcpDirectTools: ["current_mcp"],
|
|
@@ -153,6 +151,7 @@ describe("steering lifecycle ledger", () => {
|
|
|
153
151
|
cwd: "/original",
|
|
154
152
|
model: "original/model",
|
|
155
153
|
tools: ["read"],
|
|
154
|
+
allowNestedSubagents: false,
|
|
156
155
|
systemPrompt: "original prompt",
|
|
157
156
|
systemPromptMode: "replace",
|
|
158
157
|
inheritProjectContext: false,
|
|
@@ -164,6 +163,7 @@ describe("steering lifecycle ledger", () => {
|
|
|
164
163
|
});
|
|
165
164
|
assert.equal(recovered.model, "original/model");
|
|
166
165
|
assert.deepEqual(recovered.tools, ["read"]);
|
|
166
|
+
assert.equal(recovered.allowNestedSubagents, false);
|
|
167
167
|
assert.equal(recovered.systemPrompt, "original prompt");
|
|
168
168
|
assert.equal(recovered.inheritProjectContext, false);
|
|
169
169
|
assert.deepEqual(recovered.toolBudget, { hard: 7, block: ["read"] });
|
|
@@ -204,9 +204,8 @@ describe("steering lifecycle ledger", () => {
|
|
|
204
204
|
assert.equal(recovered.maxThinking, "low");
|
|
205
205
|
});
|
|
206
206
|
|
|
207
|
-
it("rejects recovery when
|
|
207
|
+
it("rejects recovery when a configured deadline or tool budget is exhausted", () => {
|
|
208
208
|
assert.throws(() => remainingSteeringRecoveryLimits({ absoluteDeadlineAt: 5 }, {}, 5), /deadline budget/);
|
|
209
|
-
assert.throws(() => remainingSteeringRecoveryLimits({ initialTurnBudget: { maxTurns: 2, graceTurns: 1 } }, { turnCount: 3 }), /turn budget/);
|
|
210
209
|
assert.throws(() => remainingSteeringRecoveryLimits({ initialToolBudget: { hard: 2, block: "*" } }, { toolCount: 2 }), /tool budget/);
|
|
211
210
|
});
|
|
212
211
|
});
|
|
@@ -54,14 +54,6 @@ describe("subagent action recovery", () => {
|
|
|
54
54
|
assert.match(message, /Valid: .*status/);
|
|
55
55
|
});
|
|
56
56
|
|
|
57
|
-
it("does not list removed legacy controls", () => {
|
|
58
|
-
const message = unknownSubagentActionMessage("not-a-real-action");
|
|
59
|
-
|
|
60
|
-
assert.doesNotMatch(message, /append-step/);
|
|
61
|
-
assert.doesNotMatch(message, /approve-checkpoint/);
|
|
62
|
-
assert.doesNotMatch(message, /reject-checkpoint/);
|
|
63
|
-
});
|
|
64
|
-
|
|
65
57
|
it("does not suggest a destructive near-miss", () => {
|
|
66
58
|
const message = unknownSubagentActionMessage("del");
|
|
67
59
|
|
|
@@ -21,4 +21,9 @@ describe("subagent guide", () => {
|
|
|
21
21
|
it("registers the guide action for action recovery", () => {
|
|
22
22
|
assert.ok(SUBAGENT_ACTIONS.includes("guide"));
|
|
23
23
|
});
|
|
24
|
+
|
|
25
|
+
it("documents external CLI runner limits in packaged guide topics", () => {
|
|
26
|
+
assert.match(readSubagentGuide("tool-reference"), /External CLI agent profiles[\s\S]*native Pi child options[\s\S]*model override[\s\S]*native Pi tools/);
|
|
27
|
+
assert.match(readSubagentGuide("agents"), /External CLI agents use their own runner contract[\s\S]*native Pi child options/);
|
|
28
|
+
});
|
|
24
29
|
});
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
import { RUNTIME_EXTENSION_ACK_EVENT, RUNTIME_EXTENSION_ACK_PATH_ENV } from "../../src/runs/shared/runtime-acknowledged-extensions.ts";
|
|
20
20
|
import { STRUCTURED_OUTPUT_CAPTURE_ENV, STRUCTURED_OUTPUT_SCHEMA_ENV } from "../../src/runs/shared/structured-output.ts";
|
|
21
21
|
import { TOOL_BUDGET_ENV } from "../../src/runs/shared/tool-budget.ts";
|
|
22
|
+
import { getAgentDir } from "../../src/shared/utils.ts";
|
|
22
23
|
import { PERMISSION_POLICY_ENV } from "../../src/runs/shared/permissions.ts";
|
|
23
24
|
import { CHILD_TOOL_DIAGNOSTIC_PATH_ENV, formatChildToolDiagnostic, MCP_DIRECT_CHILD_TOOLS_ENV, readChildToolDiagnostic, REQUIRED_CHILD_TOOLS_ENV } from "../../src/runs/shared/tool-availability.ts";
|
|
24
25
|
import { CHILD_WATCHDOG_CONFIG_ENV } from "../../src/watchdog/child-status.ts";
|
|
@@ -30,6 +31,7 @@ import registerSubagentPromptRuntime, {
|
|
|
30
31
|
registerPermissionGate,
|
|
31
32
|
registerSteeringInbox,
|
|
32
33
|
rewriteSubagentPrompt,
|
|
34
|
+
stripGlobalContext,
|
|
33
35
|
stripInheritedSkills,
|
|
34
36
|
stripParentOnlySubagentMessages,
|
|
35
37
|
stripProjectContext,
|
|
@@ -38,6 +40,7 @@ import registerSubagentPromptRuntime, {
|
|
|
38
40
|
|
|
39
41
|
const envSnapshot = {
|
|
40
42
|
SELESAI_SUBAGENT_INHERIT_PROJECT_CONTEXT: process.env.SELESAI_SUBAGENT_INHERIT_PROJECT_CONTEXT,
|
|
43
|
+
SELESAI_SUBAGENT_INHERIT_GLOBAL_CONTEXT: process.env.SELESAI_SUBAGENT_INHERIT_GLOBAL_CONTEXT,
|
|
41
44
|
SELESAI_SUBAGENT_INHERIT_SKILLS: process.env.SELESAI_SUBAGENT_INHERIT_SKILLS,
|
|
42
45
|
SELESAI_SUBAGENT_INTERCOM_SESSION_NAME: process.env.SELESAI_SUBAGENT_INTERCOM_SESSION_NAME,
|
|
43
46
|
SELESAI_SUBAGENT_FANOUT_CHILD: process.env.SELESAI_SUBAGENT_FANOUT_CHILD,
|
|
@@ -59,6 +62,7 @@ const envSnapshot = {
|
|
|
59
62
|
SELESAI_SUBAGENT_CHILD_AGENT: process.env.SELESAI_SUBAGENT_CHILD_AGENT,
|
|
60
63
|
SELESAI_SUBAGENT_CHILD_INDEX: process.env.SELESAI_SUBAGENT_CHILD_INDEX,
|
|
61
64
|
SELESAI_SUBAGENT_WATCHDOG_CHILD_CONFIG: process.env.SELESAI_SUBAGENT_WATCHDOG_CHILD_CONFIG,
|
|
65
|
+
PI_SUBAGENT_SESSION_NAME: process.env.PI_SUBAGENT_SESSION_NAME,
|
|
62
66
|
};
|
|
63
67
|
|
|
64
68
|
const SKILLS_SECTION = "\n\nThe following skills provide specialized instructions for specific tasks.\nUse the read tool to load a skill's file when the task matches its description.\nWhen a skill file references a relative path, resolve it against the skill directory (parent of SKILL.md / dirname of the path) and use that absolute path in tool commands.\n\n<available_skills>\n <skill>\n <name>safe-bash</name>\n <description>desc</description>\n <location>/tmp/SKILL.md</location>\n </skill>\n <skill>\n <name>pi-subagents</name>\n <description>delegate to subagents</description>\n <location>/tmp/pi-subagents/SKILL.md</location>\n </skill>\n</available_skills>";
|
|
@@ -83,6 +87,8 @@ const CONFIGURED_SKILLS_SECTION = "\n\nThe following configured skills are avail
|
|
|
83
87
|
afterEach(() => {
|
|
84
88
|
if (envSnapshot.SELESAI_SUBAGENT_INHERIT_PROJECT_CONTEXT === undefined) delete process.env.SELESAI_SUBAGENT_INHERIT_PROJECT_CONTEXT;
|
|
85
89
|
else process.env.SELESAI_SUBAGENT_INHERIT_PROJECT_CONTEXT = envSnapshot.SELESAI_SUBAGENT_INHERIT_PROJECT_CONTEXT;
|
|
90
|
+
if (envSnapshot.SELESAI_SUBAGENT_INHERIT_GLOBAL_CONTEXT === undefined) delete process.env.SELESAI_SUBAGENT_INHERIT_GLOBAL_CONTEXT;
|
|
91
|
+
else process.env.SELESAI_SUBAGENT_INHERIT_GLOBAL_CONTEXT = envSnapshot.SELESAI_SUBAGENT_INHERIT_GLOBAL_CONTEXT;
|
|
86
92
|
if (envSnapshot.SELESAI_SUBAGENT_INHERIT_SKILLS === undefined) delete process.env.SELESAI_SUBAGENT_INHERIT_SKILLS;
|
|
87
93
|
else process.env.SELESAI_SUBAGENT_INHERIT_SKILLS = envSnapshot.SELESAI_SUBAGENT_INHERIT_SKILLS;
|
|
88
94
|
if (envSnapshot.SELESAI_SUBAGENT_INTERCOM_SESSION_NAME === undefined) delete process.env.SELESAI_SUBAGENT_INTERCOM_SESSION_NAME;
|
|
@@ -125,6 +131,8 @@ afterEach(() => {
|
|
|
125
131
|
else process.env[SUBAGENT_CHILD_INDEX_ENV] = envSnapshot.SELESAI_SUBAGENT_CHILD_INDEX;
|
|
126
132
|
if (envSnapshot.SELESAI_SUBAGENT_WATCHDOG_CHILD_CONFIG === undefined) delete process.env[CHILD_WATCHDOG_CONFIG_ENV];
|
|
127
133
|
else process.env[CHILD_WATCHDOG_CONFIG_ENV] = envSnapshot.SELESAI_SUBAGENT_WATCHDOG_CHILD_CONFIG;
|
|
134
|
+
if (envSnapshot.PI_SUBAGENT_SESSION_NAME === undefined) delete process.env.PI_SUBAGENT_SESSION_NAME;
|
|
135
|
+
else process.env.PI_SUBAGENT_SESSION_NAME = envSnapshot.PI_SUBAGENT_SESSION_NAME;
|
|
128
136
|
});
|
|
129
137
|
|
|
130
138
|
function setSupervisorEnv(): void {
|
|
@@ -785,6 +793,126 @@ describe("subagent prompt runtime", () => {
|
|
|
785
793
|
assert.ok(rewritten.includes("Current date: 2026-04-16"));
|
|
786
794
|
});
|
|
787
795
|
|
|
796
|
+
it("strips an XML <project_context> block as full project context removal", () => {
|
|
797
|
+
const globalDir = getAgentDir();
|
|
798
|
+
const prompt = [
|
|
799
|
+
"You are a subagent.",
|
|
800
|
+
"\n\n<project_context>\n\nProject-specific instructions and guidelines:\n\n",
|
|
801
|
+
`<project_instructions path="${globalDir}/AGENTS.md">\nGlobal rules\n</project_instructions>\n\n`,
|
|
802
|
+
"<project_instructions path=\"/repo/AGENTS.md\">\nRepo rules\n</project_instructions>\n\n",
|
|
803
|
+
"</project_context>\n\n",
|
|
804
|
+
"Current working directory: /repo",
|
|
805
|
+
].join("");
|
|
806
|
+
const rewritten = stripProjectContext(prompt);
|
|
807
|
+
assert.ok(!rewritten.includes("<project_context>"));
|
|
808
|
+
assert.ok(!rewritten.includes("<project_instructions"));
|
|
809
|
+
assert.ok(rewritten.includes("Current working directory: /repo"));
|
|
810
|
+
});
|
|
811
|
+
|
|
812
|
+
it("strips only global context files while preserving repository context", () => {
|
|
813
|
+
const globalDir = getAgentDir();
|
|
814
|
+
const prompt = [
|
|
815
|
+
"You are a subagent.",
|
|
816
|
+
"\n\n<project_context>\n\nProject-specific instructions and guidelines:\n\n",
|
|
817
|
+
`<project_instructions path="${globalDir}/AGENTS.md">\nGlobal rules\n</project_instructions>\n\n`,
|
|
818
|
+
"<project_instructions path=\"/repo/AGENTS.md\">\nRepo rules\n</project_instructions>\n\n",
|
|
819
|
+
"</project_context>\n\n",
|
|
820
|
+
"Current working directory: /repo",
|
|
821
|
+
].join("");
|
|
822
|
+
const rewritten = stripGlobalContext(prompt);
|
|
823
|
+
assert.ok(!rewritten.includes("Global rules"));
|
|
824
|
+
assert.ok(rewritten.includes("Repo rules"));
|
|
825
|
+
assert.ok(rewritten.includes("</project_context>"));
|
|
826
|
+
});
|
|
827
|
+
|
|
828
|
+
it("strips only global context files from legacy Markdown while preserving repository context", () => {
|
|
829
|
+
const globalDir = getAgentDir();
|
|
830
|
+
const prompt = [
|
|
831
|
+
"You are a subagent.",
|
|
832
|
+
"\n\n# Project Context\n\nProject-specific instructions and guidelines:\n\n",
|
|
833
|
+
`## ${globalDir}/AGENTS.md\n\nGlobal rules\n\n`,
|
|
834
|
+
"## /repo/AGENTS.md\n\nRepo rules\n\n",
|
|
835
|
+
SKILLS_SECTION,
|
|
836
|
+
"\nCurrent date: 2026-04-16",
|
|
837
|
+
].join("");
|
|
838
|
+
const rewritten = rewriteSubagentPrompt(prompt, {
|
|
839
|
+
inheritProjectContext: true,
|
|
840
|
+
inheritGlobalContext: false,
|
|
841
|
+
inheritSkills: true,
|
|
842
|
+
});
|
|
843
|
+
assert.ok(!rewritten.includes("Global rules"));
|
|
844
|
+
assert.ok(rewritten.includes("## /repo/AGENTS.md"));
|
|
845
|
+
assert.ok(rewritten.includes("Repo rules"));
|
|
846
|
+
});
|
|
847
|
+
|
|
848
|
+
it("recognizes Pi context filenames case-insensitively", () => {
|
|
849
|
+
const globalDir = getAgentDir();
|
|
850
|
+
const prompt = [
|
|
851
|
+
"You are a subagent.",
|
|
852
|
+
"\n\n<project_context>\n\nProject-specific instructions and guidelines:\n\n",
|
|
853
|
+
`<project_instructions path="${globalDir}/AGENTS.MD">\nGlobal rules\n</project_instructions>\n\n`,
|
|
854
|
+
"<project_instructions path=\"/repo/AGENTS.MD\">\nRepo rules\n</project_instructions>\n\n",
|
|
855
|
+
"</project_context>\n\n",
|
|
856
|
+
"Current working directory: /repo",
|
|
857
|
+
].join("");
|
|
858
|
+
const rewritten = stripGlobalContext(prompt);
|
|
859
|
+
assert.ok(!rewritten.includes("Global rules"));
|
|
860
|
+
assert.ok(rewritten.includes("Repo rules"));
|
|
861
|
+
});
|
|
862
|
+
|
|
863
|
+
for (const [label, prompt] of [
|
|
864
|
+
["CRLF context", `<project_context>\r\n<project_instructions path="${getAgentDir()}/AGENTS.md">\r\nGlobal rules\r\n</project_instructions>\r\n<project_instructions path="/repo/AGENTS.md">\r\nRepo rules\r\n</project_instructions>\r\n</project_context>`],
|
|
865
|
+
["content without a trailing newline", `<project_context><project_instructions path="${getAgentDir()}/AGENTS.md">Global rules</project_instructions><project_instructions path="/repo/AGENTS.md">Repo rules</project_instructions></project_context>`],
|
|
866
|
+
["same-line content", `<project_context><project_instructions path="${getAgentDir()}/CLAUDE.md">Global rules</project_instructions><project_instructions path="/repo/CLAUDE.md">Repo rules</project_instructions></project_context>`],
|
|
867
|
+
] as const) {
|
|
868
|
+
it(`strips global instructions from ${label}`, () => {
|
|
869
|
+
const rewritten = stripGlobalContext(prompt);
|
|
870
|
+
assert.ok(!rewritten.includes("Global rules"));
|
|
871
|
+
assert.ok(rewritten.includes("Repo rules"));
|
|
872
|
+
});
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
it("does not strip matching examples outside project context", () => {
|
|
876
|
+
const example = `<project_instructions path="${getAgentDir()}/AGENTS.md">Example only</project_instructions>`;
|
|
877
|
+
assert.equal(stripGlobalContext(example), example);
|
|
878
|
+
});
|
|
879
|
+
|
|
880
|
+
it("inherits global context when inheritGlobalContext is true", () => {
|
|
881
|
+
const globalDir = getAgentDir();
|
|
882
|
+
const prompt = [
|
|
883
|
+
"You are a subagent.",
|
|
884
|
+
"\n\n<project_context>\n\nProject-specific instructions and guidelines:\n\n",
|
|
885
|
+
`<project_instructions path="${globalDir}/AGENTS.md">\nGlobal rules\n</project_instructions>\n\n`,
|
|
886
|
+
"</project_context>\n\n",
|
|
887
|
+
"Current working directory: /repo",
|
|
888
|
+
].join("");
|
|
889
|
+
const rewritten = rewriteSubagentPrompt(prompt, {
|
|
890
|
+
inheritProjectContext: true,
|
|
891
|
+
inheritGlobalContext: true,
|
|
892
|
+
inheritSkills: true,
|
|
893
|
+
});
|
|
894
|
+
assert.ok(rewritten.includes("Global rules"));
|
|
895
|
+
});
|
|
896
|
+
|
|
897
|
+
it("removes global context files while keeping repository context via rewriteSubagentPrompt", () => {
|
|
898
|
+
const globalDir = getAgentDir();
|
|
899
|
+
const prompt = [
|
|
900
|
+
"You are a subagent.",
|
|
901
|
+
"\n\n<project_context>\n\nProject-specific instructions and guidelines:\n\n",
|
|
902
|
+
`<project_instructions path="${globalDir}/AGENTS.md">\nGlobal rules\n</project_instructions>\n\n`,
|
|
903
|
+
"<project_instructions path=\"/repo/AGENTS.md\">\nRepo rules\n</project_instructions>\n\n",
|
|
904
|
+
"</project_context>\n\n",
|
|
905
|
+
"Current working directory: /repo",
|
|
906
|
+
].join("");
|
|
907
|
+
const rewritten = rewriteSubagentPrompt(prompt, {
|
|
908
|
+
inheritProjectContext: true,
|
|
909
|
+
inheritGlobalContext: false,
|
|
910
|
+
inheritSkills: true,
|
|
911
|
+
});
|
|
912
|
+
assert.ok(!rewritten.includes("Global rules"));
|
|
913
|
+
assert.ok(rewritten.includes("Repo rules"));
|
|
914
|
+
});
|
|
915
|
+
|
|
788
916
|
it("strips only the inherited skills block", () => {
|
|
789
917
|
const rewritten = stripInheritedSkills(BASE_PROMPT);
|
|
790
918
|
assert.ok(rewritten.includes("# Project Context"));
|
|
@@ -795,6 +923,7 @@ describe("subagent prompt runtime", () => {
|
|
|
795
923
|
it("can strip both inherited sections together", () => {
|
|
796
924
|
const rewritten = rewriteSubagentPrompt(BASE_PROMPT, {
|
|
797
925
|
inheritProjectContext: false,
|
|
926
|
+
inheritGlobalContext: false,
|
|
798
927
|
inheritSkills: false,
|
|
799
928
|
});
|
|
800
929
|
assert.ok(!rewritten.includes("# Project Context"));
|
|
@@ -805,6 +934,7 @@ describe("subagent prompt runtime", () => {
|
|
|
805
934
|
it("injects a child-only boundary that forbids proposing or running subagents", () => {
|
|
806
935
|
const rewritten = rewriteSubagentPrompt(BASE_PROMPT, {
|
|
807
936
|
inheritProjectContext: true,
|
|
937
|
+
inheritGlobalContext: true,
|
|
808
938
|
inheritSkills: true,
|
|
809
939
|
});
|
|
810
940
|
|
|
@@ -813,14 +943,15 @@ describe("subagent prompt runtime", () => {
|
|
|
813
943
|
assert.ok(rewritten.includes("If you need to edit files, use the available editing tools."));
|
|
814
944
|
assert.ok(!rewritten.includes("call the actual edit/write tools"));
|
|
815
945
|
assert.ok(rewritten.includes("Do not print tool-call syntax, patches, or pseudo-tool calls as text."));
|
|
816
|
-
assert.equal(rewriteSubagentPrompt(rewritten, { inheritProjectContext: true, inheritSkills: true }).indexOf(CHILD_SUBAGENT_BOUNDARY_INSTRUCTIONS), 0);
|
|
817
|
-
assert.equal(rewriteSubagentPrompt(rewritten, { inheritProjectContext: true, inheritSkills: true }).lastIndexOf(CHILD_SUBAGENT_BOUNDARY_INSTRUCTIONS), 0);
|
|
946
|
+
assert.equal(rewriteSubagentPrompt(rewritten, { inheritProjectContext: true, inheritGlobalContext: true, inheritSkills: true }).indexOf(CHILD_SUBAGENT_BOUNDARY_INSTRUCTIONS), 0);
|
|
947
|
+
assert.equal(rewriteSubagentPrompt(rewritten, { inheritProjectContext: true, inheritGlobalContext: true, inheritSkills: true }).lastIndexOf(CHILD_SUBAGENT_BOUNDARY_INSTRUCTIONS), 0);
|
|
818
948
|
});
|
|
819
949
|
|
|
820
950
|
it("replaces inherited child boundaries with the fanout boundary when authorized", () => {
|
|
821
951
|
const strictPrompt = `${CHILD_SUBAGENT_BOUNDARY_INSTRUCTIONS}\n\n${BASE_PROMPT}`;
|
|
822
952
|
const rewritten = rewriteSubagentPrompt(strictPrompt, {
|
|
823
953
|
inheritProjectContext: true,
|
|
954
|
+
inheritGlobalContext: true,
|
|
824
955
|
inheritSkills: true,
|
|
825
956
|
fanoutChild: true,
|
|
826
957
|
});
|
|
@@ -837,6 +968,7 @@ describe("subagent prompt runtime", () => {
|
|
|
837
968
|
const fanoutPrompt = `${CHILD_FANOUT_BOUNDARY_INSTRUCTIONS}\n\n${BASE_PROMPT}`;
|
|
838
969
|
const rewritten = rewriteSubagentPrompt(fanoutPrompt, {
|
|
839
970
|
inheritProjectContext: true,
|
|
971
|
+
inheritGlobalContext: true,
|
|
840
972
|
inheritSkills: true,
|
|
841
973
|
});
|
|
842
974
|
|
|
@@ -848,6 +980,7 @@ describe("subagent prompt runtime", () => {
|
|
|
848
980
|
it("keeps explicitly injected skill content when inherited skills are stripped", () => {
|
|
849
981
|
const rewritten = rewriteSubagentPrompt(PROMPT_WITH_EXPLICIT_SKILL, {
|
|
850
982
|
inheritProjectContext: false,
|
|
983
|
+
inheritGlobalContext: false,
|
|
851
984
|
inheritSkills: false,
|
|
852
985
|
});
|
|
853
986
|
assert.ok(rewritten.includes("<skill name=\"explicit\">"));
|
|
@@ -865,6 +998,7 @@ describe("subagent prompt runtime", () => {
|
|
|
865
998
|
].join("");
|
|
866
999
|
const rewritten = rewriteSubagentPrompt(prompt, {
|
|
867
1000
|
inheritProjectContext: false,
|
|
1001
|
+
inheritGlobalContext: false,
|
|
868
1002
|
inheritSkills: false,
|
|
869
1003
|
});
|
|
870
1004
|
|
|
@@ -877,6 +1011,7 @@ describe("subagent prompt runtime", () => {
|
|
|
877
1011
|
it("strips the subagent orchestration skill even when inherited skills remain", () => {
|
|
878
1012
|
const rewritten = rewriteSubagentPrompt(BASE_PROMPT, {
|
|
879
1013
|
inheritProjectContext: true,
|
|
1014
|
+
inheritGlobalContext: true,
|
|
880
1015
|
inheritSkills: true,
|
|
881
1016
|
});
|
|
882
1017
|
|
|
@@ -1336,6 +1471,26 @@ describe("subagent prompt runtime", () => {
|
|
|
1336
1471
|
assert.equal(contextHandler?.({ messages }, { model: { api: "openai-responses" } }), undefined);
|
|
1337
1472
|
});
|
|
1338
1473
|
|
|
1474
|
+
it("preserves composite tool ids for cursor-native children", () => {
|
|
1475
|
+
let contextHandler: ((event: { messages: unknown[] }, ctx: { model?: { api: string } }) => { messages: unknown[] } | undefined) | undefined;
|
|
1476
|
+
registerSubagentPromptRuntime({
|
|
1477
|
+
on(event: string, handler: (payload: { messages: unknown[] }, ctx: { model?: { api: string } }) => { messages: unknown[] } | undefined) {
|
|
1478
|
+
if (event === "context") contextHandler = handler;
|
|
1479
|
+
},
|
|
1480
|
+
} as { on(event: string, handler: (payload: { messages: unknown[] }, ctx: { model?: { api: string } }) => { messages: unknown[] } | undefined): void });
|
|
1481
|
+
|
|
1482
|
+
const toolCallId = "call_7XJjvAJfk07117JO8LgBCZjY\nfc_0e92b09b28010bac016a756e9e79cc8197b01825a5dc3d9eaa";
|
|
1483
|
+
const messages = [
|
|
1484
|
+
{ role: "user", content: "Task" },
|
|
1485
|
+
{ role: "assistant", content: [{ type: "toolCall", id: toolCallId, name: "read", input: { path: "README.md" } }] },
|
|
1486
|
+
{ role: "toolResult", toolName: "read", toolCallId, content: "file" },
|
|
1487
|
+
];
|
|
1488
|
+
|
|
1489
|
+
assert.equal(contextHandler?.({ messages }, { model: { api: "cursor-native" } }), undefined);
|
|
1490
|
+
assert.equal((messages[1] as { content: Array<{ id?: unknown }> }).content[0]?.id, toolCallId);
|
|
1491
|
+
assert.equal((messages[2] as { toolCallId?: unknown }).toolCallId, toolCallId);
|
|
1492
|
+
});
|
|
1493
|
+
|
|
1339
1494
|
it("does not rewrite child context when no parent-only artifacts are present", () => {
|
|
1340
1495
|
let contextHandler: ((event: { messages: unknown[] }, ctx: { model?: { api: string } }) => { messages: unknown[] } | undefined) | undefined;
|
|
1341
1496
|
registerSubagentPromptRuntime({
|
|
@@ -78,7 +78,7 @@ describe("subagent startup retry", () => {
|
|
|
78
78
|
});
|
|
79
79
|
|
|
80
80
|
assert.match(formatted ?? "", /loaded conflicting ambient Pi extensions/);
|
|
81
|
-
assert.match(formatted ?? "", /\.
|
|
81
|
+
assert.match(formatted ?? "", /\.selesai[\\/]settings\.json/);
|
|
82
82
|
assert.match(formatted ?? "", /\{"subagents":\{"agentOverrides":\{"reviewer":\{"extensions":\[\]\}\}\}\}/);
|
|
83
83
|
assert.equal(formatSubagentExtensionConflictError(conflict, { agent: "reviewer", ambientExtensionsEnabled: false }), conflict);
|
|
84
84
|
assert.equal(formatSubagentExtensionConflictError("authentication failed", { agent: "reviewer", ambientExtensionsEnabled: true }), "authentication failed");
|
|
@@ -6,7 +6,7 @@ import { describe, it } from "node:test";
|
|
|
6
6
|
import { updateActiveRunIndex } from "../../src/runs/background/active-run-index.ts";
|
|
7
7
|
import { writeAsyncResultFile } from "../../src/runs/background/result-files.ts";
|
|
8
8
|
import { createRunFanoutBudget } from "../../src/runs/shared/run-fanout-budget.ts";
|
|
9
|
-
import { WAIT_TOOL_ENABLED_ENV, resolveWaitToolConfig, waitForSubagents, type SubagentWaitDeps } from "../../src/runs/background/subagent-wait.ts";
|
|
9
|
+
import { WAIT_TOOL_DEFAULT_TIMEOUT_MS_ENV, WAIT_TOOL_ENABLED_ENV, resolveWaitToolConfig, waitForSubagents, type SubagentWaitDeps } from "../../src/runs/background/subagent-wait.ts";
|
|
10
10
|
import { recordWaitCompletion } from "../../src/runs/background/wait-completions.ts";
|
|
11
11
|
import type { AsyncStatus, SubagentState } from "../../src/shared/types.ts";
|
|
12
12
|
|
|
@@ -41,6 +41,7 @@ function writeRecoveryDescriptor(asyncRoot: string, runId: string, agent: string
|
|
|
41
41
|
cwd,
|
|
42
42
|
systemPromptMode: "append",
|
|
43
43
|
outputMode: "inline",
|
|
44
|
+
inheritGlobalContext: false,
|
|
44
45
|
inheritProjectContext: false,
|
|
45
46
|
inheritSkills: false,
|
|
46
47
|
maxSubagentDepth: 0,
|
|
@@ -88,10 +89,15 @@ describe("subagent_wait tool", () => {
|
|
|
88
89
|
assert.deepEqual(resolveWaitToolConfig(undefined, {}), { enabled: true });
|
|
89
90
|
assert.deepEqual(resolveWaitToolConfig(false, {}), { enabled: false });
|
|
90
91
|
assert.deepEqual(resolveWaitToolConfig({ enabled: false }, {}), { enabled: false });
|
|
92
|
+
assert.deepEqual(resolveWaitToolConfig({ defaultTimeoutMs: 120_000 }, {}), { enabled: true, defaultTimeoutMs: 120_000 });
|
|
93
|
+
assert.deepEqual(resolveWaitToolConfig({ defaultTimeoutMs: 120_000 }, { [WAIT_TOOL_DEFAULT_TIMEOUT_MS_ENV]: "3000" }), { enabled: true, defaultTimeoutMs: 3_000 });
|
|
91
94
|
assert.deepEqual(resolveWaitToolConfig({ enabled: false }, { [WAIT_TOOL_ENABLED_ENV]: "true" }), { enabled: true });
|
|
92
95
|
assert.deepEqual(resolveWaitToolConfig(true, { [WAIT_TOOL_ENABLED_ENV]: "off" }), { enabled: false });
|
|
93
96
|
assert.throws(() => resolveWaitToolConfig("false" as never, {}), /config\.waitTool/);
|
|
94
97
|
assert.throws(() => resolveWaitToolConfig({ enabled: "false" } as never, {}), /config\.waitTool\.enabled/);
|
|
98
|
+
assert.throws(() => resolveWaitToolConfig({ defaultTimeoutMs: 0 }, {}), /config\.waitTool\.defaultTimeoutMs/);
|
|
99
|
+
assert.throws(() => resolveWaitToolConfig({ defaultTimeoutMs: 1.5 }, {}), /config\.waitTool\.defaultTimeoutMs/);
|
|
100
|
+
assert.throws(() => resolveWaitToolConfig(undefined, { [WAIT_TOOL_DEFAULT_TIMEOUT_MS_ENV]: "0" }), /SELESAI_SUBAGENT_WAIT_TOOL_DEFAULT_TIMEOUT_MS/);
|
|
95
101
|
assert.throws(() => resolveWaitToolConfig(undefined, { [WAIT_TOOL_ENABLED_ENV]: "maybe" }), /SELESAI_SUBAGENT_WAIT_TOOL_ENABLED/);
|
|
96
102
|
});
|
|
97
103
|
|
|
@@ -335,6 +341,7 @@ describe("subagent_wait tool", () => {
|
|
|
335
341
|
success: true,
|
|
336
342
|
outputState: "present",
|
|
337
343
|
output: "full output text stays out of details",
|
|
344
|
+
usage: { input: 100, output: 50, cacheRead: 25, cacheWrite: 5, cost: 0.001, turns: 1 },
|
|
338
345
|
artifactPaths: {
|
|
339
346
|
outputPath: "/tmp/a1b2c3d4_reviewer_0_output.md",
|
|
340
347
|
metadataPath: "/tmp/a1b2c3d4_reviewer_0_meta.json",
|
|
@@ -350,6 +357,7 @@ describe("subagent_wait tool", () => {
|
|
|
350
357
|
assert.equal(completions![0]!.runId, "run-a");
|
|
351
358
|
assert.equal(completions![0]!.mode, "workflow");
|
|
352
359
|
assert.equal(completions![0]!.success, true);
|
|
360
|
+
assert.deepEqual(result.usage, { input: 100, output: 50, cacheRead: 25, cacheWrite: 5, totalTokens: 180, cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0.001 } });
|
|
353
361
|
const child = completions![0]!.results?.[0];
|
|
354
362
|
assert.equal(child?.agent, "reviewer");
|
|
355
363
|
assert.equal(child?.runId, "a1b2c3d4");
|
|
@@ -1145,11 +1153,62 @@ describe("subagent_wait tool", () => {
|
|
|
1145
1153
|
clock += ms + 10_000;
|
|
1146
1154
|
};
|
|
1147
1155
|
|
|
1148
|
-
const result = await waitForSubagents({ timeoutMs: 5_000 }, undefined, baseDeps(root, state, { now, sleep }));
|
|
1149
|
-
assert.equal(result.isError,
|
|
1156
|
+
const result = await waitForSubagents({ timeoutMs: 5_000 }, undefined, baseDeps(root, state, { now, sleep, defaultTimeoutMs: 1_000 }));
|
|
1157
|
+
assert.equal(result.isError, undefined);
|
|
1150
1158
|
const text = textOf(result);
|
|
1151
|
-
assert.match(text, /
|
|
1159
|
+
assert.match(text, /window elapsed after 5\.0s/i, "explicit timeoutMs must override the configured default");
|
|
1152
1160
|
assert.match(text, /run-stuck \(running\)/);
|
|
1161
|
+
assert.deepEqual(result.details.wait, {
|
|
1162
|
+
reason: "window_elapsed",
|
|
1163
|
+
timedOut: true,
|
|
1164
|
+
activeRunIds: ["run-stuck"],
|
|
1165
|
+
activeProviderItems: [],
|
|
1166
|
+
});
|
|
1167
|
+
} finally {
|
|
1168
|
+
fs.rmSync(root, { recursive: true, force: true });
|
|
1169
|
+
}
|
|
1170
|
+
});
|
|
1171
|
+
|
|
1172
|
+
it("uses the configured wait window when timeoutMs is omitted", async () => {
|
|
1173
|
+
const root = fs.mkdtempSync(path.join(os.tmpdir(), "pi-wait-config-timeout-"));
|
|
1174
|
+
try {
|
|
1175
|
+
const asyncRoot = path.join(root, "runs");
|
|
1176
|
+
const state = makeState("sess-1");
|
|
1177
|
+
writeStatus(asyncRoot, "run-configured", "running", { sessionId: "sess-1", pid: 999999 });
|
|
1178
|
+
let clock = 0;
|
|
1179
|
+
const result = await waitForSubagents({}, undefined, baseDeps(root, state, {
|
|
1180
|
+
now: () => clock,
|
|
1181
|
+
sleep: async (ms) => { clock += ms + 10_000; },
|
|
1182
|
+
defaultTimeoutMs: 2_000,
|
|
1183
|
+
}));
|
|
1184
|
+
|
|
1185
|
+
assert.equal(result.isError, undefined);
|
|
1186
|
+
assert.match(textOf(result), /window elapsed after 2\.0s/i);
|
|
1187
|
+
assert.equal(result.details.wait?.reason, "window_elapsed");
|
|
1188
|
+
} finally {
|
|
1189
|
+
fs.rmSync(root, { recursive: true, force: true });
|
|
1190
|
+
}
|
|
1191
|
+
});
|
|
1192
|
+
|
|
1193
|
+
it("reports still-active provider identities when the wait window elapses", async () => {
|
|
1194
|
+
const root = fs.mkdtempSync(path.join(os.tmpdir(), "pi-wait-provider-timeout-"));
|
|
1195
|
+
try {
|
|
1196
|
+
const state = makeState("sess-1");
|
|
1197
|
+
let clock = 0;
|
|
1198
|
+
const result = await waitForSubagents({ timeoutMs: 1_000 }, undefined, baseDeps(root, state, {
|
|
1199
|
+
now: () => clock,
|
|
1200
|
+
sleep: async (ms) => { clock += ms + 10_000; },
|
|
1201
|
+
backgroundWork: {
|
|
1202
|
+
snapshot: () => ({
|
|
1203
|
+
providers: ["herdr"],
|
|
1204
|
+
items: [{ provider: "herdr", id: "pane-1", sessionId: "sess-1" }],
|
|
1205
|
+
}),
|
|
1206
|
+
wakeChannels: () => [],
|
|
1207
|
+
},
|
|
1208
|
+
}));
|
|
1209
|
+
|
|
1210
|
+
assert.equal(result.isError, undefined);
|
|
1211
|
+
assert.deepEqual(result.details.wait?.activeProviderItems, [{ provider: "herdr", id: "pane-1" }]);
|
|
1153
1212
|
} finally {
|
|
1154
1213
|
fs.rmSync(root, { recursive: true, force: true });
|
|
1155
1214
|
}
|
|
@@ -9,11 +9,8 @@ import {
|
|
|
9
9
|
buildSubagentToolDescription,
|
|
10
10
|
buildSubagentToolPromptMetadata,
|
|
11
11
|
COMPACT_SUBAGENT_TOOL_DESCRIPTION,
|
|
12
|
-
DEFAULT_SUBAGENT_TOOL_DESCRIPTION,
|
|
13
12
|
FULL_SUBAGENT_TOOL_DESCRIPTION,
|
|
14
13
|
SUBAGENT_SAFETY_GUIDANCE,
|
|
15
|
-
SUBAGENT_TOOL_PROMPT_GUIDELINES,
|
|
16
|
-
SUBAGENT_TOOL_PROMPT_SNIPPET,
|
|
17
14
|
} from "../../src/extension/tool-description.ts";
|
|
18
15
|
import { SUBAGENT_CHILD_ENV, SUBAGENT_FANOUT_CHILD_ENV } from "../../src/runs/shared/pi-args.ts";
|
|
19
16
|
|
|
@@ -32,31 +29,26 @@ function parentToolEnv(agentDir?: string): NodeJS.ProcessEnv {
|
|
|
32
29
|
}
|
|
33
30
|
|
|
34
31
|
describe("registered subagent tool description", () => {
|
|
35
|
-
it("uses
|
|
32
|
+
it("uses the full description by default", () => {
|
|
36
33
|
const description = buildSubagentToolDescription();
|
|
37
34
|
const metadata = buildSubagentToolPromptMetadata();
|
|
38
|
-
assert.equal(description,
|
|
39
|
-
assert.equal(
|
|
40
|
-
assert.equal(metadata.
|
|
41
|
-
assert.
|
|
42
|
-
assert.
|
|
43
|
-
assert.equal(Buffer.byteLength(metadata.promptGuidelines!.join("\n")), 1249);
|
|
44
|
-
assert.match(metadata.promptGuidelines!.join("\n"), /Use subagent only when delegation is needed/i);
|
|
45
|
-
assert.match(metadata.promptGuidelines!.join("\n"), /action: \"list\".*executable, non-disabled/i);
|
|
46
|
-
assert.match(metadata.promptGuidelines!.join("\n"), /workflowScript for multi-step or parallel work/i);
|
|
47
|
-
assert.match(metadata.promptGuidelines!.join("\n"), /workflowScript means exactly one top-level subagent tool call with async:true/i);
|
|
48
|
-
assert.match(metadata.promptGuidelines!.join("\n"), /Inside it, use runs\.run\/runs\.all to launch children/i);
|
|
49
|
-
assert.match(metadata.promptGuidelines!.join("\n"), /do not make another top-level subagent call for those children/i);
|
|
50
|
-
assert.match(metadata.promptGuidelines!.join("\n"), /await runs\.all.*do not read \.output from unawaited runs\.run launches/i);
|
|
35
|
+
assert.equal(description, FULL_SUBAGENT_TOOL_DESCRIPTION);
|
|
36
|
+
assert.equal(metadata.promptSnippet, undefined);
|
|
37
|
+
assert.equal(metadata.promptGuidelines, undefined);
|
|
38
|
+
assert.match(description, /^Run one child with \{ agent, task\? \}; use \{ workflowScript \} for inline orchestration/i);
|
|
39
|
+
assert.match(description, /SAFETY-CRITICAL SUBAGENT GUIDANCE/);
|
|
51
40
|
});
|
|
52
41
|
|
|
53
42
|
it("keeps the full description when configured", () => {
|
|
54
43
|
const description = buildSubagentToolDescription({ toolDescriptionMode: "full" });
|
|
55
44
|
assert.equal(buildSubagentToolPromptMetadata({ toolDescriptionMode: "full" }).promptSnippet, undefined);
|
|
56
|
-
assert.match(description, /^Run one child with \{ agent, task\? \}; use \{ workflowScript \} for orchestration/i);
|
|
45
|
+
assert.match(description, /^Run one child with \{ agent, task\? \}; use \{ workflowScript \} for inline orchestration or \{ workflowScriptPath \}/i);
|
|
46
|
+
assert.match(description, /workflowScriptPath:"workflows\/review\.js".*host reads the file.*sandbox/i);
|
|
57
47
|
assert.match(description, /SINGLE CHILD:.*starts exactly one direct child/i);
|
|
58
|
-
assert.match(description, /
|
|
48
|
+
assert.match(description, /lane\.status.*lane\.recordMerge.*lane\.recordSupersession/i);
|
|
49
|
+
assert.match(description, /Do not combine agent\/task with action, workflowScript, or workflowScriptPath/i);
|
|
59
50
|
assert.match(description, /runs\.run for one child and await runs\.all.*ordinary parallel children/i);
|
|
51
|
+
assert.match(description, /runs\.lanes\(\[\{key,stages:.*later stages sequence per lane/i);
|
|
60
52
|
assert.match(description, /do not read \.output from unawaited runs\.run launches/i);
|
|
61
53
|
assert.match(description, /runs\.steer\(key, message, \{mode\?, index\?, ackTimeoutMs\?\}\).*prior keyed child.*without exposing its run id/i);
|
|
62
54
|
assert.match(description, /receipts are queued, delivered, missed, or failed/i);
|
|
@@ -74,19 +66,26 @@ describe("registered subagent tool description", () => {
|
|
|
74
66
|
assert.match(description, /continue independent work only until its next dependency barrier; consume the result before work that depends on it/i);
|
|
75
67
|
assert.match(description, /children\.list.*resumable\/not-resumable reasons/i);
|
|
76
68
|
assert.match(description, /Resume only rows reported resumable/i);
|
|
69
|
+
assert.match(description, /Each workflow key identifies one result lane.*new stable workflow key.*retained resume pass/i);
|
|
70
|
+
assert.match(description, /output.*not an output declaration.*outputReference.*outputPathMapping.*artifactPaths/i);
|
|
77
71
|
assert.match(description, /implementation challenge.*\{action:\"resume\", id:\"run-id\", message:\"\.\.\.\"\}/i);
|
|
78
72
|
assert.match(description, /Resume keeps the stored agent\/model\/tool contract/i);
|
|
79
73
|
assert.match(description, /Oracle\/advisor consultations should use supervisor dialogue for material unknowns when available/i);
|
|
80
74
|
assert.match(description, /same-role fallback challenge and label it as fallback/i);
|
|
81
75
|
assert.match(description, /status\.json/);
|
|
76
|
+
assert.match(description, /suffix on the model string.*off\/minimal\/low\/medium\/high\/xhigh\/max/i);
|
|
77
|
+
assert.match(description, /suffix wins over the agent's thinking default/i);
|
|
78
|
+
assert.match(description, /watchdog\.configure' and is ignored on dispatch/i);
|
|
82
79
|
});
|
|
83
80
|
|
|
84
81
|
it("offers a compact mode that keeps the two-tier contract and safety guidance", () => {
|
|
85
82
|
const description = buildSubagentToolDescription({ toolDescriptionMode: "compact" });
|
|
86
83
|
assert.equal(description, COMPACT_SUBAGENT_TOOL_DESCRIPTION);
|
|
87
|
-
assert.match(description, /^Run one child with \{ agent, task\? \}; use \{ workflowScript \} for orchestration/i);
|
|
84
|
+
assert.match(description, /^Run one child with \{ agent, task\? \}; use \{ workflowScript \} for inline orchestration or \{ workflowScriptPath \}/i);
|
|
85
|
+
assert.match(description, /workflowScriptPath:"workflows\/review\.js".*request cwd.*sandbox/i);
|
|
88
86
|
assert.match(description, /SINGLE .*starts exactly one direct child/i);
|
|
89
87
|
assert.match(description, /runs\.run for one child and await runs\.all.*ordinary parallel work/i);
|
|
88
|
+
assert.match(description, /runs\.lanes\(\[\{key,stages:.*later stages sequence per lane/i);
|
|
90
89
|
assert.match(description, /do not read \.output from unawaited runs\.run launches/i);
|
|
91
90
|
assert.match(description, /runs\.steer\(key,message,options\?\).*prior keyed child/i);
|
|
92
91
|
assert.match(description, /never accepts a raw run id/i);
|
|
@@ -95,12 +94,17 @@ describe("registered subagent tool description", () => {
|
|
|
95
94
|
assert.match(description, /subagent_wait/i);
|
|
96
95
|
assert.match(description, /continue independent work only until its next dependency barrier; consume the result before work that depends on it/i);
|
|
97
96
|
assert.match(description, /children\.list.*resume only rows reported resumable/i);
|
|
97
|
+
assert.match(description, /Each workflow key identifies one result lane.*new stable workflow key.*retained resume pass/i);
|
|
98
|
+
assert.match(description, /output.*not an output declaration.*outputReference.*outputPathMapping.*artifactPaths/i);
|
|
98
99
|
assert.match(description, /\{action:\"resume\",id:\"run-id\",message:\"\.\.\.\"\} for a simple follow-up or challenge/i);
|
|
99
100
|
assert.match(description, /resume keeps the stored agent\/model\/tool contract/i);
|
|
100
101
|
assert.match(description, /Oracle\/advisor consultations use available supervisor dialogue/i);
|
|
101
102
|
assert.match(description, /same-role fallback challenge and label it as fallback/i);
|
|
102
103
|
assert.match(description, /exactly one non-empty title or summary/i);
|
|
103
104
|
assert.match(description, /goal may only be true and requires budget:\{tokens\}/i);
|
|
105
|
+
assert.match(description, /Per-run thinking is a suffix on the model string.*off\/minimal\/low\/medium\/high\/xhigh\/max/i);
|
|
106
|
+
assert.match(description, /suffix wins over the agent's thinking default/i);
|
|
107
|
+
assert.match(description, /watchdog\.configure' and is ignored on dispatch/i);
|
|
104
108
|
assert.ok(description.length < FULL_SUBAGENT_TOOL_DESCRIPTION.length);
|
|
105
109
|
});
|
|
106
110
|
|
|
@@ -258,9 +262,9 @@ describe("registered subagent tool description", () => {
|
|
|
258
262
|
const defaultAgentDir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-subagents-tool-desc-default-"));
|
|
259
263
|
writeExtensionConfig(defaultAgentDir, {});
|
|
260
264
|
const defaultTool = readRegisteredTool(defaultAgentDir);
|
|
261
|
-
assert.equal(defaultTool.description,
|
|
262
|
-
assert.equal(defaultTool.promptSnippet,
|
|
263
|
-
assert.
|
|
265
|
+
assert.equal(defaultTool.description, FULL_SUBAGENT_TOOL_DESCRIPTION);
|
|
266
|
+
assert.equal(defaultTool.promptSnippet, undefined);
|
|
267
|
+
assert.equal(defaultTool.promptGuidelines, undefined);
|
|
264
268
|
|
|
265
269
|
const fullAgentDir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-subagents-tool-desc-full-"));
|
|
266
270
|
writeExtensionConfig(fullAgentDir, { toolDescriptionMode: "full" });
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { describe, it } from "node:test";
|
|
3
|
+
import { toWaitCompletion } from "../../src/runs/background/wait-completions.ts";
|
|
4
|
+
|
|
5
|
+
describe("workflow wait completion projection", () => {
|
|
6
|
+
it("retains the bounded workflow-child summary and excludes result output", () => {
|
|
7
|
+
const completion = toWaitCompletion({
|
|
8
|
+
agent: "workflow",
|
|
9
|
+
mode: "workflow",
|
|
10
|
+
state: "complete",
|
|
11
|
+
success: true,
|
|
12
|
+
workflowChildren: {
|
|
13
|
+
version: 1,
|
|
14
|
+
parentToolCallId: "tool-1",
|
|
15
|
+
workflowRunId: "workflow-1",
|
|
16
|
+
inventoryComplete: true,
|
|
17
|
+
workflowState: "completed",
|
|
18
|
+
children: [{ childId: "review", runId: "run-1", agent: "reviewer", model: "openai-codex/gpt", thinking: "high", state: "completed" }],
|
|
19
|
+
},
|
|
20
|
+
results: [{
|
|
21
|
+
agent: "reviewer",
|
|
22
|
+
runId: "run-1",
|
|
23
|
+
success: true,
|
|
24
|
+
sessionFile: "/sessions/run-1.jsonl",
|
|
25
|
+
usage: { input: 10, output: 2, cacheRead: 30, cacheWrite: 0, cost: 0.04, turns: 1 },
|
|
26
|
+
output: "must not be copied",
|
|
27
|
+
task: "must not be copied",
|
|
28
|
+
}],
|
|
29
|
+
}, "workflow-1");
|
|
30
|
+
|
|
31
|
+
assert.equal(completion.workflowChildren?.children[0]?.childId, "review");
|
|
32
|
+
assert.deepEqual(completion.results?.[0]?.usage, { input: 10, output: 2, cacheRead: 30, cacheWrite: 0, cost: 0.04, turns: 1 });
|
|
33
|
+
assert.equal(completion.results?.[0]?.sessionFile, "/sessions/run-1.jsonl");
|
|
34
|
+
assert.doesNotMatch(JSON.stringify(completion), /must not be copied/);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it("rejects unbounded or unknown summary fields at the replay boundary", () => {
|
|
38
|
+
assert.throws(() => toWaitCompletion({ workflowChildren: { version: 1, parentToolCallId: "tool", workflowRunId: "run", inventoryComplete: true, workflowState: "completed", children: [], output: "secret" } }, "run"), /unsupported fields/);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it("rejects a summary bound to another completion", () => {
|
|
42
|
+
assert.throws(() => toWaitCompletion({ workflowChildren: { version: 1, parentToolCallId: "tool", workflowRunId: "other", inventoryComplete: true, workflowState: "completed", children: [] } }, "run"), /does not match its completion run id/);
|
|
43
|
+
});
|
|
44
|
+
});
|