pi-crew 0.9.16 → 0.9.17
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 +81 -0
- package/README.md +19 -0
- package/dist/build-meta.json +21790 -0
- package/dist/index.mjs +83070 -0
- package/dist/index.mjs.map +7 -0
- package/docs/A +358 -0
- package/docs/M-A +357 -0
- package/docs/REVIEW-FINDINGS-2026-06 +357 -0
- package/docs/Y +357 -0
- package/docs/a +357 -0
- package/docs/aA +358 -0
- package/docs/archive/README.md +91 -0
- package/docs/patterns/command-agent-skill.md +1 -1
- package/docs/skills/REFERENCE.md +0 -17
- package/docs//303/242mmaAAA/303/242 +357 -0
- package/index.bundle.ts +25 -0
- package/index.ts +95 -4
- package/package.json +15 -4
- package/skills/iterative-audit/SKILL.md +0 -1
- package/skills/widget-rendering/SKILL.md +17 -0
- package/src/adapters/claude-adapter.ts +1 -3
- package/src/adapters/export-util.ts +16 -16
- package/src/adapters/index.ts +5 -5
- package/src/agents/agent-config.ts +20 -14
- package/src/agents/agent-serializer.ts +1 -1
- package/src/agents/discover-agents.ts +83 -39
- package/src/benchmark/benchmark-runner.ts +51 -51
- package/src/benchmark/feedback-loop.ts +1 -1
- package/src/config/config.ts +166 -590
- package/src/config/defaults.ts +28 -2
- package/src/config/drift-detector.ts +11 -14
- package/src/config/markers.ts +201 -203
- package/src/config/resilient-parser.ts +14 -6
- package/src/config/role-tools.ts +3 -3
- package/src/config/suggestions.ts +5 -12
- package/src/config/types.ts +9 -25
- package/src/errors.ts +151 -157
- package/src/extension/action-suggestions.ts +54 -9
- package/src/extension/async-notifier.ts +43 -13
- package/src/extension/autonomous-policy.ts +77 -37
- package/src/extension/command-completions.ts +9 -8
- package/src/extension/context-status-injection.ts +14 -12
- package/src/extension/crew-autocomplete.ts +8 -16
- package/src/extension/crew-cleanup.ts +2 -1
- package/src/extension/crew-shortcuts.ts +9 -6
- package/src/extension/cross-extension-rpc.ts +136 -42
- package/src/extension/help.ts +1 -1
- package/src/extension/import-index.ts +10 -5
- package/src/extension/knowledge-injection.ts +88 -15
- package/src/extension/management.ts +89 -349
- package/src/extension/message-renderers.ts +3 -4
- package/src/extension/notification-router.ts +22 -5
- package/src/extension/notification-sink.ts +6 -3
- package/src/extension/pi-api.ts +17 -8
- package/src/extension/plan-orchestrate.ts +8 -27
- package/src/extension/project-init.ts +21 -6
- package/src/extension/register.ts +329 -975
- package/src/extension/registration/artifact-cleanup.ts +9 -4
- package/src/extension/registration/command-utils.ts +5 -1
- package/src/extension/registration/commands.ts +806 -314
- package/src/extension/registration/compaction-guard.ts +15 -15
- package/src/extension/registration/lifecycle.ts +259 -0
- package/src/extension/registration/observability.ts +293 -0
- package/src/extension/registration/subagent-helpers.ts +29 -7
- package/src/extension/registration/subagent-tools.ts +253 -44
- package/src/extension/registration/team-tool.ts +19 -84
- package/src/extension/registration/ui.ts +168 -0
- package/src/extension/registration/viewers.ts +64 -24
- package/src/extension/result-watcher.ts +18 -7
- package/src/extension/run-bundle-schema.ts +21 -6
- package/src/extension/run-export.ts +15 -6
- package/src/extension/run-import.ts +64 -29
- package/src/extension/run-index.ts +28 -9
- package/src/extension/run-maintenance.ts +32 -12
- package/src/extension/session-summary.ts +1 -1
- package/src/extension/team-manager-command.ts +64 -7
- package/src/extension/team-onboard.ts +151 -150
- package/src/extension/team-recommendation.ts +121 -21
- package/src/extension/team-tool/anchor.ts +31 -64
- package/src/extension/team-tool/api.ts +929 -141
- package/src/extension/team-tool/auto-summarize.ts +14 -26
- package/src/extension/team-tool/cache-control.ts +1 -5
- package/src/extension/team-tool/cancel.ts +138 -38
- package/src/extension/team-tool/chain-dispatch.ts +5 -13
- package/src/extension/team-tool/chain-executor.ts +29 -51
- package/src/extension/team-tool/config-patch.ts +1 -1
- package/src/extension/team-tool/context.ts +40 -20
- package/src/extension/team-tool/destructive-gate.ts +10 -5
- package/src/extension/team-tool/doctor.ts +170 -51
- package/src/extension/team-tool/explain.ts +228 -214
- package/src/extension/team-tool/failure-patterns.ts +3 -9
- package/src/extension/team-tool/goal-wrap.ts +71 -29
- package/src/extension/team-tool/goal.ts +185 -35
- package/src/extension/team-tool/handle-schedule.ts +34 -15
- package/src/extension/team-tool/handle-settings.ts +94 -56
- package/src/extension/team-tool/health-monitor.ts +27 -108
- package/src/extension/team-tool/inspect.ts +42 -9
- package/src/extension/team-tool/intent-policy.ts +4 -1
- package/src/extension/team-tool/lifecycle-actions.ts +244 -48
- package/src/extension/team-tool/orchestrate.ts +7 -18
- package/src/extension/team-tool/parallel-dispatch.ts +51 -29
- package/src/extension/team-tool/plan.ts +29 -5
- package/src/extension/team-tool/respond.ts +49 -16
- package/src/extension/team-tool/run-not-found.ts +3 -8
- package/src/extension/team-tool/run.ts +80 -317
- package/src/extension/team-tool/status.ts +135 -43
- package/src/extension/team-tool/workflow-manage.ts +92 -25
- package/src/extension/team-tool-types.ts +8 -1
- package/src/extension/team-tool.ts +142 -551
- package/src/extension/validate-resources.ts +39 -8
- package/src/hooks/registry.ts +66 -17
- package/src/hooks/types.ts +1 -1
- package/src/i18n.ts +25 -11
- package/src/observability/correlation.ts +17 -3
- package/src/observability/event-bus.ts +51 -56
- package/src/observability/event-to-metric.ts +117 -15
- package/src/observability/exporters/otlp-exporter.ts +56 -17
- package/src/observability/exporters/prometheus-exporter.ts +1 -1
- package/src/observability/metric-registry.ts +16 -4
- package/src/observability/metric-retention.ts +8 -2
- package/src/observability/metric-sink.ts +11 -3
- package/src/observability/metrics-primitives.ts +42 -9
- package/src/plugins/plugin-define.ts +2 -2
- package/src/plugins/plugin-registry.ts +25 -25
- package/src/plugins/plugins/index.ts +1 -1
- package/src/plugins/plugins/nextjs.ts +16 -16
- package/src/plugins/plugins/vite.ts +7 -11
- package/src/plugins/plugins/vitest.ts +6 -11
- package/src/runtime/adaptive-plan.ts +225 -40
- package/src/runtime/agent-control.ts +58 -15
- package/src/runtime/agent-memory.ts +15 -9
- package/src/runtime/agent-observability.ts +10 -2
- package/src/runtime/anchor-manager.ts +27 -25
- package/src/runtime/async-marker.ts +7 -1
- package/src/runtime/async-runner.ts +27 -23
- package/src/runtime/auto-summarize.ts +7 -13
- package/src/runtime/background-runner.ts +189 -251
- package/src/runtime/batch-barrier.ts +18 -16
- package/src/runtime/cancellation-token.ts +16 -6
- package/src/runtime/cancellation.ts +46 -8
- package/src/runtime/capability-inventory.ts +6 -4
- package/src/runtime/chain-parser.ts +44 -11
- package/src/runtime/chain-runner.ts +63 -69
- package/src/runtime/checkpoint.ts +12 -56
- package/src/runtime/child-pi.ts +343 -78
- package/src/runtime/coalesce-tasks.ts +268 -0
- package/src/runtime/code-summary.ts +71 -26
- package/src/runtime/compact-stages/index.ts +15 -5
- package/src/runtime/compact-stages/tail-capture-stage.ts +7 -2
- package/src/runtime/compact-stages/truncation-stage.ts +4 -1
- package/src/runtime/compaction-summary.ts +17 -10
- package/src/runtime/completion-guard.ts +33 -16
- package/src/runtime/crash-classification.ts +28 -7
- package/src/runtime/crash-recovery.ts +177 -37
- package/src/runtime/crew-agent-records.ts +145 -47
- package/src/runtime/crew-hooks.ts +9 -24
- package/src/runtime/cross-extension-rpc.ts +25 -23
- package/src/runtime/custom-tools/irc-tool.ts +43 -15
- package/src/runtime/custom-tools/submit-result-tool.ts +16 -5
- package/src/runtime/delivery-coordinator.ts +34 -7
- package/src/runtime/delta-conflict.ts +9 -21
- package/src/runtime/deterministic-ast.ts +1 -1
- package/src/runtime/diagnostic-export.ts +53 -20
- package/src/runtime/direct-run.ts +12 -2
- package/src/runtime/dwf-state-store.ts +1 -1
- package/src/runtime/dynamic-workflow-context.ts +186 -58
- package/src/runtime/dynamic-workflow-runner.ts +42 -20
- package/src/runtime/effectiveness.ts +16 -8
- package/src/runtime/errors/crew-errors.ts +7 -11
- package/src/runtime/event-stream-bridge.ts +9 -3
- package/src/runtime/foreground-control.ts +54 -14
- package/src/runtime/foreground-watchdog.ts +9 -6
- package/src/runtime/goal-achievement.ts +27 -10
- package/src/runtime/goal-evaluator.ts +54 -19
- package/src/runtime/goal-loop-runner.ts +280 -99
- package/src/runtime/goal-state-store.ts +27 -17
- package/src/runtime/green-contract.ts +11 -2
- package/src/runtime/group-join.ts +64 -31
- package/src/runtime/handoff-manager.ts +37 -42
- package/src/runtime/heartbeat-gradient.ts +10 -2
- package/src/runtime/heartbeat-watcher.ts +32 -6
- package/src/runtime/hidden-handoff.ts +12 -30
- package/src/runtime/important-line-classifier.ts +12 -2
- package/src/runtime/iteration-hooks.ts +25 -15
- package/src/runtime/live-agent-control.ts +55 -7
- package/src/runtime/live-agent-manager.ts +130 -27
- package/src/runtime/live-control-realtime.ts +23 -3
- package/src/runtime/live-irc.ts +4 -1
- package/src/runtime/live-session-health.ts +12 -4
- package/src/runtime/live-session-runtime.ts +379 -117
- package/src/runtime/manifest-cache.ts +28 -12
- package/src/runtime/mcp-proxy.ts +8 -16
- package/src/runtime/metric-parser.ts +1 -5
- package/src/runtime/model-fallback.ts +55 -18
- package/src/runtime/model-resolver.ts +2 -6
- package/src/runtime/model-scope.ts +19 -3
- package/src/runtime/notebook-helpers.ts +60 -62
- package/src/runtime/orphan-worker-registry.ts +37 -26
- package/src/runtime/output-validator.ts +18 -3
- package/src/runtime/overflow-recovery.ts +5 -4
- package/src/runtime/parallel-research.ts +29 -5
- package/src/runtime/parallel-utils.ts +9 -11
- package/src/runtime/path-overlap.ts +150 -0
- package/src/runtime/peer-dep.ts +12 -17
- package/src/runtime/per-write-validator.ts +1 -3
- package/src/runtime/phase-tracker.ts +342 -330
- package/src/runtime/pi-args.ts +26 -8
- package/src/runtime/pi-json-output.ts +1 -1
- package/src/runtime/pi-spawn.ts +30 -19
- package/src/runtime/pipeline-runner.ts +56 -55
- package/src/runtime/plan-templates.ts +5 -6
- package/src/runtime/policy-engine.ts +43 -7
- package/src/runtime/post-checks.ts +12 -4
- package/src/runtime/post-exit-stdio-guard.ts +2 -2
- package/src/runtime/process-lifecycle.ts +20 -10
- package/src/runtime/process-status.ts +16 -5
- package/src/runtime/progress-event-coalescer.ts +2 -1
- package/src/runtime/progress-tracker.ts +103 -103
- package/src/runtime/prose-compressor.ts +9 -11
- package/src/runtime/recovery-recipes.ts +118 -24
- package/src/runtime/replace.ts +25 -10
- package/src/runtime/resilient-edit.ts +10 -25
- package/src/runtime/result-extractor.ts +1 -2
- package/src/runtime/retry-executor.ts +20 -4
- package/src/runtime/retry-runner.ts +26 -50
- package/src/runtime/role-permission.ts +6 -1
- package/src/runtime/run-coalesced-task-group.ts +256 -0
- package/src/runtime/run-drift.ts +14 -15
- package/src/runtime/run-tracker.ts +6 -28
- package/src/runtime/runtime-policy.ts +1 -6
- package/src/runtime/runtime-resolver.ts +80 -15
- package/src/runtime/scheduler.ts +47 -18
- package/src/runtime/semaphore.ts +5 -7
- package/src/runtime/sensitive-paths.ts +2 -1
- package/src/runtime/session-usage.ts +1 -1
- package/src/runtime/settings-store.ts +16 -12
- package/src/runtime/sidechain-output.ts +6 -2
- package/src/runtime/single-agent-compose.ts +1 -4
- package/src/runtime/skill-effectiveness.ts +29 -97
- package/src/runtime/skill-instructions.ts +40 -83
- package/src/runtime/stale-reconciler.ts +73 -197
- package/src/runtime/stream-preview.ts +1 -1
- package/src/runtime/streaming-output.ts +1 -1
- package/src/runtime/subagent-manager.ts +44 -169
- package/src/runtime/subprocess-tool-registry.ts +4 -1
- package/src/runtime/supervisor-contact.ts +10 -5
- package/src/runtime/task-display.ts +19 -5
- package/src/runtime/task-graph-scheduler.ts +95 -21
- package/src/runtime/task-graph.ts +5 -11
- package/src/runtime/task-health.ts +54 -47
- package/src/runtime/task-id.ts +11 -18
- package/src/runtime/task-output-context.ts +265 -81
- package/src/runtime/task-packet.ts +12 -20
- package/src/runtime/task-quality.ts +6 -14
- package/src/runtime/task-runner/context-retrieval.ts +4 -13
- package/src/runtime/task-runner/live-executor.ts +114 -36
- package/src/runtime/task-runner/output-splitter.ts +152 -0
- package/src/runtime/task-runner/progress.ts +50 -12
- package/src/runtime/task-runner/prompt-builder.ts +31 -7
- package/src/runtime/task-runner/prompt-pipeline.ts +31 -7
- package/src/runtime/task-runner/result-utils.ts +3 -1
- package/src/runtime/task-runner/retrieval-orchestrator.ts +310 -0
- package/src/runtime/task-runner/run-projection.ts +27 -8
- package/src/runtime/task-runner/state-helpers.ts +29 -8
- package/src/runtime/task-runner/tail-read.ts +2 -6
- package/src/runtime/task-runner.ts +180 -326
- package/src/runtime/team-runner-artifacts.ts +13 -0
- package/src/runtime/team-runner.ts +456 -974
- package/src/runtime/tool-output-pruner.ts +6 -9
- package/src/runtime/tool-progress.ts +11 -21
- package/src/runtime/verification-gates.ts +33 -24
- package/src/runtime/verification-integrity.ts +1 -4
- package/src/runtime/verification-worktree.ts +62 -12
- package/src/runtime/worker-heartbeat.ts +5 -1
- package/src/runtime/worker-startup.ts +29 -5
- package/src/runtime/workflow-state.ts +17 -9
- package/src/runtime/workspace-lock.ts +30 -35
- package/src/runtime/workspace-tree.ts +20 -32
- package/src/runtime/yield-handler.ts +43 -9
- package/src/runtime/zombie-scanner.ts +5 -4
- package/src/schema/config-schema.ts +266 -172
- package/src/schema/team-tool-schema.ts +29 -74
- package/src/schema/validation-types.ts +25 -17
- package/src/skills/discover-skills.ts +35 -10
- package/src/skills/skill-templates.ts +109 -27
- package/src/skills/validate.ts +26 -8
- package/src/state/active-run-registry.ts +87 -28
- package/src/state/artifact-store.ts +9 -5
- package/src/state/atomic-write-v2.ts +85 -63
- package/src/state/atomic-write.ts +105 -26
- package/src/state/blob-store.ts +47 -20
- package/src/state/contracts.ts +20 -5
- package/src/state/crew-init.ts +5 -22
- package/src/state/decision-ledger.ts +19 -73
- package/src/state/event-log-rotation.ts +41 -15
- package/src/state/event-log.ts +168 -53
- package/src/state/event-reconstructor.ts +11 -1
- package/src/state/gitignore-manager.ts +2 -8
- package/src/state/health-store.ts +57 -57
- package/src/state/hook-instinct-bridge.ts +1 -1
- package/src/state/hook-integrations.ts +1 -1
- package/src/state/instinct-store.ts +17 -5
- package/src/state/jsonl-writer.ts +1 -1
- package/src/state/locks.ts +23 -9
- package/src/state/mailbox.ts +151 -28
- package/src/state/observation-store.ts +20 -14
- package/src/state/run-cache.ts +142 -135
- package/src/state/run-graph.ts +6 -15
- package/src/state/run-metrics.ts +5 -18
- package/src/state/schedule.ts +15 -9
- package/src/state/state-store.ts +129 -45
- package/src/state/task-claims.ts +12 -2
- package/src/state/tiered-eval.ts +52 -43
- package/src/state/types-eval.ts +2 -2
- package/src/state/types.ts +24 -20
- package/src/state/usage.ts +20 -4
- package/src/state/worker-atomic-writer.ts +6 -3
- package/src/subagents/index.ts +2 -2
- package/src/teams/discover-teams.ts +21 -6
- package/src/tools/safe-bash-extension.ts +5 -6
- package/src/tools/safe-bash.ts +10 -11
- package/src/types/new-api-types.ts +6 -10
- package/src/ui/agent-management-overlay.ts +52 -40
- package/src/ui/card-colors.ts +13 -4
- package/src/ui/crew-footer.ts +8 -7
- package/src/ui/crew-select-list.ts +1 -1
- package/src/ui/dashboard-panes/agents-pane.ts +41 -25
- package/src/ui/dashboard-panes/cancellation-pane.ts +1 -1
- package/src/ui/dashboard-panes/capability-pane.ts +32 -15
- package/src/ui/dashboard-panes/health-pane.ts +2 -1
- package/src/ui/dashboard-panes/metrics-pane.ts +4 -1
- package/src/ui/dashboard-panes/progress-pane.ts +12 -9
- package/src/ui/heartbeat-aggregator.ts +15 -4
- package/src/ui/keybinding-map.ts +40 -7
- package/src/ui/live-conversation-overlay.ts +36 -20
- package/src/ui/live-duration.ts +1 -4
- package/src/ui/live-run-sidebar.ts +88 -25
- package/src/ui/loaders.ts +2 -8
- package/src/ui/mascot.ts +20 -36
- package/src/ui/overlays/agent-picker-overlay.ts +11 -3
- package/src/ui/overlays/confirm-overlay.ts +4 -2
- package/src/ui/overlays/help-overlay.ts +25 -14
- package/src/ui/overlays/mailbox-compose-overlay.ts +48 -11
- package/src/ui/overlays/mailbox-compose-preview.ts +20 -5
- package/src/ui/overlays/mailbox-detail-overlay.ts +27 -6
- package/src/ui/pi-ui-compat.ts +7 -7
- package/src/ui/powerbar-publisher.ts +120 -42
- package/src/ui/render-diff.ts +10 -3
- package/src/ui/render-scheduler.ts +12 -4
- package/src/ui/run-action-dispatcher.ts +81 -18
- package/src/ui/run-dashboard.ts +172 -76
- package/src/ui/run-event-bus.ts +59 -37
- package/src/ui/run-snapshot-cache.ts +276 -86
- package/src/ui/settings-overlay.ts +361 -74
- package/src/ui/status-colors.ts +12 -1
- package/src/ui/syntax-highlight.ts +1 -1
- package/src/ui/theme-adapter.ts +16 -14
- package/src/ui/theme-discovery.ts +13 -2
- package/src/ui/tool-progress-formatter.ts +7 -7
- package/src/ui/tool-render.ts +128 -56
- package/src/ui/tool-renderers/brief-mode.ts +45 -27
- package/src/ui/tool-renderers/index.ts +109 -43
- package/src/ui/transcript-cache.ts +32 -6
- package/src/ui/transcript-entries.ts +25 -23
- package/src/ui/transcript-viewer.ts +78 -29
- package/src/ui/widget/index.ts +99 -40
- package/src/ui/widget/widget-formatters.ts +13 -6
- package/src/ui/widget/widget-model.ts +19 -8
- package/src/ui/widget/widget-renderer.ts +23 -13
- package/src/ui/widget/widget-types.ts +1 -1
- package/src/utils/bm25-search.ts +199 -199
- package/src/utils/conflict-detect.ts +22 -21
- package/src/utils/env-filter.ts +14 -7
- package/src/utils/file-coalescer.ts +5 -1
- package/src/utils/fingerprint.ts +3 -6
- package/src/utils/frontmatter.ts +3 -1
- package/src/utils/fs-watch.ts +2 -6
- package/src/utils/gh-protocol.ts +119 -44
- package/src/utils/git.ts +13 -15
- package/src/utils/guards.ts +2 -5
- package/src/utils/ids.ts +9 -2
- package/src/utils/incremental-reader.ts +14 -3
- package/src/utils/internal-error.ts +2 -1
- package/src/utils/names.ts +12 -3
- package/src/utils/paths.ts +49 -5
- package/src/utils/project-detector.ts +2 -2
- package/src/utils/redaction.ts +29 -19
- package/src/utils/resolve-shell.ts +9 -7
- package/src/utils/run-watcher-registry.ts +19 -31
- package/src/utils/safe-paths.ts +45 -24
- package/src/utils/scan-cache.ts +9 -2
- package/src/utils/session-utils.ts +2 -4
- package/src/utils/sleep.ts +12 -5
- package/src/utils/sse-parser.ts +5 -17
- package/src/utils/visual.ts +52 -32
- package/src/workflows/discover-workflows.ts +41 -109
- package/src/workflows/intermediate-store.ts +5 -21
- package/src/workflows/preflight-validator.ts +6 -33
- package/src/workflows/topology-analyzer.ts +5 -21
- package/src/workflows/workflow-config.ts +7 -6
- package/src/worktree/branch-freshness.ts +66 -8
- package/src/worktree/cleanup.ts +130 -20
- package/src/worktree/worktree-manager.ts +212 -69
- package/skills/artifact-analysis-loop/SKILL.md +0 -303
- package/skills/detection-pipeline-design/SKILL.md +0 -286
- package/skills/hunting-investigation-loop/SKILL.md +0 -402
- package/skills/incident-playbook-construction/SKILL.md +0 -384
- package/skills/security-review/SKILL.md +0 -561
- package/skills/threat-hypothesis-framework/SKILL.md +0 -176
- package/skills/ui-render-performance/SKILL.md +0 -58
- /package/docs/{followup-review-round3-2026-05-12.md → archive/followup-review-round3-2026-05-12.md} +0 -0
- /package/docs/{followup-review-round4-2026-05-13.md → archive/followup-review-round4-2026-05-13.md} +0 -0
- /package/docs/{pi-crew-bugs.md → archive/pi-crew-bugs.md} +0 -0
- /package/docs/{pi-crew-test-final.md → archive/pi-crew-test-final.md} +0 -0
- /package/docs/{pi-crew-test-results.md → archive/pi-crew-test-results.md} +0 -0
- /package/docs/{pi-crew-test-round2.md → archive/pi-crew-test-round2.md} +0 -0
- /package/docs/{pi-crew-test-round4.md → archive/pi-crew-test-round4.md} +0 -0
- /package/docs/{pi-crew-test-round5.md → archive/pi-crew-test-round5.md} +0 -0
- /package/docs/{pi-crew-test-round6.md → archive/pi-crew-test-round6.md} +0 -0
- /package/docs/{pi-crew-v0.5.10-audit-fix-plan.md → archive/pi-crew-v0.5.10-audit-fix-plan.md} +0 -0
- /package/docs/{pi-crew-v0.5.11-audit-fix-plan.md → archive/pi-crew-v0.5.11-audit-fix-plan.md} +0 -0
- /package/docs/{pi-crew-v0.5.12-audit-fix-plan.md → archive/pi-crew-v0.5.12-audit-fix-plan.md} +0 -0
- /package/docs/{pi-crew-v0.5.13-audit-fix-plan.md → archive/pi-crew-v0.5.13-audit-fix-plan.md} +0 -0
- /package/docs/{pi-crew-v0.5.14-audit-fix-plan.md → archive/pi-crew-v0.5.14-audit-fix-plan.md} +0 -0
- /package/docs/{pi-crew-v0.5.16-audit-fix-plan.md → archive/pi-crew-v0.5.16-audit-fix-plan.md} +0 -0
- /package/docs/{pi-crew-v0.5.17-audit-fix-plan.md → archive/pi-crew-v0.5.17-audit-fix-plan.md} +0 -0
- /package/docs/{pi-crew-v0.5.5-audit-fix-plan.md → archive/pi-crew-v0.5.5-audit-fix-plan.md} +0 -0
- /package/docs/{pi-crew-v0.5.9-audit-fix-plan.md → archive/pi-crew-v0.5.9-audit-fix-plan.md} +0 -0
- /package/docs/{pi-mono-opportunities.md → archive/pi-mono-opportunities.md} +0 -0
- /package/docs/{pi-mono-review.md → archive/pi-mono-review.md} +0 -0
- /package/docs/{pi-subagent4-comparison.md → archive/pi-subagent4-comparison.md} +0 -0
- /package/docs/{pi-subagents3-deep-analysis.md → archive/pi-subagents3-deep-analysis.md} +0 -0
|
@@ -2,9 +2,13 @@ import type { ExtensionAPI, ExtensionCommandContext, ExtensionContext } from "@e
|
|
|
2
2
|
import { loadConfig } from "../../config/config.ts";
|
|
3
3
|
// Lazy-loaded: team-tool.ts pulls in entire runtime chain (1.4s+).
|
|
4
4
|
import type { handleTeamTool as HandleTeamToolFn } from "../team-tool.ts";
|
|
5
|
+
|
|
5
6
|
let _cachedHandleTeamTool: typeof HandleTeamToolFn | undefined;
|
|
6
7
|
let _handleTeamToolPromise: Promise<typeof HandleTeamToolFn> | undefined;
|
|
7
|
-
async function handleTeamTool(
|
|
8
|
+
async function handleTeamTool(
|
|
9
|
+
params: Parameters<typeof HandleTeamToolFn>[0],
|
|
10
|
+
ctx: Parameters<typeof HandleTeamToolFn>[1],
|
|
11
|
+
): Promise<Awaited<ReturnType<typeof HandleTeamToolFn>>> {
|
|
8
12
|
if (!_cachedHandleTeamTool) {
|
|
9
13
|
if (!_handleTeamToolPromise) {
|
|
10
14
|
_handleTeamToolPromise = import("../team-tool.ts").then((mod) => {
|
|
@@ -17,41 +21,55 @@ async function handleTeamTool(params: Parameters<typeof HandleTeamToolFn>[0], ct
|
|
|
17
21
|
}
|
|
18
22
|
return _cachedHandleTeamTool(params, ctx);
|
|
19
23
|
}
|
|
20
|
-
|
|
21
|
-
import
|
|
22
|
-
import { handleTeamManagerCommand } from "../team-manager-command.ts";
|
|
23
|
-
import { loadRunManifestById } from "../../state/state-store.ts";
|
|
24
|
-
import type { TeamRunManifest } from "../../state/types.ts";
|
|
25
|
-
import { readCrewAgents } from "../../runtime/crew-agent-records.ts";
|
|
26
|
-
import { suggestRunIds, suggestTaskIds, suggestTeams } from "../command-completions.ts";
|
|
24
|
+
|
|
25
|
+
import * as fs from "node:fs";
|
|
27
26
|
import * as path from "node:path";
|
|
28
|
-
// Heavy UI modules — lazy-loaded because they're only used in /crew commands.
|
|
29
|
-
// RunDashboard (288ms), DurableTextViewer (658ms), Overlays are unnecessary at Pi startup.
|
|
30
|
-
import type { RunDashboard as RunDashboardType, RunDashboardSelection } from "../../ui/run-dashboard.ts";
|
|
31
|
-
import type { DurableTextViewer as DurableTextViewerType } from "../../ui/transcript-viewer.ts";
|
|
32
|
-
import type { ConfirmOverlay as ConfirmOverlayType, ConfirmOptions } from "../../ui/overlays/confirm-overlay.ts";
|
|
33
|
-
import type { MailboxDetailOverlay as MailboxDetailOverlayType, MailboxAction } from "../../ui/overlays/mailbox-detail-overlay.ts";
|
|
34
|
-
import type { MailboxComposeOverlay as MailboxComposeOverlayType, MailboxComposeResult } from "../../ui/overlays/mailbox-compose-overlay.ts";
|
|
35
|
-
import type { AgentPickerOverlay as AgentPickerOverlayType } from "../../ui/overlays/agent-picker-overlay.ts";
|
|
36
|
-
import type { AnimatedMascot as AnimatedMascotType } from "../../ui/mascot.ts";
|
|
37
|
-
// Eagerly import lightweight modules
|
|
38
|
-
import { dispatchDiagnosticExport, dispatchHealthRecovery, dispatchKillStaleWorkers, dispatchMailboxAck, dispatchMailboxAckAll, dispatchMailboxCompose, dispatchMailboxNudge } from "../../ui/run-action-dispatcher.ts";
|
|
39
27
|
import { DEFAULT_UI } from "../../config/defaults.ts";
|
|
28
|
+
import type { MetricRegistry } from "../../observability/metric-registry.ts";
|
|
29
|
+
import { readCrewAgents } from "../../runtime/crew-agent-records.ts";
|
|
40
30
|
import { listRecentDiagnostic } from "../../runtime/diagnostic-export.ts";
|
|
41
|
-
import { commandText, notifyCommandResult, parseRunArgs, parseScalar, pushUnset, setNestedConfig } from "./command-utils.ts";
|
|
42
|
-
import { openTranscriptViewer, selectAgentTask, openLiveConversation } from "./viewers.ts";
|
|
43
31
|
import { getBuiltinTemplates, instantiateTemplate, listTemplates } from "../../skills/skill-templates.ts";
|
|
44
|
-
import
|
|
45
|
-
import {
|
|
32
|
+
import { loadRunManifestById } from "../../state/state-store.ts";
|
|
33
|
+
import type { TeamRunManifest } from "../../state/types.ts";
|
|
34
|
+
import type { AnimatedMascot as AnimatedMascotType } from "../../ui/mascot.ts";
|
|
35
|
+
import type { AgentPickerOverlay as AgentPickerOverlayType } from "../../ui/overlays/agent-picker-overlay.ts";
|
|
36
|
+
import type { ConfirmOptions, ConfirmOverlay as ConfirmOverlayType } from "../../ui/overlays/confirm-overlay.ts";
|
|
37
|
+
import type {
|
|
38
|
+
MailboxComposeOverlay as MailboxComposeOverlayType,
|
|
39
|
+
MailboxComposeResult,
|
|
40
|
+
} from "../../ui/overlays/mailbox-compose-overlay.ts";
|
|
41
|
+
import type { MailboxAction, MailboxDetailOverlay as MailboxDetailOverlayType } from "../../ui/overlays/mailbox-detail-overlay.ts";
|
|
46
42
|
import { requestRenderTarget } from "../../ui/pi-ui-compat.ts";
|
|
43
|
+
// Eagerly import lightweight modules
|
|
44
|
+
import {
|
|
45
|
+
dispatchDiagnosticExport,
|
|
46
|
+
dispatchHealthRecovery,
|
|
47
|
+
dispatchKillStaleWorkers,
|
|
48
|
+
dispatchMailboxAck,
|
|
49
|
+
dispatchMailboxAckAll,
|
|
50
|
+
dispatchMailboxCompose,
|
|
51
|
+
dispatchMailboxNudge,
|
|
52
|
+
} from "../../ui/run-action-dispatcher.ts";
|
|
53
|
+
// Heavy UI modules — lazy-loaded because they're only used in /crew commands.
|
|
54
|
+
// RunDashboard (288ms), DurableTextViewer (658ms), Overlays are unnecessary at Pi startup.
|
|
55
|
+
import type { RunDashboardSelection, RunDashboard as RunDashboardType } from "../../ui/run-dashboard.ts";
|
|
47
56
|
import type { createRunSnapshotCache } from "../../ui/run-snapshot-cache.ts";
|
|
48
|
-
import type {
|
|
57
|
+
import type { DurableTextViewer as DurableTextViewerType } from "../../ui/transcript-viewer.ts";
|
|
58
|
+
import { printTimings, time } from "../../utils/timings.ts";
|
|
59
|
+
import { suggestRunIds, suggestTaskIds, suggestTeams } from "../command-completions.ts";
|
|
60
|
+
import { piTeamsHelp } from "../help.ts";
|
|
61
|
+
import { handleTeamManagerCommand } from "../team-manager-command.ts";
|
|
62
|
+
import { withSessionId } from "../team-tool/context.ts";
|
|
63
|
+
import { commandText, notifyCommandResult, parseRunArgs, parseScalar, pushUnset, setNestedConfig } from "./command-utils.ts";
|
|
64
|
+
import { openLiveConversation, openTranscriptViewer, selectAgentTask } from "./viewers.ts";
|
|
49
65
|
|
|
50
66
|
export interface RegisterTeamCommandsDeps {
|
|
51
67
|
startForegroundRun: (ctx: ExtensionContext, runner: (signal?: AbortSignal) => Promise<void>, runId?: string) => void;
|
|
52
68
|
abortForegroundRun: (runId: string) => boolean;
|
|
53
69
|
openLiveSidebar: (ctx: ExtensionContext, runId: string) => void;
|
|
54
|
-
getManifestCache: (cwd: string) => {
|
|
70
|
+
getManifestCache: (cwd: string) => {
|
|
71
|
+
list(max?: number): TeamRunManifest[];
|
|
72
|
+
};
|
|
55
73
|
getRunSnapshotCache?: (cwd: string) => ReturnType<typeof createRunSnapshotCache>;
|
|
56
74
|
getMetricRegistry?: () => MetricRegistry | undefined;
|
|
57
75
|
dismissNotifications?: () => void;
|
|
@@ -59,15 +77,17 @@ export interface RegisterTeamCommandsDeps {
|
|
|
59
77
|
|
|
60
78
|
// Lazy-loaded UI module cache — avoids importing 900ms+ of UI at Pi startup.
|
|
61
79
|
// These modules are only needed when user invokes /crew commands.
|
|
62
|
-
let _uiCache:
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
80
|
+
let _uiCache:
|
|
81
|
+
| {
|
|
82
|
+
RunDashboard: typeof RunDashboardType;
|
|
83
|
+
DurableTextViewer: typeof DurableTextViewerType;
|
|
84
|
+
ConfirmOverlay: typeof ConfirmOverlayType;
|
|
85
|
+
MailboxDetailOverlay: typeof MailboxDetailOverlayType;
|
|
86
|
+
MailboxComposeOverlay: typeof MailboxComposeOverlayType;
|
|
87
|
+
AgentPickerOverlay: typeof AgentPickerOverlayType;
|
|
88
|
+
AnimatedMascot: typeof AnimatedMascotType;
|
|
89
|
+
}
|
|
90
|
+
| undefined;
|
|
71
91
|
let _uiCachePromise: Promise<NonNullable<typeof _uiCache>> | undefined;
|
|
72
92
|
async function ui(): Promise<NonNullable<typeof _uiCache>> {
|
|
73
93
|
if (!_uiCache) {
|
|
@@ -103,13 +123,26 @@ async function ui(): Promise<NonNullable<typeof _uiCache>> {
|
|
|
103
123
|
async function openConfirm(ctx: ExtensionCommandContext, options: ConfirmOptions): Promise<boolean> {
|
|
104
124
|
if (!ctx.hasUI) return false;
|
|
105
125
|
const { ConfirmOverlay } = await ui();
|
|
106
|
-
return await ctx.ui.custom<boolean>((_tui, theme, _keybindings, done) => new ConfirmOverlay(options, done, theme), {
|
|
126
|
+
return await ctx.ui.custom<boolean>((_tui, theme, _keybindings, done) => new ConfirmOverlay(options, done, theme), {
|
|
127
|
+
overlay: true,
|
|
128
|
+
overlayOptions: { width: 64, maxHeight: "70%", anchor: "center" },
|
|
129
|
+
});
|
|
107
130
|
}
|
|
108
131
|
|
|
109
132
|
async function handleMailboxDashboardAction(ctx: ExtensionCommandContext, runId: string): Promise<void> {
|
|
110
133
|
if (!ctx.hasUI) return;
|
|
111
134
|
const { MailboxDetailOverlay } = await ui();
|
|
112
|
-
const action = await ctx.ui.custom<MailboxAction | undefined>(
|
|
135
|
+
const action = await ctx.ui.custom<MailboxAction | undefined>(
|
|
136
|
+
(_tui, theme, _keybindings, done) => new MailboxDetailOverlay({ runId, cwd: ctx.cwd, done, theme }),
|
|
137
|
+
{
|
|
138
|
+
overlay: true,
|
|
139
|
+
overlayOptions: {
|
|
140
|
+
width: "90%",
|
|
141
|
+
maxHeight: "85%",
|
|
142
|
+
anchor: "center",
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
);
|
|
113
146
|
if (!action || action.type === "close") return;
|
|
114
147
|
let resultMessage: string | undefined;
|
|
115
148
|
let ok = true;
|
|
@@ -118,14 +151,29 @@ async function handleMailboxDashboardAction(ctx: ExtensionCommandContext, runId:
|
|
|
118
151
|
ok = result.ok;
|
|
119
152
|
resultMessage = result.message;
|
|
120
153
|
} else if (action.type === "ackAll") {
|
|
121
|
-
const confirmed = await openConfirm(ctx, {
|
|
154
|
+
const confirmed = await openConfirm(ctx, {
|
|
155
|
+
title: "Acknowledge all unread messages?",
|
|
156
|
+
body: "This cannot be undone. Y=ack all, N=cancel.",
|
|
157
|
+
dangerLevel: "medium",
|
|
158
|
+
defaultAction: "cancel",
|
|
159
|
+
});
|
|
122
160
|
if (!confirmed) return;
|
|
123
161
|
const result = await dispatchMailboxAckAll(ctx as ExtensionContext, runId);
|
|
124
162
|
ok = result.ok;
|
|
125
163
|
resultMessage = result.message;
|
|
126
164
|
} else if (action.type === "compose") {
|
|
127
165
|
const { MailboxComposeOverlay } = await ui();
|
|
128
|
-
const compose = await ctx.ui.custom<MailboxComposeResult>(
|
|
166
|
+
const compose = await ctx.ui.custom<MailboxComposeResult>(
|
|
167
|
+
(_tui, theme, _keybindings, done) => new MailboxComposeOverlay({ done, theme }),
|
|
168
|
+
{
|
|
169
|
+
overlay: true,
|
|
170
|
+
overlayOptions: {
|
|
171
|
+
width: "90%",
|
|
172
|
+
maxHeight: "85%",
|
|
173
|
+
anchor: "center",
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
);
|
|
129
177
|
if (compose.type === "cancel") return;
|
|
130
178
|
const result = await dispatchMailboxCompose(ctx as ExtensionContext, runId, compose.payload);
|
|
131
179
|
ok = result.ok;
|
|
@@ -134,11 +182,32 @@ async function handleMailboxDashboardAction(ctx: ExtensionCommandContext, runId:
|
|
|
134
182
|
let agentId = action.agentId;
|
|
135
183
|
if (!agentId) {
|
|
136
184
|
const { AgentPickerOverlay } = await ui();
|
|
137
|
-
const picked = await ctx.ui.custom<{ agentId: string } | undefined>(
|
|
185
|
+
const picked = await ctx.ui.custom<{ agentId: string } | undefined>(
|
|
186
|
+
(_tui, theme, _keybindings, done) =>
|
|
187
|
+
new AgentPickerOverlay({
|
|
188
|
+
cwd: ctx.cwd,
|
|
189
|
+
runId,
|
|
190
|
+
done,
|
|
191
|
+
theme,
|
|
192
|
+
}),
|
|
193
|
+
{
|
|
194
|
+
overlay: true,
|
|
195
|
+
overlayOptions: {
|
|
196
|
+
width: 72,
|
|
197
|
+
maxHeight: "75%",
|
|
198
|
+
anchor: "center",
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
);
|
|
138
202
|
agentId = picked?.agentId;
|
|
139
203
|
}
|
|
140
204
|
if (!agentId) return;
|
|
141
|
-
const result = await dispatchMailboxNudge(
|
|
205
|
+
const result = await dispatchMailboxNudge(
|
|
206
|
+
ctx as ExtensionContext,
|
|
207
|
+
runId,
|
|
208
|
+
agentId,
|
|
209
|
+
"Please report your current status, blocker, or smallest next step.",
|
|
210
|
+
);
|
|
142
211
|
ok = result.ok;
|
|
143
212
|
resultMessage = result.message;
|
|
144
213
|
}
|
|
@@ -171,55 +240,77 @@ export async function openTeamSettingsOverlay(ctx: ExtensionContext): Promise<vo
|
|
|
171
240
|
]);
|
|
172
241
|
const loaded = loadConfig(ctx.cwd);
|
|
173
242
|
const config = loaded.config as Record<string, unknown>;
|
|
174
|
-
await ctx.ui.custom<undefined>(
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
// Action callbacks (Pi theme switch) write to a different store
|
|
193
|
-
// than pi-crew config (e.g. ~/.pi/agent/settings.json).
|
|
194
|
-
try {
|
|
195
|
-
if (action === "piTheme" && typeof value === "string") {
|
|
196
|
-
// Live theme switch: ctx.ui.setTheme() swaps the global theme,
|
|
197
|
-
// persists it to settings.json, and triggers a UI redraw — no
|
|
198
|
-
// restart needed. Falls back to file-write + restart hint if
|
|
199
|
-
// the live API is unavailable (e.g. non-TUI mode).
|
|
200
|
-
if (typeof ctx.ui.setTheme === "function") {
|
|
201
|
-
const res = ctx.ui.setTheme(value);
|
|
202
|
-
if (res.success) {
|
|
203
|
-
ctx.ui.notify(`Theme: ${value} (applied live)`, "info");
|
|
243
|
+
await ctx.ui.custom<undefined>(
|
|
244
|
+
(_tui, _theme, _keybindings, done) => {
|
|
245
|
+
const theme = asCrewTheme(_theme);
|
|
246
|
+
const { overlay } = createSettingsOverlay(
|
|
247
|
+
config,
|
|
248
|
+
theme,
|
|
249
|
+
(id: string, value: unknown) => {
|
|
250
|
+
try {
|
|
251
|
+
const patch: Record<string, unknown> = {};
|
|
252
|
+
const keys = id.split(".");
|
|
253
|
+
let target: Record<string, unknown> = patch;
|
|
254
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
255
|
+
if (!target[keys[i]!] || typeof target[keys[i]!] !== "object") target[keys[i]!] = {};
|
|
256
|
+
target = target[keys[i]!] as Record<string, unknown>;
|
|
257
|
+
}
|
|
258
|
+
target[keys[keys.length - 1]!] = value;
|
|
259
|
+
if (value === undefined) {
|
|
260
|
+
updateConfig({}, { unsetPaths: [id] });
|
|
204
261
|
} else {
|
|
205
|
-
|
|
206
|
-
const { setPiTheme } = await import("../../ui/theme-discovery.ts");
|
|
207
|
-
setPiTheme(value);
|
|
208
|
-
ctx.ui.notify(`Theme saved as '${value}' but failed to apply: ${res.error ?? "unknown"}. Restart Pi.`, "warning");
|
|
262
|
+
updateConfig(parseConfig(patch));
|
|
209
263
|
}
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
const { setPiTheme } = await import("../../ui/theme-discovery.ts");
|
|
213
|
-
setPiTheme(value);
|
|
214
|
-
ctx.ui.notify(`Pi theme set to '${value}'. Restart Pi to apply.`, "info");
|
|
264
|
+
} catch (error) {
|
|
265
|
+
ctx.ui.notify(`Failed to save: ${error instanceof Error ? error.message : String(error)}`, "error");
|
|
215
266
|
}
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
267
|
+
},
|
|
268
|
+
() => done(undefined),
|
|
269
|
+
async (action: string, value: unknown) => {
|
|
270
|
+
// Action callbacks (Pi theme switch) write to a different store
|
|
271
|
+
// than pi-crew config (e.g. ~/.pi/agent/settings.json).
|
|
272
|
+
try {
|
|
273
|
+
if (action === "piTheme" && typeof value === "string") {
|
|
274
|
+
// Live theme switch: ctx.ui.setTheme() swaps the global theme,
|
|
275
|
+
// persists it to settings.json, and triggers a UI redraw — no
|
|
276
|
+
// restart needed. Falls back to file-write + restart hint if
|
|
277
|
+
// the live API is unavailable (e.g. non-TUI mode).
|
|
278
|
+
if (typeof ctx.ui.setTheme === "function") {
|
|
279
|
+
const res = ctx.ui.setTheme(value);
|
|
280
|
+
if (res.success) {
|
|
281
|
+
ctx.ui.notify(`Theme: ${value} (applied live)`, "info");
|
|
282
|
+
} else {
|
|
283
|
+
// LAZY: defer dynamic import of ../../ui/theme-discovery.ts to its call site.
|
|
284
|
+
const { setPiTheme } = await import("../../ui/theme-discovery.ts");
|
|
285
|
+
setPiTheme(value);
|
|
286
|
+
ctx.ui.notify(
|
|
287
|
+
`Theme saved as '${value}' but failed to apply: ${res.error ?? "unknown"}. Restart Pi.`,
|
|
288
|
+
"warning",
|
|
289
|
+
);
|
|
290
|
+
}
|
|
291
|
+
} else {
|
|
292
|
+
// LAZY: defer dynamic import of ../../ui/theme-discovery.ts to its call site.
|
|
293
|
+
const { setPiTheme } = await import("../../ui/theme-discovery.ts");
|
|
294
|
+
setPiTheme(value);
|
|
295
|
+
ctx.ui.notify(`Pi theme set to '${value}'. Restart Pi to apply.`, "info");
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
} catch (error) {
|
|
299
|
+
ctx.ui.notify(`Failed: ${error instanceof Error ? error.message : String(error)}`, "error");
|
|
300
|
+
}
|
|
301
|
+
},
|
|
302
|
+
);
|
|
303
|
+
return overlay;
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
overlay: true,
|
|
307
|
+
overlayOptions: {
|
|
308
|
+
width: "90%",
|
|
309
|
+
maxHeight: "85%",
|
|
310
|
+
anchor: "center",
|
|
311
|
+
},
|
|
312
|
+
},
|
|
313
|
+
);
|
|
223
314
|
}
|
|
224
315
|
|
|
225
316
|
async function handleHealthDashboardAction(ctx: ExtensionCommandContext, selection: RunDashboardSelection): Promise<void> {
|
|
@@ -233,14 +324,24 @@ async function handleHealthDashboardAction(ctx: ExtensionCommandContext, selecti
|
|
|
233
324
|
depsNotify(ctx, "Recovery is only available for foreground runs.", "warning");
|
|
234
325
|
return;
|
|
235
326
|
}
|
|
236
|
-
const confirmed = await openConfirm(ctx, {
|
|
327
|
+
const confirmed = await openConfirm(ctx, {
|
|
328
|
+
title: "Interrupt foreground run?",
|
|
329
|
+
body: "Tasks may be marked failed. Y=interrupt, N=cancel.",
|
|
330
|
+
dangerLevel: "high",
|
|
331
|
+
defaultAction: "cancel",
|
|
332
|
+
});
|
|
237
333
|
if (!confirmed) return;
|
|
238
334
|
const result = await dispatchHealthRecovery(ctx as ExtensionContext, selection.runId);
|
|
239
335
|
depsNotify(ctx, result.message, result.ok ? "info" : "error");
|
|
240
336
|
return;
|
|
241
337
|
}
|
|
242
338
|
if (selection.action === "health-kill-stale") {
|
|
243
|
-
const confirmed = await openConfirm(ctx, {
|
|
339
|
+
const confirmed = await openConfirm(ctx, {
|
|
340
|
+
title: "Mark stale workers dead?",
|
|
341
|
+
body: "This updates worker heartbeat state. Y=mark dead, N=cancel.",
|
|
342
|
+
dangerLevel: "medium",
|
|
343
|
+
defaultAction: "cancel",
|
|
344
|
+
});
|
|
244
345
|
if (!confirmed) return;
|
|
245
346
|
const result = await dispatchKillStaleWorkers(ctx as ExtensionContext, selection.runId);
|
|
246
347
|
depsNotify(ctx, result.message, result.ok ? "info" : "error");
|
|
@@ -250,10 +351,16 @@ async function handleHealthDashboardAction(ctx: ExtensionCommandContext, selecti
|
|
|
250
351
|
const diagDir = path.join(loaded.manifest.artifactsRoot, "diagnostic");
|
|
251
352
|
const recent = listRecentDiagnostic(diagDir, 60_000);
|
|
252
353
|
if (recent) {
|
|
253
|
-
const confirmed = await openConfirm(ctx, {
|
|
354
|
+
const confirmed = await openConfirm(ctx, {
|
|
355
|
+
title: "Recent diagnostic exists",
|
|
356
|
+
body: `File ${recent} was created <1min ago. Export another diagnostic?`,
|
|
357
|
+
defaultAction: "cancel",
|
|
358
|
+
});
|
|
254
359
|
if (!confirmed) return;
|
|
255
360
|
}
|
|
256
|
-
const result = await dispatchDiagnosticExport(ctx as ExtensionContext, selection.runId, {
|
|
361
|
+
const result = await dispatchDiagnosticExport(ctx as ExtensionContext, selection.runId, {
|
|
362
|
+
registry: depsRef?.getMetricRegistry?.(),
|
|
363
|
+
});
|
|
257
364
|
depsNotify(ctx, result.message, result.ok ? "info" : "error");
|
|
258
365
|
}
|
|
259
366
|
}
|
|
@@ -292,7 +399,34 @@ export async function openTeamDashboard(ctx: ExtensionContext): Promise<void> {
|
|
|
292
399
|
const rightPanel = (uiConfig?.dashboardPlacement ?? DEFAULT_UI.dashboardPlacement) === "right";
|
|
293
400
|
const width = rightPanel ? Math.min(90, Math.max(40, uiConfig?.dashboardWidth ?? DEFAULT_UI.dashboardWidth)) : "90%";
|
|
294
401
|
const { RunDashboard } = await ui();
|
|
295
|
-
const selection = await cmdCtx.ui.custom<RunDashboardSelection | undefined>(
|
|
402
|
+
const selection = await cmdCtx.ui.custom<RunDashboardSelection | undefined>(
|
|
403
|
+
(tui, theme, _keybindings, done) =>
|
|
404
|
+
new RunDashboard(runs, done, theme, {
|
|
405
|
+
placement: rightPanel ? "right" : "center",
|
|
406
|
+
showModel: uiConfig?.showModel,
|
|
407
|
+
showTokens: uiConfig?.showTokens,
|
|
408
|
+
showTools: uiConfig?.showTools,
|
|
409
|
+
snapshotCache: deps.getRunSnapshotCache?.(cmdCtx.cwd),
|
|
410
|
+
runProvider: () => deps.getManifestCache(cmdCtx.cwd).list(50),
|
|
411
|
+
registry: deps.getMetricRegistry?.(),
|
|
412
|
+
workspaceId: sessionId,
|
|
413
|
+
requestRender: () => requestRenderTarget(tui),
|
|
414
|
+
}),
|
|
415
|
+
{
|
|
416
|
+
overlay: true,
|
|
417
|
+
overlayOptions: rightPanel
|
|
418
|
+
? {
|
|
419
|
+
width,
|
|
420
|
+
minWidth: 40,
|
|
421
|
+
maxHeight: "100%",
|
|
422
|
+
anchor: "top-right",
|
|
423
|
+
offsetX: 0,
|
|
424
|
+
offsetY: 0,
|
|
425
|
+
margin: { top: 0, right: 0, bottom: 0, left: 0 },
|
|
426
|
+
}
|
|
427
|
+
: { width, maxHeight: "90%", anchor: "center", margin: 2 },
|
|
428
|
+
},
|
|
429
|
+
);
|
|
296
430
|
if (!selection) return;
|
|
297
431
|
if (selection.action === "reload") continue;
|
|
298
432
|
if (selection.action === "notifications-dismiss") {
|
|
@@ -305,16 +439,102 @@ export async function openTeamDashboard(ctx: ExtensionContext): Promise<void> {
|
|
|
305
439
|
deps.getRunSnapshotCache?.(cmdCtx.cwd).invalidate(selection.runId);
|
|
306
440
|
continue;
|
|
307
441
|
}
|
|
308
|
-
if (
|
|
442
|
+
if (
|
|
443
|
+
selection.action === "health-recovery" ||
|
|
444
|
+
selection.action === "health-kill-stale" ||
|
|
445
|
+
selection.action === "health-diagnostic-export"
|
|
446
|
+
) {
|
|
309
447
|
await handleHealthDashboardAction(cmdCtx, selection);
|
|
310
448
|
deps.getRunSnapshotCache?.(cmdCtx.cwd).invalidate(selection.runId);
|
|
311
449
|
continue;
|
|
312
450
|
}
|
|
313
|
-
if (selection.action === "agent-transcript" && await openTranscriptViewer(cmdCtx, selection.runId)) continue;
|
|
314
|
-
if (selection.action === "agent-live" && await openLiveConversation(cmdCtx, selection.runId)) continue;
|
|
315
|
-
if (selection.action === "agent-live") {
|
|
316
|
-
|
|
317
|
-
|
|
451
|
+
if (selection.action === "agent-transcript" && (await openTranscriptViewer(cmdCtx, selection.runId))) continue;
|
|
452
|
+
if (selection.action === "agent-live" && (await openLiveConversation(cmdCtx, selection.runId))) continue;
|
|
453
|
+
if (selection.action === "agent-live") {
|
|
454
|
+
await notifyCommandResult(
|
|
455
|
+
cmdCtx,
|
|
456
|
+
commandText({
|
|
457
|
+
content: [
|
|
458
|
+
{
|
|
459
|
+
type: "text",
|
|
460
|
+
text: "No live agent found for this run.",
|
|
461
|
+
},
|
|
462
|
+
],
|
|
463
|
+
}),
|
|
464
|
+
);
|
|
465
|
+
continue;
|
|
466
|
+
}
|
|
467
|
+
const result =
|
|
468
|
+
selection.action === "api"
|
|
469
|
+
? await handleTeamTool(
|
|
470
|
+
{
|
|
471
|
+
action: "api",
|
|
472
|
+
runId: selection.runId,
|
|
473
|
+
config: { operation: "read-manifest" },
|
|
474
|
+
},
|
|
475
|
+
teamCommandContext(cmdCtx),
|
|
476
|
+
)
|
|
477
|
+
: selection.action === "agents"
|
|
478
|
+
? await handleTeamTool(
|
|
479
|
+
{
|
|
480
|
+
action: "api",
|
|
481
|
+
runId: selection.runId,
|
|
482
|
+
config: { operation: "agent-dashboard" },
|
|
483
|
+
},
|
|
484
|
+
teamCommandContext(cmdCtx),
|
|
485
|
+
)
|
|
486
|
+
: selection.action === "mailbox"
|
|
487
|
+
? await handleTeamTool(
|
|
488
|
+
{
|
|
489
|
+
action: "api",
|
|
490
|
+
runId: selection.runId,
|
|
491
|
+
config: { operation: "read-mailbox" },
|
|
492
|
+
},
|
|
493
|
+
teamCommandContext(cmdCtx),
|
|
494
|
+
)
|
|
495
|
+
: selection.action === "agent-events"
|
|
496
|
+
? await handleTeamTool(
|
|
497
|
+
{
|
|
498
|
+
action: "api",
|
|
499
|
+
runId: selection.runId,
|
|
500
|
+
config: {
|
|
501
|
+
operation: "read-agent-events",
|
|
502
|
+
limit: 50,
|
|
503
|
+
},
|
|
504
|
+
},
|
|
505
|
+
teamCommandContext(cmdCtx),
|
|
506
|
+
)
|
|
507
|
+
: selection.action === "agent-output"
|
|
508
|
+
? await handleTeamTool(
|
|
509
|
+
{
|
|
510
|
+
action: "api",
|
|
511
|
+
runId: selection.runId,
|
|
512
|
+
config: {
|
|
513
|
+
operation: "read-agent-output",
|
|
514
|
+
maxBytes: 32_000,
|
|
515
|
+
},
|
|
516
|
+
},
|
|
517
|
+
teamCommandContext(cmdCtx),
|
|
518
|
+
)
|
|
519
|
+
: selection.action === "agent-transcript"
|
|
520
|
+
? await handleTeamTool(
|
|
521
|
+
{
|
|
522
|
+
action: "api",
|
|
523
|
+
runId: selection.runId,
|
|
524
|
+
config: {
|
|
525
|
+
operation: "read-agent-transcript",
|
|
526
|
+
},
|
|
527
|
+
},
|
|
528
|
+
teamCommandContext(cmdCtx),
|
|
529
|
+
)
|
|
530
|
+
: // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
531
|
+
await handleTeamTool(
|
|
532
|
+
{
|
|
533
|
+
action: selection.action as any,
|
|
534
|
+
runId: selection.runId,
|
|
535
|
+
},
|
|
536
|
+
teamCommandContext(cmdCtx),
|
|
537
|
+
);
|
|
318
538
|
await notifyCommandResult(cmdCtx, commandText(result));
|
|
319
539
|
return;
|
|
320
540
|
}
|
|
@@ -335,7 +555,13 @@ export function registerTeamCommands(pi: ExtensionAPI, deps: RegisterTeamCommand
|
|
|
335
555
|
// Round 13 UX: suggest team names for Tab-completion of the first positional arg.
|
|
336
556
|
getArgumentCompletions: (argumentPrefix: string) => suggestTeams(argumentPrefix),
|
|
337
557
|
handler: async (args: string, ctx: ExtensionCommandContext) => {
|
|
338
|
-
const result = await handleTeamTool(parseRunArgs(args), {
|
|
558
|
+
const result = await handleTeamTool(parseRunArgs(args), {
|
|
559
|
+
...teamCommandContext(ctx),
|
|
560
|
+
metricRegistry: deps.getMetricRegistry?.(),
|
|
561
|
+
startForegroundRun: (runner, runId) => deps.startForegroundRun(ctx as ExtensionContext, runner, runId),
|
|
562
|
+
abortForegroundRun: deps.abortForegroundRun,
|
|
563
|
+
onRunStarted: undefined,
|
|
564
|
+
});
|
|
339
565
|
await notifyCommandResult(ctx, commandText(result));
|
|
340
566
|
},
|
|
341
567
|
});
|
|
@@ -356,7 +582,13 @@ export function registerTeamCommands(pi: ExtensionAPI, deps: RegisterTeamCommand
|
|
|
356
582
|
getArgumentCompletions: (argumentPrefix: string) => suggestRunIds(argumentPrefix),
|
|
357
583
|
handler: async (args: string, ctx: ExtensionCommandContext) => {
|
|
358
584
|
const runId = args.trim() || undefined;
|
|
359
|
-
const result = await handleTeamTool(
|
|
585
|
+
const result = await handleTeamTool(
|
|
586
|
+
{ action, runId },
|
|
587
|
+
{
|
|
588
|
+
...teamCommandContext(ctx),
|
|
589
|
+
getRunSnapshotCache: deps.getRunSnapshotCache,
|
|
590
|
+
},
|
|
591
|
+
);
|
|
360
592
|
await notifyCommandResult(ctx, commandText(result));
|
|
361
593
|
},
|
|
362
594
|
});
|
|
@@ -371,7 +603,13 @@ export function registerTeamCommands(pi: ExtensionAPI, deps: RegisterTeamCommand
|
|
|
371
603
|
await notifyCommandResult(ctx, "Usage: /team-invalidate <runId>");
|
|
372
604
|
return;
|
|
373
605
|
}
|
|
374
|
-
const result = await handleTeamTool(
|
|
606
|
+
const result = await handleTeamTool(
|
|
607
|
+
{ action: "invalidate", runId },
|
|
608
|
+
{
|
|
609
|
+
...teamCommandContext(ctx),
|
|
610
|
+
getRunSnapshotCache: deps.getRunSnapshotCache,
|
|
611
|
+
},
|
|
612
|
+
);
|
|
375
613
|
await notifyCommandResult(ctx, commandText(result));
|
|
376
614
|
},
|
|
377
615
|
});
|
|
@@ -387,7 +625,13 @@ export function registerTeamCommands(pi: ExtensionAPI, deps: RegisterTeamCommand
|
|
|
387
625
|
await notifyCommandResult(ctx, "Usage: /team-retry <runId> [taskId]");
|
|
388
626
|
return;
|
|
389
627
|
}
|
|
390
|
-
const retryResult = await handleTeamTool(
|
|
628
|
+
const retryResult = await handleTeamTool(
|
|
629
|
+
{ action: "retry", runId, taskId },
|
|
630
|
+
{
|
|
631
|
+
...teamCommandContext(ctx),
|
|
632
|
+
getRunSnapshotCache: deps.getRunSnapshotCache,
|
|
633
|
+
},
|
|
634
|
+
);
|
|
391
635
|
await notifyCommandResult(ctx, commandText(retryResult));
|
|
392
636
|
},
|
|
393
637
|
});
|
|
@@ -415,10 +659,20 @@ export function registerTeamCommands(pi: ExtensionAPI, deps: RegisterTeamCommand
|
|
|
415
659
|
const taskId = tokens.shift();
|
|
416
660
|
const prompt = tokens.join(" ") || undefined;
|
|
417
661
|
if (!runId || !taskId || !prompt) {
|
|
418
|
-
await notifyCommandResult(
|
|
662
|
+
await notifyCommandResult(
|
|
663
|
+
ctx,
|
|
664
|
+
"Usage: /team-follow-up <runId> <taskId> <prompt>. Use /team-respond for waiting-task replies.",
|
|
665
|
+
);
|
|
419
666
|
return;
|
|
420
667
|
}
|
|
421
|
-
const result = await handleTeamTool(
|
|
668
|
+
const result = await handleTeamTool(
|
|
669
|
+
{
|
|
670
|
+
action: "api",
|
|
671
|
+
runId,
|
|
672
|
+
config: { operation: "follow-up-agent", taskId, prompt },
|
|
673
|
+
},
|
|
674
|
+
teamCommandContext(ctx),
|
|
675
|
+
);
|
|
422
676
|
await notifyCommandResult(ctx, commandText(result));
|
|
423
677
|
},
|
|
424
678
|
});
|
|
@@ -444,7 +698,8 @@ export function registerTeamCommands(pi: ExtensionAPI, deps: RegisterTeamCommand
|
|
|
444
698
|
});
|
|
445
699
|
|
|
446
700
|
pi.registerCommand("team-goal", {
|
|
447
|
-
description:
|
|
701
|
+
description:
|
|
702
|
+
"Autonomous goal loop control: [start|status|pause|resume|stop|step|clear] [goalId] [--objective=...] [--evaluatorModel=...] [--maxTurns=N]",
|
|
448
703
|
handler: async (args: string, ctx: ExtensionCommandContext) => {
|
|
449
704
|
const tokens = args.trim().split(/\s+/).filter(Boolean);
|
|
450
705
|
const knownSubs = new Set(["start", "status", "pause", "resume", "stop", "step", "clear", "cancel", "reset"]);
|
|
@@ -470,238 +725,475 @@ export function registerTeamCommands(pi: ExtensionAPI, deps: RegisterTeamCommand
|
|
|
470
725
|
},
|
|
471
726
|
});
|
|
472
727
|
|
|
473
|
-
pi.registerCommand("team-metrics", {
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
728
|
+
pi.registerCommand("team-metrics", {
|
|
729
|
+
description: "Show pi-crew metrics snapshot: [filter]",
|
|
730
|
+
handler: async (args: string, ctx: ExtensionCommandContext) => {
|
|
731
|
+
const filter = args.trim() || undefined;
|
|
732
|
+
const result = await handleTeamTool(
|
|
733
|
+
{
|
|
734
|
+
action: "api",
|
|
735
|
+
config: { operation: "metrics-snapshot", filter },
|
|
736
|
+
},
|
|
737
|
+
{
|
|
738
|
+
...teamCommandContext(ctx),
|
|
739
|
+
metricRegistry: deps.getMetricRegistry?.(),
|
|
740
|
+
},
|
|
741
|
+
);
|
|
742
|
+
await notifyCommandResult(ctx, commandText(result));
|
|
743
|
+
},
|
|
744
|
+
});
|
|
745
|
+
|
|
746
|
+
pi.registerCommand("team-imports", {
|
|
747
|
+
description: "List imported pi-crew run bundles",
|
|
748
|
+
handler: async (_args: string, ctx: ExtensionCommandContext) => {
|
|
749
|
+
const result = await handleTeamTool({ action: "imports" }, teamCommandContext(ctx));
|
|
750
|
+
await notifyCommandResult(ctx, commandText(result));
|
|
751
|
+
},
|
|
752
|
+
});
|
|
753
|
+
|
|
754
|
+
pi.registerCommand("team-import", {
|
|
755
|
+
description: "Import a pi-crew run-export.json bundle into local imports",
|
|
756
|
+
handler: async (args: string, ctx: ExtensionCommandContext) => {
|
|
757
|
+
const tokens = args.trim().split(/\s+/).filter(Boolean);
|
|
758
|
+
const pathArg = tokens.find((token) => !token.startsWith("--"));
|
|
759
|
+
const scope = tokens.includes("--user") ? "user" : "project";
|
|
760
|
+
const result = await handleTeamTool({ action: "import", config: { path: pathArg, scope } }, teamCommandContext(ctx));
|
|
761
|
+
await notifyCommandResult(ctx, commandText(result));
|
|
762
|
+
},
|
|
763
|
+
});
|
|
764
|
+
|
|
765
|
+
pi.registerCommand("team-prune", {
|
|
766
|
+
description: "Prune old finished pi-crew runs, keeping the newest N",
|
|
767
|
+
handler: async (args: string, ctx: ExtensionCommandContext) => {
|
|
768
|
+
const tokens = args.trim().split(/\s+/).filter(Boolean);
|
|
769
|
+
const keepToken = tokens.find((token) => token.startsWith("--keep="));
|
|
770
|
+
const keep = keepToken ? Number.parseInt(keepToken.slice("--keep=".length), 10) : undefined;
|
|
771
|
+
const result = await handleTeamTool(
|
|
772
|
+
{
|
|
773
|
+
action: "prune",
|
|
774
|
+
keep,
|
|
775
|
+
confirm: tokens.includes("--confirm"),
|
|
776
|
+
},
|
|
777
|
+
teamCommandContext(ctx),
|
|
778
|
+
);
|
|
779
|
+
await notifyCommandResult(ctx, commandText(result));
|
|
780
|
+
},
|
|
781
|
+
});
|
|
782
|
+
|
|
783
|
+
pi.registerCommand("team-forget", {
|
|
784
|
+
description: "Forget a pi-crew run by deleting its state and artifacts",
|
|
785
|
+
getArgumentCompletions: (argumentPrefix: string) => suggestRunIds(argumentPrefix),
|
|
786
|
+
handler: async (args: string, ctx: ExtensionCommandContext) => {
|
|
787
|
+
const tokens = args.trim().split(/\s+/).filter(Boolean);
|
|
788
|
+
const runId = tokens.find((token) => !token.startsWith("--"));
|
|
789
|
+
const result = await handleTeamTool(
|
|
790
|
+
{
|
|
791
|
+
action: "forget",
|
|
792
|
+
runId,
|
|
793
|
+
force: tokens.includes("--force"),
|
|
794
|
+
confirm: tokens.includes("--confirm"),
|
|
795
|
+
},
|
|
796
|
+
teamCommandContext(ctx),
|
|
797
|
+
);
|
|
798
|
+
await notifyCommandResult(ctx, commandText(result));
|
|
799
|
+
},
|
|
800
|
+
});
|
|
506
801
|
|
|
507
802
|
pi.registerCommand("team-settings", {
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
}
|
|
514
|
-
const result = await handleTeamTool({ action: "settings", config: { args: args.trim() } }, teamCommandContext(ctx));
|
|
515
|
-
await notifyCommandResult(ctx, commandText(result));
|
|
516
|
-
// Live-switch hook: when the text subcommand 'theme <name>' succeeds,
|
|
517
|
-
// also apply the theme live via ctx.ui.setTheme() (no restart). The
|
|
518
|
-
// handler above only writes to settings.json.
|
|
519
|
-
const trimmed = args.trim();
|
|
520
|
-
if (trimmed.startsWith("theme ")) {
|
|
521
|
-
const themeName = trimmed.slice(6).trim();
|
|
522
|
-
if (themeName && typeof ctx.ui.setTheme === "function") {
|
|
523
|
-
const res = ctx.ui.setTheme(themeName);
|
|
524
|
-
if (res.success) ctx.ui.notify(`Theme: ${themeName} (applied live)`, "info");
|
|
525
|
-
else ctx.ui.notify(`Saved but live-switch failed: ${res.error ?? "unknown"}. Restart Pi.`, "warning");
|
|
803
|
+
description: "View or update pi-crew settings: interactive UI or [list|get <key>|set <key> <value>|unset <key>|path|scope]",
|
|
804
|
+
handler: async (args: string, ctx: ExtensionCommandContext) => {
|
|
805
|
+
if (ctx.hasUI && !args.trim()) {
|
|
806
|
+
await openTeamSettingsOverlay(ctx);
|
|
807
|
+
return;
|
|
526
808
|
}
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
809
|
+
const result = await handleTeamTool({ action: "settings", config: { args: args.trim() } }, teamCommandContext(ctx));
|
|
810
|
+
await notifyCommandResult(ctx, commandText(result));
|
|
811
|
+
// Live-switch hook: when the text subcommand 'theme <name>' succeeds,
|
|
812
|
+
// also apply the theme live via ctx.ui.setTheme() (no restart). The
|
|
813
|
+
// handler above only writes to settings.json.
|
|
814
|
+
const trimmed = args.trim();
|
|
815
|
+
if (trimmed.startsWith("theme ")) {
|
|
816
|
+
const themeName = trimmed.slice(6).trim();
|
|
817
|
+
if (themeName && typeof ctx.ui.setTheme === "function") {
|
|
818
|
+
const res = ctx.ui.setTheme(themeName);
|
|
819
|
+
if (res.success) ctx.ui.notify(`Theme: ${themeName} (applied live)`, "info");
|
|
820
|
+
else ctx.ui.notify(`Saved but live-switch failed: ${res.error ?? "unknown"}. Restart Pi.`, "warning");
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
},
|
|
824
|
+
});
|
|
530
825
|
|
|
531
|
-
pi.registerCommand("team-manager", {
|
|
826
|
+
pi.registerCommand("team-manager", {
|
|
827
|
+
description: "Open the pi-crew interactive menu (list/run/status/cleanup/manage resources/doctor)",
|
|
828
|
+
handler: handleTeamManagerCommand,
|
|
829
|
+
});
|
|
532
830
|
// Backward-compat alias: this command was originally registered as "team-cleanup"
|
|
533
831
|
// (the interactive menu predates the runId-targeted cleanup action). Keep both so
|
|
534
832
|
// existing muscle memory + help docs both work.
|
|
535
|
-
pi.registerCommand("team-cleanup-menu", {
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
const
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
833
|
+
pi.registerCommand("team-cleanup-menu", {
|
|
834
|
+
description: "Alias for /team-manager (pi-crew interactive menu)",
|
|
835
|
+
handler: handleTeamManagerCommand,
|
|
836
|
+
});
|
|
837
|
+
|
|
838
|
+
pi.registerCommand("team-result", {
|
|
839
|
+
description: "Open a pi-crew agent result viewer: <runId> [taskId]",
|
|
840
|
+
getArgumentCompletions: async (argumentPrefix: string) => {
|
|
841
|
+
const parts = argumentPrefix.trim().split(/\s+/);
|
|
842
|
+
return parts.length <= 1 ? suggestRunIds(parts[0] ?? "") : suggestTaskIds(parts[0] ?? "", parts[1] ?? "");
|
|
843
|
+
},
|
|
844
|
+
handler: async (args: string, ctx: ExtensionCommandContext) => {
|
|
845
|
+
const [runId, rawTaskId] = args.trim().split(/\s+/).filter(Boolean);
|
|
846
|
+
const selected = await selectAgentTask(ctx, runId, rawTaskId);
|
|
847
|
+
const loaded = selected ? loadRunManifestById(ctx.cwd, selected.runId) : undefined; // NOTE: no withRunLock - best-effort only; concurrent writes may cause inconsistency
|
|
848
|
+
if (ctx.hasUI && loaded) {
|
|
849
|
+
const agent =
|
|
850
|
+
readCrewAgents(loaded.manifest).find((item) => item.taskId === selected?.taskId || item.id === selected?.taskId) ??
|
|
851
|
+
readCrewAgents(loaded.manifest)[0];
|
|
852
|
+
const resultText = agent?.resultArtifactPath
|
|
853
|
+
? commandText(
|
|
854
|
+
await handleTeamTool(
|
|
855
|
+
{
|
|
856
|
+
action: "api",
|
|
857
|
+
runId: selected?.runId ?? "",
|
|
858
|
+
config: {
|
|
859
|
+
operation: "read-agent-output",
|
|
860
|
+
agentId: agent.taskId,
|
|
861
|
+
maxBytes: 64_000,
|
|
862
|
+
},
|
|
863
|
+
},
|
|
864
|
+
teamCommandContext(ctx),
|
|
865
|
+
),
|
|
866
|
+
)
|
|
867
|
+
: "(no result)";
|
|
868
|
+
const { DurableTextViewer } = await ui();
|
|
869
|
+
await ctx.ui.custom<undefined>(
|
|
870
|
+
(_tui, theme, _keybindings, done) =>
|
|
871
|
+
new DurableTextViewer(
|
|
872
|
+
"pi-crew result",
|
|
873
|
+
`${selected?.runId ?? ""}:${agent?.taskId ?? "unknown"}`,
|
|
874
|
+
resultText.split(/\r?\n/),
|
|
875
|
+
theme,
|
|
876
|
+
done,
|
|
877
|
+
),
|
|
878
|
+
{
|
|
879
|
+
overlay: true,
|
|
880
|
+
overlayOptions: {
|
|
881
|
+
width: "90%",
|
|
882
|
+
maxHeight: "85%",
|
|
883
|
+
anchor: "center",
|
|
884
|
+
},
|
|
885
|
+
},
|
|
886
|
+
);
|
|
887
|
+
return;
|
|
888
|
+
}
|
|
889
|
+
const result = await handleTeamTool(
|
|
890
|
+
{
|
|
891
|
+
action: "api",
|
|
892
|
+
runId,
|
|
893
|
+
config: {
|
|
894
|
+
operation: "read-agent-output",
|
|
895
|
+
agentId: rawTaskId,
|
|
896
|
+
maxBytes: 64_000,
|
|
897
|
+
},
|
|
898
|
+
},
|
|
899
|
+
teamCommandContext(ctx),
|
|
900
|
+
);
|
|
594
901
|
await notifyCommandResult(ctx, commandText(result));
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
902
|
+
},
|
|
903
|
+
});
|
|
904
|
+
|
|
905
|
+
pi.registerCommand("team-transcript", {
|
|
906
|
+
description: "Open a pi-crew transcript viewer: <runId> [taskId]",
|
|
907
|
+
getArgumentCompletions: async (argumentPrefix: string) => {
|
|
908
|
+
const parts = argumentPrefix.trim().split(/\s+/);
|
|
909
|
+
return parts.length <= 1 ? suggestRunIds(parts[0] ?? "") : suggestTaskIds(parts[0] ?? "", parts[1] ?? "");
|
|
910
|
+
},
|
|
911
|
+
handler: async (args: string, ctx: ExtensionCommandContext) => {
|
|
912
|
+
const [runId, taskId] = args.trim().split(/\s+/).filter(Boolean);
|
|
913
|
+
if (await openTranscriptViewer(ctx, runId, taskId)) return;
|
|
914
|
+
const result = await handleTeamTool(
|
|
915
|
+
{
|
|
916
|
+
action: "api",
|
|
917
|
+
runId,
|
|
918
|
+
config: {
|
|
919
|
+
operation: "read-agent-transcript",
|
|
920
|
+
agentId: taskId,
|
|
921
|
+
},
|
|
922
|
+
},
|
|
923
|
+
teamCommandContext(ctx),
|
|
924
|
+
);
|
|
925
|
+
await notifyCommandResult(ctx, commandText(result));
|
|
926
|
+
},
|
|
927
|
+
});
|
|
928
|
+
|
|
929
|
+
pi.registerCommand("team-dashboard", {
|
|
930
|
+
description: "Open a pi-crew run dashboard overlay",
|
|
931
|
+
handler: async (_args: string, ctx: ExtensionCommandContext) => {
|
|
932
|
+
await openTeamDashboard(ctx);
|
|
933
|
+
},
|
|
934
|
+
});
|
|
935
|
+
|
|
936
|
+
pi.registerCommand("team-mascot", {
|
|
937
|
+
description: "Show an animated mascot splash",
|
|
938
|
+
handler: async (args: string, ctx: ExtensionCommandContext) => {
|
|
939
|
+
if (!ctx.hasUI) return;
|
|
940
|
+
const tokens = args.trim().split(/\s+/).filter(Boolean);
|
|
941
|
+
const uiConfig = loadConfig(ctx.cwd).config.ui;
|
|
942
|
+
const styleArg = tokens.find((t) => t === "cat" || t === "armin");
|
|
943
|
+
const effectArg = tokens.find((t) =>
|
|
944
|
+
["random", "none", "typewriter", "scanline", "rain", "fade", "crt", "glitch", "dissolve"].includes(t),
|
|
945
|
+
);
|
|
946
|
+
const style = (styleArg as "cat" | "armin" | undefined) ?? uiConfig?.mascotStyle ?? DEFAULT_UI.mascotStyle;
|
|
947
|
+
const effect =
|
|
948
|
+
(effectArg as
|
|
949
|
+
| "random"
|
|
950
|
+
| "none"
|
|
951
|
+
| "typewriter"
|
|
952
|
+
| "scanline"
|
|
953
|
+
| "rain"
|
|
954
|
+
| "fade"
|
|
955
|
+
| "crt"
|
|
956
|
+
| "glitch"
|
|
957
|
+
| "dissolve"
|
|
958
|
+
| undefined) ??
|
|
959
|
+
uiConfig?.mascotEffect ??
|
|
960
|
+
DEFAULT_UI.mascotEffect;
|
|
961
|
+
const { AnimatedMascot } = await ui();
|
|
962
|
+
await ctx.ui.custom<undefined>(
|
|
963
|
+
(tui, theme, _keybindings, done) =>
|
|
964
|
+
new AnimatedMascot(theme, () => done(undefined), {
|
|
965
|
+
frameIntervalMs: style === "armin" ? 33 : 180,
|
|
966
|
+
autoCloseMs: 7000,
|
|
967
|
+
requestRender: () => requestRenderTarget(tui),
|
|
968
|
+
style,
|
|
969
|
+
effect,
|
|
970
|
+
}),
|
|
971
|
+
{
|
|
972
|
+
overlay: true,
|
|
973
|
+
overlayOptions: {
|
|
974
|
+
width: style === "armin" ? 48 : 62,
|
|
975
|
+
maxHeight: "85%",
|
|
976
|
+
anchor: "center",
|
|
977
|
+
},
|
|
978
|
+
},
|
|
979
|
+
);
|
|
980
|
+
},
|
|
981
|
+
});
|
|
982
|
+
|
|
983
|
+
pi.registerCommand("team-init", {
|
|
984
|
+
description: "Initialize pi-crew layout and global config. Use --project-config to write .pi/pi-crew.json.",
|
|
985
|
+
handler: async (args: string, ctx: ExtensionCommandContext) => {
|
|
986
|
+
const tokens = args.trim().split(/\s+/).filter(Boolean);
|
|
987
|
+
const configScope =
|
|
988
|
+
tokens.includes("--project-config") || tokens.includes("--project")
|
|
989
|
+
? "project"
|
|
990
|
+
: tokens.includes("--no-config")
|
|
991
|
+
? "none"
|
|
992
|
+
: "global";
|
|
993
|
+
const result = await handleTeamTool(
|
|
994
|
+
{
|
|
995
|
+
action: "init",
|
|
996
|
+
config: {
|
|
997
|
+
copyBuiltins: tokens.includes("--copy-builtins"),
|
|
998
|
+
overwrite: tokens.includes("--overwrite"),
|
|
999
|
+
configScope,
|
|
1000
|
+
},
|
|
1001
|
+
},
|
|
1002
|
+
teamCommandContext(ctx),
|
|
1003
|
+
);
|
|
1004
|
+
await notifyCommandResult(ctx, commandText(result));
|
|
1005
|
+
},
|
|
1006
|
+
});
|
|
1007
|
+
|
|
1008
|
+
pi.registerCommand("team-autonomy", {
|
|
1009
|
+
description: "Show or toggle pi-crew autonomous delegation policy: status|on|off",
|
|
1010
|
+
handler: async (args: string, ctx: ExtensionCommandContext) => {
|
|
1011
|
+
const tokens = args.trim().split(/\s+/).filter(Boolean);
|
|
1012
|
+
const mode = tokens[0]?.toLowerCase();
|
|
1013
|
+
const config =
|
|
1014
|
+
mode === "on"
|
|
1015
|
+
? {
|
|
1016
|
+
profile: "suggested",
|
|
1017
|
+
enabled: true,
|
|
1018
|
+
injectPolicy: true,
|
|
1019
|
+
}
|
|
1020
|
+
: mode === "off"
|
|
1021
|
+
? { profile: "manual", enabled: false }
|
|
1022
|
+
: mode === "manual" || mode === "suggested" || mode === "assisted" || mode === "aggressive"
|
|
1023
|
+
? {
|
|
1024
|
+
profile: mode,
|
|
1025
|
+
enabled: mode !== "manual",
|
|
1026
|
+
injectPolicy: mode !== "manual",
|
|
1027
|
+
}
|
|
1028
|
+
: {
|
|
1029
|
+
preferAsyncForLongTasks: tokens.includes("--prefer-async") ? true : undefined,
|
|
1030
|
+
allowWorktreeSuggestion: tokens.includes("--no-worktree-suggest") ? false : undefined,
|
|
1031
|
+
};
|
|
1032
|
+
const result = await handleTeamTool({ action: "autonomy", config }, teamCommandContext(ctx));
|
|
1033
|
+
await notifyCommandResult(ctx, commandText(result));
|
|
1034
|
+
},
|
|
1035
|
+
});
|
|
1036
|
+
|
|
1037
|
+
pi.registerCommand("team-config", {
|
|
1038
|
+
description: "Show or update pi-crew config. Use key=value [--project] to update.",
|
|
1039
|
+
handler: async (args: string, ctx: ExtensionCommandContext) => {
|
|
1040
|
+
const tokens = args.trim().split(/\s+/).filter(Boolean);
|
|
1041
|
+
if (tokens.length === 0) {
|
|
1042
|
+
const result = await handleTeamTool({ action: "config" }, teamCommandContext(ctx));
|
|
1043
|
+
await notifyCommandResult(ctx, commandText(result));
|
|
1044
|
+
return;
|
|
602
1045
|
}
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
const
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
1046
|
+
const config: Record<string, unknown> = {
|
|
1047
|
+
scope: tokens.includes("--project") ? "project" : "user",
|
|
1048
|
+
};
|
|
1049
|
+
for (const token of tokens) {
|
|
1050
|
+
if (token.startsWith("--unset=")) {
|
|
1051
|
+
pushUnset(config, token.slice("--unset=".length));
|
|
1052
|
+
continue;
|
|
1053
|
+
}
|
|
1054
|
+
if (!token.includes("=")) continue;
|
|
1055
|
+
const [key, ...rest] = token.split("=");
|
|
1056
|
+
if (!key) continue;
|
|
1057
|
+
const raw = rest.join("=");
|
|
1058
|
+
if (raw === "unset" || raw === "null") pushUnset(config, key);
|
|
1059
|
+
else setNestedConfig(config, key, parseScalar(raw));
|
|
1060
|
+
}
|
|
1061
|
+
const result = await handleTeamTool({ action: "config", config }, teamCommandContext(ctx));
|
|
1062
|
+
await notifyCommandResult(ctx, commandText(result));
|
|
1063
|
+
},
|
|
1064
|
+
});
|
|
613
1065
|
|
|
614
1066
|
for (const [name, action, description] of [
|
|
615
1067
|
["team-validate", "validate", "Validate pi-crew agents, teams, and workflows"],
|
|
616
1068
|
["team-doctor", "doctor", "Check pi-crew installation and discovery readiness"],
|
|
617
|
-
] as const)
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
1069
|
+
] as const)
|
|
1070
|
+
pi.registerCommand(name, {
|
|
1071
|
+
description,
|
|
1072
|
+
handler: async (_args: string, ctx: ExtensionCommandContext) => {
|
|
1073
|
+
const result = await handleTeamTool({ action }, teamCommandContext(ctx));
|
|
1074
|
+
await notifyCommandResult(ctx, commandText(result));
|
|
1075
|
+
},
|
|
1076
|
+
});
|
|
1077
|
+
|
|
1078
|
+
pi.registerCommand("skill-list", {
|
|
1079
|
+
description: "List available builtin skill templates. Use --json for machine-readable output.",
|
|
1080
|
+
handler: async (args: string, ctx: ExtensionCommandContext) => {
|
|
1081
|
+
const asJson = args.trim().split(/\s+/).includes("--json");
|
|
1082
|
+
const templates = listTemplates();
|
|
1083
|
+
if (asJson) {
|
|
1084
|
+
await notifyCommandResult(ctx, JSON.stringify(templates, null, 2));
|
|
1085
|
+
} else {
|
|
1086
|
+
const lines = ["Available builtin skill templates:", ""];
|
|
1087
|
+
for (const t of templates) {
|
|
1088
|
+
lines.push(` ${t.id.padEnd(20)} ${t.description}`);
|
|
1089
|
+
lines.push(
|
|
1090
|
+
` Variables: ${t.variables.map((v) => (v.required ? "[required] " : "[optional] ") + v.name).join(", ")}`,
|
|
1091
|
+
);
|
|
1092
|
+
}
|
|
1093
|
+
lines.push("");
|
|
1094
|
+
lines.push("Create a skill: /skill-create <template-id> --var key=value [--var ...]");
|
|
1095
|
+
await notifyCommandResult(ctx, lines.join("\n"));
|
|
632
1096
|
}
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
const entry = varEntries.find(([k]) => k === v.name);
|
|
661
|
-
if (!entry) {
|
|
662
|
-
if (v.required) errors.push(`Missing required variable: ${v.name} (${v.description})`);
|
|
663
|
-
else if (v.defaultValue !== undefined) variables[v.name] = v.defaultValue;
|
|
664
|
-
continue;
|
|
1097
|
+
},
|
|
1098
|
+
});
|
|
1099
|
+
|
|
1100
|
+
pi.registerCommand("skill-create", {
|
|
1101
|
+
description: "Create a skill from a builtin template: <template-id> [--var key=value...] [--project]",
|
|
1102
|
+
handler: async (args: string, ctx: ExtensionCommandContext) => {
|
|
1103
|
+
// LAZY: load withSessionId only when needed for skill-create command
|
|
1104
|
+
const { withSessionId } = await import("../team-tool/context.ts");
|
|
1105
|
+
const sessionId = withSessionId(ctx);
|
|
1106
|
+
const cwd =
|
|
1107
|
+
(
|
|
1108
|
+
ctx as unknown as {
|
|
1109
|
+
workspaceFolder?: { uri: { fsPath: string } };
|
|
1110
|
+
}
|
|
1111
|
+
).workspaceFolder?.uri?.fsPath ?? process.cwd();
|
|
1112
|
+
const tokens = args.trim().split(/\s+/).filter(Boolean);
|
|
1113
|
+
const useProject = tokens.includes("--project");
|
|
1114
|
+
const varEntries = tokens
|
|
1115
|
+
.filter((t) => t.startsWith("--var=") || t.startsWith("--var "))
|
|
1116
|
+
.map((t) => t.replace(/^--var(?:\s+|=)/, "").split("=", 2) as [string, string]);
|
|
1117
|
+
const templateId = tokens.find((t) => !t.startsWith("--") && !t.includes("="));
|
|
1118
|
+
if (!templateId) {
|
|
1119
|
+
await notifyCommandResult(
|
|
1120
|
+
ctx,
|
|
1121
|
+
"Usage: /skill-create <template-id> [--var key=value...] [--project]\nRun /skill-list to see available templates.",
|
|
1122
|
+
);
|
|
1123
|
+
return;
|
|
665
1124
|
}
|
|
666
|
-
const
|
|
667
|
-
if (
|
|
668
|
-
|
|
669
|
-
|
|
1125
|
+
const template = getBuiltinTemplates().find((t) => t.id === templateId);
|
|
1126
|
+
if (!template) {
|
|
1127
|
+
await notifyCommandResult(ctx, `Unknown template '${templateId}'. Run /skill-list to see available templates.`);
|
|
1128
|
+
return;
|
|
670
1129
|
}
|
|
671
|
-
variables
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
1130
|
+
const variables: Record<string, string> = {};
|
|
1131
|
+
const errors: string[] = [];
|
|
1132
|
+
for (const v of template.variables) {
|
|
1133
|
+
const entry = varEntries.find(([k]) => k === v.name);
|
|
1134
|
+
if (!entry) {
|
|
1135
|
+
if (v.required) errors.push(`Missing required variable: ${v.name} (${v.description})`);
|
|
1136
|
+
else if (v.defaultValue !== undefined) variables[v.name] = v.defaultValue;
|
|
1137
|
+
continue;
|
|
1138
|
+
}
|
|
1139
|
+
const [, value] = entry;
|
|
1140
|
+
if (v.options && !v.options.includes(value)) {
|
|
1141
|
+
errors.push(`Invalid value '${value}' for '${v.name}'. Allowed: ${v.options.join(", ")}`);
|
|
1142
|
+
continue;
|
|
1143
|
+
}
|
|
1144
|
+
variables[v.name] = value;
|
|
1145
|
+
}
|
|
1146
|
+
if (errors.length > 0) {
|
|
1147
|
+
await notifyCommandResult(ctx, errors.join("\n"));
|
|
1148
|
+
return;
|
|
1149
|
+
}
|
|
1150
|
+
let instantiated: { filename: string; content: string };
|
|
1151
|
+
try {
|
|
1152
|
+
instantiated = instantiateTemplate(template, variables);
|
|
1153
|
+
} catch (error) {
|
|
1154
|
+
await notifyCommandResult(ctx, error instanceof Error ? error.message : String(error));
|
|
1155
|
+
return;
|
|
1156
|
+
}
|
|
1157
|
+
const skillsDir = path.resolve(
|
|
1158
|
+
cwd,
|
|
1159
|
+
useProject
|
|
1160
|
+
? "skills"
|
|
1161
|
+
: path.join(
|
|
1162
|
+
path.dirname(
|
|
1163
|
+
require.resolve("../../../package.json", {
|
|
1164
|
+
paths: [__dirname],
|
|
1165
|
+
}),
|
|
1166
|
+
),
|
|
1167
|
+
"skills",
|
|
1168
|
+
),
|
|
1169
|
+
);
|
|
1170
|
+
const skillDir = path.join(skillsDir, template.id);
|
|
1171
|
+
const skillPath = path.join(skillDir, "SKILL.md");
|
|
1172
|
+
try {
|
|
1173
|
+
fs.mkdirSync(skillDir, { recursive: true });
|
|
1174
|
+
fs.writeFileSync(skillPath, instantiated.content, "utf-8");
|
|
1175
|
+
await notifyCommandResult(
|
|
1176
|
+
ctx,
|
|
1177
|
+
`Created skill '${template.id}' at:\n${skillPath}\n\n${instantiated.content.slice(0, 200)}...`,
|
|
1178
|
+
);
|
|
1179
|
+
} catch (error) {
|
|
1180
|
+
await notifyCommandResult(ctx, `Failed to write skill: ${error instanceof Error ? error.message : String(error)}`);
|
|
1181
|
+
}
|
|
1182
|
+
},
|
|
1183
|
+
});
|
|
695
1184
|
|
|
696
|
-
pi.registerCommand("team-help", {
|
|
697
|
-
|
|
698
|
-
|
|
1185
|
+
pi.registerCommand("team-help", {
|
|
1186
|
+
description: "Show pi-crew command help",
|
|
1187
|
+
handler: async (_args: string, ctx: ExtensionCommandContext) => {
|
|
1188
|
+
await notifyCommandResult(ctx, piTeamsHelp());
|
|
1189
|
+
},
|
|
1190
|
+
});
|
|
699
1191
|
|
|
700
1192
|
// Brief mode command — toggle compact tool output display
|
|
701
1193
|
pi.registerCommand("crew-brief", {
|
|
702
1194
|
description: "Toggle brief tool output mode: on | off | status",
|
|
703
1195
|
handler: async (args: string, ctx: ExtensionCommandContext) => {
|
|
704
|
-
|
|
1196
|
+
// LAZY: defer dynamic import of ../../ui/tool-renderers/brief-mode.ts to its call site. Multi-line form breaks scripts/check-lazy-imports.mjs (which does `lines[lineNum - 2]`), so keep destructuring + await import on one line and place this LAZY marker directly above.
|
|
705
1197
|
const { isBrief, setBrief, BRIEF_ENTRY_TYPE, makeBriefEntry } = await import("../../ui/tool-renderers/brief-mode.ts");
|
|
706
1198
|
const trimmed = args.trim();
|
|
707
1199
|
|