pi-crew 0.9.53 → 0.9.55
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 +45 -0
- package/package.json +6 -3
- package/scripts/clean-strip-types.mjs +60 -0
- package/src/adapters/claude-adapter.ts +23 -0
- package/src/adapters/codex-adapter.ts +21 -0
- package/src/adapters/cursor-adapter.ts +17 -0
- package/src/adapters/export-util.ts +143 -0
- package/src/adapters/index.ts +15 -0
- package/src/adapters/registry.ts +18 -0
- package/src/adapters/types.ts +23 -0
- package/src/agents/agent-config.ts +194 -0
- package/src/agents/agent-search.ts +98 -0
- package/src/agents/agent-serializer.ts +38 -0
- package/src/agents/discover-agents.ts +623 -0
- package/src/benchmark/benchmark-runner.ts +313 -0
- package/src/benchmark/feedback-loop.ts +73 -0
- package/src/config/config.ts +1270 -0
- package/src/config/defaults.ts +193 -0
- package/src/config/drift-detector.ts +290 -0
- package/src/config/markers.ts +330 -0
- package/src/config/resilient-parser.ts +117 -0
- package/src/config/role-tools.ts +118 -0
- package/src/config/suggestions.ts +75 -0
- package/src/config/types.ts +280 -0
- package/src/errors.ts +194 -0
- package/src/extension/action-suggestions.ts +117 -0
- package/src/extension/async-notifier.ts +179 -0
- package/src/extension/autonomous-policy.ts +209 -0
- package/src/extension/command-completions.ts +120 -0
- package/src/extension/context-status-injection.ts +185 -0
- package/src/extension/crew-autocomplete.ts +131 -0
- package/src/extension/crew-cleanup.ts +168 -0
- package/src/extension/crew-input-router.ts +93 -0
- package/src/extension/crew-shortcuts.ts +87 -0
- package/src/extension/crew-vibes/cat-frames.ts +18 -0
- package/src/extension/crew-vibes/config.ts +195 -0
- package/src/extension/crew-vibes/figures.ts +101 -0
- package/src/extension/crew-vibes/font-detect.ts +71 -0
- package/src/extension/crew-vibes/footer.ts +292 -0
- package/src/extension/crew-vibes/index.ts +432 -0
- package/src/extension/crew-vibes/provider-usage.ts +396 -0
- package/src/extension/crew-vibes/render.ts +206 -0
- package/src/extension/crew-vibes/speed.ts +286 -0
- package/src/extension/cross-extension-rpc.ts +350 -0
- package/src/extension/help.ts +62 -0
- package/src/extension/import-index.ts +74 -0
- package/src/extension/knowledge-injection.ts +402 -0
- package/src/extension/management.ts +571 -0
- package/src/extension/message-renderers.ts +108 -0
- package/src/extension/notification-router.ts +152 -0
- package/src/extension/notification-sink.ts +54 -0
- package/src/extension/pi-api.ts +56 -0
- package/src/extension/plan-orchestrate.ts +302 -0
- package/src/extension/project-init.ts +170 -0
- package/src/extension/register.ts +113 -0
- package/src/extension/registration/artifact-cleanup.ts +20 -0
- package/src/extension/registration/command-registration.ts +58 -0
- package/src/extension/registration/command-utils.ts +58 -0
- package/src/extension/registration/commands.ts +1228 -0
- package/src/extension/registration/compaction-guard.ts +333 -0
- package/src/extension/registration/context-builder.ts +135 -0
- package/src/extension/registration/crash-recovery-cache.ts +54 -0
- package/src/extension/registration/foreground-run-controller.ts +238 -0
- package/src/extension/registration/hook-registration.ts +119 -0
- package/src/extension/registration/lazy-configurers.ts +124 -0
- package/src/extension/registration/lifecycle-handlers.ts +923 -0
- package/src/extension/registration/lifecycle.ts +259 -0
- package/src/extension/registration/observability.ts +322 -0
- package/src/extension/registration/registration-types.ts +158 -0
- package/src/extension/registration/runtime-cleanup.ts +230 -0
- package/src/extension/registration/subagent-helpers.ts +125 -0
- package/src/extension/registration/subagent-manager-setup.ts +330 -0
- package/src/extension/registration/subagent-tools.ts +456 -0
- package/src/extension/registration/team-tool.ts +225 -0
- package/src/extension/registration/tool-registration.ts +50 -0
- package/src/extension/registration/ui.ts +172 -0
- package/src/extension/registration/viewers.ts +121 -0
- package/src/extension/registration/wire-cross-extension.ts +37 -0
- package/src/extension/result-watcher.ts +139 -0
- package/src/extension/rpc-hmac.ts +256 -0
- package/src/extension/run-bundle-schema.ts +104 -0
- package/src/extension/run-export.ts +97 -0
- package/src/extension/run-import.ts +168 -0
- package/src/extension/run-index.ts +131 -0
- package/src/extension/run-maintenance.ts +190 -0
- package/src/extension/session-summary.ts +18 -0
- package/src/extension/team-manager-command.ts +153 -0
- package/src/extension/team-onboard.ts +180 -0
- package/src/extension/team-recommendation.ts +288 -0
- package/src/extension/team-tool/anchor.ts +172 -0
- package/src/extension/team-tool/api.ts +1244 -0
- package/src/extension/team-tool/auto-summarize.ts +142 -0
- package/src/extension/team-tool/cache-control.ts +19 -0
- package/src/extension/team-tool/cancel.ts +337 -0
- package/src/extension/team-tool/chain-dispatch.ts +95 -0
- package/src/extension/team-tool/chain-executor.ts +379 -0
- package/src/extension/team-tool/config-patch.ts +50 -0
- package/src/extension/team-tool/context.ts +149 -0
- package/src/extension/team-tool/destructive-gate.ts +52 -0
- package/src/extension/team-tool/dispatch/automate.ts +80 -0
- package/src/extension/team-tool/dispatch/control.ts +42 -0
- package/src/extension/team-tool/dispatch/index.ts +95 -0
- package/src/extension/team-tool/dispatch/manage.ts +161 -0
- package/src/extension/team-tool/dispatch/run.ts +53 -0
- package/src/extension/team-tool/dispatch/status.ts +187 -0
- package/src/extension/team-tool/doctor.ts +431 -0
- package/src/extension/team-tool/explain.ts +282 -0
- package/src/extension/team-tool/failure-patterns.ts +118 -0
- package/src/extension/team-tool/goal-wrap.ts +330 -0
- package/src/extension/team-tool/goal.ts +556 -0
- package/src/extension/team-tool/handle-schedule.ts +332 -0
- package/src/extension/team-tool/handle-settings.ts +520 -0
- package/src/extension/team-tool/health-monitor.ts +481 -0
- package/src/extension/team-tool/inspect.ts +88 -0
- package/src/extension/team-tool/intent-policy.ts +45 -0
- package/src/extension/team-tool/lifecycle-actions.ts +615 -0
- package/src/extension/team-tool/orchestrate.ts +98 -0
- package/src/extension/team-tool/parallel-dispatch.ts +183 -0
- package/src/extension/team-tool/plan.ts +50 -0
- package/src/extension/team-tool/respond.ts +150 -0
- package/src/extension/team-tool/run-deadline.ts +66 -0
- package/src/extension/team-tool/run-not-found.ts +49 -0
- package/src/extension/team-tool/run.ts +1051 -0
- package/src/extension/team-tool/status.ts +260 -0
- package/src/extension/team-tool/workflow-manage.ts +261 -0
- package/src/extension/team-tool-types.ts +26 -0
- package/src/extension/team-tool.ts +750 -0
- package/src/extension/tool-result.ts +16 -0
- package/src/extension/validate-resources.ts +108 -0
- package/src/hooks/registry.ts +200 -0
- package/src/hooks/types.ts +69 -0
- package/src/i18n.ts +212 -0
- package/src/observability/correlation.ts +50 -0
- package/src/observability/event-bus.ts +86 -0
- package/src/observability/event-to-metric.ts +170 -0
- package/src/observability/exporters/adapter.ts +27 -0
- package/src/observability/exporters/otlp-exporter.ts +356 -0
- package/src/observability/exporters/prometheus-exporter.ts +54 -0
- package/src/observability/metric-registry.ts +100 -0
- package/src/observability/metric-retention.ts +64 -0
- package/src/observability/metric-sink.ts +99 -0
- package/src/observability/metrics-primitives.ts +219 -0
- package/src/plugins/plugin-define.ts +6 -0
- package/src/plugins/plugin-registry.ts +32 -0
- package/src/plugins/plugins/index.ts +3 -0
- package/src/plugins/plugins/nextjs.ts +19 -0
- package/src/plugins/plugins/vite.ts +10 -0
- package/src/plugins/plugins/vitest.ts +9 -0
- package/src/prompt/prompt-runtime.ts +380 -0
- package/src/runtime/adaptive-plan.ts +563 -0
- package/src/runtime/agent-control.ts +215 -0
- package/src/runtime/agent-memory.ts +81 -0
- package/src/runtime/agent-observability.ts +122 -0
- package/src/runtime/anchor-manager.ts +475 -0
- package/src/runtime/async-marker.ts +32 -0
- package/src/runtime/async-runner.ts +381 -0
- package/src/runtime/attention-events.ts +28 -0
- package/src/runtime/auto-summarize.ts +344 -0
- package/src/runtime/background-runner.ts +840 -0
- package/src/runtime/batch-barrier.ts +147 -0
- package/src/runtime/broker-issuer.ts +39 -0
- package/src/runtime/cancellation-token.ts +99 -0
- package/src/runtime/cancellation.ts +99 -0
- package/src/runtime/capability-inventory.ts +137 -0
- package/src/runtime/chain-parser.ts +237 -0
- package/src/runtime/chain-runner.ts +606 -0
- package/src/runtime/checkpoint.ts +291 -0
- package/src/runtime/child-pi-constants.ts +42 -0
- package/src/runtime/child-pi-kill.ts +180 -0
- package/src/runtime/child-pi-pool.ts +68 -0
- package/src/runtime/child-pi-spawn.ts +287 -0
- package/src/runtime/child-pi-steering.ts +128 -0
- package/src/runtime/child-pi-streams.ts +296 -0
- package/src/runtime/child-pi-transcript.ts +169 -0
- package/src/runtime/child-pi.ts +1105 -0
- package/src/runtime/coalesce-tasks.ts +268 -0
- package/src/runtime/code-summary.ts +292 -0
- package/src/runtime/command-trace.ts +105 -0
- package/src/runtime/compact-pipeline.ts +56 -0
- package/src/runtime/compact-stages/ansi-strip-stage.ts +25 -0
- package/src/runtime/compact-stages/blank-collapse-stage.ts +31 -0
- package/src/runtime/compact-stages/deduplicate-stage.ts +34 -0
- package/src/runtime/compact-stages/head-snap-stage.ts +57 -0
- package/src/runtime/compact-stages/index.ts +23 -0
- package/src/runtime/compact-stages/tail-capture-stage.ts +77 -0
- package/src/runtime/compact-stages/truncation-stage.ts +74 -0
- package/src/runtime/compaction-summary.ts +278 -0
- package/src/runtime/completion-guard.ts +207 -0
- package/src/runtime/concurrency.ts +58 -0
- package/src/runtime/crash-classification.ts +229 -0
- package/src/runtime/crash-recovery.ts +594 -0
- package/src/runtime/crew-agent-records.ts +595 -0
- package/src/runtime/crew-agent-runtime.ts +62 -0
- package/src/runtime/crew-broker-child.ts +88 -0
- package/src/runtime/crew-broker-client.ts +673 -0
- package/src/runtime/crew-broker-tokens.ts +159 -0
- package/src/runtime/crew-broker.ts +1304 -0
- package/src/runtime/crew-hooks.ts +227 -0
- package/src/runtime/cross-extension-rpc.ts +143 -0
- package/src/runtime/custom-tools/irc-tool.ts +282 -0
- package/src/runtime/custom-tools/submit-result-tool.ts +102 -0
- package/src/runtime/deadletter.ts +47 -0
- package/src/runtime/delivery-coordinator.ts +211 -0
- package/src/runtime/delta-conflict.ts +348 -0
- package/src/runtime/deterministic-ast.ts +161 -0
- package/src/runtime/diagnostic-export.ts +171 -0
- package/src/runtime/direct-run.ts +45 -0
- package/src/runtime/dwf-state-store.ts +102 -0
- package/src/runtime/dynamic-workflow-context.ts +1013 -0
- package/src/runtime/dynamic-workflow-runner.ts +325 -0
- package/src/runtime/effectiveness.ts +90 -0
- package/src/runtime/errors/crew-errors.ts +162 -0
- package/src/runtime/event-stream-bridge.ts +98 -0
- package/src/runtime/foreground-control.ts +193 -0
- package/src/runtime/foreground-watchdog.ts +132 -0
- package/src/runtime/global-worker-cap.ts +96 -0
- package/src/runtime/goal-achievement.ts +148 -0
- package/src/runtime/goal-evaluator.ts +365 -0
- package/src/runtime/goal-loop-runner.ts +825 -0
- package/src/runtime/goal-state-store.ts +219 -0
- package/src/runtime/green-contract.ts +55 -0
- package/src/runtime/group-join.ts +267 -0
- package/src/runtime/handoff-manager.ts +598 -0
- package/src/runtime/heartbeat-gradient.ts +36 -0
- package/src/runtime/heartbeat-watcher.ts +239 -0
- package/src/runtime/hidden-handoff.ts +407 -0
- package/src/runtime/important-line-classifier.ts +140 -0
- package/src/runtime/intercom-bridge.ts +187 -0
- package/src/runtime/iteration-hooks.ts +305 -0
- package/src/runtime/live-agent-control.ts +136 -0
- package/src/runtime/live-agent-manager.ts +704 -0
- package/src/runtime/live-control-realtime.ts +56 -0
- package/src/runtime/live-extension-bridge.ts +148 -0
- package/src/runtime/live-irc.ts +97 -0
- package/src/runtime/live-session-health.ts +108 -0
- package/src/runtime/live-session-runtime.ts +1146 -0
- package/src/runtime/loop-gates.ts +128 -0
- package/src/runtime/manifest-cache.ts +375 -0
- package/src/runtime/mcp-proxy.ts +105 -0
- package/src/runtime/metric-parser.ts +36 -0
- package/src/runtime/model-fallback.ts +409 -0
- package/src/runtime/model-resolver.ts +126 -0
- package/src/runtime/model-scope.ts +158 -0
- package/src/runtime/orphan-worker-registry.ts +465 -0
- package/src/runtime/output-validator.ts +202 -0
- package/src/runtime/overflow-recovery.ts +206 -0
- package/src/runtime/parallel-research.ts +68 -0
- package/src/runtime/parallel-utils.ts +160 -0
- package/src/runtime/parent-guard.ts +134 -0
- package/src/runtime/path-overlap.ts +150 -0
- package/src/runtime/peer-dep.ts +292 -0
- package/src/runtime/per-write-validator.ts +181 -0
- package/src/runtime/phase-progress.ts +217 -0
- package/src/runtime/phase-tracker.ts +385 -0
- package/src/runtime/pi-args.ts +655 -0
- package/src/runtime/pi-json-output.ts +170 -0
- package/src/runtime/pi-spawn.ts +273 -0
- package/src/runtime/pipeline-runner.ts +523 -0
- package/src/runtime/plan-templates.ts +201 -0
- package/src/runtime/policy-engine.ts +115 -0
- package/src/runtime/post-checks.ts +142 -0
- package/src/runtime/post-exit-stdio-guard.ts +109 -0
- package/src/runtime/process-lifecycle.ts +491 -0
- package/src/runtime/process-status.ts +154 -0
- package/src/runtime/progress-event-coalescer.ts +44 -0
- package/src/runtime/progress-tracker.ts +124 -0
- package/src/runtime/prose-compressor.ts +162 -0
- package/src/runtime/recovery-recipes.ts +203 -0
- package/src/runtime/replace.ts +570 -0
- package/src/runtime/resilient-edit.ts +153 -0
- package/src/runtime/result-extractor.ts +217 -0
- package/src/runtime/retry-executor.ts +109 -0
- package/src/runtime/retry-runner.ts +336 -0
- package/src/runtime/role-permission.ts +59 -0
- package/src/runtime/run-coalesced-task-group.ts +308 -0
- package/src/runtime/run-drift.ts +219 -0
- package/src/runtime/run-tracker.ts +116 -0
- package/src/runtime/run-worker.ts +78 -0
- package/src/runtime/runtime-policy.ts +29 -0
- package/src/runtime/runtime-resolver.ts +172 -0
- package/src/runtime/runtime-warmup.ts +160 -0
- package/src/runtime/scheduler.ts +353 -0
- package/src/runtime/semaphore.ts +141 -0
- package/src/runtime/sensitive-paths.ts +93 -0
- package/src/runtime/session-resources.ts +25 -0
- package/src/runtime/session-snapshot.ts +59 -0
- package/src/runtime/session-usage.ts +79 -0
- package/src/runtime/settings-store.ts +155 -0
- package/src/runtime/sidechain-output.ts +35 -0
- package/src/runtime/single-agent-compose.ts +84 -0
- package/src/runtime/skill-effectiveness.ts +524 -0
- package/src/runtime/skill-instructions.ts +394 -0
- package/src/runtime/stale-reconciler.ts +680 -0
- package/src/runtime/stream-preview.ts +184 -0
- package/src/runtime/streaming-output.ts +50 -0
- package/src/runtime/subagent-manager.ts +561 -0
- package/src/runtime/subprocess-tool-registry.ts +70 -0
- package/src/runtime/supervisor-contact.ts +64 -0
- package/src/runtime/task-display.ts +52 -0
- package/src/runtime/task-graph-scheduler.ts +227 -0
- package/src/runtime/task-graph.ts +290 -0
- package/src/runtime/task-health.ts +83 -0
- package/src/runtime/task-id.ts +161 -0
- package/src/runtime/task-output-context.ts +602 -0
- package/src/runtime/task-packet.ts +268 -0
- package/src/runtime/task-quality.ts +199 -0
- package/src/runtime/task-runner/capabilities.ts +78 -0
- package/src/runtime/task-runner/child-executor.ts +790 -0
- package/src/runtime/task-runner/context-retrieval.ts +163 -0
- package/src/runtime/task-runner/live-executor.ts +227 -0
- package/src/runtime/task-runner/output-splitter.ts +152 -0
- package/src/runtime/task-runner/post-execution.ts +480 -0
- package/src/runtime/task-runner/pre-execution.ts +365 -0
- package/src/runtime/task-runner/progress.ts +157 -0
- package/src/runtime/task-runner/prompt-builder.ts +278 -0
- package/src/runtime/task-runner/prompt-pipeline.ts +88 -0
- package/src/runtime/task-runner/result-utils.ts +16 -0
- package/src/runtime/task-runner/retrieval-orchestrator.ts +310 -0
- package/src/runtime/task-runner/run-projection.ts +125 -0
- package/src/runtime/task-runner/scaffold-executor.ts +25 -0
- package/src/runtime/task-runner/state-helpers.ts +176 -0
- package/src/runtime/task-runner/tail-read.ts +34 -0
- package/src/runtime/task-runner.ts +216 -0
- package/src/runtime/team-runner-artifacts.ts +13 -0
- package/src/runtime/team-runner.ts +2396 -0
- package/src/runtime/tool-output-pruner.ts +333 -0
- package/src/runtime/tool-progress.ts +278 -0
- package/src/runtime/usage-tracker.ts +73 -0
- package/src/runtime/verification-gates.ts +579 -0
- package/src/runtime/verification-integrity.ts +108 -0
- package/src/runtime/verification-worktree.ts +186 -0
- package/src/runtime/worker-heartbeat.ts +25 -0
- package/src/runtime/worker-startup.ts +83 -0
- package/src/runtime/workflow-state.ts +195 -0
- package/src/runtime/workspace-lock.ts +443 -0
- package/src/runtime/workspace-tree.ts +312 -0
- package/src/runtime/yield-handler.ts +224 -0
- package/src/runtime/zombie-scanner.ts +298 -0
- package/src/schema/config-schema.ts +327 -0
- package/src/schema/team-tool-schema.ts +492 -0
- package/src/schema/validation-types.ts +159 -0
- package/src/skills/discover-skills.ts +203 -0
- package/src/skills/skill-templates.ts +456 -0
- package/src/skills/validate.ts +285 -0
- package/src/state/active-run-registry.ts +439 -0
- package/src/state/artifact-store.ts +176 -0
- package/src/state/atomic-write.ts +970 -0
- package/src/state/blob-store.ts +308 -0
- package/src/state/contracts.ts +160 -0
- package/src/state/crew-init.ts +269 -0
- package/src/state/decision-ledger.ts +372 -0
- package/src/state/event-log-rotation.ts +399 -0
- package/src/state/event-log.ts +1465 -0
- package/src/state/event-reconstructor.ts +229 -0
- package/src/state/gitignore-manager.ts +46 -0
- package/src/state/health-store.ts +79 -0
- package/src/state/hook-instinct-bridge.ts +94 -0
- package/src/state/hook-integrations.ts +51 -0
- package/src/state/instinct-store.ts +275 -0
- package/src/state/jsonl-writer.ts +107 -0
- package/src/state/locks.ts +562 -0
- package/src/state/mailbox.ts +916 -0
- package/src/state/observation-store.ts +176 -0
- package/src/state/run-cache.ts +193 -0
- package/src/state/run-graph.ts +183 -0
- package/src/state/run-metrics.ts +165 -0
- package/src/state/schedule.ts +166 -0
- package/src/state/session-state-map.ts +51 -0
- package/src/state/state-store.ts +973 -0
- package/src/state/task-claims.ts +61 -0
- package/src/state/tiered-eval.ts +480 -0
- package/src/state/types-eval.ts +58 -0
- package/src/state/types.ts +447 -0
- package/src/state/usage.ts +138 -0
- package/src/state/worker-atomic-writer.ts +198 -0
- package/src/subagents/async-entry.ts +1 -0
- package/src/subagents/index.ts +3 -0
- package/src/subagents/live/control.ts +1 -0
- package/src/subagents/live/manager.ts +1 -0
- package/src/subagents/live/realtime.ts +1 -0
- package/src/subagents/live/session-runtime.ts +1 -0
- package/src/subagents/manager.ts +1 -0
- package/src/subagents/spawn.ts +1 -0
- package/src/teams/discover-teams.ts +187 -0
- package/src/teams/team-config.ts +27 -0
- package/src/teams/team-serializer.ts +38 -0
- package/src/tools/safe-bash-extension.ts +54 -0
- package/src/tools/safe-bash.ts +505 -0
- package/src/types/diff.d.ts +18 -0
- package/src/types/new-api-types.ts +35 -0
- package/src/ui/agent-management-overlay.ts +160 -0
- package/src/ui/card-colors.ts +139 -0
- package/src/ui/crew-footer.ts +102 -0
- package/src/ui/crew-select-list.ts +112 -0
- package/src/ui/dashboard-panes/agents-pane.ts +164 -0
- package/src/ui/dashboard-panes/cancellation-pane.ts +66 -0
- package/src/ui/dashboard-panes/capability-pane.ts +77 -0
- package/src/ui/dashboard-panes/health-pane.ts +31 -0
- package/src/ui/dashboard-panes/mailbox-pane.ts +35 -0
- package/src/ui/dashboard-panes/metrics-pane.ts +37 -0
- package/src/ui/dashboard-panes/progress-pane.ts +38 -0
- package/src/ui/dashboard-panes/transcript-pane.ts +10 -0
- package/src/ui/deploy-bundled-themes.ts +71 -0
- package/src/ui/dwf-phase-display.ts +151 -0
- package/src/ui/dynamic-border.ts +35 -0
- package/src/ui/format-helpers.ts +31 -0
- package/src/ui/heartbeat-aggregator.ts +74 -0
- package/src/ui/key-utils.ts +42 -0
- package/src/ui/keybinding-map.ts +248 -0
- package/src/ui/layout-primitives.ts +106 -0
- package/src/ui/live-conversation-overlay.ts +183 -0
- package/src/ui/live-duration.ts +55 -0
- package/src/ui/live-run-sidebar.ts +293 -0
- package/src/ui/loaders.ts +6 -0
- package/src/ui/mascot.ts +449 -0
- package/src/ui/overlays/agent-picker-overlay.ts +66 -0
- package/src/ui/overlays/confirm-overlay.ts +60 -0
- package/src/ui/overlays/help-overlay.ts +177 -0
- package/src/ui/overlays/mailbox-compose-overlay.ts +181 -0
- package/src/ui/overlays/mailbox-compose-preview.ts +78 -0
- package/src/ui/overlays/mailbox-detail-overlay.ts +155 -0
- package/src/ui/pi-ui-compat.ts +68 -0
- package/src/ui/powerbar-publisher.ts +459 -0
- package/src/ui/render-coalescer.ts +101 -0
- package/src/ui/render-diff.ts +160 -0
- package/src/ui/render-scheduler.ts +278 -0
- package/src/ui/run-action-dispatcher.ts +182 -0
- package/src/ui/run-dashboard.ts +910 -0
- package/src/ui/run-event-bus.ts +381 -0
- package/src/ui/run-snapshot-cache.ts +1057 -0
- package/src/ui/settings-overlay.ts +1067 -0
- package/src/ui/shared-overlay-scheduler.ts +96 -0
- package/src/ui/snapshot-types.ts +90 -0
- package/src/ui/spinner.ts +17 -0
- package/src/ui/status-colors.ts +143 -0
- package/src/ui/syntax-highlight.ts +136 -0
- package/src/ui/terminal-status.ts +269 -0
- package/src/ui/theme-adapter.ts +271 -0
- package/src/ui/theme-discovery.ts +199 -0
- package/src/ui/tool-progress-formatter.ts +93 -0
- package/src/ui/tool-renderers/brief-mode.ts +225 -0
- package/src/ui/tool-renderers/index.ts +726 -0
- package/src/ui/transcript-cache.ts +128 -0
- package/src/ui/transcript-entries.ts +256 -0
- package/src/ui/transcript-viewer.ts +424 -0
- package/src/ui/widget/index.ts +418 -0
- package/src/ui/widget/widget-formatters.ts +182 -0
- package/src/ui/widget/widget-model.ts +110 -0
- package/src/ui/widget/widget-renderer.ts +182 -0
- package/src/ui/widget/widget-types.ts +36 -0
- package/src/utils/bm25-search.ts +235 -0
- package/src/utils/completion-dedupe.ts +63 -0
- package/src/utils/conflict-detect.ts +668 -0
- package/src/utils/env-allowlist.ts +30 -0
- package/src/utils/env-filter.ts +155 -0
- package/src/utils/file-coalescer.ts +98 -0
- package/src/utils/fingerprint.ts +180 -0
- package/src/utils/frontmatter.ts +70 -0
- package/src/utils/fs-watch.ts +37 -0
- package/src/utils/gh-protocol.ts +556 -0
- package/src/utils/git.ts +260 -0
- package/src/utils/guards.ts +107 -0
- package/src/utils/ids.ts +24 -0
- package/src/utils/incremental-reader.ts +220 -0
- package/src/utils/internal-error.ts +10 -0
- package/src/utils/names.ts +36 -0
- package/src/utils/ndjson.ts +115 -0
- package/src/utils/paths.ts +227 -0
- package/src/utils/project-detector.ts +160 -0
- package/src/utils/redaction.ts +370 -0
- package/src/utils/resolve-shell.ts +36 -0
- package/src/utils/run-watcher-registry.ts +152 -0
- package/src/utils/safe-paths.ts +393 -0
- package/src/utils/scan-cache.ts +144 -0
- package/src/utils/session-utils.ts +110 -0
- package/src/utils/sleep.ts +54 -0
- package/src/utils/socket-path.ts +164 -0
- package/src/utils/sse-parser.ts +131 -0
- package/src/utils/task-name-generator.ts +337 -0
- package/src/utils/timings.ts +33 -0
- package/src/utils/token-counter.ts +200 -0
- package/src/utils/visual.ts +207 -0
- package/src/workflows/cost-estimator.ts +34 -0
- package/src/workflows/discover-workflows.ts +308 -0
- package/src/workflows/intermediate-store.ts +166 -0
- package/src/workflows/preflight-validator.ts +168 -0
- package/src/workflows/topology-analyzer.ts +203 -0
- package/src/workflows/validate-workflow.ts +50 -0
- package/src/workflows/workflow-config.ts +75 -0
- package/src/workflows/workflow-serializer.ts +32 -0
- package/src/worktree/branch-freshness.ts +112 -0
- package/src/worktree/cleanup.ts +341 -0
- package/src/worktree/worktree-manager.ts +1204 -0
|
@@ -0,0 +1,459 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import type { CrewUiConfig } from "../config/config.ts";
|
|
3
|
+
import { listRecentRuns } from "../extension/run-index.ts";
|
|
4
|
+
import { readCrewAgents } from "../runtime/crew-agent-records.ts";
|
|
5
|
+
import { listLiveAgents } from "../runtime/live-agent-manager.ts";
|
|
6
|
+
import type { ManifestCache } from "../runtime/manifest-cache.ts";
|
|
7
|
+
import { isDisplayActiveRun } from "../runtime/process-status.ts";
|
|
8
|
+
import type { TeamRunManifest, TeamTaskState } from "../state/types.ts";
|
|
9
|
+
import { aggregateUsage } from "../state/usage.ts";
|
|
10
|
+
import { readJsonFileCoalesced } from "../utils/file-coalescer.ts";
|
|
11
|
+
import { logInternalError } from "../utils/internal-error.ts";
|
|
12
|
+
import { allWorkflows, discoverWorkflows } from "../workflows/discover-workflows.ts";
|
|
13
|
+
import { RenderCoalescer } from "./render-coalescer.ts";
|
|
14
|
+
import type { RunSnapshotCache, RunUiSnapshot } from "./snapshot-types.ts";
|
|
15
|
+
import { notificationBadge } from "./widget/widget-formatters.ts";
|
|
16
|
+
|
|
17
|
+
type EventBus =
|
|
18
|
+
| {
|
|
19
|
+
emit?: (event: string, data: unknown) => void;
|
|
20
|
+
listenerCount?: (event: string) => number;
|
|
21
|
+
}
|
|
22
|
+
| undefined;
|
|
23
|
+
type StatusContext =
|
|
24
|
+
| {
|
|
25
|
+
hasUI?: boolean;
|
|
26
|
+
ui?: {
|
|
27
|
+
setStatus?: (key: string, text: string | undefined) => void;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
| undefined;
|
|
31
|
+
|
|
32
|
+
const TASK_READ_TTL_MS = 200;
|
|
33
|
+
|
|
34
|
+
function hasPowerbarConsumer(events: EventBus): boolean {
|
|
35
|
+
try {
|
|
36
|
+
return (events?.listenerCount?.("powerbar:register-segment") ?? 0) > 0 || (events?.listenerCount?.("powerbar:update") ?? 0) > 0;
|
|
37
|
+
} catch {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function setStatusFallback(ctx: StatusContext, text: string | undefined): void {
|
|
43
|
+
try {
|
|
44
|
+
if (ctx?.hasUI) ctx.ui?.setStatus?.("pi-crew", text);
|
|
45
|
+
} catch (error) {
|
|
46
|
+
logInternalError("powerbar.statusFallback", error);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function safeEmit(events: EventBus, event: string, data: unknown): void {
|
|
51
|
+
try {
|
|
52
|
+
events?.emit?.(event, data);
|
|
53
|
+
} catch (error) {
|
|
54
|
+
logInternalError("powerbar.safeEmit", error, `event=${event}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function readTasks(tasksPath: string): TeamTaskState[] {
|
|
59
|
+
try {
|
|
60
|
+
const parse = () => {
|
|
61
|
+
const parsed = JSON.parse(fs.readFileSync(tasksPath, "utf-8"));
|
|
62
|
+
return Array.isArray(parsed) ? (parsed as TeamTaskState[]) : [];
|
|
63
|
+
};
|
|
64
|
+
return readJsonFileCoalesced(tasksPath, TASK_READ_TTL_MS, parse);
|
|
65
|
+
} catch (error) {
|
|
66
|
+
logInternalError("powerbar.readTasks", error, tasksPath);
|
|
67
|
+
return [];
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function compactTokens(total: number): string {
|
|
72
|
+
return total >= 1000 ? `${Math.round(total / 1000)}k` : `${total}`;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function registerPiCrewPowerbarSegments(events: EventBus, config?: CrewUiConfig): void {
|
|
76
|
+
if (config?.powerbar === false) return;
|
|
77
|
+
safeEmit(events, "powerbar:register-segment", {
|
|
78
|
+
id: "pi-crew-active",
|
|
79
|
+
label: "pi-crew active agents",
|
|
80
|
+
});
|
|
81
|
+
safeEmit(events, "powerbar:register-segment", {
|
|
82
|
+
id: "pi-crew-progress",
|
|
83
|
+
label: "pi-crew run progress",
|
|
84
|
+
});
|
|
85
|
+
safeEmit(events, "powerbar:register-segment", {
|
|
86
|
+
id: "pi-crew-steps",
|
|
87
|
+
label: "pi-crew workflow steps",
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function updatePiCrewPowerbar(
|
|
92
|
+
events: EventBus,
|
|
93
|
+
cwd: string,
|
|
94
|
+
config?: CrewUiConfig,
|
|
95
|
+
manifestCache?: ManifestCache,
|
|
96
|
+
snapshotCache?: RunSnapshotCache,
|
|
97
|
+
ctx?: StatusContext,
|
|
98
|
+
notificationCount = 0,
|
|
99
|
+
preloadedManifests?: TeamRunManifest[],
|
|
100
|
+
): void {
|
|
101
|
+
powerbarPublisher.update(events, cwd, config, manifestCache, snapshotCache, ctx, notificationCount, preloadedManifests);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// --- Dedup state + coalescer live on a class instance so they survive hot-reload
|
|
105
|
+
// cleanly: previously these were module-level globals (`lastActiveKey`,
|
|
106
|
+
// `latestArgs`, `powerbarCoalescer`) that survived across reloads and could
|
|
107
|
+
// leak between independent sessions. Encapsulating the state on an instance
|
|
108
|
+
// lets `dispose()` tear it down and a fresh `new PowerbarPublisher()` start
|
|
109
|
+
// from clean slate. The module-level functions remain for back-compat and
|
|
110
|
+
// delegate to a process-wide singleton.
|
|
111
|
+
|
|
112
|
+
interface PowerbarPayloadShape {
|
|
113
|
+
id?: string;
|
|
114
|
+
text?: string;
|
|
115
|
+
suffix?: string;
|
|
116
|
+
bar?: number;
|
|
117
|
+
color?: string;
|
|
118
|
+
icon?: string;
|
|
119
|
+
barSegments?: number;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function powerbarKey(payload: PowerbarPayloadShape): string {
|
|
123
|
+
return `${payload.text ?? ""}|${payload.suffix ?? ""}|${payload.bar ?? ""}|${payload.color ?? ""}|${payload.icon ?? ""}|${payload.barSegments ?? ""}`;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
interface ActiveItem {
|
|
127
|
+
run: TeamRunManifest;
|
|
128
|
+
agents: ReturnType<typeof readCrewAgents>;
|
|
129
|
+
tasks: TeamTaskState[];
|
|
130
|
+
snapshot?: RunUiSnapshot;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Build the workflow steps segment showing: ✓explore › →plan › ○execute › ○verify
|
|
135
|
+
* with the current/active step highlighted using → arrow.
|
|
136
|
+
*/
|
|
137
|
+
function buildStepsPayload(active: ActiveItem[], allTasks: TeamTaskState[]): PowerbarPayloadShape {
|
|
138
|
+
if (!active.length) {
|
|
139
|
+
return { id: "pi-crew-steps" };
|
|
140
|
+
}
|
|
141
|
+
const run = active[0]!.run;
|
|
142
|
+
const workflowName = run.workflow ?? "default";
|
|
143
|
+
// Load workflow steps
|
|
144
|
+
const workflows = allWorkflows(discoverWorkflows(run.cwd));
|
|
145
|
+
const workflow = workflows.find((w) => w.name === workflowName);
|
|
146
|
+
if (!workflow || workflow.steps.length === 0) {
|
|
147
|
+
return { id: "pi-crew-steps", text: workflowName };
|
|
148
|
+
}
|
|
149
|
+
// Build step status map from tasks
|
|
150
|
+
const stepStatus = new Map<string, "completed" | "running" | "pending">();
|
|
151
|
+
for (const task of allTasks) {
|
|
152
|
+
if (!task.stepId) continue;
|
|
153
|
+
if (!stepStatus.has(task.stepId)) {
|
|
154
|
+
if (task.status === "completed") {
|
|
155
|
+
stepStatus.set(task.stepId, "completed");
|
|
156
|
+
} else if (task.status === "running" || task.status === "queued" || task.status === "waiting") {
|
|
157
|
+
stepStatus.set(task.stepId, "running");
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
// Format: "✓explore › →plan › ○execute › ○verify"
|
|
162
|
+
// ✓ = completed, → = running (current), ○ = pending
|
|
163
|
+
const stepParts: string[] = [];
|
|
164
|
+
for (const step of workflow.steps) {
|
|
165
|
+
const status = stepStatus.get(step.id) ?? "pending";
|
|
166
|
+
const icon = status === "completed" ? "✓" : status === "running" ? "→" : "○";
|
|
167
|
+
// Shorten long step names
|
|
168
|
+
const stepName = step.id.length > 10 ? step.id.slice(0, 9) + "…" : step.id;
|
|
169
|
+
stepParts.push(`${icon}${stepName}`);
|
|
170
|
+
}
|
|
171
|
+
const stepsText = stepParts.join(" › ");
|
|
172
|
+
// Color: accent if running step exists, success if all complete, dim otherwise
|
|
173
|
+
const hasRunningStep = [...stepStatus.values()].includes("running");
|
|
174
|
+
const allComplete = stepStatus.size === workflow.steps.length && ![...stepStatus.values()].includes("running");
|
|
175
|
+
const color = allComplete ? "success" : hasRunningStep ? "accent" : "dim";
|
|
176
|
+
return {
|
|
177
|
+
id: "pi-crew-steps",
|
|
178
|
+
text: stepsText,
|
|
179
|
+
color,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// --- Coalesced powerbar update ---
|
|
184
|
+
|
|
185
|
+
interface PowerbarUpdateArgs {
|
|
186
|
+
events: EventBus;
|
|
187
|
+
cwd: string;
|
|
188
|
+
config?: CrewUiConfig;
|
|
189
|
+
manifestCache?: ManifestCache;
|
|
190
|
+
snapshotCache?: RunSnapshotCache;
|
|
191
|
+
ctx?: StatusContext;
|
|
192
|
+
notificationCount: number;
|
|
193
|
+
preloadedManifests?: TeamRunManifest[];
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Owns the per-segment dedup keys and the coalescer. Module-level functions
|
|
198
|
+
* (`updatePiCrewPowerbar`, `requestPowerbarUpdate`, etc.) are thin facades
|
|
199
|
+
* over a process-wide singleton so existing call sites and tests keep
|
|
200
|
+
* working without code changes.
|
|
201
|
+
*/
|
|
202
|
+
class PowerbarPublisher {
|
|
203
|
+
#lastActiveKey: string | undefined;
|
|
204
|
+
#lastProgressKey: string | undefined;
|
|
205
|
+
#lastStepsKey: string | undefined;
|
|
206
|
+
#latestArgs: PowerbarUpdateArgs | null = null;
|
|
207
|
+
readonly #coalescer: RenderCoalescer;
|
|
208
|
+
|
|
209
|
+
constructor() {
|
|
210
|
+
this.#coalescer = new RenderCoalescer(() => {
|
|
211
|
+
const a = this.#latestArgs;
|
|
212
|
+
this.#latestArgs = null;
|
|
213
|
+
if (!a) return;
|
|
214
|
+
this.update(a.events, a.cwd, a.config, a.manifestCache, a.snapshotCache, a.ctx, a.notificationCount, a.preloadedManifests);
|
|
215
|
+
}, 200);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
update(
|
|
219
|
+
events: EventBus,
|
|
220
|
+
cwd: string,
|
|
221
|
+
config?: CrewUiConfig,
|
|
222
|
+
manifestCache?: ManifestCache,
|
|
223
|
+
snapshotCache?: RunSnapshotCache,
|
|
224
|
+
ctx?: StatusContext,
|
|
225
|
+
notificationCount = 0,
|
|
226
|
+
preloadedManifests?: TeamRunManifest[],
|
|
227
|
+
): void {
|
|
228
|
+
if (config?.powerbar === false) return;
|
|
229
|
+
const useStatusFallback = !hasPowerbarConsumer(events);
|
|
230
|
+
const runs = preloadedManifests ?? (manifestCache ? manifestCache.list(20) : listRecentRuns(cwd, 20));
|
|
231
|
+
const active = runs
|
|
232
|
+
.map((run) => {
|
|
233
|
+
let snapshot: RunUiSnapshot | undefined;
|
|
234
|
+
try {
|
|
235
|
+
// 1.2: render path is read-only. Use cache.get() only; the background
|
|
236
|
+
// preload loop in register.ts populates entries on its own cadence.
|
|
237
|
+
snapshot = snapshotCache?.get(run.runId);
|
|
238
|
+
} catch (error) {
|
|
239
|
+
logInternalError("powerbar.snapshot", error, run.runId);
|
|
240
|
+
}
|
|
241
|
+
if (snapshot)
|
|
242
|
+
return {
|
|
243
|
+
run: snapshot.manifest,
|
|
244
|
+
agents: snapshot.agents,
|
|
245
|
+
tasks: snapshot.tasks,
|
|
246
|
+
snapshot,
|
|
247
|
+
};
|
|
248
|
+
let agents: ReturnType<typeof readCrewAgents> = [];
|
|
249
|
+
try {
|
|
250
|
+
agents = readCrewAgents(run);
|
|
251
|
+
} catch (error) {
|
|
252
|
+
logInternalError("powerbar.readCrewAgents", error, run.runId);
|
|
253
|
+
}
|
|
254
|
+
return { run, agents, tasks: readTasks(run.tasksPath), snapshot };
|
|
255
|
+
})
|
|
256
|
+
.filter((item) => isDisplayActiveRun(item.run, item.agents));
|
|
257
|
+
if (!active.length) {
|
|
258
|
+
this.#lastActiveKey = undefined;
|
|
259
|
+
this.#lastProgressKey = undefined;
|
|
260
|
+
this.#lastStepsKey = undefined;
|
|
261
|
+
safeEmit(events, "powerbar:update", { id: "pi-crew-active" });
|
|
262
|
+
safeEmit(events, "powerbar:update", { id: "pi-crew-progress" });
|
|
263
|
+
safeEmit(events, "powerbar:update", { id: "pi-crew-steps" });
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
const agents = active.flatMap((item) => item.agents);
|
|
267
|
+
const tasks = active.flatMap((item) => item.tasks);
|
|
268
|
+
const running = agents.filter((agent) => agent.status === "running").length;
|
|
269
|
+
const waiting = active.reduce(
|
|
270
|
+
(sum, item) =>
|
|
271
|
+
sum +
|
|
272
|
+
(item.snapshot
|
|
273
|
+
? item.snapshot.progress.queued + (item.snapshot.progress.waiting ?? 0)
|
|
274
|
+
: item.tasks.reduce((s, t) => s + (t.status === "queued" || t.status === "waiting" ? 1 : 0), 0)),
|
|
275
|
+
0,
|
|
276
|
+
);
|
|
277
|
+
const completed = active.reduce(
|
|
278
|
+
(sum, item) =>
|
|
279
|
+
sum + (item.snapshot?.progress.completed ?? item.tasks.reduce((s, t) => s + (t.status === "completed" ? 1 : 0), 0)),
|
|
280
|
+
0,
|
|
281
|
+
);
|
|
282
|
+
const total = Math.max(
|
|
283
|
+
1,
|
|
284
|
+
active.reduce((sum, item) => sum + (item.snapshot?.progress.total ?? item.tasks.length), 0) || agents.length,
|
|
285
|
+
);
|
|
286
|
+
const usage = aggregateUsage(tasks);
|
|
287
|
+
const snapshotTokens = active.reduce(
|
|
288
|
+
(sum, item) => sum + (item.snapshot ? item.snapshot.usage.tokensIn + item.snapshot.usage.tokensOut : 0),
|
|
289
|
+
0,
|
|
290
|
+
);
|
|
291
|
+
const hasUsage = usage && (usage.input ?? 0) + (usage.output ?? 0) + (usage.cacheRead ?? 0) + (usage.cacheWrite ?? 0) > 0;
|
|
292
|
+
const tokenTotal = hasUsage
|
|
293
|
+
? (usage.input ?? 0) + (usage.output ?? 0) + (usage.cacheRead ?? 0) + (usage.cacheWrite ?? 0)
|
|
294
|
+
: snapshotTokens;
|
|
295
|
+
const model =
|
|
296
|
+
config?.showModel === false
|
|
297
|
+
? undefined
|
|
298
|
+
: agents
|
|
299
|
+
.find((agent) => agent.model)
|
|
300
|
+
?.model?.split("/")
|
|
301
|
+
.at(-1);
|
|
302
|
+
const tokenText = config?.showTokens === false || !tokenTotal ? undefined : compactTokens(tokenTotal);
|
|
303
|
+
const liveRunning = listLiveAgents().filter((a) => a.status === "running").length;
|
|
304
|
+
// Always show consistent status: running count + queued count from live tasks only
|
|
305
|
+
// Avoid snapshot cache for counts to prevent UI jumping
|
|
306
|
+
const runningCount = agents.filter((a) => a.status === "running").length;
|
|
307
|
+
// Count queued/waiting tasks directly from tasks array (not snapshot) for consistency
|
|
308
|
+
const queuedCount = active.reduce(
|
|
309
|
+
(sum, item) => sum + item.tasks.reduce((s, t) => s + (t.status === "queued" || t.status === "waiting" ? 1 : 0), 0),
|
|
310
|
+
0,
|
|
311
|
+
);
|
|
312
|
+
// Format: "1 running", "2 running · 1 queued", "3 queued", "idle"
|
|
313
|
+
const runningLabel = runningCount === 1 ? "1 running" : `${runningCount} running`;
|
|
314
|
+
const queuedLabel = queuedCount === 1 ? "1 queued" : `${queuedCount} queued`;
|
|
315
|
+
const crewStatus =
|
|
316
|
+
runningCount > 0 && queuedCount > 0
|
|
317
|
+
? `${runningLabel} · ${queuedLabel}`
|
|
318
|
+
: runningCount > 0
|
|
319
|
+
? runningLabel
|
|
320
|
+
: queuedCount > 0
|
|
321
|
+
? queuedLabel
|
|
322
|
+
: "idle";
|
|
323
|
+
const liveSuffix = liveRunning > 0 ? ` (${liveRunning} live)` : "";
|
|
324
|
+
const notificationText = notificationBadge(notificationCount);
|
|
325
|
+
// Always show model + tokens as suffix when available (for activePayload consistency)
|
|
326
|
+
const suffixParts = [model, tokenText].filter(Boolean);
|
|
327
|
+
const activeSuffix = suffixParts.length > 0 ? suffixParts.join(" · ") : undefined;
|
|
328
|
+
// Progress always includes token count for consistency
|
|
329
|
+
const progressSuffix = `${completed}/${total}${tokenText ? ` · ${tokenText}` : ""}`;
|
|
330
|
+
// Build complete, always-consistent fallback text AND event payload to prevent UI flickering
|
|
331
|
+
// Both fallback and events must use the SAME format - no conditional display
|
|
332
|
+
// Format: "⚙ 1 running · 1 queued · model · 30k · 0/1" (never changes based on availability)
|
|
333
|
+
const progressPart = `${completed}/${total}`;
|
|
334
|
+
const allParts = [`⚙ ${crewStatus}`, model ?? "", tokenText ?? "", progressPart].filter(Boolean);
|
|
335
|
+
const unifiedText = allParts.join(" · ");
|
|
336
|
+
// activePayload.text includes notification badge for event payload
|
|
337
|
+
const activePayload = {
|
|
338
|
+
id: "pi-crew-active",
|
|
339
|
+
icon: "⚙",
|
|
340
|
+
text: `⚙ ${crewStatus}${liveSuffix}${notificationText}${activeSuffix ? ` · ${activeSuffix}` : ""}`,
|
|
341
|
+
suffix: activeSuffix,
|
|
342
|
+
color: running ? "accent" : "warning",
|
|
343
|
+
} as const;
|
|
344
|
+
const progressPayload = {
|
|
345
|
+
id: "pi-crew-progress",
|
|
346
|
+
text: (active[0]?.run as TeamRunManifest)?.team ?? "crew",
|
|
347
|
+
bar: Math.round((completed / total) * 100),
|
|
348
|
+
suffix: progressSuffix,
|
|
349
|
+
color: completed === total ? "success" : "accent",
|
|
350
|
+
barSegments: 8,
|
|
351
|
+
} as const;
|
|
352
|
+
// Build step progress: "explorer > planner > executor > verifier" with current step highlighted
|
|
353
|
+
const stepsPayload = buildStepsPayload(active, tasks);
|
|
354
|
+
// 1.8: dedup per segment using a key over every visible field. Previously
|
|
355
|
+
// the dedup string only carried text/suffix/running, so changes to `bar`
|
|
356
|
+
// (progress %) or `color` could be swallowed and stale UI emitted again
|
|
357
|
+
// later as a single noisy burst.
|
|
358
|
+
const activeKey = powerbarKey(activePayload);
|
|
359
|
+
const progressKey = powerbarKey(progressPayload);
|
|
360
|
+
const stepsKey = powerbarKey(stepsPayload);
|
|
361
|
+
if (activeKey !== this.#lastActiveKey) {
|
|
362
|
+
this.#lastActiveKey = activeKey;
|
|
363
|
+
safeEmit(events, "powerbar:update", activePayload);
|
|
364
|
+
}
|
|
365
|
+
if (progressKey !== this.#lastProgressKey) {
|
|
366
|
+
this.#lastProgressKey = progressKey;
|
|
367
|
+
safeEmit(events, "powerbar:update", progressPayload);
|
|
368
|
+
}
|
|
369
|
+
if (stepsKey !== this.#lastStepsKey) {
|
|
370
|
+
this.#lastStepsKey = stepsKey;
|
|
371
|
+
safeEmit(events, "powerbar:update", stepsPayload);
|
|
372
|
+
}
|
|
373
|
+
// Never call setStatusFallback - crew-widget manages "pi-crew" status with its own widget format
|
|
374
|
+
// Powerbar only emits events; it does not set status directly
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* Request a coalesced powerbar update. Multiple rapid calls are batched
|
|
379
|
+
* into a single render pass within 200ms, preventing UI flicker from
|
|
380
|
+
* event bursts.
|
|
381
|
+
*/
|
|
382
|
+
request(
|
|
383
|
+
events: EventBus,
|
|
384
|
+
cwd: string,
|
|
385
|
+
config?: CrewUiConfig,
|
|
386
|
+
manifestCache?: ManifestCache,
|
|
387
|
+
snapshotCache?: RunSnapshotCache,
|
|
388
|
+
ctx?: StatusContext,
|
|
389
|
+
notificationCount = 0,
|
|
390
|
+
preloadedManifests?: TeamRunManifest[],
|
|
391
|
+
): void {
|
|
392
|
+
if (config?.powerbar === false) return;
|
|
393
|
+
this.#latestArgs = {
|
|
394
|
+
events,
|
|
395
|
+
cwd,
|
|
396
|
+
config,
|
|
397
|
+
manifestCache,
|
|
398
|
+
snapshotCache,
|
|
399
|
+
ctx,
|
|
400
|
+
notificationCount,
|
|
401
|
+
preloadedManifests,
|
|
402
|
+
};
|
|
403
|
+
this.#coalescer.request();
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
clear(events: EventBus): void {
|
|
407
|
+
this.#lastActiveKey = undefined;
|
|
408
|
+
this.#lastProgressKey = undefined;
|
|
409
|
+
this.#lastStepsKey = undefined;
|
|
410
|
+
safeEmit(events, "powerbar:update", { id: "pi-crew-active" });
|
|
411
|
+
safeEmit(events, "powerbar:update", { id: "pi-crew-progress" });
|
|
412
|
+
safeEmit(events, "powerbar:update", { id: "pi-crew-steps" });
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/** Reset dedup state on session lifecycle events. */
|
|
416
|
+
resetDedupState(): void {
|
|
417
|
+
this.#lastActiveKey = undefined;
|
|
418
|
+
this.#lastProgressKey = undefined;
|
|
419
|
+
this.#lastStepsKey = undefined;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
dispose(): void {
|
|
423
|
+
this.#coalescer.flush();
|
|
424
|
+
this.#coalescer.dispose();
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
const powerbarPublisher = new PowerbarPublisher();
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* Request a coalesced powerbar update. Multiple rapid calls are batched into a single
|
|
432
|
+
* render pass within 200ms, preventing UI flicker from event bursts.
|
|
433
|
+
*/
|
|
434
|
+
export function requestPowerbarUpdate(
|
|
435
|
+
events: EventBus,
|
|
436
|
+
cwd: string,
|
|
437
|
+
config?: CrewUiConfig,
|
|
438
|
+
manifestCache?: ManifestCache,
|
|
439
|
+
snapshotCache?: RunSnapshotCache,
|
|
440
|
+
ctx?: StatusContext,
|
|
441
|
+
notificationCount = 0,
|
|
442
|
+
preloadedManifests?: TeamRunManifest[],
|
|
443
|
+
): void {
|
|
444
|
+
powerbarPublisher.request(events, cwd, config, manifestCache, snapshotCache, ctx, notificationCount, preloadedManifests);
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
/** Dispose the powerbar coalescer. Call during extension cleanup. */
|
|
448
|
+
export function disposePowerbarCoalescer(): void {
|
|
449
|
+
powerbarPublisher.dispose();
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
export function clearPiCrewPowerbar(events: EventBus): void {
|
|
453
|
+
powerbarPublisher.clear(events);
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
/** Reset dedup state on session lifecycle events. */
|
|
457
|
+
export function resetPowerbarDedupState(): void {
|
|
458
|
+
powerbarPublisher.resetDedupState();
|
|
459
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RenderCoalescer — batches multiple render requests into single render passes.
|
|
3
|
+
* Prevents UI flicker when many events arrive in quick succession.
|
|
4
|
+
* Inspired by oh-my-pi's PROGRESS_COALESCE_MS (150ms) pattern.
|
|
5
|
+
*/
|
|
6
|
+
import { logInternalError } from "../utils/internal-error.ts";
|
|
7
|
+
|
|
8
|
+
export interface RenderCoalescerOptions {
|
|
9
|
+
/**
|
|
10
|
+
* Invoked once per coalesce window with the number of `request()` calls
|
|
11
|
+
* that were collapsed into the most recent scheduled render. Defaults to
|
|
12
|
+
* a debug-scoped `logInternalError` so dropped bursts surface in logs
|
|
13
|
+
* (gated behind PI_TEAMS_DEBUG) without callers having to wire one up.
|
|
14
|
+
*/
|
|
15
|
+
onDrop?: (droppedCount: number) => void;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export class RenderCoalescer {
|
|
19
|
+
#pending = false;
|
|
20
|
+
#timerId: ReturnType<typeof setTimeout> | null = null;
|
|
21
|
+
#callback: () => void;
|
|
22
|
+
#intervalMs: number;
|
|
23
|
+
#onDrop: (droppedCount: number) => void;
|
|
24
|
+
#dropped = 0;
|
|
25
|
+
|
|
26
|
+
constructor(callback: () => void, intervalMs = 32, options: RenderCoalescerOptions = {}) {
|
|
27
|
+
this.#callback = callback;
|
|
28
|
+
this.#intervalMs = intervalMs;
|
|
29
|
+
this.#onDrop =
|
|
30
|
+
options.onDrop ??
|
|
31
|
+
((count) => {
|
|
32
|
+
logInternalError(
|
|
33
|
+
"render-coalescer",
|
|
34
|
+
new Error(`coalesced ${count} dropped request(s) into a single render`),
|
|
35
|
+
undefined,
|
|
36
|
+
"debug",
|
|
37
|
+
);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Request a render. Will be coalesced with other requests within the interval. */
|
|
42
|
+
request(): void {
|
|
43
|
+
if (this.#pending) {
|
|
44
|
+
// A render is already scheduled — coalesce this request and bump
|
|
45
|
+
// the drop counter so the scheduled flush can report how many
|
|
46
|
+
// bursts were collapsed (useful for diagnosing UI lag).
|
|
47
|
+
this.#dropped += 1;
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
this.#pending = true;
|
|
51
|
+
const timer = setTimeout(() => {
|
|
52
|
+
this.#pending = false;
|
|
53
|
+
this.#timerId = null;
|
|
54
|
+
const dropped = this.#dropped;
|
|
55
|
+
this.#dropped = 0;
|
|
56
|
+
if (dropped > 0) {
|
|
57
|
+
try {
|
|
58
|
+
this.#onDrop(dropped);
|
|
59
|
+
} catch {
|
|
60
|
+
/* drop callback errors are non-fatal */
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
this.#callback();
|
|
64
|
+
}, this.#intervalMs);
|
|
65
|
+
timer.unref();
|
|
66
|
+
this.#timerId = timer;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Force an immediate render, bypassing coalescing. */
|
|
70
|
+
flush(): void {
|
|
71
|
+
if (this.#timerId !== null) {
|
|
72
|
+
clearTimeout(this.#timerId);
|
|
73
|
+
this.#timerId = null;
|
|
74
|
+
}
|
|
75
|
+
this.#pending = false;
|
|
76
|
+
const dropped = this.#dropped;
|
|
77
|
+
this.#dropped = 0;
|
|
78
|
+
if (dropped > 0) {
|
|
79
|
+
try {
|
|
80
|
+
this.#onDrop(dropped);
|
|
81
|
+
} catch {
|
|
82
|
+
/* drop callback errors are non-fatal */
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
this.#callback();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** Check if a render is pending. */
|
|
89
|
+
get pending(): boolean {
|
|
90
|
+
return this.#pending;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** Clean up timers. Call when the coalescer is no longer needed. */
|
|
94
|
+
dispose(): void {
|
|
95
|
+
if (this.#timerId !== null) {
|
|
96
|
+
clearTimeout(this.#timerId);
|
|
97
|
+
this.#timerId = null;
|
|
98
|
+
}
|
|
99
|
+
this.#pending = false;
|
|
100
|
+
}
|
|
101
|
+
}
|