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,152 @@
|
|
|
1
|
+
import { logInternalError } from "../utils/internal-error.ts";
|
|
2
|
+
|
|
3
|
+
export type Severity = "info" | "warning" | "error" | "critical";
|
|
4
|
+
|
|
5
|
+
export interface NotificationDescriptor {
|
|
6
|
+
id?: string;
|
|
7
|
+
severity: Severity;
|
|
8
|
+
source: string;
|
|
9
|
+
runId?: string;
|
|
10
|
+
title: string;
|
|
11
|
+
body?: string;
|
|
12
|
+
timestamp?: number;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface NotificationRouterOptions {
|
|
16
|
+
dedupWindowMs?: number;
|
|
17
|
+
batchWindowMs?: number;
|
|
18
|
+
quietHours?: string;
|
|
19
|
+
severityFilter?: Severity[];
|
|
20
|
+
sink?: (notification: NotificationDescriptor) => void;
|
|
21
|
+
now?: () => number;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const DEFAULT_SEVERITY_FILTER: Severity[] = ["warning", "error", "critical"];
|
|
25
|
+
const SEVERITY_RANK: Record<Severity, number> = {
|
|
26
|
+
info: 0,
|
|
27
|
+
warning: 1,
|
|
28
|
+
error: 2,
|
|
29
|
+
critical: 3,
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export function parseHHMMRange(range: string): {
|
|
33
|
+
startMin: number;
|
|
34
|
+
endMin: number;
|
|
35
|
+
} {
|
|
36
|
+
const match = /^(\d{2}):(\d{2})-(\d{2}):(\d{2})$/.exec(range);
|
|
37
|
+
if (!match) throw new Error(`Invalid quiet-hours range '${range}'. Expected HH:MM-HH:MM.`);
|
|
38
|
+
const [, sh, sm, eh, em] = match;
|
|
39
|
+
const startHour = Number(sh);
|
|
40
|
+
const startMinute = Number(sm);
|
|
41
|
+
const endHour = Number(eh);
|
|
42
|
+
const endMinute = Number(em);
|
|
43
|
+
if (startHour > 23 || endHour > 23 || startMinute > 59 || endMinute > 59) throw new Error(`Invalid quiet-hours range '${range}'.`);
|
|
44
|
+
return {
|
|
45
|
+
startMin: startHour * 60 + startMinute,
|
|
46
|
+
endMin: endHour * 60 + endMinute,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function isInQuietHours(range: string, now = new Date()): boolean {
|
|
51
|
+
const { startMin, endMin } = parseHHMMRange(range);
|
|
52
|
+
const current = now.getHours() * 60 + now.getMinutes();
|
|
53
|
+
if (startMin === endMin) return false;
|
|
54
|
+
return startMin <= endMin ? current >= startMin && current < endMin : current >= startMin || current < endMin;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function notificationKey(notification: NotificationDescriptor): string {
|
|
58
|
+
return notification.id ?? `${notification.source}:${notification.runId ?? "global"}:${notification.title}`;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function batchSeverity(items: NotificationDescriptor[]): Severity {
|
|
62
|
+
return items.reduce(
|
|
63
|
+
(highest, item) => (SEVERITY_RANK[item.severity] > SEVERITY_RANK[highest] ? item.severity : highest),
|
|
64
|
+
"info" as Severity,
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export class NotificationRouter {
|
|
69
|
+
private readonly opts: NotificationRouterOptions;
|
|
70
|
+
private readonly deliver: (notification: NotificationDescriptor) => void;
|
|
71
|
+
private readonly seen = new Map<string, number>();
|
|
72
|
+
private batch: NotificationDescriptor[] = [];
|
|
73
|
+
private timer: ReturnType<typeof setTimeout> | undefined;
|
|
74
|
+
private static readonly SEEN_MAP_MAX_SIZE = 10000;
|
|
75
|
+
|
|
76
|
+
constructor(opts: NotificationRouterOptions = {}, deliver: (notification: NotificationDescriptor) => void) {
|
|
77
|
+
this.opts = opts;
|
|
78
|
+
this.deliver = deliver;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Evict oldest entries from seen Map if it exceeds MAX_SIZE.
|
|
83
|
+
* This prevents unbounded memory growth from notifications without TTL.
|
|
84
|
+
*/
|
|
85
|
+
private evictSeenIfNeeded(): void {
|
|
86
|
+
if (this.seen.size > NotificationRouter.SEEN_MAP_MAX_SIZE) {
|
|
87
|
+
// Sort by timestamp (oldest first) and keep only half
|
|
88
|
+
const entries = [...this.seen.entries()].sort((a, b) => a[1] - b[1]);
|
|
89
|
+
const keepCount = Math.floor(NotificationRouter.SEEN_MAP_MAX_SIZE / 2);
|
|
90
|
+
for (const [key] of entries.slice(0, entries.length - keepCount)) {
|
|
91
|
+
this.seen.delete(key);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
enqueue(notification: NotificationDescriptor): boolean {
|
|
97
|
+
const now = this.opts.now?.() ?? Date.now();
|
|
98
|
+
const withTime = {
|
|
99
|
+
...notification,
|
|
100
|
+
timestamp: notification.timestamp ?? now,
|
|
101
|
+
};
|
|
102
|
+
try {
|
|
103
|
+
this.opts.sink?.(withTime);
|
|
104
|
+
} catch (sinkError) {
|
|
105
|
+
logInternalError("notification-sink", sinkError);
|
|
106
|
+
}
|
|
107
|
+
const filter = this.opts.severityFilter ?? DEFAULT_SEVERITY_FILTER;
|
|
108
|
+
if (!filter.includes(withTime.severity)) return false;
|
|
109
|
+
if (this.opts.quietHours && isInQuietHours(this.opts.quietHours, new Date(now))) return false;
|
|
110
|
+
const key = notificationKey(withTime);
|
|
111
|
+
const dedupWindow = this.opts.dedupWindowMs ?? 30_000;
|
|
112
|
+
const previous = this.seen.get(key);
|
|
113
|
+
if (previous !== undefined && now - previous < dedupWindow) return false;
|
|
114
|
+
this.seen.set(key, now);
|
|
115
|
+
this.evictSeenIfNeeded();
|
|
116
|
+
const batchWindow = this.opts.batchWindowMs ?? 0;
|
|
117
|
+
if (batchWindow <= 0) {
|
|
118
|
+
this.deliver(withTime);
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
this.batch.push(withTime);
|
|
122
|
+
if (!this.timer) this.timer = setTimeout(() => this.flush(), batchWindow);
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
flush(): void {
|
|
127
|
+
if (this.timer) clearTimeout(this.timer);
|
|
128
|
+
this.timer = undefined;
|
|
129
|
+
if (this.batch.length === 0) return;
|
|
130
|
+
const items = this.batch;
|
|
131
|
+
this.batch = [];
|
|
132
|
+
if (items.length === 1) {
|
|
133
|
+
this.deliver(items[0]!);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
this.deliver({
|
|
137
|
+
id: `batch:${items.map((item) => notificationKey(item)).join(",")}`,
|
|
138
|
+
severity: batchSeverity(items),
|
|
139
|
+
source: "batch",
|
|
140
|
+
title: `${items.length} pi-crew notifications`,
|
|
141
|
+
body: items.map((item) => `• ${item.title}`).join("\n"),
|
|
142
|
+
timestamp: this.opts.now?.() ?? Date.now(),
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
dispose(): void {
|
|
147
|
+
if (this.timer) clearTimeout(this.timer);
|
|
148
|
+
this.timer = undefined;
|
|
149
|
+
this.batch = [];
|
|
150
|
+
this.seen.clear();
|
|
151
|
+
}
|
|
152
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import { logInternalError } from "../utils/internal-error.ts";
|
|
4
|
+
import { redactSecrets } from "../utils/redaction.ts";
|
|
5
|
+
import type { NotificationDescriptor } from "./notification-router.ts";
|
|
6
|
+
|
|
7
|
+
export interface NotificationSink {
|
|
8
|
+
write(notification: NotificationDescriptor): void;
|
|
9
|
+
dispose(): void;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function rotateOldFiles(dir: string, retentionDays: number, now = Date.now()): void {
|
|
13
|
+
if (!fs.existsSync(dir)) return;
|
|
14
|
+
const cutoff = now - retentionDays * 24 * 60 * 60 * 1000;
|
|
15
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
16
|
+
if (!entry.isFile() || !entry.name.endsWith(".jsonl")) continue;
|
|
17
|
+
const filePath = path.join(dir, entry.name);
|
|
18
|
+
try {
|
|
19
|
+
if (fs.statSync(filePath).mtimeMs < cutoff) fs.unlinkSync(filePath);
|
|
20
|
+
} catch (error) {
|
|
21
|
+
logInternalError("notification-sink.rotate", error, filePath);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function createJsonlSink(crewRoot: string, retentionDays = 7): NotificationSink {
|
|
27
|
+
const dir = path.join(crewRoot, "state", "notifications");
|
|
28
|
+
let lastRotateDate = "";
|
|
29
|
+
return {
|
|
30
|
+
write(notification: NotificationDescriptor): void {
|
|
31
|
+
try {
|
|
32
|
+
const timestamp = notification.timestamp ?? Date.now();
|
|
33
|
+
const date = new Date(timestamp).toISOString().slice(0, 10);
|
|
34
|
+
if (date !== lastRotateDate) {
|
|
35
|
+
rotateOldFiles(dir, retentionDays, timestamp);
|
|
36
|
+
lastRotateDate = date;
|
|
37
|
+
}
|
|
38
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
39
|
+
const payload = redactSecrets({
|
|
40
|
+
...notification,
|
|
41
|
+
timestamp,
|
|
42
|
+
}) as NotificationDescriptor;
|
|
43
|
+
fs.appendFileSync(path.join(dir, `${date}.jsonl`), `${JSON.stringify(payload)}\n`, "utf-8");
|
|
44
|
+
} catch (error) {
|
|
45
|
+
logInternalError("notification-sink.write", error);
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
dispose(): void {
|
|
49
|
+
// Synchronous append-only sink has no resources to close.
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export const __test__ = { rotateOldFiles };
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pi-api.ts — pi-crew's stable seam against the Pi extension API.
|
|
3
|
+
*
|
|
4
|
+
* PURPOSE (roadmap Phase 0 / Pillar 4 "Pi-Native, Protocol-Aware"):
|
|
5
|
+
* Centralize every symbol pi-crew imports from
|
|
6
|
+
* `@earendil-works/pi-coding-agent` so that:
|
|
7
|
+
* 1. The coupling surface is auditable in ONE file (8 symbols today).
|
|
8
|
+
* 2. A Pi API rename/restructure requires updating only this seam.
|
|
9
|
+
* 3. New code imports from here ("./pi-api") rather than the raw package,
|
|
10
|
+
* establishing the indirection that hedges Pi-coupling risk.
|
|
11
|
+
*
|
|
12
|
+
* COUpling SURFACE (kept intentionally small — public extension API only):
|
|
13
|
+
* - ExtensionAPI the registration entry point (pi)
|
|
14
|
+
* - ExtensionContext per-event/session context (ctx)
|
|
15
|
+
* - ExtensionCommandContext slash-command context
|
|
16
|
+
* - ToolDefinition tool schema type
|
|
17
|
+
* - defineTool tool factory
|
|
18
|
+
* - createBashTool built-in bash tool (for custom tooling)
|
|
19
|
+
* - AgentSessionEvent session event type
|
|
20
|
+
* - BeforeAgentStartEvent pre-turn system-prompt hook event
|
|
21
|
+
*
|
|
22
|
+
* NEW code should `import { ExtensionAPI, ExtensionContext } from "./pi-api"`.
|
|
23
|
+
* Existing files may keep their direct imports; migrate opportunistically
|
|
24
|
+
* (no big-bang refactor — see roadmap Phase 0 T0.3/T0.4 notes).
|
|
25
|
+
*
|
|
26
|
+
* Note: these are TYPE-level re-exports (erased at runtime). Runtime coupling
|
|
27
|
+
* to Pi is via the `pi` and `ctx` objects passed by Pi's loader — that is
|
|
28
|
+
* unavoidable and correct (pi-crew IS a Pi extension). This seam documents
|
|
29
|
+
* and centralizes the type-level surface.
|
|
30
|
+
*/
|
|
31
|
+
export type {
|
|
32
|
+
AgentSessionEvent,
|
|
33
|
+
BeforeAgentStartEvent,
|
|
34
|
+
ExtensionAPI,
|
|
35
|
+
ExtensionCommandContext,
|
|
36
|
+
ExtensionContext,
|
|
37
|
+
ToolDefinition,
|
|
38
|
+
} from "@earendil-works/pi-coding-agent";
|
|
39
|
+
|
|
40
|
+
export { createBashTool, defineTool } from "@earendil-works/pi-coding-agent";
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @deprecated Drift detector removed in Phase 5 follow-up to H1.
|
|
44
|
+
*
|
|
45
|
+
* History: this constant was meant to surface version-drift between
|
|
46
|
+
* dev-time type-check and runtime peer-dep version. pi-crew declares
|
|
47
|
+
* peer deps as `*` so the runtime version is set by whatever host pi
|
|
48
|
+
* install the user has — pinning this constant to a specific devDep
|
|
49
|
+
* range was a false invariant that did not reflect how extensions
|
|
50
|
+
* actually consume peer packages.
|
|
51
|
+
*
|
|
52
|
+
* Kept exported (now `"0.0.0-unset"`) only for any downstream consumers
|
|
53
|
+
* that may import it via re-exports. No diagnostic uses it anymore.
|
|
54
|
+
* Will be removed in a future major version.
|
|
55
|
+
*/
|
|
56
|
+
export const BUILT_AGAINST_PI_VERSION = "0.0.0-unset";
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plan Orchestrate — Decompose plan documents into agent chain commands.
|
|
3
|
+
*
|
|
4
|
+
* Parses tagged sections from markdown plan documents and builds commands
|
|
5
|
+
* for sequential agent chain execution based on ECC recommendations.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import * as fs from "node:fs";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Tag → Agent chain mapping from ECC recommendations.
|
|
12
|
+
*/
|
|
13
|
+
export const TAG_TO_CHAIN: Record<string, string[]> = {
|
|
14
|
+
design: ["planner", "architect"],
|
|
15
|
+
impl: ["tdd-guide", "lang-reviewer"],
|
|
16
|
+
security: ["security-reviewer", "lang-reviewer"],
|
|
17
|
+
build: ["build-error-resolver"],
|
|
18
|
+
test: ["test-engineer", "verifier"],
|
|
19
|
+
review: ["reviewer"],
|
|
20
|
+
} as const;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Options for plan orchestration.
|
|
24
|
+
*/
|
|
25
|
+
export interface OrchestrateOptions {
|
|
26
|
+
/** Path to the plan markdown document. */
|
|
27
|
+
planPath: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* A single orchestrated step parsed from a plan section.
|
|
32
|
+
*/
|
|
33
|
+
export interface OrchestratedStep {
|
|
34
|
+
/** Unique step identifier. */
|
|
35
|
+
stepId: string;
|
|
36
|
+
/** Tag from the parsed section. */
|
|
37
|
+
tag: string;
|
|
38
|
+
/** Agent chain for this step. */
|
|
39
|
+
chain: string[];
|
|
40
|
+
/** Prompt/goal text extracted from the section. */
|
|
41
|
+
prompt: string;
|
|
42
|
+
/** Raw heading text if present. */
|
|
43
|
+
heading?: string;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Parse tagged sections from a plan markdown document.
|
|
48
|
+
*
|
|
49
|
+
* Expected format:
|
|
50
|
+
* ```markdown
|
|
51
|
+
* # Design Phase
|
|
52
|
+
* <!-- tag: design -->
|
|
53
|
+
* Design the authentication system...
|
|
54
|
+
*
|
|
55
|
+
* # Implementation
|
|
56
|
+
* <!-- tag: impl -->
|
|
57
|
+
* Implement the JWT auth...
|
|
58
|
+
* ```
|
|
59
|
+
*
|
|
60
|
+
* @param planPath - Path to the plan markdown document.
|
|
61
|
+
* @returns Array of OrchestratedStep parsed from the document.
|
|
62
|
+
*/
|
|
63
|
+
export function parsePlanDocument(planPath: string): OrchestratedStep[] {
|
|
64
|
+
if (!fs.existsSync(planPath)) {
|
|
65
|
+
throw new Error(`Plan document not found: ${planPath}`);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const content = fs.readFileSync(planPath, "utf-8");
|
|
69
|
+
return parsePlanDocumentContent(content);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Parse tagged sections from plan content string.
|
|
74
|
+
* This is the core parsing logic used by both parsePlanDocument and parsePlanDocumentSimple.
|
|
75
|
+
*/
|
|
76
|
+
function parsePlanDocumentContent(content: string): OrchestratedStep[] {
|
|
77
|
+
const steps: OrchestratedStep[] = [];
|
|
78
|
+
|
|
79
|
+
// Find all tag matches with their positions
|
|
80
|
+
const tagRegex = /<!--\s*tag:\s*(\w+)\s*-->/g;
|
|
81
|
+
const tagMatches: Array<{ tag: string; start: number; end: number }> = [];
|
|
82
|
+
|
|
83
|
+
let match: RegExpExecArray | null;
|
|
84
|
+
while ((match = tagRegex.exec(content)) !== null) {
|
|
85
|
+
tagMatches.push({
|
|
86
|
+
tag: match[1],
|
|
87
|
+
start: match.index,
|
|
88
|
+
end: match.index + match[0].length,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (tagMatches.length === 0) {
|
|
93
|
+
return [];
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// For each tag, extract the content before it (to get heading)
|
|
97
|
+
// and the content after it until either another tag or section
|
|
98
|
+
for (let i = 0; i < tagMatches.length; i++) {
|
|
99
|
+
const current = tagMatches[i];
|
|
100
|
+
const nextTagStart = i < tagMatches.length - 1 ? tagMatches[i + 1].start : content.length;
|
|
101
|
+
|
|
102
|
+
// Find the heading by looking back from the tag position.
|
|
103
|
+
// Use global regex to find ALL headings in the window, then take the LAST
|
|
104
|
+
// (nearest to the tag) — simple `.match()` only finds the FIRST heading.
|
|
105
|
+
const textBeforeTag = content.slice(Math.max(0, current.start - 500), current.start);
|
|
106
|
+
const headingRegex = /(^|\n)(#{1,6})\s+(.+?)(\n|$)/g;
|
|
107
|
+
let lastHeadingMatch: RegExpExecArray | null = null;
|
|
108
|
+
let hm: RegExpExecArray | null;
|
|
109
|
+
while ((hm = headingRegex.exec(textBeforeTag)) !== null) {
|
|
110
|
+
lastHeadingMatch = hm;
|
|
111
|
+
}
|
|
112
|
+
const heading = lastHeadingMatch ? lastHeadingMatch[3].trim() : undefined;
|
|
113
|
+
|
|
114
|
+
// Get content after the tag until next tag or heading
|
|
115
|
+
// Start from end of tag comment, skip any whitespace/newline
|
|
116
|
+
const afterTagContent = content.slice(current.end);
|
|
117
|
+
|
|
118
|
+
// Find the section content: capture until next heading (##) or next tag
|
|
119
|
+
const sectionEndMatch = afterTagContent.search(/(^|\n)(#{1,6}\s|\n<!--\s*tag:)/m);
|
|
120
|
+
const sectionContent = sectionEndMatch >= 0 ? afterTagContent.slice(0, sectionEndMatch) : afterTagContent;
|
|
121
|
+
|
|
122
|
+
// Extract prompt text - remove the tag comment lines and empty lines
|
|
123
|
+
const promptLines: string[] = [];
|
|
124
|
+
const lines = sectionContent.split("\n");
|
|
125
|
+
for (const line of lines) {
|
|
126
|
+
const trimmed = line.trim();
|
|
127
|
+
if (!trimmed || trimmed.startsWith("<!--")) continue;
|
|
128
|
+
promptLines.push(trimmed);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const prompt = promptLines.join("\n").trim();
|
|
132
|
+
if (!prompt) continue;
|
|
133
|
+
|
|
134
|
+
const chain = TAG_TO_CHAIN[current.tag] ?? [];
|
|
135
|
+
|
|
136
|
+
steps.push({
|
|
137
|
+
stepId: `step-${(i + 1).toString().padStart(2, "0")}-${current.tag}`,
|
|
138
|
+
tag: current.tag,
|
|
139
|
+
chain,
|
|
140
|
+
prompt,
|
|
141
|
+
heading,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return steps;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Alternative simpler parser for plans that use explicit tag blocks.
|
|
150
|
+
* Actually uses the same core logic as parsePlanDocument.
|
|
151
|
+
*
|
|
152
|
+
* @param planPath - Path to the plan markdown document.
|
|
153
|
+
* @returns Array of OrchestratedStep parsed from the document.
|
|
154
|
+
*/
|
|
155
|
+
export function parsePlanDocumentSimple(planPath: string): OrchestratedStep[] {
|
|
156
|
+
if (!fs.existsSync(planPath)) {
|
|
157
|
+
throw new Error(`Plan document not found: ${planPath}`);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const content = fs.readFileSync(planPath, "utf-8");
|
|
161
|
+
const steps = parsePlanDocumentContent(content);
|
|
162
|
+
|
|
163
|
+
if (steps.length === 0) {
|
|
164
|
+
// Try implicit detection
|
|
165
|
+
const tag = detectImplicitTag(content);
|
|
166
|
+
if (tag) {
|
|
167
|
+
return [
|
|
168
|
+
{
|
|
169
|
+
stepId: "step-01-unknown",
|
|
170
|
+
tag,
|
|
171
|
+
chain: TAG_TO_CHAIN[tag] ?? [],
|
|
172
|
+
prompt: content.trim(),
|
|
173
|
+
},
|
|
174
|
+
];
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return steps;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Detect implicit tag from content keywords when no explicit tag is present.
|
|
183
|
+
*/
|
|
184
|
+
function detectImplicitTag(content: string): string | undefined {
|
|
185
|
+
const lowerContent = content.toLowerCase();
|
|
186
|
+
// Use word-boundary regex to avoid substring false matches.
|
|
187
|
+
// E.g., "implementation" must NOT trigger "impl" — only the word "implement" should.
|
|
188
|
+
const hasWord = (word: string): boolean => new RegExp(`\\b${word}\\b`).test(lowerContent);
|
|
189
|
+
|
|
190
|
+
if (hasWord("design") || hasWord("architecture")) return "design";
|
|
191
|
+
if (hasWord("implement") || hasWord("coding")) return "impl";
|
|
192
|
+
if (hasWord("security") || hasWord("audit")) return "security";
|
|
193
|
+
if (hasWord("build") || hasWord("compile")) return "build";
|
|
194
|
+
if (hasWord("test") || hasWord("verify")) return "test";
|
|
195
|
+
if (hasWord("review") || hasWord("feedback")) return "review";
|
|
196
|
+
return undefined;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Build agent chain command strings from orchestrated steps.
|
|
201
|
+
*
|
|
202
|
+
* @param steps - Array of OrchestratedStep to convert to commands.
|
|
203
|
+
* @returns Array of command strings for execution.
|
|
204
|
+
*/
|
|
205
|
+
export function buildAgentChain(steps: OrchestratedStep[]): string[] {
|
|
206
|
+
return steps.map((step) => {
|
|
207
|
+
const agentList = step.chain.join(",");
|
|
208
|
+
// Escape single quotes in the goal for shell safety
|
|
209
|
+
const escapedGoal = step.prompt.replace(/'/g, "'\\''");
|
|
210
|
+
return `team action='run' agent='${agentList}' goal='${escapedGoal}'`;
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Build structured chain data (useful for programmatic use).
|
|
216
|
+
*
|
|
217
|
+
* @param steps - Array of OrchestratedStep to convert.
|
|
218
|
+
* @returns Array of chain objects with step data and commands.
|
|
219
|
+
*/
|
|
220
|
+
export function buildChainData(steps: OrchestratedStep[]): Array<{
|
|
221
|
+
step: OrchestratedStep;
|
|
222
|
+
commands: string[];
|
|
223
|
+
}> {
|
|
224
|
+
return steps.map((step) => ({
|
|
225
|
+
step,
|
|
226
|
+
commands: buildAgentChain([step]),
|
|
227
|
+
}));
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Parse and return a formatted overview of the plan.
|
|
232
|
+
*
|
|
233
|
+
* @param planPath - Path to the plan markdown document.
|
|
234
|
+
* @returns Summary string with step count and breakdown by tag.
|
|
235
|
+
*/
|
|
236
|
+
export function formatPlanOverview(planPath: string): string {
|
|
237
|
+
const steps = parsePlanDocument(planPath);
|
|
238
|
+
|
|
239
|
+
if (steps.length === 0) {
|
|
240
|
+
// Try simple parser
|
|
241
|
+
const simpleSteps = parsePlanDocumentSimple(planPath);
|
|
242
|
+
if (simpleSteps.length === 0) {
|
|
243
|
+
return "No tagged sections found in plan document.";
|
|
244
|
+
}
|
|
245
|
+
return formatStepsOverview(simpleSteps);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
return formatStepsOverview(steps);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
function formatStepsOverview(steps: OrchestratedStep[]): string {
|
|
252
|
+
const lines: string[] = [`Plan Orchestration: ${steps.length} step(s)`, ""];
|
|
253
|
+
|
|
254
|
+
const tagCounts: Record<string, number> = {};
|
|
255
|
+
for (const step of steps) {
|
|
256
|
+
tagCounts[step.tag] = (tagCounts[step.tag] ?? 0) + 1;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
lines.push("Summary by tag:");
|
|
260
|
+
for (const [tag, count] of Object.entries(tagCounts)) {
|
|
261
|
+
const chain = TAG_TO_CHAIN[tag]?.join(", ") ?? "(unknown)";
|
|
262
|
+
lines.push(` - ${tag}: ${count} step(s) → agents: ${chain}`);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
lines.push("", "Steps:");
|
|
266
|
+
for (const step of steps) {
|
|
267
|
+
const preview = step.prompt.length > 60 ? step.prompt.slice(0, 60) + "..." : step.prompt;
|
|
268
|
+
// Include heading if available (e.g., "Security Review" from the plan's heading)
|
|
269
|
+
const headingPrefix = step.heading ? `${step.heading}: ` : "";
|
|
270
|
+
lines.push(` ${step.stepId} [${step.tag}] ${step.chain.join(",")}: ${headingPrefix}${preview}`);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
return lines.join("\n");
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Main orchestration function that parses a plan and returns pre-formatted output.
|
|
278
|
+
*/
|
|
279
|
+
export async function orchestratePlan(options: OrchestrateOptions): Promise<{
|
|
280
|
+
steps: OrchestratedStep[];
|
|
281
|
+
chain: string[];
|
|
282
|
+
overview: string;
|
|
283
|
+
}> {
|
|
284
|
+
const { planPath } = options;
|
|
285
|
+
|
|
286
|
+
// Try primary parser first
|
|
287
|
+
let steps = parsePlanDocument(planPath);
|
|
288
|
+
|
|
289
|
+
// Fall back to simple parser if no results
|
|
290
|
+
if (steps.length === 0) {
|
|
291
|
+
steps = parsePlanDocumentSimple(planPath);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
if (steps.length === 0) {
|
|
295
|
+
throw new Error(`No tagged sections found in plan document: ${planPath}`);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
const chain = buildAgentChain(steps);
|
|
299
|
+
const overview = formatPlanOverview(planPath);
|
|
300
|
+
|
|
301
|
+
return { steps, chain, overview };
|
|
302
|
+
}
|