pi-crew 0.9.16 → 0.9.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +130 -0
- package/README.md +19 -0
- package/dist/build-meta.json +21784 -0
- package/dist/index.mjs +83169 -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/migration/atomic-write-v2-migration.md +297 -0
- package/docs/patterns/command-agent-skill.md +1 -1
- package/docs/perf/performance-review-2026-07.md +287 -0
- 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 +303 -591
- 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 +149 -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 +39 -24
- 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 +344 -79
- 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 +187 -59
- 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 +13 -31
- 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 +10 -18
- 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 +2 -6
- package/src/runtime/retry-executor.ts +20 -4
- package/src/runtime/retry-runner.ts +27 -51
- 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 +12 -19
- 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 +50 -14
- 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 +2 -7
- 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 +106 -27
- 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 +137 -47
- 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/terminal-status.ts +1 -3
- 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 +46 -29
- 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
|
@@ -1,17 +1,10 @@
|
|
|
1
1
|
import { statSync } from "node:fs";
|
|
2
|
-
import type {
|
|
3
|
-
ExtensionAPI,
|
|
4
|
-
ExtensionContext,
|
|
5
|
-
ToolDefinition,
|
|
6
|
-
} from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import type { ExtensionAPI, ExtensionContext, ToolDefinition } from "@earendil-works/pi-coding-agent";
|
|
7
3
|
import { Text } from "@earendil-works/pi-tui";
|
|
8
4
|
import { loadConfig } from "../../config/config.ts";
|
|
9
5
|
import type { MetricRegistry } from "../../observability/metric-registry.ts";
|
|
10
6
|
import type { createManifestCache } from "../../runtime/manifest-cache.ts";
|
|
11
|
-
import {
|
|
12
|
-
TeamToolParams,
|
|
13
|
-
type TeamToolParamsValue,
|
|
14
|
-
} from "../../schema/team-tool-schema.ts";
|
|
7
|
+
import { TeamToolParams, type TeamToolParamsValue } from "../../schema/team-tool-schema.ts";
|
|
15
8
|
import { updatePiCrewPowerbar } from "../../ui/powerbar-publisher.ts";
|
|
16
9
|
import type { createRunSnapshotCache } from "../../ui/run-snapshot-cache.ts";
|
|
17
10
|
import { statusIcon, teamToolRenderer } from "../../ui/tool-renderers/index.ts";
|
|
@@ -47,17 +40,11 @@ type OnUpdate = (chunk: { content: { type: "text"; text: string }[] }) => void;
|
|
|
47
40
|
|
|
48
41
|
export interface RegisterTeamToolDeps {
|
|
49
42
|
foregroundControllers: Map<string | symbol, AbortController>;
|
|
50
|
-
startForegroundRun: (
|
|
51
|
-
ctx: ExtensionContext,
|
|
52
|
-
runner: (signal?: AbortSignal) => Promise<void>,
|
|
53
|
-
runId?: string,
|
|
54
|
-
) => void;
|
|
43
|
+
startForegroundRun: (ctx: ExtensionContext, runner: (signal?: AbortSignal) => Promise<void>, runId?: string) => void;
|
|
55
44
|
abortForegroundRun: (runId: string) => boolean;
|
|
56
45
|
openLiveSidebar: (ctx: ExtensionContext, runId: string) => void;
|
|
57
46
|
getManifestCache: (cwd: string) => ReturnType<typeof createManifestCache>;
|
|
58
|
-
getRunSnapshotCache?: (
|
|
59
|
-
cwd: string,
|
|
60
|
-
) => ReturnType<typeof createRunSnapshotCache>;
|
|
47
|
+
getRunSnapshotCache?: (cwd: string) => ReturnType<typeof createRunSnapshotCache>;
|
|
61
48
|
getMetricRegistry?: () => MetricRegistry | undefined;
|
|
62
49
|
widgetState: CrewWidgetState;
|
|
63
50
|
onJsonEvent?: (taskId: string, runId: string, event: unknown) => void;
|
|
@@ -83,10 +70,7 @@ export function resolveCwdOverride(
|
|
|
83
70
|
}
|
|
84
71
|
}
|
|
85
72
|
|
|
86
|
-
export function registerTeamTool(
|
|
87
|
-
pi: ExtensionAPI,
|
|
88
|
-
deps: RegisterTeamToolDeps,
|
|
89
|
-
): void {
|
|
73
|
+
export function registerTeamTool(pi: ExtensionAPI, deps: RegisterTeamToolDeps): void {
|
|
90
74
|
const tool: ToolDefinition = {
|
|
91
75
|
name: "team",
|
|
92
76
|
label: "Team",
|
|
@@ -112,37 +96,22 @@ export function registerTeamTool(
|
|
|
112
96
|
deps.foregroundControllers.set(toolKey, controller);
|
|
113
97
|
const abort = (): void => controller.abort();
|
|
114
98
|
signal?.addEventListener("abort", abort, { once: true });
|
|
115
|
-
const stopProgress = startTeamToolProgressBinder(
|
|
116
|
-
onUpdate as OnUpdate | undefined,
|
|
117
|
-
);
|
|
99
|
+
const stopProgress = startTeamToolProgressBinder(onUpdate as OnUpdate | undefined);
|
|
118
100
|
try {
|
|
119
101
|
const resolved = params as TeamToolParamsValue;
|
|
120
102
|
const cwdOverride = resolveCwdOverride(ctx.cwd, resolved.cwd);
|
|
121
|
-
if (!cwdOverride.ok)
|
|
122
|
-
return toolResult(
|
|
123
|
-
cwdOverride.error,
|
|
124
|
-
{ action: resolved.action ?? "list", status: "error" },
|
|
125
|
-
true,
|
|
126
|
-
);
|
|
103
|
+
if (!cwdOverride.ok) return toolResult(cwdOverride.error, { action: resolved.action ?? "list", status: "error" }, true);
|
|
127
104
|
const toolCtx = withSessionId({ ...ctx, cwd: cwdOverride.cwd });
|
|
128
105
|
// Phase 1.5: Auto-set session name from team run context
|
|
129
|
-
if (
|
|
130
|
-
resolved.
|
|
131
|
-
resolved.goal
|
|
132
|
-
!pi.getSessionName()
|
|
133
|
-
) {
|
|
134
|
-
const runLabel =
|
|
135
|
-
resolved.team ?? resolved.agent ?? "direct";
|
|
136
|
-
pi.setSessionName(
|
|
137
|
-
`pi-crew: ${runLabel}/${resolved.workflow ?? "default"} — ${resolved.goal.slice(0, 60)}`,
|
|
138
|
-
);
|
|
106
|
+
if (resolved.action === "run" && resolved.goal && !pi.getSessionName()) {
|
|
107
|
+
const runLabel = resolved.team ?? resolved.agent ?? "direct";
|
|
108
|
+
pi.setSessionName(`pi-crew: ${runLabel}/${resolved.workflow ?? "default"} — ${resolved.goal.slice(0, 60)}`);
|
|
139
109
|
}
|
|
140
110
|
const output = await handleTeamTool(resolved, {
|
|
141
111
|
...toolCtx,
|
|
142
112
|
signal: controller.signal,
|
|
143
113
|
metricRegistry: deps.getMetricRegistry?.(),
|
|
144
|
-
startForegroundRun: (runner, runId) =>
|
|
145
|
-
deps.startForegroundRun(toolCtx, runner, runId),
|
|
114
|
+
startForegroundRun: (runner, runId) => deps.startForegroundRun(toolCtx, runner, runId),
|
|
146
115
|
abortForegroundRun: deps.abortForegroundRun,
|
|
147
116
|
onRunStarted: (runId) => {
|
|
148
117
|
stopProgress.attach(toolCtx.cwd, runId);
|
|
@@ -151,11 +120,7 @@ export function registerTeamTool(
|
|
|
151
120
|
onJsonEvent: deps.onJsonEvent,
|
|
152
121
|
getRunSnapshotCache: deps.getRunSnapshotCache,
|
|
153
122
|
});
|
|
154
|
-
if (
|
|
155
|
-
resolved.action === "run" &&
|
|
156
|
-
!output.isError &&
|
|
157
|
-
typeof output.details?.runId === "string"
|
|
158
|
-
) {
|
|
123
|
+
if (resolved.action === "run" && !output.isError && typeof output.details?.runId === "string") {
|
|
159
124
|
pi.appendEntry("crew:run-started", {
|
|
160
125
|
runId: output.details.runId,
|
|
161
126
|
team: resolved.team,
|
|
@@ -169,21 +134,8 @@ export function registerTeamTool(
|
|
|
169
134
|
const config = loadConfig(toolCtx.cwd).config.ui;
|
|
170
135
|
const cache = deps.getManifestCache(toolCtx.cwd);
|
|
171
136
|
const snapshotCache = deps.getRunSnapshotCache?.(toolCtx.cwd);
|
|
172
|
-
updateCrewWidget(
|
|
173
|
-
|
|
174
|
-
deps.widgetState,
|
|
175
|
-
config,
|
|
176
|
-
cache,
|
|
177
|
-
snapshotCache,
|
|
178
|
-
);
|
|
179
|
-
updatePiCrewPowerbar(
|
|
180
|
-
pi.events,
|
|
181
|
-
toolCtx.cwd,
|
|
182
|
-
config,
|
|
183
|
-
cache,
|
|
184
|
-
snapshotCache,
|
|
185
|
-
toolCtx,
|
|
186
|
-
);
|
|
137
|
+
updateCrewWidget(toolCtx, deps.widgetState, config, cache, snapshotCache);
|
|
138
|
+
updatePiCrewPowerbar(pi.events, toolCtx.cwd, config, cache, snapshotCache, toolCtx);
|
|
187
139
|
return output;
|
|
188
140
|
} finally {
|
|
189
141
|
signal?.removeEventListener("abort", abort);
|
|
@@ -198,12 +150,7 @@ export function registerTeamTool(
|
|
|
198
150
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
199
151
|
renderResult(result: any, options: any, theme: any, context: any): any {
|
|
200
152
|
try {
|
|
201
|
-
return teamToolRenderer.renderResult(
|
|
202
|
-
result,
|
|
203
|
-
options,
|
|
204
|
-
theme,
|
|
205
|
-
context,
|
|
206
|
-
);
|
|
153
|
+
return teamToolRenderer.renderResult(result, options, theme, context);
|
|
207
154
|
} catch {
|
|
208
155
|
return new Text(statusIcon("completed", theme) + " done", 0, 0);
|
|
209
156
|
}
|
|
@@ -217,9 +164,7 @@ interface TeamToolProgressBinder {
|
|
|
217
164
|
stop: () => void;
|
|
218
165
|
}
|
|
219
166
|
|
|
220
|
-
function startTeamToolProgressBinder(
|
|
221
|
-
onUpdate: OnUpdate | undefined,
|
|
222
|
-
): TeamToolProgressBinder {
|
|
167
|
+
function startTeamToolProgressBinder(onUpdate: OnUpdate | undefined): TeamToolProgressBinder {
|
|
223
168
|
if (!onUpdate) {
|
|
224
169
|
return { attach: () => {}, stop: () => {} };
|
|
225
170
|
}
|
|
@@ -229,20 +174,14 @@ function startTeamToolProgressBinder(
|
|
|
229
174
|
const tick = (): void => {
|
|
230
175
|
try {
|
|
231
176
|
if (!cwd || !runId) {
|
|
232
|
-
const elapsed = Math.max(
|
|
233
|
-
0,
|
|
234
|
-
Math.round((Date.now() - startedAt) / 1000),
|
|
235
|
-
);
|
|
177
|
+
const elapsed = Math.max(0, Math.round((Date.now() - startedAt) / 1000));
|
|
236
178
|
const msg = `team status=starting elapsed=${elapsed}s`;
|
|
237
179
|
onUpdate({ content: [{ type: "text", text: msg }] });
|
|
238
180
|
return;
|
|
239
181
|
}
|
|
240
182
|
const loaded = loadRunManifestById(cwd, runId);
|
|
241
183
|
if (!loaded) {
|
|
242
|
-
const elapsed = Math.max(
|
|
243
|
-
0,
|
|
244
|
-
Math.round((Date.now() - startedAt) / 1000),
|
|
245
|
-
);
|
|
184
|
+
const elapsed = Math.max(0, Math.round((Date.now() - startedAt) / 1000));
|
|
246
185
|
const msg = `team run=${runId} elapsed=${elapsed}s (manifest pending)`;
|
|
247
186
|
onUpdate({ content: [{ type: "text", text: msg }] });
|
|
248
187
|
return;
|
|
@@ -264,11 +203,7 @@ function startTeamToolProgressBinder(
|
|
|
264
203
|
});
|
|
265
204
|
onUpdate({ content: [{ type: "text", text }] });
|
|
266
205
|
} catch (error) {
|
|
267
|
-
logInternalError(
|
|
268
|
-
"team-tool.progress",
|
|
269
|
-
error,
|
|
270
|
-
`runId=${runId ?? ""}`,
|
|
271
|
-
);
|
|
206
|
+
logInternalError("team-tool.progress", error, `runId=${runId ?? ""}`);
|
|
272
207
|
}
|
|
273
208
|
};
|
|
274
209
|
tick();
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UI installer (H3 + L2 — Phase 4 of cleanup plan).
|
|
3
|
+
*
|
|
4
|
+
* Owns the dashboard / sidebar / powerbar overlay logic that is gated on
|
|
5
|
+
* the user actually opening the dashboard (autoOpenDashboard flag) or a
|
|
6
|
+
* foreground run starting.
|
|
7
|
+
*
|
|
8
|
+
* Extracted from src/extension/register.ts. State holder is `UiState`;
|
|
9
|
+
* installer is `installLiveSidebar(ctx, runId, state, deps)`.
|
|
10
|
+
*
|
|
11
|
+
* Lazy by construction: the LiveRunSidebar class (and its transcript-viewer
|
|
12
|
+
* dependency tree) is only loaded when the user opens a sidebar overlay.
|
|
13
|
+
*/
|
|
14
|
+
import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
15
|
+
import { loadConfig } from "../../config/config.ts";
|
|
16
|
+
import { DEFAULT_UI } from "../../config/defaults.ts";
|
|
17
|
+
import type { LiveRunSidebar as LiveRunSidebarType } from "../../ui/live-run-sidebar.ts";
|
|
18
|
+
import { requestRender, setExtensionWidget, showCustom } from "../../ui/pi-ui-compat.ts";
|
|
19
|
+
import {
|
|
20
|
+
clearPiCrewPowerbar,
|
|
21
|
+
registerPiCrewPowerbarSegments,
|
|
22
|
+
requestPowerbarUpdate,
|
|
23
|
+
resetPowerbarDedupState,
|
|
24
|
+
updatePiCrewPowerbar,
|
|
25
|
+
} from "../../ui/powerbar-publisher.ts";
|
|
26
|
+
import type { CrewWidgetState } from "../../ui/widget/index.ts";
|
|
27
|
+
import { stopCrewWidget, updateCrewWidget } from "../../ui/widget/index.ts";
|
|
28
|
+
import { logInternalError } from "../../utils/internal-error.ts";
|
|
29
|
+
|
|
30
|
+
/** Cached live-run-sidebar constructor (lazy-loaded on first overlay open). */
|
|
31
|
+
let _cachedLiveRunSidebar: typeof LiveRunSidebarType | undefined;
|
|
32
|
+
async function importLiveRunSidebar(): Promise<typeof LiveRunSidebarType> {
|
|
33
|
+
if (!_cachedLiveRunSidebar) {
|
|
34
|
+
// LAZY: defer LiveRunSidebar import until the user opens a sidebar overlay.
|
|
35
|
+
const mod = await import("../../ui/live-run-sidebar.ts");
|
|
36
|
+
_cachedLiveRunSidebar = mod.LiveRunSidebar;
|
|
37
|
+
}
|
|
38
|
+
return _cachedLiveRunSidebar;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Mutable state owned by register.ts. */
|
|
42
|
+
export interface UiState {
|
|
43
|
+
liveSidebarRunId: string | undefined;
|
|
44
|
+
dashboardOpened: boolean;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Dependencies passed in by register.ts. */
|
|
48
|
+
export interface UiDeps {
|
|
49
|
+
pi: ExtensionAPI;
|
|
50
|
+
widgetState: CrewWidgetState;
|
|
51
|
+
getManifestCache: (cwd: string) => ReturnType<typeof import("../../runtime/manifest-cache.ts").createManifestCache>;
|
|
52
|
+
getRunSnapshotCache: (cwd: string) => ReturnType<typeof import("../../ui/run-snapshot-cache.ts").createRunSnapshotCache>;
|
|
53
|
+
isCleanedUp: () => boolean;
|
|
54
|
+
getCurrentCtx: () => ExtensionContext | undefined;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Open the live-run sidebar overlay if autoOpenDashboard is enabled. Gated by
|
|
59
|
+
* ui.autoOpenDashboard / autoOpenDashboardForForegroundRuns / placement.
|
|
60
|
+
*
|
|
61
|
+
* Returns true if the sidebar was opened (or was already open for this runId),
|
|
62
|
+
* false if gated off.
|
|
63
|
+
*/
|
|
64
|
+
export async function installLiveSidebar(ctx: ExtensionContext, runId: string, state: UiState, deps: UiDeps): Promise<boolean> {
|
|
65
|
+
const uiConfig = loadConfig(ctx.cwd).config.ui;
|
|
66
|
+
const autoOpen = uiConfig?.autoOpenDashboard === true;
|
|
67
|
+
const foregroundAutoOpen = uiConfig?.autoOpenDashboardForForegroundRuns ?? DEFAULT_UI.autoOpenDashboardForForegroundRuns;
|
|
68
|
+
if (!ctx.hasUI || !autoOpen || !foregroundAutoOpen || (uiConfig?.dashboardPlacement ?? DEFAULT_UI.dashboardPlacement) !== "right") {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
if (state.liveSidebarRunId === runId) return true;
|
|
72
|
+
state.liveSidebarRunId = runId;
|
|
73
|
+
state.dashboardOpened = true;
|
|
74
|
+
const widgetPlacement = uiConfig?.widgetPlacement ?? DEFAULT_UI.widgetPlacement;
|
|
75
|
+
setExtensionWidget(ctx, "pi-crew", undefined, { placement: widgetPlacement });
|
|
76
|
+
setExtensionWidget(ctx, "pi-crew-active", undefined, { placement: widgetPlacement });
|
|
77
|
+
deps.widgetState.lastVisibility = "hidden";
|
|
78
|
+
deps.widgetState.lastPlacement = widgetPlacement;
|
|
79
|
+
deps.widgetState.lastKey = "pi-crew-active";
|
|
80
|
+
deps.widgetState.model = undefined;
|
|
81
|
+
const width = Math.min(90, Math.max(40, uiConfig?.dashboardWidth ?? DEFAULT_UI.dashboardWidth));
|
|
82
|
+
|
|
83
|
+
try {
|
|
84
|
+
const LiveRunSidebar = await importLiveRunSidebar();
|
|
85
|
+
if (deps.isCleanedUp() || !deps.getCurrentCtx()) return false;
|
|
86
|
+
void showCustom<undefined>(
|
|
87
|
+
ctx,
|
|
88
|
+
(_tui, theme, _keybindings, done) =>
|
|
89
|
+
new LiveRunSidebar({
|
|
90
|
+
cwd: ctx.cwd,
|
|
91
|
+
runId,
|
|
92
|
+
done,
|
|
93
|
+
theme,
|
|
94
|
+
config: uiConfig,
|
|
95
|
+
snapshotCache: deps.getRunSnapshotCache(ctx.cwd),
|
|
96
|
+
}),
|
|
97
|
+
{
|
|
98
|
+
overlay: true,
|
|
99
|
+
overlayOptions: {
|
|
100
|
+
width,
|
|
101
|
+
minWidth: 40,
|
|
102
|
+
maxHeight: "100%",
|
|
103
|
+
anchor: "top-right",
|
|
104
|
+
offsetX: 0,
|
|
105
|
+
offsetY: 0,
|
|
106
|
+
margin: { top: 0, right: 0, bottom: 0, left: 0 },
|
|
107
|
+
visible: (termWidth: number) => termWidth >= 100,
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
).finally(() => {
|
|
111
|
+
if (state.liveSidebarRunId === runId) state.liveSidebarRunId = undefined;
|
|
112
|
+
const c = deps.getCurrentCtx();
|
|
113
|
+
if (!c) return;
|
|
114
|
+
updateCrewWidget(
|
|
115
|
+
c,
|
|
116
|
+
deps.widgetState,
|
|
117
|
+
loadConfig(c.cwd).config.ui,
|
|
118
|
+
deps.getManifestCache(c.cwd),
|
|
119
|
+
deps.getRunSnapshotCache(c.cwd),
|
|
120
|
+
);
|
|
121
|
+
});
|
|
122
|
+
return true;
|
|
123
|
+
} catch (error) {
|
|
124
|
+
logInternalError("register.live-sidebar-lazy-import", error);
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/** Clear the powerbar (called on session switch). */
|
|
130
|
+
export function clearDashboardPowerbar(state: UiState, deps: UiDeps): void {
|
|
131
|
+
const c = deps.getCurrentCtx();
|
|
132
|
+
if (c) stopCrewWidget(c, deps.widgetState, loadConfig(c.cwd).config.ui);
|
|
133
|
+
clearPiCrewPowerbar(deps.pi.events);
|
|
134
|
+
resetPowerbarDedupState();
|
|
135
|
+
state.dashboardOpened = false;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/** Register powerbar segments for a session. Idempotent. */
|
|
139
|
+
export function registerPowerbarSegments(deps: UiDeps, uiConfig: unknown): void {
|
|
140
|
+
registerPiCrewPowerbarSegments(deps.pi.events, uiConfig as Parameters<typeof registerPiCrewPowerbarSegments>[1]);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** Push a powerbar update with current run state. */
|
|
144
|
+
export function pushPowerbarUpdate(ctx: ExtensionContext, deps: UiDeps, notificationCount: number): void {
|
|
145
|
+
const config = loadConfig(ctx.cwd).config.ui;
|
|
146
|
+
requestPowerbarUpdate(
|
|
147
|
+
deps.pi.events,
|
|
148
|
+
ctx.cwd,
|
|
149
|
+
config,
|
|
150
|
+
deps.getManifestCache(ctx.cwd),
|
|
151
|
+
deps.getRunSnapshotCache(ctx.cwd),
|
|
152
|
+
ctx,
|
|
153
|
+
notificationCount,
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/** Initial powerbar update after session_start. */
|
|
158
|
+
export function primePowerbarAndWidget(ctx: ExtensionContext, deps: UiDeps, notificationCount: number): void {
|
|
159
|
+
const uiConfig = loadConfig(ctx.cwd).config.ui;
|
|
160
|
+
const cache = deps.getManifestCache(ctx.cwd);
|
|
161
|
+
updateCrewWidget(ctx, deps.widgetState, uiConfig, cache, deps.getRunSnapshotCache(ctx.cwd));
|
|
162
|
+
updatePiCrewPowerbar(deps.pi.events, ctx.cwd, uiConfig, cache, deps.getRunSnapshotCache(ctx.cwd), ctx, notificationCount);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/** Force-render the current context (used by sidebar open path). */
|
|
166
|
+
export function requestUiRender(ctx: ExtensionContext): void {
|
|
167
|
+
requestRender(ctx);
|
|
168
|
+
}
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import type { ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
|
|
2
|
-
import { loadRunManifestById } from "../../state/state-store.ts";
|
|
3
|
-
import { readCrewAgents } from "../../runtime/crew-agent-records.ts";
|
|
4
2
|
import { loadConfig } from "../../config/config.ts";
|
|
3
|
+
import { readCrewAgents } from "../../runtime/crew-agent-records.ts";
|
|
5
4
|
import { listLiveAgents } from "../../runtime/live-agent-manager.ts";
|
|
5
|
+
import { loadRunManifestById } from "../../state/state-store.ts";
|
|
6
6
|
import { LiveConversationOverlay } from "../../ui/live-conversation-overlay.ts";
|
|
7
7
|
import { asCrewTheme } from "../../ui/theme-adapter.ts";
|
|
8
8
|
// Lazy-loaded: DurableTranscriptViewer is 658ms — only needed for /crew transcript command
|
|
9
9
|
import type { DurableTranscriptViewer as DurableTranscriptViewerType } from "../../ui/transcript-viewer.ts";
|
|
10
|
+
|
|
10
11
|
let _cachedViewer: typeof DurableTranscriptViewerType | undefined;
|
|
11
12
|
let _viewerPromise: Promise<typeof DurableTranscriptViewerType> | undefined;
|
|
12
13
|
async function getViewer(): Promise<typeof DurableTranscriptViewerType> {
|
|
@@ -20,20 +21,31 @@ async function getViewer(): Promise<typeof DurableTranscriptViewerType> {
|
|
|
20
21
|
return _viewerPromise;
|
|
21
22
|
}
|
|
22
23
|
|
|
23
|
-
export async function selectAgentTask(
|
|
24
|
+
export async function selectAgentTask(
|
|
25
|
+
ctx: ExtensionCommandContext,
|
|
26
|
+
runId: string | undefined,
|
|
27
|
+
taskId?: string,
|
|
28
|
+
): Promise<{ runId: string; taskId?: string } | undefined> {
|
|
24
29
|
if (!runId) return undefined;
|
|
25
30
|
if (taskId) return { runId, taskId };
|
|
26
31
|
const loaded = loadRunManifestById(ctx.cwd, runId); // NOTE: no withRunLock - best-effort only; concurrent writes may cause inconsistency
|
|
27
32
|
if (!loaded) return { runId };
|
|
28
33
|
const agents = readCrewAgents(loaded.manifest);
|
|
29
34
|
if (ctx.hasUI && agents.length > 1) {
|
|
30
|
-
const choice = await ctx.ui.select(
|
|
35
|
+
const choice = await ctx.ui.select(
|
|
36
|
+
"Select pi-crew agent",
|
|
37
|
+
agents.map((agent) => `${agent.taskId} ${agent.role}→${agent.agent} [${agent.status}]`),
|
|
38
|
+
);
|
|
31
39
|
return { runId, taskId: choice?.split(" ")[0] };
|
|
32
40
|
}
|
|
33
41
|
return { runId, taskId: agents[0]?.taskId };
|
|
34
42
|
}
|
|
35
43
|
|
|
36
|
-
export async function openTranscriptViewer(
|
|
44
|
+
export async function openTranscriptViewer(
|
|
45
|
+
ctx: ExtensionCommandContext,
|
|
46
|
+
initialRunId: string | undefined,
|
|
47
|
+
initialTaskId?: string,
|
|
48
|
+
): Promise<boolean> {
|
|
37
49
|
const selected = await selectAgentTask(ctx, initialRunId, initialTaskId);
|
|
38
50
|
if (!selected) return false;
|
|
39
51
|
const runId = selected.runId;
|
|
@@ -43,15 +55,29 @@ export async function openTranscriptViewer(ctx: ExtensionCommandContext, initial
|
|
|
43
55
|
if (!loaded) return false;
|
|
44
56
|
const uiConfig = loadConfig(ctx.cwd).config.ui;
|
|
45
57
|
const DurableTranscriptViewer = await getViewer();
|
|
46
|
-
await ctx.ui.custom<undefined>(
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
58
|
+
await ctx.ui.custom<undefined>(
|
|
59
|
+
(_tui, theme, _keybindings, done) =>
|
|
60
|
+
new DurableTranscriptViewer(loaded.manifest, theme, done, taskId, {
|
|
61
|
+
maxTailBytes: uiConfig?.transcriptTailBytes,
|
|
62
|
+
}),
|
|
63
|
+
{
|
|
64
|
+
overlay: true,
|
|
65
|
+
overlayOptions: {
|
|
66
|
+
width: "90%",
|
|
67
|
+
maxHeight: "85%",
|
|
68
|
+
anchor: "center",
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
);
|
|
50
72
|
return true;
|
|
51
73
|
}
|
|
52
74
|
|
|
53
75
|
/** R2: Open live conversation overlay for a running live-session agent. */
|
|
54
|
-
export async function openLiveConversation(
|
|
76
|
+
export async function openLiveConversation(
|
|
77
|
+
ctx: ExtensionCommandContext,
|
|
78
|
+
initialRunId: string | undefined,
|
|
79
|
+
initialTaskId?: string,
|
|
80
|
+
): Promise<boolean> {
|
|
55
81
|
const selected = await selectAgentTask(ctx, initialRunId, initialTaskId);
|
|
56
82
|
if (!selected || !ctx.hasUI) return false;
|
|
57
83
|
const liveAgents = listLiveAgents();
|
|
@@ -59,20 +85,34 @@ export async function openLiveConversation(ctx: ExtensionCommandContext, initial
|
|
|
59
85
|
if (!handle) return false;
|
|
60
86
|
const theme = asCrewTheme({});
|
|
61
87
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
62
|
-
await ctx.ui.custom<undefined>(
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
88
|
+
await ctx.ui.custom<undefined>(
|
|
89
|
+
(tui: any, _theme: any, _keybindings: any, done: (result: undefined) => void) => {
|
|
90
|
+
const columns = tui?.terminal?.columns ?? 80;
|
|
91
|
+
const rows = tui?.terminal?.rows ?? 24;
|
|
92
|
+
const overlay = new LiveConversationOverlay(handle, theme, columns, rows);
|
|
93
|
+
return {
|
|
94
|
+
render(width: number) {
|
|
95
|
+
return overlay.render(width);
|
|
96
|
+
},
|
|
97
|
+
handleInput(data: string) {
|
|
98
|
+
if (data === "\x1b" || data === "q") {
|
|
99
|
+
overlay.close();
|
|
100
|
+
done(undefined);
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
invalidate() {
|
|
104
|
+
/* overlay polls */
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
overlay: true,
|
|
110
|
+
overlayOptions: {
|
|
111
|
+
width: "90%",
|
|
112
|
+
maxHeight: "85%",
|
|
113
|
+
anchor: "center",
|
|
70
114
|
},
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}, {
|
|
74
|
-
overlay: true,
|
|
75
|
-
overlayOptions: { width: "90%", maxHeight: "85%", anchor: "center" },
|
|
76
|
-
});
|
|
115
|
+
},
|
|
116
|
+
);
|
|
77
117
|
return true;
|
|
78
118
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
3
|
import { buildCompletionKey, getGlobalSeenMap, markSeenWithTtl } from "../utils/completion-dedupe.ts";
|
|
4
|
-
import { closeWatcher, watchWithErrorHandler } from "../utils/fs-watch.ts";
|
|
5
4
|
import { createFileCoalescer } from "../utils/file-coalescer.ts";
|
|
5
|
+
import { closeWatcher, watchWithErrorHandler } from "../utils/fs-watch.ts";
|
|
6
6
|
import { logInternalError } from "../utils/internal-error.ts";
|
|
7
7
|
|
|
8
8
|
export interface ResultWatcherEvents {
|
|
@@ -42,7 +42,11 @@ function readJson(filePath: string): unknown | undefined {
|
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
export function createResultWatcher(
|
|
45
|
+
export function createResultWatcher(
|
|
46
|
+
events: ResultWatcherEvents,
|
|
47
|
+
resultsDir: string,
|
|
48
|
+
eventNameOrOptions: string | ResultWatcherOptions = "pi-crew:run-result",
|
|
49
|
+
): ResultWatcherHandle {
|
|
46
50
|
const options: ResultWatcherOptions = typeof eventNameOrOptions === "string" ? { eventName: eventNameOrOptions } : eventNameOrOptions;
|
|
47
51
|
const eventName = options.eventName ?? "pi-crew:run-result";
|
|
48
52
|
const completionTtlMs = options.completionTtlMs ?? 5 * 60_000;
|
|
@@ -61,7 +65,10 @@ export function createResultWatcher(events: ResultWatcherEvents, resultsDir: str
|
|
|
61
65
|
coalescer.schedule(file, RESULT_WATCHER_POLL_MS);
|
|
62
66
|
return;
|
|
63
67
|
}
|
|
64
|
-
const key = buildCompletionKey(
|
|
68
|
+
const key = buildCompletionKey(
|
|
69
|
+
payload && typeof payload === "object" && !Array.isArray(payload) ? (payload as Record<string, unknown>) : {},
|
|
70
|
+
`file:${file}`,
|
|
71
|
+
);
|
|
65
72
|
if (!markSeenWithTtl(seen, key, Date.now(), completionTtlMs)) {
|
|
66
73
|
events.emit(eventName, payload);
|
|
67
74
|
}
|
|
@@ -105,10 +112,14 @@ export function createResultWatcher(events: ResultWatcherEvents, resultsDir: str
|
|
|
105
112
|
if (!isCurrent()) return;
|
|
106
113
|
fs.mkdirSync(resultsDir, { recursive: true });
|
|
107
114
|
if (watcher) closeWatcher(watcher);
|
|
108
|
-
watcher = watch(
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
115
|
+
watcher = watch(
|
|
116
|
+
resultsDir,
|
|
117
|
+
(event, fileName) => {
|
|
118
|
+
if (event !== "rename" || !fileName) return;
|
|
119
|
+
coalescer.schedule(fileName.toString());
|
|
120
|
+
},
|
|
121
|
+
scheduleRestart,
|
|
122
|
+
);
|
|
112
123
|
if (watcher) stopPolling();
|
|
113
124
|
watcher?.unref();
|
|
114
125
|
},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { isTeamRunStatus, isTeamTaskStatus } from "../state/contracts.ts";
|
|
2
|
-
import type { TeamRunManifest, TeamTaskState, ArtifactDescriptor } from "../state/types.ts";
|
|
3
2
|
import type { TeamEvent } from "../state/event-log.ts";
|
|
3
|
+
import type { ArtifactDescriptor, TeamRunManifest, TeamTaskState } from "../state/types.ts";
|
|
4
4
|
import type { ExportedRunBundle } from "./run-export.ts";
|
|
5
5
|
|
|
6
6
|
export interface BundleValidationResult {
|
|
@@ -22,7 +22,8 @@ function validateArtifact(value: unknown, index: number, errors: string[]): valu
|
|
|
22
22
|
if (typeof value.path !== "string") errors.push(`manifest.artifacts[${index}].path must be a string.`);
|
|
23
23
|
if (typeof value.createdAt !== "string") errors.push(`manifest.artifacts[${index}].createdAt must be a string.`);
|
|
24
24
|
if (typeof value.producer !== "string") errors.push(`manifest.artifacts[${index}].producer must be a string.`);
|
|
25
|
-
if (value.retention !== "run" && value.retention !== "project" && value.retention !== "temporary")
|
|
25
|
+
if (value.retention !== "run" && value.retention !== "project" && value.retention !== "temporary")
|
|
26
|
+
errors.push(`manifest.artifacts[${index}].retention is invalid.`);
|
|
26
27
|
return errors.length === before;
|
|
27
28
|
}
|
|
28
29
|
|
|
@@ -33,11 +34,23 @@ function validateManifest(value: unknown, errors: string[]): value is TeamRunMan
|
|
|
33
34
|
}
|
|
34
35
|
const before = errors.length;
|
|
35
36
|
if (value.schemaVersion !== 1) errors.push("manifest.schemaVersion must be 1.");
|
|
36
|
-
for (const field of [
|
|
37
|
+
for (const field of [
|
|
38
|
+
"runId",
|
|
39
|
+
"team",
|
|
40
|
+
"goal",
|
|
41
|
+
"createdAt",
|
|
42
|
+
"updatedAt",
|
|
43
|
+
"cwd",
|
|
44
|
+
"stateRoot",
|
|
45
|
+
"artifactsRoot",
|
|
46
|
+
"tasksPath",
|
|
47
|
+
"eventsPath",
|
|
48
|
+
] as const) {
|
|
37
49
|
if (typeof value[field] !== "string") errors.push(`manifest.${field} must be a string.`);
|
|
38
50
|
}
|
|
39
51
|
if (!isTeamRunStatus(value.status)) errors.push("manifest.status is invalid.");
|
|
40
|
-
if (value.workspaceMode !== "single" && value.workspaceMode !== "worktree")
|
|
52
|
+
if (value.workspaceMode !== "single" && value.workspaceMode !== "worktree")
|
|
53
|
+
errors.push("manifest.workspaceMode must be single or worktree.");
|
|
41
54
|
if (!Array.isArray(value.artifacts)) errors.push("manifest.artifacts must be an array.");
|
|
42
55
|
else value.artifacts.forEach((artifact, index) => validateArtifact(artifact, index, errors));
|
|
43
56
|
return errors.length === before;
|
|
@@ -79,11 +92,13 @@ export function validateRunBundle(value: unknown): BundleValidationResult {
|
|
|
79
92
|
else value.tasks.forEach((task, index) => validateTask(task, index, errors));
|
|
80
93
|
if (!Array.isArray(value.events)) errors.push("events must be an array.");
|
|
81
94
|
else value.events.forEach((event, index) => validateEvent(event, index, errors));
|
|
82
|
-
if (!Array.isArray(value.artifactPaths) || !value.artifactPaths.every((item) => typeof item === "string"))
|
|
95
|
+
if (!Array.isArray(value.artifactPaths) || !value.artifactPaths.every((item) => typeof item === "string"))
|
|
96
|
+
errors.push("artifactPaths must be an array of strings.");
|
|
83
97
|
return { ok: errors.length === 0, errors };
|
|
84
98
|
}
|
|
85
99
|
|
|
86
100
|
export function assertRunBundle(value: unknown): asserts value is ExportedRunBundle {
|
|
87
101
|
const validation = validateRunBundle(value);
|
|
88
|
-
if (!validation.ok)
|
|
102
|
+
if (!validation.ok)
|
|
103
|
+
throw new Error(`File is not a valid pi-crew exported run bundle:\n${validation.errors.map((error) => `- ${error}`).join("\n")}`);
|
|
89
104
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
+
import * as crypto from "node:crypto";
|
|
1
2
|
import * as fs from "node:fs";
|
|
2
|
-
import * as path from "node:path";
|
|
3
3
|
import * as os from "node:os";
|
|
4
|
-
import * as
|
|
5
|
-
import type { TeamRunManifest, TeamTaskState } from "../state/types.ts";
|
|
4
|
+
import * as path from "node:path";
|
|
6
5
|
import { writeArtifact } from "../state/artifact-store.ts";
|
|
7
6
|
import { readEvents, type TeamEvent } from "../state/event-log.ts";
|
|
7
|
+
import type { TeamRunManifest, TeamTaskState } from "../state/types.ts";
|
|
8
8
|
import { redactSecrets } from "../utils/redaction.ts";
|
|
9
9
|
|
|
10
10
|
/** Replace absolute paths containing home directory with ~/ */
|
|
@@ -72,13 +72,22 @@ export function exportRunBundle(manifest: TeamRunManifest, tasks: TeamTaskState[
|
|
|
72
72
|
`Goal: ${safeManifest.goal}`,
|
|
73
73
|
"",
|
|
74
74
|
"## Tasks",
|
|
75
|
-
...safeTasks.map(
|
|
75
|
+
...safeTasks.map(
|
|
76
|
+
(task) => `- ${task.id}: ${task.status} (${task.role} -> ${task.agent})${task.error ? ` - ${task.error}` : ""}`,
|
|
77
|
+
),
|
|
76
78
|
"",
|
|
77
79
|
"## Artifacts",
|
|
78
|
-
...(safeManifest.artifacts.length
|
|
80
|
+
...(safeManifest.artifacts.length
|
|
81
|
+
? safeManifest.artifacts.map((artifact) => `- ${artifact.kind}: ${artifact.path}`)
|
|
82
|
+
: ["- (none)"]),
|
|
79
83
|
"",
|
|
80
84
|
"## Recent Events",
|
|
81
|
-
...
|
|
85
|
+
...safeEvents
|
|
86
|
+
.slice(-20)
|
|
87
|
+
.map(
|
|
88
|
+
(event) =>
|
|
89
|
+
`- ${event.time} ${event.type}${event.taskId ? ` ${event.taskId}` : ""}${event.message ? `: ${event.message}` : ""}`,
|
|
90
|
+
),
|
|
82
91
|
"",
|
|
83
92
|
].join("\n"),
|
|
84
93
|
});
|