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,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Handler for `team action='orchestrate' planPath='/path/to/plan.md'`
|
|
3
|
+
*
|
|
4
|
+
* Parses a plan document and outputs agent chain commands.
|
|
5
|
+
*/
|
|
6
|
+
import * as fs from "node:fs";
|
|
7
|
+
import type { TeamToolParamsValue } from "../../schema/team-tool-schema.ts";
|
|
8
|
+
import { resolveRealContainedPath } from "../../utils/safe-paths.ts";
|
|
9
|
+
import {
|
|
10
|
+
buildAgentChain,
|
|
11
|
+
formatPlanOverview,
|
|
12
|
+
type OrchestratedStep,
|
|
13
|
+
parsePlanDocument,
|
|
14
|
+
parsePlanDocumentSimple,
|
|
15
|
+
} from "../plan-orchestrate.ts";
|
|
16
|
+
import type { PiTeamsToolResult } from "../tool-result.ts";
|
|
17
|
+
import { result, type TeamContext } from "./context.ts";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Handle the orchestrate action.
|
|
21
|
+
*
|
|
22
|
+
* Parses a plan document (markdown with `<!-- tag: <tag> -->` comments)
|
|
23
|
+
* and outputs the decomposed agent chain commands.
|
|
24
|
+
*
|
|
25
|
+
* Usage: `team action='orchestrate' planPath='/path/to/plan.md'`
|
|
26
|
+
*/
|
|
27
|
+
export function handleOrchestrate(params: TeamToolParamsValue, ctx: TeamContext): PiTeamsToolResult {
|
|
28
|
+
const planPath = params.planPath as string | undefined;
|
|
29
|
+
|
|
30
|
+
if (!planPath) {
|
|
31
|
+
return result(
|
|
32
|
+
"orchestrate requires planPath parameter pointing to a markdown plan document.",
|
|
33
|
+
{ action: "orchestrate", status: "error" },
|
|
34
|
+
true,
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Resolve and validate path stays within ctx.cwd (path-traversal protection)
|
|
39
|
+
let resolvedPath: string;
|
|
40
|
+
try {
|
|
41
|
+
resolvedPath = resolveRealContainedPath(ctx.cwd, planPath);
|
|
42
|
+
} catch {
|
|
43
|
+
return result(`planPath must be within project directory: ${planPath}`, { action: "orchestrate", status: "error" }, true);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (!fs.existsSync(resolvedPath)) {
|
|
47
|
+
return result(`Plan document not found: ${resolvedPath}`, { action: "orchestrate", status: "error" }, true);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Try primary parser
|
|
51
|
+
let steps: OrchestratedStep[] = parsePlanDocument(resolvedPath);
|
|
52
|
+
|
|
53
|
+
// Fallback to simple parser
|
|
54
|
+
if (steps.length === 0) {
|
|
55
|
+
steps = parsePlanDocumentSimple(resolvedPath);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (steps.length === 0) {
|
|
59
|
+
return result(
|
|
60
|
+
`No tagged sections found in plan document: ${resolvedPath}\n\nExpected format: <!-- tag: <tag> --> in markdown sections`,
|
|
61
|
+
{ action: "orchestrate", status: "error" },
|
|
62
|
+
true,
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Build overview and commands
|
|
67
|
+
const overview = formatPlanOverview(resolvedPath);
|
|
68
|
+
const commands = buildAgentChain(steps);
|
|
69
|
+
|
|
70
|
+
const outputLines: string[] = [
|
|
71
|
+
`Plan: ${resolvedPath}`,
|
|
72
|
+
`Steps: ${steps.length}`,
|
|
73
|
+
"",
|
|
74
|
+
"# Agent Chain Commands",
|
|
75
|
+
"",
|
|
76
|
+
...commands.map((cmd, i) => `${i + 1}. ${cmd}`),
|
|
77
|
+
"",
|
|
78
|
+
"# Full Overview",
|
|
79
|
+
overview,
|
|
80
|
+
];
|
|
81
|
+
|
|
82
|
+
return result(outputLines.join("\n"), {
|
|
83
|
+
action: "orchestrate",
|
|
84
|
+
status: "ok",
|
|
85
|
+
data: {
|
|
86
|
+
planPath: resolvedPath,
|
|
87
|
+
stepCount: steps.length,
|
|
88
|
+
commands,
|
|
89
|
+
steps: steps.map((sqs) => ({
|
|
90
|
+
stepId: sqs.stepId,
|
|
91
|
+
tag: sqs.tag,
|
|
92
|
+
chain: sqs.chain,
|
|
93
|
+
prompt: sqs.prompt,
|
|
94
|
+
heading: sqs.heading,
|
|
95
|
+
})),
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parallel dispatch handler — accepts an array of independent tasks
|
|
3
|
+
* and spawns them as concurrent background agents.
|
|
4
|
+
*
|
|
5
|
+
* Solves the host-agent limitation of only being able to emit
|
|
6
|
+
* one Agent() call per response turn. By calling `action=parallel`
|
|
7
|
+
* once with multiple tasks, the system handles fanout automatically.
|
|
8
|
+
*/
|
|
9
|
+
import { discoverAgents } from "../../agents/discover-agents.ts";
|
|
10
|
+
import { loadConfig } from "../../config/config.ts";
|
|
11
|
+
import { resolveCrewRuntime } from "../../runtime/runtime-resolver.ts";
|
|
12
|
+
import type { TeamToolParamsValue } from "../../schema/team-tool-schema.ts";
|
|
13
|
+
import { appendEvent } from "../../state/event-log.ts";
|
|
14
|
+
import { createRunManifest } from "../../state/state-store.ts";
|
|
15
|
+
import { spawnBackgroundTeamRun } from "../../subagents/async-entry.ts";
|
|
16
|
+
import { discoverTeams } from "../../teams/discover-teams.ts";
|
|
17
|
+
import type { TeamConfig } from "../../teams/team-config.ts";
|
|
18
|
+
import { discoverWorkflows } from "../../workflows/discover-workflows.ts";
|
|
19
|
+
import type { WorkflowConfig } from "../../workflows/workflow-config.ts";
|
|
20
|
+
import { resolveCwdOverride } from "../registration/team-tool.ts";
|
|
21
|
+
import type { PiTeamsToolResult } from "../tool-result.ts";
|
|
22
|
+
import { result, type TeamContext } from "./context.ts";
|
|
23
|
+
|
|
24
|
+
const MAX_CONCURRENCY = 8;
|
|
25
|
+
const DEFAULT_CONCURRENCY = 4;
|
|
26
|
+
const DEFAULT_TEAM = "fast-fix";
|
|
27
|
+
const DEFAULT_AGENT = "explorer";
|
|
28
|
+
|
|
29
|
+
export async function handleParallel(params: TeamToolParamsValue, ctx: TeamContext): Promise<PiTeamsToolResult> {
|
|
30
|
+
const tasksParam = params.config?.tasks;
|
|
31
|
+
if (!Array.isArray(tasksParam) || tasksParam.length === 0) {
|
|
32
|
+
return result("parallel action requires config.tasks: [{goal, agent?}]", { action: "parallel", status: "error" }, true);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const concurrency = Math.min(Math.max(1, Math.floor((params.config?.concurrency as number) ?? DEFAULT_CONCURRENCY)), MAX_CONCURRENCY);
|
|
36
|
+
|
|
37
|
+
const config = loadConfig(ctx.cwd);
|
|
38
|
+
const agentsResult = discoverAgents(ctx.cwd);
|
|
39
|
+
const allAgentsList = [...agentsResult.builtin, ...agentsResult.user, ...agentsResult.project];
|
|
40
|
+
const teams = discoverTeams(ctx.cwd);
|
|
41
|
+
const workflows = discoverWorkflows(ctx.cwd);
|
|
42
|
+
|
|
43
|
+
const teamName = (params.config?.team as string) ?? DEFAULT_TEAM;
|
|
44
|
+
const team =
|
|
45
|
+
teams.builtin.find((t) => t.name === teamName) ??
|
|
46
|
+
teams.user.find((t) => t.name === teamName) ??
|
|
47
|
+
teams.project.find((t) => t.name === teamName);
|
|
48
|
+
if (!team) {
|
|
49
|
+
return result(`Team '${teamName}' not found`, { action: "parallel", status: "error" }, true);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// H2: Use team's defaultWorkflow, fall back to "fast-fix"
|
|
53
|
+
const workflow = workflows.builtin.find((w) => w.name === team.defaultWorkflow) ?? workflows.builtin.find((w) => w.name === "fast-fix");
|
|
54
|
+
if (!workflow) {
|
|
55
|
+
return result("No suitable workflow found for parallel dispatch", { action: "parallel", status: "error" }, true);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const runtime = await resolveCrewRuntime(config.config);
|
|
59
|
+
|
|
60
|
+
const launched: Array<{ runId: string; goal: string; agent: string }> = [];
|
|
61
|
+
const errors: Array<{ goal: string; error: string }> = [];
|
|
62
|
+
|
|
63
|
+
// C1: Enforce concurrency limit with batched spawning
|
|
64
|
+
for (let batchStart = 0; batchStart < tasksParam.length; batchStart += concurrency) {
|
|
65
|
+
const batch = tasksParam.slice(batchStart, batchStart + concurrency);
|
|
66
|
+
const batchPromises = batch.map((task) => spawnSingleTask(task, ctx, allAgentsList, team, workflow, runtime));
|
|
67
|
+
const batchResults = await Promise.allSettled(batchPromises);
|
|
68
|
+
for (const res of batchResults) {
|
|
69
|
+
if (res.status === "fulfilled" && res.value.ok) {
|
|
70
|
+
launched.push(res.value.value);
|
|
71
|
+
} else if (res.status === "fulfilled" && !res.value.ok) {
|
|
72
|
+
errors.push(res.value.error);
|
|
73
|
+
} else {
|
|
74
|
+
const reason = (res as PromiseRejectedResult).reason;
|
|
75
|
+
errors.push({
|
|
76
|
+
goal: "(unknown)",
|
|
77
|
+
error: reason instanceof Error ? reason.message : String(reason),
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const lines: string[] = [`Parallel dispatch: ${launched.length}/${tasksParam.length} tasks launched (concurrency: ${concurrency})`, ""];
|
|
84
|
+
for (const l of launched) {
|
|
85
|
+
lines.push(` ✅ ${l.runId} — ${l.agent}: ${l.goal.slice(0, 80)}`);
|
|
86
|
+
}
|
|
87
|
+
for (const e of errors) {
|
|
88
|
+
lines.push(` ❌ ${e.goal.slice(0, 80)}: ${e.error}`);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return result(
|
|
92
|
+
lines.join("\n"),
|
|
93
|
+
{
|
|
94
|
+
action: "parallel",
|
|
95
|
+
status: errors.length === tasksParam.length ? "error" : "ok",
|
|
96
|
+
},
|
|
97
|
+
errors.length === tasksParam.length,
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
type SpawnOk = {
|
|
102
|
+
ok: true;
|
|
103
|
+
value: { runId: string; goal: string; agent: string };
|
|
104
|
+
};
|
|
105
|
+
type SpawnErr = { ok: false; error: { goal: string; error: string } };
|
|
106
|
+
type SpawnResult = SpawnOk | SpawnErr;
|
|
107
|
+
|
|
108
|
+
async function spawnSingleTask(
|
|
109
|
+
task: unknown,
|
|
110
|
+
ctx: TeamContext,
|
|
111
|
+
allAgentsList: Array<{ name: string }>,
|
|
112
|
+
team: TeamConfig,
|
|
113
|
+
workflow: WorkflowConfig,
|
|
114
|
+
runtime: { available: boolean; kind: string },
|
|
115
|
+
): Promise<SpawnResult> {
|
|
116
|
+
try {
|
|
117
|
+
const taskRec = task as Record<string, unknown>;
|
|
118
|
+
const goal = taskRec.goal as string;
|
|
119
|
+
const agentName = (taskRec.agent as string) ?? DEFAULT_AGENT;
|
|
120
|
+
const rawCwd = (taskRec.cwd as string) ?? undefined;
|
|
121
|
+
|
|
122
|
+
if (!goal) {
|
|
123
|
+
return {
|
|
124
|
+
ok: false,
|
|
125
|
+
error: {
|
|
126
|
+
goal: "(missing)",
|
|
127
|
+
error: "Each task must have a 'goal' field",
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const agent = allAgentsList.find((a) => a.name === agentName);
|
|
133
|
+
if (!agent) {
|
|
134
|
+
return {
|
|
135
|
+
ok: false,
|
|
136
|
+
error: { goal, error: `Agent '${agentName}' not found` },
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// H1: Validate taskCwd containment against project root
|
|
141
|
+
const cwdResult = resolveCwdOverride(ctx.cwd, rawCwd);
|
|
142
|
+
if (!cwdResult.ok) {
|
|
143
|
+
return { ok: false, error: { goal, error: cwdResult.error } };
|
|
144
|
+
}
|
|
145
|
+
const taskCwd = cwdResult.cwd;
|
|
146
|
+
|
|
147
|
+
const created = createRunManifest({
|
|
148
|
+
cwd: taskCwd,
|
|
149
|
+
team,
|
|
150
|
+
workflow,
|
|
151
|
+
goal,
|
|
152
|
+
// EXT F1: mirror handleRun — without ownerSessionId, the foreign-run check in
|
|
153
|
+
// cancel/retry/resume (cancel.ts:50: `typeof ownerSessionId === "string"`) is
|
|
154
|
+
// skipped and any session can cancel/retry parallel-dispatched runs.
|
|
155
|
+
ownerSessionId: ctx.sessionId,
|
|
156
|
+
runKind: "team-run",
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
appendEvent(created.manifest.eventsPath, {
|
|
160
|
+
type: "run.started",
|
|
161
|
+
runId: created.manifest.runId,
|
|
162
|
+
message: `Parallel task: ${goal}`,
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
if (runtime.available && runtime.kind === "child-process") {
|
|
166
|
+
await spawnBackgroundTeamRun(created.manifest);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return {
|
|
170
|
+
ok: true,
|
|
171
|
+
value: { runId: created.manifest.runId, goal, agent: agentName },
|
|
172
|
+
};
|
|
173
|
+
} catch (error) {
|
|
174
|
+
const goal = ((task as Record<string, unknown>).goal as string) ?? "(unknown)";
|
|
175
|
+
return {
|
|
176
|
+
ok: false,
|
|
177
|
+
error: {
|
|
178
|
+
goal,
|
|
179
|
+
error: error instanceof Error ? error.message : String(error),
|
|
180
|
+
},
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { composeSingleAgentPrompt } from "../../runtime/single-agent-compose.ts";
|
|
2
|
+
import type { TeamToolParamsValue } from "../../schema/team-tool-schema.ts";
|
|
3
|
+
import { allTeams, discoverTeams } from "../../teams/discover-teams.ts";
|
|
4
|
+
import { allWorkflows, discoverWorkflows } from "../../workflows/discover-workflows.ts";
|
|
5
|
+
import { validateWorkflowForTeam } from "../../workflows/validate-workflow.ts";
|
|
6
|
+
import type { PiTeamsToolResult } from "../tool-result.ts";
|
|
7
|
+
import { result, type TeamContext } from "./context.ts";
|
|
8
|
+
|
|
9
|
+
export function handlePlan(params: TeamToolParamsValue, ctx: TeamContext): PiTeamsToolResult {
|
|
10
|
+
const teamName = params.team ?? "default";
|
|
11
|
+
const team = allTeams(discoverTeams(ctx.cwd)).find((item) => item.name === teamName);
|
|
12
|
+
if (!team) return result(`Team '${teamName}' not found.`, { action: "plan", status: "error" }, true);
|
|
13
|
+
const workflowName = params.workflow ?? team.defaultWorkflow ?? "default";
|
|
14
|
+
const workflow = allWorkflows(discoverWorkflows(ctx.cwd)).find((item) => item.name === workflowName);
|
|
15
|
+
if (!workflow) return result(`Workflow '${workflowName}' not found.`, { action: "plan", status: "error" }, true);
|
|
16
|
+
const errors = validateWorkflowForTeam(workflow, team);
|
|
17
|
+
if (errors.length > 0)
|
|
18
|
+
return result(
|
|
19
|
+
[`Workflow '${workflow.name}' is not valid for team '${team.name}':`, ...errors.map((error) => `- ${error}`)].join("\n"),
|
|
20
|
+
{ action: "plan", status: "error" },
|
|
21
|
+
true,
|
|
22
|
+
);
|
|
23
|
+
const goal = params.goal ?? params.task ?? "(not provided)";
|
|
24
|
+
// ROADMAP T2.2: single-agent composition mode (cliff hedge).
|
|
25
|
+
if (params.singleAgent) {
|
|
26
|
+
const composed = composeSingleAgentPrompt(workflow, goal);
|
|
27
|
+
return result(
|
|
28
|
+
[
|
|
29
|
+
`Single-agent plan for ${team.name} / ${workflow.name} (${composed.stepCount} phases composed into one sequential prompt):`,
|
|
30
|
+
"",
|
|
31
|
+
composed.prompt,
|
|
32
|
+
"",
|
|
33
|
+
"This prompt can be handed to a single agent to execute the entire workflow sequentially — pi-crew's cliff-resilient mode (survives single-agent domination).",
|
|
34
|
+
].join("\n"),
|
|
35
|
+
{ action: "plan", status: "ok" },
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
const lines = [
|
|
39
|
+
`Team plan: ${team.name}`,
|
|
40
|
+
`Workflow: ${workflow.name}`,
|
|
41
|
+
`Goal: ${goal}`,
|
|
42
|
+
"",
|
|
43
|
+
"Steps:",
|
|
44
|
+
...workflow.steps.map(
|
|
45
|
+
(step, index) =>
|
|
46
|
+
`${index + 1}. ${step.id} [${step.role}]${step.dependsOn?.length ? ` after ${step.dependsOn.join(", ")}` : ""}`,
|
|
47
|
+
),
|
|
48
|
+
];
|
|
49
|
+
return result(lines.join("\n"), { action: "plan", status: "ok" });
|
|
50
|
+
}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { readCrewAgents, recordFromTask, saveCrewAgents } from "../../runtime/crew-agent-records.ts";
|
|
2
|
+
import type { TeamToolParamsValue } from "../../schema/team-tool-schema.ts";
|
|
3
|
+
import { appendEvent } from "../../state/event-log.ts";
|
|
4
|
+
import { withRunLockSync } from "../../state/locks.ts";
|
|
5
|
+
import { appendMailboxMessage, updateMailboxMessageReply } from "../../state/mailbox.ts";
|
|
6
|
+
import { loadRunManifestById, saveRunTasks, updateRunStatus } from "../../state/state-store.ts";
|
|
7
|
+
import { logInternalError } from "../../utils/internal-error.ts";
|
|
8
|
+
import { locateRunCwd } from "../team-tool.ts";
|
|
9
|
+
import type { PiTeamsToolResult } from "../tool-result.ts";
|
|
10
|
+
import { result, type TeamContext } from "./context.ts";
|
|
11
|
+
import { RUN_NOT_FOUND_HINT } from "./run-not-found.ts";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Handle `respond` action: send a message to a waiting (interactive) task.
|
|
15
|
+
* The task must be in "waiting" status. The message is stored in the task's
|
|
16
|
+
* mailbox and the task is re-queued for durable scheduler resume.
|
|
17
|
+
*/
|
|
18
|
+
export function handleRespond(params: TeamToolParamsValue, ctx: TeamContext): PiTeamsToolResult {
|
|
19
|
+
if (!params.runId) return result("Respond requires runId.", { action: "respond", status: "error" }, true);
|
|
20
|
+
if (!params.message && !params.taskId)
|
|
21
|
+
return result("Respond requires taskId and/or message.", { action: "respond", status: "error" }, true);
|
|
22
|
+
|
|
23
|
+
const runCwd = locateRunCwd(params.runId, ctx.cwd);
|
|
24
|
+
if (!runCwd) return result(`Run '${params.runId}' not found.${RUN_NOT_FOUND_HINT}`, { action: "respond", status: "error" }, true);
|
|
25
|
+
const loaded = loadRunManifestById(runCwd, params.runId); // NOTE: no withRunLock - best-effort only; concurrent writes may cause inconsistency
|
|
26
|
+
if (!loaded) return result(`Run '${params.runId}' not found.${RUN_NOT_FOUND_HINT}`, { action: "respond", status: "error" }, true);
|
|
27
|
+
|
|
28
|
+
return withRunLockSync(loaded.manifest, () => {
|
|
29
|
+
const fresh = loadRunManifestById(loaded.manifest.cwd, params.runId!); // NOTE: inside withRunLockSync - consistent read
|
|
30
|
+
if (!fresh) return result(`Run '${params.runId}' not found.${RUN_NOT_FOUND_HINT}`, { action: "respond", status: "error" }, true);
|
|
31
|
+
const foreignRun = typeof fresh.manifest.ownerSessionId === "string" && fresh.manifest.ownerSessionId !== ctx.sessionId;
|
|
32
|
+
if (foreignRun && !params.force)
|
|
33
|
+
return result(
|
|
34
|
+
`Run ${fresh.manifest.runId} belongs to another session. Use force: true to override.`,
|
|
35
|
+
{
|
|
36
|
+
action: "respond",
|
|
37
|
+
status: "error",
|
|
38
|
+
runId: fresh.manifest.runId,
|
|
39
|
+
},
|
|
40
|
+
true,
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
const taskId = params.taskId;
|
|
44
|
+
const message = params.message ?? "";
|
|
45
|
+
|
|
46
|
+
const targetTasks = taskId
|
|
47
|
+
? fresh.tasks.filter((t) => t.id === taskId && t.status === "waiting")
|
|
48
|
+
: fresh.tasks.filter((t) => t.status === "waiting");
|
|
49
|
+
|
|
50
|
+
if (targetTasks.length === 0) {
|
|
51
|
+
const existing = taskId ? fresh.tasks.find((t) => t.id === taskId) : undefined;
|
|
52
|
+
const hint =
|
|
53
|
+
" Use api operation=follow-up-agent for continuation prompts or api operation=steer-agent to interrupt active work.";
|
|
54
|
+
return result(
|
|
55
|
+
(taskId
|
|
56
|
+
? existing
|
|
57
|
+
? `Task '${taskId}' is ${existing.status}, not waiting.`
|
|
58
|
+
: `Task '${taskId}' not found.`
|
|
59
|
+
: `No waiting tasks in run ${fresh.manifest.runId}.`) + hint,
|
|
60
|
+
{
|
|
61
|
+
action: "respond",
|
|
62
|
+
status: "error",
|
|
63
|
+
runId: fresh.manifest.runId,
|
|
64
|
+
},
|
|
65
|
+
true,
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const resumed = new Set(targetTasks.map((t) => t.id));
|
|
70
|
+
const mailboxIds: string[] = [];
|
|
71
|
+
for (const task of targetTasks) {
|
|
72
|
+
const mailbox = appendMailboxMessage(fresh.manifest, {
|
|
73
|
+
direction: "inbox",
|
|
74
|
+
from: "leader",
|
|
75
|
+
to: task.id,
|
|
76
|
+
taskId: task.id,
|
|
77
|
+
body: message || "(resume)",
|
|
78
|
+
kind: "response",
|
|
79
|
+
priority: "normal",
|
|
80
|
+
deliveryMode: "next_turn",
|
|
81
|
+
data: { action: "respond", kind: "response" },
|
|
82
|
+
replyTo: params.replyTo,
|
|
83
|
+
replyFrom: params.replyFrom,
|
|
84
|
+
replyDeadline: params.replyDeadline,
|
|
85
|
+
});
|
|
86
|
+
mailboxIds.push(mailbox.id);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// If this respond includes a replyTo, update the original message with reply metadata.
|
|
90
|
+
if (params.replyTo) {
|
|
91
|
+
updateMailboxMessageReply(fresh.manifest, params.replyTo, message || "(resume)");
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Re-queue waiting tasks so durable scheduler/resume can pick them up again.
|
|
95
|
+
const updatedTasks = fresh.tasks.map((task) => {
|
|
96
|
+
if (!resumed.has(task.id)) return task;
|
|
97
|
+
return {
|
|
98
|
+
...task,
|
|
99
|
+
status: "queued" as const,
|
|
100
|
+
startedAt: undefined,
|
|
101
|
+
finishedAt: undefined,
|
|
102
|
+
error: undefined,
|
|
103
|
+
adaptive: {
|
|
104
|
+
...task.adaptive,
|
|
105
|
+
phase: "resumed",
|
|
106
|
+
task: message || task.adaptive?.task || "",
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
saveRunTasks(fresh.manifest, updatedTasks);
|
|
112
|
+
let manifest = fresh.manifest;
|
|
113
|
+
if (
|
|
114
|
+
manifest.status === "blocked" ||
|
|
115
|
+
manifest.status === "completed" ||
|
|
116
|
+
manifest.status === "failed" ||
|
|
117
|
+
manifest.status === "cancelled"
|
|
118
|
+
) {
|
|
119
|
+
manifest = updateRunStatus(manifest, "running", `Resumed ${resumed.size} waiting task(s).`);
|
|
120
|
+
}
|
|
121
|
+
for (const taskId of resumed) {
|
|
122
|
+
appendEvent(manifest.eventsPath, {
|
|
123
|
+
type: "task.resumed",
|
|
124
|
+
runId: manifest.runId,
|
|
125
|
+
taskId,
|
|
126
|
+
message: message || "Task re-queued after respond.",
|
|
127
|
+
data: { mailboxIds },
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
try {
|
|
131
|
+
const existingRuntimes = new Map(readCrewAgents(fresh.manifest).map((a) => [a.taskId, a.runtime]));
|
|
132
|
+
saveCrewAgents(
|
|
133
|
+
fresh.manifest,
|
|
134
|
+
updatedTasks.map((task) => recordFromTask(fresh.manifest, task, existingRuntimes.get(task.id) ?? "child-process")),
|
|
135
|
+
);
|
|
136
|
+
} catch (error) {
|
|
137
|
+
logInternalError("team-tool.handleRespond.crewAgents", error, `runId=${fresh.manifest.runId}`);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const resumedIds = targetTasks.map((t) => t.id);
|
|
141
|
+
return result(`Resumed ${resumedIds.length} waiting task(s): ${resumedIds.join(", ")}. Message: ${message || "(no message)"}`, {
|
|
142
|
+
action: "respond",
|
|
143
|
+
status: "ok",
|
|
144
|
+
runId: fresh.manifest.runId,
|
|
145
|
+
resumedIds,
|
|
146
|
+
mailboxIds,
|
|
147
|
+
intent: `responding to ${resumedIds.join(", ")} in ${fresh.manifest.runId}`,
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { PiTeamsConfig } from "../../config/config.ts";
|
|
2
|
+
import { loadConfig } from "../../config/config.ts";
|
|
3
|
+
import type { TeamContext } from "./context.ts";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Resolved run deadline — a shared AbortController, its signal, and the
|
|
7
|
+
* computed deadline in milliseconds.
|
|
8
|
+
*/
|
|
9
|
+
export interface RunDeadline {
|
|
10
|
+
/** AbortSignal to pass to run executors (executeTeamRun, runDynamicWorkflow). */
|
|
11
|
+
signal: AbortSignal;
|
|
12
|
+
/** Computed deadline in milliseconds (used for `waitForRun` timeoutMs). */
|
|
13
|
+
deadlineMs: number;
|
|
14
|
+
/** Underlying controller — callers may link additional parent signals. */
|
|
15
|
+
controller: AbortController;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** Fallback deadline when no config or param override is available: 1 hour. */
|
|
19
|
+
export const DEFAULT_RUN_DEADLINE_MS = 3_600_000;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Resolve a unified run deadline with a shared AbortController.
|
|
23
|
+
*
|
|
24
|
+
* CORE-8 fix: previously three code paths in run.ts used inconsistent timeout
|
|
25
|
+
* policies — the DWF path used `AbortSignal.timeout(3_600_000)`, the foreground
|
|
26
|
+
* async path used `waitForRun(timeoutMs: 3_600_000)`, and the inline scaffold
|
|
27
|
+
* path passed `ctx.signal` with **zero** deadline fallback (could hang
|
|
28
|
+
* indefinitely if the caller signal never fires).
|
|
29
|
+
*
|
|
30
|
+
* This helper unifies all three into a single resolution strategy:
|
|
31
|
+
*
|
|
32
|
+
* Priority: `params.timeoutMs` → `config.limits.maxRunMinutes * 60_000` →
|
|
33
|
+
* `DEFAULT_RUN_DEADLINE_MS` (1 hour).
|
|
34
|
+
*
|
|
35
|
+
* The returned AbortController is linked to `ctx.signal` (caller abort
|
|
36
|
+
* propagates immediately) and armed with a deadline timer (`setTimeout` +
|
|
37
|
+
* `unref` so it never keeps the event loop alive). Callers may link additional
|
|
38
|
+
* parent signals to `controller` — e.g. a `startForegroundRun` callback signal.
|
|
39
|
+
*
|
|
40
|
+
* The `params` generic accepts the full `TeamToolParamsValue` (or any object
|
|
41
|
+
* with an optional `timeoutMs`); the value is read defensively via cast so the
|
|
42
|
+
* weak-type TS2559 check does not fire.
|
|
43
|
+
*/
|
|
44
|
+
export function resolveRunDeadline<T extends object>(
|
|
45
|
+
ctx: Pick<TeamContext, "cwd" | "signal">,
|
|
46
|
+
params: T,
|
|
47
|
+
config?: PiTeamsConfig,
|
|
48
|
+
): RunDeadline {
|
|
49
|
+
const timeoutMs = (params as { timeoutMs?: number }).timeoutMs;
|
|
50
|
+
const effectiveConfig = config ?? loadConfig(ctx.cwd).config;
|
|
51
|
+
const maxRunMinutes = effectiveConfig?.limits?.maxRunMinutes;
|
|
52
|
+
const deadlineMs = timeoutMs ?? (maxRunMinutes ? maxRunMinutes * 60_000 : DEFAULT_RUN_DEADLINE_MS);
|
|
53
|
+
|
|
54
|
+
const controller = new AbortController();
|
|
55
|
+
// Propagate caller abort (ctx.signal) to the shared controller.
|
|
56
|
+
if (ctx.signal) {
|
|
57
|
+
if (ctx.signal.aborted) controller.abort();
|
|
58
|
+
else ctx.signal.addEventListener("abort", () => controller.abort(), { once: true });
|
|
59
|
+
}
|
|
60
|
+
// Arm the deadline timer (unref'd so it never blocks process exit).
|
|
61
|
+
if (deadlineMs > 0) {
|
|
62
|
+
const timer = setTimeout(() => controller.abort(), deadlineMs);
|
|
63
|
+
timer.unref?.();
|
|
64
|
+
}
|
|
65
|
+
return { signal: controller.signal, deadlineMs, controller };
|
|
66
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* run-not-found.ts — Centralized "Run not found" error helper (DX: F2).
|
|
3
|
+
*
|
|
4
|
+
* Round 16 DX audit found that a stale/typo'd runId hits a blank
|
|
5
|
+
* "Run '<id>' not found." wall in 8+ handlers (status, resume, steer, export,
|
|
6
|
+
* forget, cleanup, invalidate, worktrees, events, artifacts). The run IDs are
|
|
7
|
+
* long (`team_20260615173318_b9c8fe49a74e0760`), so typos/truncation are
|
|
8
|
+
* near-certain for new users — yet `team list` (which shows recent runs) is
|
|
9
|
+
* never suggested.
|
|
10
|
+
*
|
|
11
|
+
* This module centralizes the message + recovery hint so every handler stays
|
|
12
|
+
* consistent and the hint never drifts.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import type { TeamToolDetails } from "../team-tool-types.ts";
|
|
16
|
+
import { result, type TeamContext } from "./context.ts";
|
|
17
|
+
|
|
18
|
+
/** Recovery hint appended to every "Run not found" message. */
|
|
19
|
+
export const RUN_NOT_FOUND_HINT = "\n\nTip: run action='list' to see recent runs and their IDs.";
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Build the standard "Run not found" error result with a recovery hint.
|
|
23
|
+
*
|
|
24
|
+
* @param runId the (missing/typo'd) run id the caller passed
|
|
25
|
+
* @param action the action that was attempted (for the details.action field)
|
|
26
|
+
*/
|
|
27
|
+
export function runNotFound(runId: string, action: string): ReturnType<typeof result> {
|
|
28
|
+
return result(`Run '${runId}' not found.${RUN_NOT_FOUND_HINT}`, { action, status: "error" } satisfies TeamToolDetails, true);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Helper: resolve a runId to its cwd, returning a runNotFound() result when
|
|
33
|
+
* missing. Reduces the boilerplate `locateRunCwd → if (!runCwd) return ...`
|
|
34
|
+
* duplicated across handlers.
|
|
35
|
+
*/
|
|
36
|
+
export function resolveRunOrNotFound(
|
|
37
|
+
runId: string,
|
|
38
|
+
action: string,
|
|
39
|
+
cwd: string,
|
|
40
|
+
locate: (runId: string, cwd: string) => string | undefined,
|
|
41
|
+
): { kind: "found"; runCwd: string } | { kind: "notfound"; result: ReturnType<typeof result> } {
|
|
42
|
+
const runCwd = locate(runId, cwd);
|
|
43
|
+
if (!runCwd) return { kind: "notfound", result: runNotFound(runId, action) };
|
|
44
|
+
return { kind: "found", runCwd };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Re-export TeamContext so callers importing this helper don't need a second
|
|
48
|
+
// import line — keeps the diff in each handler to a single import swap.
|
|
49
|
+
export type { TeamContext };
|