@selesai/code 0.12.0 → 0.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -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/core/usage-totals.d.ts +2 -0
- package/dist/core/usage-totals.js +10 -0
- package/dist/extensions/ascii.txt +9 -0
- 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-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 -3
- 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 +132 -0
- 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/extensions/pi-zentui/extensions/zentui/format.ts +2 -1
- package/dist/extensions/pi-zentui/test/format.test.ts +15 -1
- package/dist/modes/interactive/components/footer.js +2 -2
- package/dist/modes/interactive/interactive-mode.js +11 -11
- 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
|
@@ -3,7 +3,7 @@ import * as fs from "node:fs";
|
|
|
3
3
|
import * as path from "node:path";
|
|
4
4
|
import { keyText, type ExtensionAPI, type ExtensionContext } from "@selesai/code";
|
|
5
5
|
import { Key, matchesKey, truncateToWidth, type Component, type KeyId, type TUI } from "@earendil-works/pi-tui";
|
|
6
|
-
import { BUILTIN_AGENT_NAMES, discoverAgents, discoverAgentsAll, findBlockingAgentDiagnostic, resolveAgentName, type AgentConfig, type AgentDiscoveryDiagnostic, type AgentScope } from "../agents/agents.ts";
|
|
6
|
+
import { BUILTIN_AGENT_NAMES, discoverAgents, discoverAgentsAll, findBlockingAgentDiagnostic, formatUnknownAgentError, resolveAgentName, unknownAgentDiagnosticContext, type AgentConfig, type AgentDiscoveryDiagnostic, type AgentScope, type UnknownAgentDiagnosticContext } from "../agents/agents.ts";
|
|
7
7
|
import { listRuntimeAgentConfigs, mergeRuntimeAgents } from "../agents/runtime-agent-registry.ts";
|
|
8
8
|
import { resolveExistingReadPaths } from "../shared/settings.ts";
|
|
9
9
|
import {
|
|
@@ -22,6 +22,11 @@ import { listAsyncRuns, formatAsyncRunProgressLabel, type AsyncRunSummary } from
|
|
|
22
22
|
import { encodeInspectReply, handleInspectRpcArgs, INSPECT_WIDGET_KEY } from "../runs/background/inspect-rpc.ts";
|
|
23
23
|
import { listScheduledRunSummaries } from "../runs/background/scheduled-runs.ts";
|
|
24
24
|
import { SUBAGENT_FANOUT_CHILD_ENV } from "../runs/shared/pi-args.ts";
|
|
25
|
+
import { resolveAsyncStatusChild } from "../runs/shared/child-identity.ts";
|
|
26
|
+
import { readStatus } from "../shared/utils.ts";
|
|
27
|
+
import { getArtifactPaths, getArtifactsDir } from "../shared/artifacts.ts";
|
|
28
|
+
import { readWorkflowReceipt } from "../workflows/workflow-receipt.ts";
|
|
29
|
+
import { FLEET_OPEN_SHORTCUT } from "../shared/shortcuts.ts";
|
|
25
30
|
import type { SlashSubagentResponse, SlashSubagentUpdate } from "./slash-bridge.ts";
|
|
26
31
|
import { registerPromptWorkflowCommands } from "./prompt-workflows.ts";
|
|
27
32
|
import { openSubagentsAdmin } from "./subagents-admin.ts";
|
|
@@ -45,7 +50,6 @@ import {
|
|
|
45
50
|
DIRS,
|
|
46
51
|
type Details,
|
|
47
52
|
type FleetKeybindingsConfig,
|
|
48
|
-
type JsonSchemaObject,
|
|
49
53
|
type SingleResult,
|
|
50
54
|
type SubagentState,
|
|
51
55
|
type Usage,
|
|
@@ -108,9 +112,9 @@ const extractExecutionFlags = (rawArgs: string): { args: string; bg: boolean; fo
|
|
|
108
112
|
return { args, bg, fork };
|
|
109
113
|
};
|
|
110
114
|
|
|
111
|
-
function discoverSlashAgents(pi: ExtensionAPI, cwd: string, scope: AgentScope): { agents: AgentConfig[]; agentDiagnostics?: AgentDiscoveryDiagnostic[] } {
|
|
115
|
+
function discoverSlashAgents(pi: ExtensionAPI, cwd: string, scope: AgentScope): { agents: AgentConfig[]; agentDiagnostics?: AgentDiscoveryDiagnostic[]; unknownAgentDiagnosticContext: UnknownAgentDiagnosticContext } {
|
|
112
116
|
const discovered = discoverAgents(cwd, scope);
|
|
113
|
-
if (listRuntimeAgentConfigs(pi).length === 0) return discovered;
|
|
117
|
+
if (listRuntimeAgentConfigs(pi).length === 0) return { ...discovered, unknownAgentDiagnosticContext: unknownAgentDiagnosticContext(discovered) };
|
|
114
118
|
const all = discoverAgentsAll(cwd);
|
|
115
119
|
const configuredAgents: AgentConfig[] = [
|
|
116
120
|
...all.builtin,
|
|
@@ -118,7 +122,8 @@ function discoverSlashAgents(pi: ExtensionAPI, cwd: string, scope: AgentScope):
|
|
|
118
122
|
...(scope !== "project" ? all.user : []),
|
|
119
123
|
...(scope !== "user" ? all.project : []),
|
|
120
124
|
];
|
|
121
|
-
|
|
125
|
+
const merged = mergeRuntimeAgents(pi, discovered, configuredAgents);
|
|
126
|
+
return { ...merged, unknownAgentDiagnosticContext: { ...unknownAgentDiagnosticContext(discovered), agents: merged.agents } };
|
|
122
127
|
}
|
|
123
128
|
|
|
124
129
|
const makeAgentCompletions = (pi: ExtensionAPI, state: SubagentState) => (prefix: string) => {
|
|
@@ -344,25 +349,60 @@ function usageHasValue(usage: Usage): boolean {
|
|
|
344
349
|
return usage.input !== 0 || usage.output !== 0 || usage.cacheRead !== 0 || usage.cacheWrite !== 0 || usage.cost !== 0 || usage.turns !== 0;
|
|
345
350
|
}
|
|
346
351
|
|
|
352
|
+
function nonNegativeNumber(value: unknown): number | undefined {
|
|
353
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : undefined;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
function usageFromValue(value: unknown, turnsOverride?: number): Usage | undefined {
|
|
357
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return undefined;
|
|
358
|
+
const record = value as Record<string, unknown>;
|
|
359
|
+
const costValue = typeof record.cost === "object" && record.cost !== null && !Array.isArray(record.cost)
|
|
360
|
+
? (record.cost as Record<string, unknown>).total
|
|
361
|
+
: record.cost;
|
|
362
|
+
const turnsValue = turnsOverride ?? record.turns;
|
|
363
|
+
const usage = {
|
|
364
|
+
input: nonNegativeNumber(record.input) ?? 0,
|
|
365
|
+
output: nonNegativeNumber(record.output) ?? 0,
|
|
366
|
+
cacheRead: nonNegativeNumber(record.cacheRead) ?? 0,
|
|
367
|
+
cacheWrite: nonNegativeNumber(record.cacheWrite) ?? 0,
|
|
368
|
+
cost: nonNegativeNumber(costValue) ?? 0,
|
|
369
|
+
turns: nonNegativeNumber(turnsValue) ?? 0,
|
|
370
|
+
};
|
|
371
|
+
return Number.isSafeInteger(usage.turns) ? usage : undefined;
|
|
372
|
+
}
|
|
373
|
+
|
|
347
374
|
function assistantUsageFromMessage(message: unknown): Usage | undefined {
|
|
348
375
|
if (!message || typeof message !== "object") return undefined;
|
|
349
376
|
const msg = message as { role?: unknown; usage?: unknown };
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
377
|
+
return msg.role === "assistant" ? usageFromValue(msg.usage, 1) : undefined;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
function compactionUsageFromEntry(entry: unknown): Usage | undefined {
|
|
381
|
+
if (!entry || typeof entry !== "object") return undefined;
|
|
382
|
+
const record = entry as { type?: unknown; usage?: unknown };
|
|
383
|
+
return record.type === "compaction" ? usageFromValue(record.usage, 0) : undefined;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
const MAX_USAGE_METADATA_BYTES = 2 * 1024 * 1024;
|
|
387
|
+
|
|
388
|
+
function readUsageMetadata(metadataPath: string): Record<string, unknown> | undefined {
|
|
389
|
+
let fd: number | undefined;
|
|
390
|
+
try {
|
|
391
|
+
fd = fs.openSync(metadataPath, "r");
|
|
392
|
+
const stat = fs.fstatSync(fd);
|
|
393
|
+
if (!stat.isFile() || stat.size > MAX_USAGE_METADATA_BYTES) return undefined;
|
|
394
|
+
const buffer = Buffer.allocUnsafe(stat.size);
|
|
395
|
+
let offset = 0;
|
|
396
|
+
while (offset < buffer.length) {
|
|
397
|
+
const bytesRead = fs.readSync(fd, buffer, offset, buffer.length - offset, null);
|
|
398
|
+
if (bytesRead <= 0) return undefined;
|
|
399
|
+
offset += bytesRead;
|
|
400
|
+
}
|
|
401
|
+
const value: unknown = JSON.parse(buffer.toString("utf-8"));
|
|
402
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value as Record<string, unknown> : undefined;
|
|
403
|
+
} finally {
|
|
404
|
+
if (fd !== undefined) fs.closeSync(fd);
|
|
405
|
+
}
|
|
366
406
|
}
|
|
367
407
|
|
|
368
408
|
function isSubagentDetails(value: unknown): value is Details {
|
|
@@ -380,10 +420,32 @@ function detailsFromSessionEntry(entry: unknown): Details | undefined {
|
|
|
380
420
|
}
|
|
381
421
|
if (record.type !== "message" || !record.message || typeof record.message !== "object") return undefined;
|
|
382
422
|
const message = record.message as { role?: unknown; toolName?: unknown; details?: unknown };
|
|
383
|
-
if (message.role !== "toolResult" || message.toolName !== "subagent") return undefined;
|
|
423
|
+
if (message.role !== "toolResult" || (message.toolName !== "subagent" && message.toolName !== "subagent_wait")) return undefined;
|
|
384
424
|
return isSubagentDetails(message.details) ? message.details : undefined;
|
|
385
425
|
}
|
|
386
426
|
|
|
427
|
+
function metadataUsage(
|
|
428
|
+
artifactsDirs: string[],
|
|
429
|
+
input: { runId: string; agent: string },
|
|
430
|
+
): Usage | undefined {
|
|
431
|
+
if (!/^[A-Za-z0-9._-]+$/.test(input.runId)) return undefined;
|
|
432
|
+
for (const artifactsDir of artifactsDirs) {
|
|
433
|
+
for (const index of [0, undefined] as const) {
|
|
434
|
+
const metadataPath = getArtifactPaths(artifactsDir, input.runId, input.agent, index).metadataPath;
|
|
435
|
+
try {
|
|
436
|
+
const metadata = readUsageMetadata(metadataPath);
|
|
437
|
+
if (!metadata) continue;
|
|
438
|
+
if (metadata.runId !== input.runId || metadata.agent !== input.agent) continue;
|
|
439
|
+
const usage = usageFromValue(metadata.usage);
|
|
440
|
+
if (usage && usageHasValue(usage)) return usage;
|
|
441
|
+
} catch (error) {
|
|
442
|
+
if ((error as NodeJS.ErrnoException).code !== "ENOENT") console.error(`Failed to read subagent usage metadata '${metadataPath}':`, error);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
return undefined;
|
|
447
|
+
}
|
|
448
|
+
|
|
387
449
|
function formatCostUsage(label: string, usage: Usage): string {
|
|
388
450
|
const extras = [
|
|
389
451
|
usage.cacheRead ? `cache read ${formatTokens(usage.cacheRead)}` : "",
|
|
@@ -393,28 +455,94 @@ function formatCostUsage(label: string, usage: Usage): string {
|
|
|
393
455
|
return `${label}: ↑${formatTokens(usage.input)} ↓${formatTokens(usage.output)} $${usage.cost.toFixed(4)}${extras.length ? ` (${extras.join(", ")})` : ""}`;
|
|
394
456
|
}
|
|
395
457
|
|
|
396
|
-
function buildSubagentCostReport(ctx: ExtensionContext): string {
|
|
458
|
+
function buildSubagentCostReport(ctx: ExtensionContext, state: SubagentState): string {
|
|
397
459
|
const parent = emptyUsage();
|
|
398
460
|
const childTotal = emptyUsage();
|
|
399
461
|
const total = emptyUsage();
|
|
400
462
|
const children: Array<{ label: string; usage: Usage; sessionFile?: string }> = [];
|
|
463
|
+
const seenChildren = new Set<string>();
|
|
464
|
+
const workflowRunIds = new Set<string>();
|
|
465
|
+
let unresolvedAsyncChildren = 0;
|
|
466
|
+
|
|
467
|
+
const addChild = (input: { agent?: string; runId?: string; usage?: Usage; sessionFile?: string }): boolean => {
|
|
468
|
+
if (!input.usage || !usageHasValue(input.usage)) return false;
|
|
469
|
+
const identity = input.runId ? `run:${input.runId}` : input.sessionFile ? `session:${input.sessionFile}` : undefined;
|
|
470
|
+
if (identity && seenChildren.has(identity)) return true;
|
|
471
|
+
if (identity) seenChildren.add(identity);
|
|
472
|
+
const usage = { ...input.usage };
|
|
473
|
+
children.push({
|
|
474
|
+
label: `Child ${children.length + 1} (${input.agent ?? "unknown"})`,
|
|
475
|
+
usage,
|
|
476
|
+
...(input.sessionFile ? { sessionFile: input.sessionFile } : {}),
|
|
477
|
+
});
|
|
478
|
+
addUsage(childTotal, usage);
|
|
479
|
+
return true;
|
|
480
|
+
};
|
|
481
|
+
|
|
401
482
|
for (const entry of ctx.sessionManager.getBranch()) {
|
|
402
483
|
const message = entry.type === "message" ? (entry as { message?: unknown }).message : undefined;
|
|
403
|
-
const parentUsage = assistantUsageFromMessage(message);
|
|
484
|
+
const parentUsage = assistantUsageFromMessage(message) ?? compactionUsageFromEntry(entry);
|
|
404
485
|
if (parentUsage) addUsage(parent, parentUsage);
|
|
405
486
|
const details = detailsFromSessionEntry(entry);
|
|
406
487
|
if (!details) continue;
|
|
488
|
+
if (details.mode === "workflow" && details.runId) workflowRunIds.add(details.runId);
|
|
407
489
|
for (const result of details.results) {
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
490
|
+
const resultRunId = (result as SingleResult & { runId?: unknown }).runId;
|
|
491
|
+
addChild({ agent: result.agent, runId: typeof resultRunId === "string" ? resultRunId : undefined, usage: usageFromValue(result.usage), sessionFile: result.sessionFile });
|
|
492
|
+
}
|
|
493
|
+
for (const completion of details.completions ?? []) {
|
|
494
|
+
if (completion.mode === "workflow") workflowRunIds.add(completion.runId);
|
|
495
|
+
for (const result of completion.results ?? []) {
|
|
496
|
+
addChild({ agent: result.agent, runId: result.runId, usage: usageFromValue(result.usage), sessionFile: result.sessionFile });
|
|
497
|
+
}
|
|
416
498
|
}
|
|
417
499
|
}
|
|
500
|
+
|
|
501
|
+
let sessionFile: string | null = null;
|
|
502
|
+
try {
|
|
503
|
+
sessionFile = ctx.sessionManager.getSessionFile() ?? null;
|
|
504
|
+
} catch { /* an unpersisted session can still report direct child usage */ }
|
|
505
|
+
const artifactsDirs = new Set<string>();
|
|
506
|
+
const addArtifactsDir = (cwd: string | undefined): void => {
|
|
507
|
+
try {
|
|
508
|
+
artifactsDirs.add(getArtifactsDir(sessionFile, cwd, state.artifactDirPreference));
|
|
509
|
+
} catch { /* invalid or unavailable project roots are ignored */ }
|
|
510
|
+
};
|
|
511
|
+
addArtifactsDir(ctx.cwd);
|
|
512
|
+
addArtifactsDir(state.baseCwd);
|
|
513
|
+
|
|
514
|
+
for (const workflowRunId of workflowRunIds) {
|
|
515
|
+
try {
|
|
516
|
+
const status = readStatus(path.join(DIRS.async, workflowRunId));
|
|
517
|
+
addArtifactsDir(status?.cwd);
|
|
518
|
+
const receipt = readWorkflowReceipt(DIRS.async, workflowRunId);
|
|
519
|
+
const summaryChildren = new Map((receipt.workflowChildren?.children ?? []).map((child) => [child.childId, child]));
|
|
520
|
+
const refsByRunId = new Map<string, { runId: string; agent: string }>();
|
|
521
|
+
const addRef = (runId: string | undefined, agent: string | undefined): void => {
|
|
522
|
+
if (!runId || !agent || refsByRunId.has(runId)) return;
|
|
523
|
+
refsByRunId.set(runId, { runId, agent });
|
|
524
|
+
};
|
|
525
|
+
for (const [key, entry] of Object.entries(receipt.entries)) {
|
|
526
|
+
const summaryChild = summaryChildren.get(key);
|
|
527
|
+
const runIds = entry.continuation?.runIds?.length
|
|
528
|
+
? entry.continuation.runIds
|
|
529
|
+
: entry.latestRunId ? [entry.latestRunId] : summaryChild?.runId ? [summaryChild.runId] : [];
|
|
530
|
+
for (const runId of runIds) addRef(runId, entry.agent ?? summaryChild?.agent);
|
|
531
|
+
}
|
|
532
|
+
for (const child of receipt.workflowChildren?.children ?? []) {
|
|
533
|
+
if (!Object.hasOwn(receipt.entries, child.childId)) addRef(child.runId, child.agent);
|
|
534
|
+
}
|
|
535
|
+
const refs = [...refsByRunId.values()];
|
|
536
|
+
for (const ref of refs) {
|
|
537
|
+
if (seenChildren.has(`run:${ref.runId}`)) continue;
|
|
538
|
+
const usage = metadataUsage([...artifactsDirs], ref);
|
|
539
|
+
if (!usage || !addChild({ ...ref, usage })) unresolvedAsyncChildren += 1;
|
|
540
|
+
}
|
|
541
|
+
} catch (error) {
|
|
542
|
+
if ((error as NodeJS.ErrnoException).code !== "ENOENT") console.error(`Failed to resolve async subagent usage for '${workflowRunId}':`, error);
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
|
|
418
546
|
addUsage(total, parent);
|
|
419
547
|
addUsage(total, childTotal);
|
|
420
548
|
const lines = [
|
|
@@ -430,6 +558,7 @@ function buildSubagentCostReport(ctx: ExtensionContext): string {
|
|
|
430
558
|
if (child.sessionFile) lines.push(` Session: ${child.sessionFile}`);
|
|
431
559
|
}
|
|
432
560
|
}
|
|
561
|
+
if (unresolvedAsyncChildren > 0) lines.push(`Async child usage unavailable: ${unresolvedAsyncChildren}.`);
|
|
433
562
|
lines.push("────────────────────────────", formatCostUsage("Children", childTotal), formatCostUsage("Total", total));
|
|
434
563
|
return lines.join("\n");
|
|
435
564
|
}
|
|
@@ -445,50 +574,76 @@ function getProfileWorkerModel(profile: { subagents?: { agentOverrides?: Record<
|
|
|
445
574
|
return typeof model === "string" && model.trim() ? model.trim() : undefined;
|
|
446
575
|
}
|
|
447
576
|
|
|
577
|
+
function isStaleExtensionContextError(error: unknown): boolean {
|
|
578
|
+
return error instanceof Error
|
|
579
|
+
&& (error.message.includes("This extension ctx is stale")
|
|
580
|
+
|| error.message.includes("Extension context no longer active"));
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
function slashHasUI(ctx: ExtensionContext): boolean | undefined {
|
|
584
|
+
try {
|
|
585
|
+
return ctx.hasUI;
|
|
586
|
+
} catch (error) {
|
|
587
|
+
if (isStaleExtensionContextError(error)) return undefined;
|
|
588
|
+
throw error;
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
|
|
448
592
|
|
|
449
593
|
async function requestSlashRun(
|
|
450
594
|
pi: ExtensionAPI,
|
|
451
595
|
ctx: ExtensionContext,
|
|
452
596
|
requestId: string,
|
|
453
597
|
params: SubagentParamsLike,
|
|
598
|
+
signal?: AbortSignal,
|
|
454
599
|
): Promise<SlashSubagentResponse> {
|
|
455
600
|
return new Promise((resolve, reject) => {
|
|
456
601
|
let done = false;
|
|
457
602
|
let started = false;
|
|
458
|
-
|
|
459
|
-
const startTimeoutMs = 15_000;
|
|
460
|
-
const startTimeout = setTimeout(() => {
|
|
461
|
-
finish(() => reject(new Error(
|
|
462
|
-
"Slash subagent bridge did not start within 15s. Ensure the extension is loaded correctly.",
|
|
463
|
-
)));
|
|
464
|
-
}, startTimeoutMs);
|
|
603
|
+
let startTimeout: ReturnType<typeof setTimeout> | undefined;
|
|
465
604
|
|
|
466
605
|
const onStarted = (data: unknown) => {
|
|
467
|
-
if (done || !data || typeof data !== "object") return;
|
|
606
|
+
if (done || signal?.aborted || !data || typeof data !== "object") return;
|
|
468
607
|
if ((data as { requestId?: unknown }).requestId !== requestId) return;
|
|
469
608
|
started = true;
|
|
470
|
-
clearTimeout(startTimeout);
|
|
471
|
-
|
|
609
|
+
if (startTimeout) clearTimeout(startTimeout);
|
|
610
|
+
try {
|
|
611
|
+
if (ctx.hasUI) ctx.ui.setStatus("subagent-slash", "running...");
|
|
612
|
+
} catch (error) {
|
|
613
|
+
if (isStaleExtensionContextError(error)) {
|
|
614
|
+
finish(() => reject(error));
|
|
615
|
+
return;
|
|
616
|
+
}
|
|
617
|
+
throw error;
|
|
618
|
+
}
|
|
472
619
|
};
|
|
473
620
|
|
|
474
621
|
const onResponse = (data: unknown) => {
|
|
475
|
-
if (done || !data || typeof data !== "object") return;
|
|
622
|
+
if (done || signal?.aborted || !data || typeof data !== "object") return;
|
|
476
623
|
const response = data as Partial<SlashSubagentResponse>;
|
|
477
624
|
if (response.requestId !== requestId) return;
|
|
478
|
-
clearTimeout(startTimeout);
|
|
625
|
+
if (startTimeout) clearTimeout(startTimeout);
|
|
479
626
|
finish(() => resolve(response as SlashSubagentResponse));
|
|
480
627
|
};
|
|
481
628
|
|
|
482
629
|
const onUpdate = (data: unknown) => {
|
|
483
|
-
if (done || !data || typeof data !== "object") return;
|
|
630
|
+
if (done || signal?.aborted || !data || typeof data !== "object") return;
|
|
484
631
|
const update = data as SlashSubagentUpdate;
|
|
485
632
|
if (update.requestId !== requestId) return;
|
|
486
633
|
applySlashUpdate(requestId, update);
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
634
|
+
try {
|
|
635
|
+
if (!ctx.hasUI) return;
|
|
636
|
+
const tool = update.currentTool ? ` ${update.currentTool}` : "";
|
|
637
|
+
const count = update.toolCount ?? 0;
|
|
638
|
+
const liveDetailKey = keyText("app.tools.expand");
|
|
639
|
+
ctx.ui.setStatus("subagent-slash", `${count} tools${tool} | ${liveDetailKey} live detail`);
|
|
640
|
+
} catch (error) {
|
|
641
|
+
if (isStaleExtensionContextError(error)) {
|
|
642
|
+
finish(() => reject(error));
|
|
643
|
+
return;
|
|
644
|
+
}
|
|
645
|
+
throw error;
|
|
646
|
+
}
|
|
492
647
|
};
|
|
493
648
|
|
|
494
649
|
const onTerminalInput = ctx.hasUI
|
|
@@ -504,18 +659,43 @@ async function requestSlashRun(
|
|
|
504
659
|
const unsubResponse = pi.events.on(SLASH_SUBAGENT_RESPONSE_EVENT, onResponse);
|
|
505
660
|
const unsubUpdate = pi.events.on(SLASH_SUBAGENT_UPDATE_EVENT, onUpdate);
|
|
506
661
|
|
|
662
|
+
let onAbort: () => void;
|
|
507
663
|
const finish = (next: () => void) => {
|
|
508
664
|
if (done) return;
|
|
509
665
|
done = true;
|
|
510
|
-
clearTimeout(startTimeout);
|
|
666
|
+
if (startTimeout) clearTimeout(startTimeout);
|
|
511
667
|
unsubStarted();
|
|
512
668
|
unsubResponse();
|
|
513
669
|
unsubUpdate();
|
|
514
|
-
|
|
670
|
+
try {
|
|
671
|
+
onTerminalInput?.();
|
|
672
|
+
} catch (error) {
|
|
673
|
+
if (!isStaleExtensionContextError(error)) throw error;
|
|
674
|
+
}
|
|
675
|
+
signal?.removeEventListener("abort", onAbort);
|
|
515
676
|
next();
|
|
516
677
|
};
|
|
678
|
+
onAbort = () => finish(() => reject(new Error("Slash subagent request canceled during session replacement or reload.")));
|
|
679
|
+
startTimeout = setTimeout(() => {
|
|
680
|
+
finish(() => reject(new Error(
|
|
681
|
+
"Slash subagent bridge did not start within 15s. Ensure the extension is loaded correctly.",
|
|
682
|
+
)));
|
|
683
|
+
}, 15_000);
|
|
517
684
|
|
|
518
|
-
|
|
685
|
+
if (signal?.aborted) {
|
|
686
|
+
onAbort();
|
|
687
|
+
return;
|
|
688
|
+
}
|
|
689
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
690
|
+
try {
|
|
691
|
+
pi.events.emit(SLASH_SUBAGENT_REQUEST_EVENT, { requestId, params, ctx });
|
|
692
|
+
} catch (error) {
|
|
693
|
+
if (isStaleExtensionContextError(error)) {
|
|
694
|
+
finish(() => reject(error));
|
|
695
|
+
return;
|
|
696
|
+
}
|
|
697
|
+
throw error;
|
|
698
|
+
}
|
|
519
699
|
|
|
520
700
|
// Bridge emits STARTED synchronously during REQUEST emit.
|
|
521
701
|
// If not started, no bridge received the request.
|
|
@@ -581,53 +761,73 @@ async function runSlashSubagent(
|
|
|
581
761
|
pi: ExtensionAPI,
|
|
582
762
|
ctx: ExtensionContext,
|
|
583
763
|
params: SubagentParamsLike,
|
|
764
|
+
signal?: AbortSignal,
|
|
584
765
|
): Promise<void> {
|
|
585
|
-
if (
|
|
766
|
+
if (signal?.aborted) return;
|
|
767
|
+
const initialHasUI = slashHasUI(ctx);
|
|
768
|
+
if (initialHasUI === undefined) return;
|
|
769
|
+
try {
|
|
770
|
+
if (initialHasUI) ctx.ui.setToolsExpanded(false);
|
|
771
|
+
} catch (error) {
|
|
772
|
+
if (isStaleExtensionContextError(error)) return;
|
|
773
|
+
throw error;
|
|
774
|
+
}
|
|
586
775
|
const requestId = randomUUID();
|
|
587
776
|
const initialDetails = buildSlashInitialResult(requestId, params);
|
|
588
777
|
const initialText = extractSlashMessageText(initialDetails.result.content) || "Running subagent...";
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
778
|
+
try {
|
|
779
|
+
pi.sendMessage({
|
|
780
|
+
customType: SLASH_RESULT_TYPE,
|
|
781
|
+
content: initialText,
|
|
782
|
+
display: true,
|
|
783
|
+
details: initialDetails,
|
|
784
|
+
});
|
|
785
|
+
} catch (error) {
|
|
786
|
+
if (isStaleExtensionContextError(error)) return;
|
|
787
|
+
throw error;
|
|
788
|
+
}
|
|
595
789
|
persistSlashSessionSnapshot(ctx);
|
|
596
790
|
|
|
597
791
|
try {
|
|
598
|
-
const response = await requestSlashRun(pi, ctx, requestId, params);
|
|
792
|
+
const response = await requestSlashRun(pi, ctx, requestId, params, signal);
|
|
793
|
+
if (signal?.aborted) return;
|
|
794
|
+
const hasUI = slashHasUI(ctx);
|
|
795
|
+
if (hasUI === undefined) return;
|
|
599
796
|
const finalDetails = finalizeSlashResult(response);
|
|
600
797
|
pi.sendMessage({
|
|
601
798
|
customType: SLASH_RESULT_TYPE,
|
|
602
799
|
content: buildSlashExportText(response),
|
|
603
|
-
display: !
|
|
800
|
+
display: !hasUI,
|
|
604
801
|
details: finalDetails,
|
|
605
802
|
});
|
|
606
803
|
persistSlashSessionSnapshot(ctx);
|
|
607
|
-
if (
|
|
804
|
+
if (hasUI) {
|
|
608
805
|
ctx.ui.setStatus("subagent-slash", undefined);
|
|
609
806
|
}
|
|
610
|
-
if (response.isError &&
|
|
807
|
+
if (response.isError && hasUI) {
|
|
611
808
|
ctx.ui.notify(response.errorText || "Subagent failed", "error");
|
|
612
809
|
}
|
|
613
810
|
} catch (error) {
|
|
811
|
+
if (signal?.aborted || isStaleExtensionContextError(error)) return;
|
|
614
812
|
const message = error instanceof Error ? error.message : String(error);
|
|
813
|
+
const hasUI = slashHasUI(ctx);
|
|
814
|
+
if (hasUI === undefined) return;
|
|
615
815
|
const failedDetails = failSlashResult(requestId, params, message);
|
|
616
816
|
pi.sendMessage({
|
|
617
817
|
customType: SLASH_RESULT_TYPE,
|
|
618
818
|
content: `## Subagent result\n\n${message}`,
|
|
619
|
-
display: !
|
|
819
|
+
display: !hasUI,
|
|
620
820
|
details: failedDetails,
|
|
621
821
|
});
|
|
622
822
|
persistSlashSessionSnapshot(ctx);
|
|
623
|
-
if (
|
|
823
|
+
if (hasUI) {
|
|
624
824
|
ctx.ui.setStatus("subagent-slash", undefined);
|
|
625
825
|
}
|
|
626
826
|
if (message === "Cancelled") {
|
|
627
|
-
if (
|
|
827
|
+
if (hasUI) ctx.ui.notify("Cancelled", "warning");
|
|
628
828
|
return;
|
|
629
829
|
}
|
|
630
|
-
if (
|
|
830
|
+
if (hasUI) ctx.ui.notify(message, "error");
|
|
631
831
|
}
|
|
632
832
|
}
|
|
633
833
|
|
|
@@ -639,6 +839,7 @@ export function launchSlashSubagent(
|
|
|
639
839
|
void runSlashSubagent(pi, ctx, params);
|
|
640
840
|
}
|
|
641
841
|
|
|
842
|
+
|
|
642
843
|
function slashRunWorkflowScript(key: string, child: Record<string, unknown>): string {
|
|
643
844
|
return `return runs.run(${JSON.stringify(key)}, ${JSON.stringify(child)})`;
|
|
644
845
|
}
|
|
@@ -647,12 +848,23 @@ export function registerSlashCommands(
|
|
|
647
848
|
pi: ExtensionAPI,
|
|
648
849
|
state: SubagentState,
|
|
649
850
|
options: { fleetKeybindings?: FleetKeybindingsConfig; foregroundDetachShortcut?: string } = {},
|
|
650
|
-
): void {
|
|
851
|
+
): { dispose: () => void } {
|
|
651
852
|
let fleetOpen = false;
|
|
853
|
+
let disposed = false;
|
|
854
|
+
const pendingRequests = new Set<AbortController>();
|
|
855
|
+
const runCommand = (ctx: ExtensionContext, params: SubagentParamsLike): Promise<void> => {
|
|
856
|
+
if (disposed) return Promise.resolve();
|
|
857
|
+
const controller = new AbortController();
|
|
858
|
+
pendingRequests.add(controller);
|
|
859
|
+
return runSlashSubagent(pi, ctx, params, controller.signal).finally(() => pendingRequests.delete(controller));
|
|
860
|
+
};
|
|
861
|
+
const launchCommand = (ctx: ExtensionContext, params: SubagentParamsLike): void => {
|
|
862
|
+
void runCommand(ctx, params);
|
|
863
|
+
};
|
|
652
864
|
const showFleet = async (ctx: ExtensionContext) => {
|
|
653
865
|
state.lastUiContext = ctx;
|
|
654
866
|
if (!ctx.hasUI) {
|
|
655
|
-
await
|
|
867
|
+
await runCommand(ctx, { action: "status", view: "fleet" });
|
|
656
868
|
return;
|
|
657
869
|
}
|
|
658
870
|
if (fleetOpen) {
|
|
@@ -693,7 +905,7 @@ export function registerSlashCommands(
|
|
|
693
905
|
: resolvedAgent.agent;
|
|
694
906
|
const diagnostic = findBlockingAgentDiagnostic(agentName, candidates, discovered.agentDiagnostics);
|
|
695
907
|
if (diagnostic || resolvedAgent.error || !resolvedAgent.agent) {
|
|
696
|
-
ctx.ui.notify(diagnostic ? `Agent '${agentName}' has invalid configuration: ${diagnostic.error}` : resolvedAgent.error ??
|
|
908
|
+
ctx.ui.notify(diagnostic ? `Agent '${agentName}' has invalid configuration: ${diagnostic.error}` : resolvedAgent.error ?? formatUnknownAgentError(agentName, discovered.unknownAgentDiagnosticContext), "error");
|
|
697
909
|
return;
|
|
698
910
|
}
|
|
699
911
|
|
|
@@ -708,21 +920,21 @@ export function registerSlashCommands(
|
|
|
708
920
|
if (inline.skill !== undefined) child.skill = inline.skill;
|
|
709
921
|
if (inline.model) child.model = inline.model;
|
|
710
922
|
if (fork) child.context = "fork";
|
|
711
|
-
|
|
923
|
+
launchCommand(ctx, { workflowScript: slashRunWorkflowScript("run", child), async: bg ? true : false });
|
|
712
924
|
},
|
|
713
925
|
});
|
|
714
926
|
|
|
715
927
|
pi.registerCommand("subagent-cost", {
|
|
716
928
|
description: "Show parent and subagent child usage cost for this session",
|
|
717
929
|
handler: async (_args, ctx) => {
|
|
718
|
-
sendSlashText(pi, buildSubagentCostReport(ctx));
|
|
930
|
+
sendSlashText(pi, buildSubagentCostReport(ctx, state));
|
|
719
931
|
},
|
|
720
932
|
});
|
|
721
933
|
|
|
722
934
|
pi.registerCommand("subagents-doctor", {
|
|
723
935
|
description: "Show subagent diagnostics",
|
|
724
936
|
handler: async (_args, ctx) => {
|
|
725
|
-
await
|
|
937
|
+
await runCommand(ctx, { action: "doctor" });
|
|
726
938
|
},
|
|
727
939
|
});
|
|
728
940
|
|
|
@@ -754,7 +966,7 @@ export function registerSlashCommands(
|
|
|
754
966
|
ctx.ui.notify("Usage: /subagents-guide [topic]", "error");
|
|
755
967
|
return;
|
|
756
968
|
}
|
|
757
|
-
await
|
|
969
|
+
await runCommand(ctx, { action: "guide", ...(topic ? { topic } : {}) });
|
|
758
970
|
},
|
|
759
971
|
});
|
|
760
972
|
|
|
@@ -767,7 +979,7 @@ export function registerSlashCommands(
|
|
|
767
979
|
ctx.ui.notify("Usage: /subagents-refine <agent>", "error");
|
|
768
980
|
return;
|
|
769
981
|
}
|
|
770
|
-
await
|
|
982
|
+
await runCommand(ctx, { action: "refine", agent: parts[0] });
|
|
771
983
|
},
|
|
772
984
|
});
|
|
773
985
|
|
|
@@ -776,7 +988,7 @@ export function registerSlashCommands(
|
|
|
776
988
|
handler: async (_args, ctx) => showFleet(ctx),
|
|
777
989
|
});
|
|
778
990
|
|
|
779
|
-
pi.registerShortcut(
|
|
991
|
+
pi.registerShortcut(FLEET_OPEN_SHORTCUT, {
|
|
780
992
|
description: "Open subagent fleet inspector",
|
|
781
993
|
handler: async (ctx) => showFleet(ctx),
|
|
782
994
|
});
|
|
@@ -818,11 +1030,15 @@ export function registerSlashCommands(
|
|
|
818
1030
|
}
|
|
819
1031
|
|
|
820
1032
|
pi.registerCommand("subagents-stop", {
|
|
821
|
-
description: "Stop a current-session async subagent run",
|
|
1033
|
+
description: "Stop a current-session async subagent run, or one child of it with /subagents-stop <run-id> <child-id>",
|
|
822
1034
|
handler: async (args, ctx) => {
|
|
823
|
-
const id = args.trim();
|
|
1035
|
+
const [id, childId, ...extra] = args.trim().split(/\s+/).filter(Boolean);
|
|
1036
|
+
if (extra.length > 0) {
|
|
1037
|
+
sendSlashText(pi, "Usage: /subagents-stop [run-id] [child-id]");
|
|
1038
|
+
return;
|
|
1039
|
+
}
|
|
824
1040
|
if (id) {
|
|
825
|
-
await
|
|
1041
|
+
await runCommand(ctx, childId ? { action: "stop", id, childId } : { action: "stop", id });
|
|
826
1042
|
return;
|
|
827
1043
|
}
|
|
828
1044
|
|
|
@@ -854,27 +1070,91 @@ export function registerSlashCommands(
|
|
|
854
1070
|
);
|
|
855
1071
|
if (!result?.confirmed || !result.target) return;
|
|
856
1072
|
if (result.target.kind === "scheduled") {
|
|
857
|
-
await
|
|
1073
|
+
await runCommand(ctx, { action: "schedule.pause", id: result.target.id });
|
|
1074
|
+
return;
|
|
1075
|
+
}
|
|
1076
|
+
await runCommand(ctx, { action: "stop", id: result.target.id });
|
|
1077
|
+
},
|
|
1078
|
+
});
|
|
1079
|
+
|
|
1080
|
+
pi.registerCommand("subagents-steer", {
|
|
1081
|
+
description: "Steer a live async subagent run with a message, or one child of it with --child <child-id>",
|
|
1082
|
+
handler: async (args, ctx) => {
|
|
1083
|
+
const tokens = args.trim().split(/\s+/).filter(Boolean);
|
|
1084
|
+
const usage = "Usage: /subagents-steer <run-id> [--child <child-id>] <message>";
|
|
1085
|
+
const [id, ...rest] = tokens;
|
|
1086
|
+
if (!id || id.startsWith("--")) {
|
|
1087
|
+
sendSlashText(pi, usage);
|
|
858
1088
|
return;
|
|
859
1089
|
}
|
|
860
|
-
|
|
1090
|
+
// Only the optional child selector is parsed as a flag. Everything
|
|
1091
|
+
// after the run id (or selector) is free-form message text, including
|
|
1092
|
+
// a leading token such as `--verbose`.
|
|
1093
|
+
let childId: string | undefined;
|
|
1094
|
+
let messageStart = 0;
|
|
1095
|
+
if (rest[0] === "--child" && rest[1] && !rest[1].startsWith("--")) {
|
|
1096
|
+
childId = rest[1];
|
|
1097
|
+
messageStart = 2;
|
|
1098
|
+
}
|
|
1099
|
+
const message = rest.slice(messageStart).join(" ").trim();
|
|
1100
|
+
if (!message) {
|
|
1101
|
+
sendSlashText(pi, usage);
|
|
1102
|
+
return;
|
|
1103
|
+
}
|
|
1104
|
+
let targetId = id;
|
|
1105
|
+
let childIndex: number | undefined;
|
|
1106
|
+
if (childId !== undefined) {
|
|
1107
|
+
const sessionId = state.currentSessionId ?? ctx.sessionManager.getSessionId() ?? undefined;
|
|
1108
|
+
const run = listAsyncRuns(DIRS.async, {
|
|
1109
|
+
runId: id,
|
|
1110
|
+
states: ["queued", "running", "paused"],
|
|
1111
|
+
...(sessionId ? { sessionId } : {}),
|
|
1112
|
+
})[0];
|
|
1113
|
+
const status = run ? readStatus(run.asyncDir) : null;
|
|
1114
|
+
if (!run || !status) {
|
|
1115
|
+
sendSlashText(pi, `No current-session async run found for '${id}'.`);
|
|
1116
|
+
return;
|
|
1117
|
+
}
|
|
1118
|
+
const resolutionStatus = {
|
|
1119
|
+
...status,
|
|
1120
|
+
steps: status.steps?.map((step, index) => ({ ...step, children: run.steps[index]?.children ?? step.children })),
|
|
1121
|
+
};
|
|
1122
|
+
const resolution = resolveAsyncStatusChild(resolutionStatus, childId, { includeNested: true });
|
|
1123
|
+
if (!resolution.ok) {
|
|
1124
|
+
sendSlashText(pi, resolution.message);
|
|
1125
|
+
return;
|
|
1126
|
+
}
|
|
1127
|
+
if (resolution.child.nested) targetId = resolution.child.nested.id;
|
|
1128
|
+
else if (resolution.child.step.runId) targetId = resolution.child.step.runId;
|
|
1129
|
+
else childIndex = resolution.child.index;
|
|
1130
|
+
}
|
|
1131
|
+
await runCommand(ctx, {
|
|
1132
|
+
action: "steer",
|
|
1133
|
+
id: targetId,
|
|
1134
|
+
message,
|
|
1135
|
+
...(childIndex !== undefined ? { index: childIndex } : {}),
|
|
1136
|
+
// Host-style exact-child authority, matching the extension RPC
|
|
1137
|
+
// nonRecoveringSteer guarantee: never swap the addressed child for
|
|
1138
|
+
// a pause-and-revive replacement after a missed acknowledgment.
|
|
1139
|
+
steeringRecovery: false,
|
|
1140
|
+
});
|
|
861
1141
|
},
|
|
862
1142
|
});
|
|
863
1143
|
|
|
864
1144
|
registerPromptWorkflowCommands({
|
|
865
1145
|
pi,
|
|
866
1146
|
run: async (params, ctx) => {
|
|
867
|
-
|
|
1147
|
+
launchCommand(ctx, params);
|
|
868
1148
|
},
|
|
869
1149
|
});
|
|
870
1150
|
|
|
871
1151
|
pi.registerCommand("subagents-models", {
|
|
872
1152
|
description: "Show runtime-loaded builtin subagent models",
|
|
873
1153
|
getArgumentCompletions: makeBuiltinAgentNameCompletions(),
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
1154
|
+
handler: async (args, ctx) => {
|
|
1155
|
+
const trimmed = args.trim();
|
|
1156
|
+
if (!trimmed) {
|
|
1157
|
+
await runCommand(ctx, { action: "models" });
|
|
878
1158
|
return;
|
|
879
1159
|
}
|
|
880
1160
|
const parts = trimmed.split(/\s+/).filter(Boolean);
|
|
@@ -887,7 +1167,7 @@ export function registerSlashCommands(
|
|
|
887
1167
|
ctx.ui.notify(`Unknown builtin agent: ${agent}`, "error");
|
|
888
1168
|
return;
|
|
889
1169
|
}
|
|
890
|
-
await
|
|
1170
|
+
await runCommand(ctx, { action: "models", agent });
|
|
891
1171
|
},
|
|
892
1172
|
});
|
|
893
1173
|
|
|
@@ -1060,4 +1340,14 @@ export function registerSlashCommands(
|
|
|
1060
1340
|
},
|
|
1061
1341
|
});
|
|
1062
1342
|
|
|
1343
|
+
return {
|
|
1344
|
+
dispose: () => {
|
|
1345
|
+
if (disposed) return;
|
|
1346
|
+
disposed = true;
|
|
1347
|
+
// A reload revokes the command context; do not let delayed responses
|
|
1348
|
+
// resume a command against the old Pi context.
|
|
1349
|
+
for (const controller of pendingRequests) controller.abort();
|
|
1350
|
+
pendingRequests.clear();
|
|
1351
|
+
},
|
|
1352
|
+
};
|
|
1063
1353
|
}
|