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,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Iterative retrieval loop — workers progressively discover needed context.
|
|
3
|
+
*
|
|
4
|
+
* Pattern origin: ECC/skills/iterative-retrieval/SKILL.md — 4-phase loop:
|
|
5
|
+
* Dispatch → Evaluate → Refine → Loop. Max 3 cycles. Convergence when
|
|
6
|
+
* ≥3 high-relevance files found AND no critical gaps.
|
|
7
|
+
*
|
|
8
|
+
* This module provides the scoring and convergence logic.
|
|
9
|
+
* The actual file discovery is delegated to the caller (prompt-builder or task-runner).
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
// ── Types ────────────────────────────────────────────────────────────────
|
|
13
|
+
|
|
14
|
+
export interface RetrievalQuery {
|
|
15
|
+
patterns: string[];
|
|
16
|
+
keywords: string[];
|
|
17
|
+
excludes: string[];
|
|
18
|
+
focusAreas?: string[];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface RelevanceEvaluation {
|
|
22
|
+
path: string;
|
|
23
|
+
relevance: number; // 0.0–1.0
|
|
24
|
+
reason: string;
|
|
25
|
+
missingContext: string[];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface RetrievalResult {
|
|
29
|
+
query: RetrievalQuery;
|
|
30
|
+
evaluations: RelevanceEvaluation[];
|
|
31
|
+
cycle: number;
|
|
32
|
+
converged: boolean;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// ── Scoring ──────────────────────────────────────────────────────────────
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Score relevance of a file to a task description.
|
|
39
|
+
*
|
|
40
|
+
* Uses keyword matching as a heuristic. In production, this would be
|
|
41
|
+
* replaced by embedding-based similarity or BM25 scoring.
|
|
42
|
+
*
|
|
43
|
+
* @param filePath - Path to the file
|
|
44
|
+
* @param fileContent - Content of the file (or excerpt)
|
|
45
|
+
* @param keywords - Task-relevant keywords
|
|
46
|
+
* @returns Relevance score 0.0–1.0
|
|
47
|
+
*/
|
|
48
|
+
export function scoreRelevance(filePath: string, fileContent: string, keywords: string[]): number {
|
|
49
|
+
if (keywords.length === 0) return 0;
|
|
50
|
+
|
|
51
|
+
const pathLower = filePath.toLowerCase();
|
|
52
|
+
const contentLower = fileContent.toLowerCase();
|
|
53
|
+
let matchCount = 0;
|
|
54
|
+
let weightedScore = 0;
|
|
55
|
+
|
|
56
|
+
for (const keyword of keywords) {
|
|
57
|
+
const kw = keyword.toLowerCase();
|
|
58
|
+
// Path match is worth more (file naming is intentional)
|
|
59
|
+
if (pathLower.includes(kw)) {
|
|
60
|
+
matchCount++;
|
|
61
|
+
weightedScore += 0.3;
|
|
62
|
+
}
|
|
63
|
+
// Content match
|
|
64
|
+
const contentMatches = contentLower.split(kw).length - 1;
|
|
65
|
+
if (contentMatches > 0) {
|
|
66
|
+
matchCount++;
|
|
67
|
+
// Diminishing returns for repeated matches
|
|
68
|
+
weightedScore += Math.min(0.2, 0.05 * Math.log2(contentMatches + 1));
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Normalize: if all keywords matched, score is high
|
|
73
|
+
const keywordCoverage = matchCount / keywords.length;
|
|
74
|
+
const rawScore = keywordCoverage * 0.6 + Math.min(weightedScore, 0.4);
|
|
75
|
+
|
|
76
|
+
return Math.min(1.0, Math.max(0.0, rawScore));
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// ── Convergence ──────────────────────────────────────────────────────────
|
|
80
|
+
|
|
81
|
+
const CONVERGENCE_MIN_HIGH_RELEVANCE = 3;
|
|
82
|
+
const HIGH_RELEVANCE_THRESHOLD = 0.7;
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Check if retrieval has converged — enough high-relevance files found.
|
|
86
|
+
*
|
|
87
|
+
* @param evaluations - Current relevance evaluations
|
|
88
|
+
* @returns true if converged
|
|
89
|
+
*/
|
|
90
|
+
export function hasConverged(evaluations: RelevanceEvaluation[]): boolean {
|
|
91
|
+
const highRelevance = evaluations.filter((e) => e.relevance >= HIGH_RELEVANCE_THRESHOLD);
|
|
92
|
+
if (highRelevance.length < CONVERGENCE_MIN_HIGH_RELEVANCE) return false;
|
|
93
|
+
|
|
94
|
+
// Check for critical gaps — any evaluation with empty missingContext
|
|
95
|
+
const criticalGaps = evaluations.some((e) => e.relevance < 0.3 && e.missingContext.length > 0);
|
|
96
|
+
|
|
97
|
+
return !criticalGaps;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// ── Refinement ───────────────────────────────────────────────────────────
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Refine a retrieval query based on evaluation results.
|
|
104
|
+
*
|
|
105
|
+
* Extracts new keywords from high-relevance files, adds discovered
|
|
106
|
+
* terminology, and excludes confirmed-irrelevant paths.
|
|
107
|
+
*
|
|
108
|
+
* @param query - Original query
|
|
109
|
+
* @param evaluations - Results from the current cycle
|
|
110
|
+
* @returns Refined query for the next cycle
|
|
111
|
+
*/
|
|
112
|
+
export function refineQuery(query: RetrievalQuery, evaluations: RelevanceEvaluation[]): RetrievalQuery {
|
|
113
|
+
const newKeywords = new Set(query.keywords);
|
|
114
|
+
const newExcludes = new Set(query.excludes);
|
|
115
|
+
const newFocusAreas = new Set(query.focusAreas ?? []);
|
|
116
|
+
|
|
117
|
+
for (const eval_ of evaluations) {
|
|
118
|
+
if (eval_.relevance >= HIGH_RELEVANCE_THRESHOLD) {
|
|
119
|
+
// Extract potential keywords from the file path
|
|
120
|
+
const parts = eval_.path.replace(/[\\/]/g, "/").split("/");
|
|
121
|
+
for (const part of parts) {
|
|
122
|
+
// Skip common non-informative segments
|
|
123
|
+
if (part.length > 2 && !["src", "lib", "test", "dist", "node_modules"].includes(part)) {
|
|
124
|
+
// Use the filename stem as a keyword hint
|
|
125
|
+
const stem = part.replace(/\.[^.]+$/, "").replace(/[.-]/g, " ");
|
|
126
|
+
for (const word of stem.split(/\s+/)) {
|
|
127
|
+
if (word.length > 3) newKeywords.add(word);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (eval_.relevance < 0.2) {
|
|
134
|
+
// Exclude confirmed-irrelevant paths
|
|
135
|
+
newExcludes.add(eval_.path);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Track missing context as focus areas
|
|
139
|
+
for (const gap of eval_.missingContext) {
|
|
140
|
+
newFocusAreas.add(gap);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return {
|
|
145
|
+
patterns: query.patterns, // patterns don't change
|
|
146
|
+
keywords: [...newKeywords],
|
|
147
|
+
excludes: [...newExcludes],
|
|
148
|
+
focusAreas: newFocusAreas.size > 0 ? [...newFocusAreas] : undefined,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// ── Loop Control ─────────────────────────────────────────────────────────
|
|
153
|
+
|
|
154
|
+
const MAX_CYCLES = 3;
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Determine if another retrieval cycle should run.
|
|
158
|
+
*/
|
|
159
|
+
export function shouldContinue(evaluations: RelevanceEvaluation[], cycle: number): boolean {
|
|
160
|
+
if (cycle >= MAX_CYCLES) return false;
|
|
161
|
+
if (hasConverged(evaluations)) return false;
|
|
162
|
+
return true;
|
|
163
|
+
}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import type { AgentConfig } from "../../agents/agent-config.ts";
|
|
3
|
+
import type { CrewRuntimeConfig } from "../../config/config.ts";
|
|
4
|
+
import { writeArtifact } from "../../state/artifact-store.ts";
|
|
5
|
+
import { appendEventFireAndForget } from "../../state/event-log.ts";
|
|
6
|
+
import { loadRunManifestById } from "../../state/state-store.ts";
|
|
7
|
+
import type { ArtifactDescriptor, TeamRunManifest, TeamTaskState } from "../../state/types.ts";
|
|
8
|
+
import type { WorkflowStep } from "../../workflows/workflow-config.ts";
|
|
9
|
+
import {
|
|
10
|
+
appendCrewAgentEvent,
|
|
11
|
+
appendCrewAgentOutput,
|
|
12
|
+
emptyCrewAgentProgress,
|
|
13
|
+
recordFromTask,
|
|
14
|
+
upsertCrewAgent,
|
|
15
|
+
} from "../crew-agent-records.ts";
|
|
16
|
+
import { runLiveSessionTask } from "../live-session-runtime.ts";
|
|
17
|
+
import type { ParsedPiJsonOutput } from "../pi-json-output.ts";
|
|
18
|
+
import { type ProgressEventSummary, shouldAppendProgressEventUpdate } from "../progress-event-coalescer.ts";
|
|
19
|
+
import { createWorkerHeartbeat, touchWorkerHeartbeat } from "../worker-heartbeat.ts";
|
|
20
|
+
import { createStartupEvidence, type WorkerStartupEvidence } from "../worker-startup.ts";
|
|
21
|
+
import { applyAgentProgressEvent, applyUsageToProgress, progressEventSummary, shouldFlushProgressEvent } from "./progress.ts";
|
|
22
|
+
import { persistSingleTaskUpdate } from "./state-helpers.ts";
|
|
23
|
+
|
|
24
|
+
export interface RunLiveTaskInput {
|
|
25
|
+
manifest: TeamRunManifest;
|
|
26
|
+
tasks: TeamTaskState[];
|
|
27
|
+
task: TeamTaskState;
|
|
28
|
+
step: WorkflowStep;
|
|
29
|
+
agent: AgentConfig;
|
|
30
|
+
prompt: string;
|
|
31
|
+
signal?: AbortSignal;
|
|
32
|
+
runtimeConfig?: CrewRuntimeConfig;
|
|
33
|
+
parentContext?: string;
|
|
34
|
+
parentModel?: unknown;
|
|
35
|
+
modelRegistry?: unknown;
|
|
36
|
+
modelOverride?: string;
|
|
37
|
+
teamRoleModel?: string;
|
|
38
|
+
isCurrent?: () => boolean;
|
|
39
|
+
/** Workspace where this task run was initiated — used for session-scoped live-agent visibility. */
|
|
40
|
+
workspaceId: string;
|
|
41
|
+
/** Phase 2: Output schema for validating yield data. */
|
|
42
|
+
outputSchema?: unknown;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface RunLiveTaskOutput {
|
|
46
|
+
task: TeamTaskState;
|
|
47
|
+
tasks: TeamTaskState[];
|
|
48
|
+
startupEvidence: WorkerStartupEvidence;
|
|
49
|
+
exitCode: number | null;
|
|
50
|
+
error?: string;
|
|
51
|
+
parsedOutput?: ParsedPiJsonOutput;
|
|
52
|
+
resultArtifact: ArtifactDescriptor;
|
|
53
|
+
logArtifact?: ArtifactDescriptor;
|
|
54
|
+
transcriptArtifact?: ArtifactDescriptor;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function updateTask(tasks: TeamTaskState[], updated: TeamTaskState): TeamTaskState[] {
|
|
58
|
+
return tasks.map((task) => (task.id === updated.id ? updated : task));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export async function runLiveTask(input: RunLiveTaskInput): Promise<RunLiveTaskOutput> {
|
|
62
|
+
const { manifest, step, agent, prompt } = input;
|
|
63
|
+
let task = input.task;
|
|
64
|
+
let tasks = input.tasks;
|
|
65
|
+
const transcriptPath = `${manifest.artifactsRoot}/transcripts/${task.id}.jsonl`;
|
|
66
|
+
const isCurrent =
|
|
67
|
+
input.isCurrent ??
|
|
68
|
+
(() => {
|
|
69
|
+
if (input.signal?.aborted) return false;
|
|
70
|
+
const loaded = loadRunManifestById(manifest.cwd, manifest.runId); // NOTE: no withRunLock - best-effort only; concurrent writes may cause inconsistency;
|
|
71
|
+
const currentTask = loaded?.tasks.find((item) => item.id === task.id);
|
|
72
|
+
if (loaded?.manifest.status && loaded.manifest.status !== "running") return false;
|
|
73
|
+
return currentTask ? currentTask.status === "running" : true;
|
|
74
|
+
});
|
|
75
|
+
let lastAgentRecordPersistedAt = 0;
|
|
76
|
+
let lastRunProgressPersistedAt = 0;
|
|
77
|
+
let lastHeartbeatPersistedAt = 0;
|
|
78
|
+
let lastRunProgressSummary: ProgressEventSummary | undefined;
|
|
79
|
+
const persistLiveProgress = (event: unknown, force = false): void => {
|
|
80
|
+
if (!isCurrent()) return;
|
|
81
|
+
const now = Date.now();
|
|
82
|
+
if (force || shouldFlushProgressEvent(event) || now - lastAgentRecordPersistedAt >= 500) {
|
|
83
|
+
upsertCrewAgent(manifest, recordFromTask(manifest, task, "live-session"));
|
|
84
|
+
lastAgentRecordPersistedAt = now;
|
|
85
|
+
}
|
|
86
|
+
// Bug #5 fix: also persist heartbeat to tasks.json so heartbeat-watcher can detect live-session activity
|
|
87
|
+
if (force || now - lastHeartbeatPersistedAt >= 1000) {
|
|
88
|
+
task = {
|
|
89
|
+
...task,
|
|
90
|
+
heartbeat: touchWorkerHeartbeat(task.heartbeat ?? createWorkerHeartbeat(task.id)),
|
|
91
|
+
};
|
|
92
|
+
tasks = persistSingleTaskUpdate(manifest, tasks, task);
|
|
93
|
+
lastHeartbeatPersistedAt = now;
|
|
94
|
+
}
|
|
95
|
+
const summary = progressEventSummary(task, event);
|
|
96
|
+
const decision = shouldAppendProgressEventUpdate({
|
|
97
|
+
previous: lastRunProgressSummary,
|
|
98
|
+
next: summary,
|
|
99
|
+
nowMs: now,
|
|
100
|
+
lastAppendMs: lastRunProgressPersistedAt || undefined,
|
|
101
|
+
minIntervalMs: 1000,
|
|
102
|
+
force,
|
|
103
|
+
});
|
|
104
|
+
if (decision.shouldAppend) {
|
|
105
|
+
// 2.2 caller migration: see task-runner.ts.
|
|
106
|
+
appendEventFireAndForget(manifest.eventsPath, {
|
|
107
|
+
type: "task.progress",
|
|
108
|
+
runId: manifest.runId,
|
|
109
|
+
taskId: task.id,
|
|
110
|
+
data: { ...summary, coalesceReason: decision.reason },
|
|
111
|
+
});
|
|
112
|
+
lastRunProgressSummary = summary;
|
|
113
|
+
lastRunProgressPersistedAt = now;
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
const attemptStartedAt = new Date();
|
|
117
|
+
// Apply agent-level maxTurns override if specified (only positive integers)
|
|
118
|
+
const agentMax = agent.maxTurns;
|
|
119
|
+
const effectiveRuntimeConfig =
|
|
120
|
+
agentMax != null && agentMax > 0 && (!input.runtimeConfig?.maxTurns || agentMax < input.runtimeConfig.maxTurns)
|
|
121
|
+
? { ...input.runtimeConfig, maxTurns: agentMax }
|
|
122
|
+
: input.runtimeConfig;
|
|
123
|
+
const liveResult = await runLiveSessionTask({
|
|
124
|
+
manifest,
|
|
125
|
+
task,
|
|
126
|
+
step,
|
|
127
|
+
agent,
|
|
128
|
+
prompt,
|
|
129
|
+
signal: input.signal,
|
|
130
|
+
transcriptPath,
|
|
131
|
+
runtimeConfig: effectiveRuntimeConfig,
|
|
132
|
+
parentContext: input.parentContext,
|
|
133
|
+
parentModel: input.parentModel,
|
|
134
|
+
modelRegistry: input.modelRegistry,
|
|
135
|
+
modelOverride: input.modelOverride,
|
|
136
|
+
teamRoleModel: input.teamRoleModel,
|
|
137
|
+
isCurrent,
|
|
138
|
+
workspaceId: input.workspaceId,
|
|
139
|
+
// Phase 2: Pass output schema for yield validation
|
|
140
|
+
outputSchema: undefined,
|
|
141
|
+
onOutput: (text) => {
|
|
142
|
+
if (!isCurrent()) return;
|
|
143
|
+
appendCrewAgentOutput(manifest, task.id, text);
|
|
144
|
+
},
|
|
145
|
+
onEvent: (event) => {
|
|
146
|
+
if (!isCurrent()) return;
|
|
147
|
+
appendCrewAgentEvent(manifest, task.id, event);
|
|
148
|
+
task = {
|
|
149
|
+
...task,
|
|
150
|
+
agentProgress: applyAgentProgressEvent(task.agentProgress ?? emptyCrewAgentProgress(), event, task.startedAt),
|
|
151
|
+
};
|
|
152
|
+
tasks = updateTask(tasks, task);
|
|
153
|
+
persistLiveProgress(event);
|
|
154
|
+
},
|
|
155
|
+
});
|
|
156
|
+
const startupEvidence = createStartupEvidence({
|
|
157
|
+
command: "live-session",
|
|
158
|
+
startedAt: attemptStartedAt,
|
|
159
|
+
finishedAt: new Date(),
|
|
160
|
+
promptSentAt: attemptStartedAt,
|
|
161
|
+
promptAccepted: liveResult.exitCode === 0 && !liveResult.error,
|
|
162
|
+
stderr: liveResult.stderr,
|
|
163
|
+
error: liveResult.error,
|
|
164
|
+
exitCode: liveResult.exitCode,
|
|
165
|
+
});
|
|
166
|
+
const exitCode = liveResult.exitCode;
|
|
167
|
+
const error =
|
|
168
|
+
liveResult.error ||
|
|
169
|
+
(liveResult.exitCode && liveResult.exitCode !== 0
|
|
170
|
+
? liveResult.stderr || `Live session exited with ${liveResult.exitCode}`
|
|
171
|
+
: undefined);
|
|
172
|
+
const parsedOutput = {
|
|
173
|
+
finalText: liveResult.stdout,
|
|
174
|
+
textEvents: liveResult.stdout ? [liveResult.stdout] : [],
|
|
175
|
+
jsonEvents: liveResult.jsonEvents,
|
|
176
|
+
usage: liveResult.usage,
|
|
177
|
+
};
|
|
178
|
+
if (liveResult.usage && isCurrent())
|
|
179
|
+
task = {
|
|
180
|
+
...task,
|
|
181
|
+
usage: liveResult.usage,
|
|
182
|
+
agentProgress: applyUsageToProgress(task.agentProgress, liveResult.usage),
|
|
183
|
+
};
|
|
184
|
+
persistLiveProgress({ type: "attempt_finished" }, true);
|
|
185
|
+
const resultArtifact = writeArtifact(manifest.artifactsRoot, {
|
|
186
|
+
kind: "result",
|
|
187
|
+
relativePath: `results/${task.id}.txt`,
|
|
188
|
+
content: liveResult.stdout || liveResult.stderr || "(no output)",
|
|
189
|
+
producer: task.id,
|
|
190
|
+
});
|
|
191
|
+
const logArtifact = writeArtifact(manifest.artifactsRoot, {
|
|
192
|
+
kind: "log",
|
|
193
|
+
relativePath: `logs/${task.id}.log`,
|
|
194
|
+
content: [
|
|
195
|
+
`runtime=live-session`,
|
|
196
|
+
`finalExitCode=${exitCode ?? "null"}`,
|
|
197
|
+
`jsonEvents=${liveResult.jsonEvents}`,
|
|
198
|
+
liveResult.usage ? `usage=${JSON.stringify(liveResult.usage)}` : "",
|
|
199
|
+
"",
|
|
200
|
+
"STDOUT:",
|
|
201
|
+
liveResult.stdout,
|
|
202
|
+
"",
|
|
203
|
+
"STDERR:",
|
|
204
|
+
liveResult.stderr,
|
|
205
|
+
].join("\n"),
|
|
206
|
+
producer: task.id,
|
|
207
|
+
});
|
|
208
|
+
const transcriptArtifact = fs.existsSync(transcriptPath)
|
|
209
|
+
? writeArtifact(manifest.artifactsRoot, {
|
|
210
|
+
kind: "log",
|
|
211
|
+
relativePath: `transcripts/${task.id}.jsonl`,
|
|
212
|
+
content: fs.readFileSync(transcriptPath, "utf-8"),
|
|
213
|
+
producer: task.id,
|
|
214
|
+
})
|
|
215
|
+
: undefined;
|
|
216
|
+
return {
|
|
217
|
+
task,
|
|
218
|
+
tasks,
|
|
219
|
+
startupEvidence,
|
|
220
|
+
exitCode,
|
|
221
|
+
error: error || undefined,
|
|
222
|
+
parsedOutput,
|
|
223
|
+
resultArtifact,
|
|
224
|
+
logArtifact,
|
|
225
|
+
transcriptArtifact,
|
|
226
|
+
};
|
|
227
|
+
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* output-splitter.ts — partition one worker's combined output into N
|
|
3
|
+
* per-task results (M6 real-dispatch, MVP).
|
|
4
|
+
*
|
|
5
|
+
* The combined worker is told to wrap each task's result in
|
|
6
|
+
* `<<<TASK_RESULT:{taskId}>>>` ... `<<<END_TASK_RESULT>>>` delimiters.
|
|
7
|
+
* This module parses the raw output and returns a Map<taskId, resultText>.
|
|
8
|
+
*
|
|
9
|
+
* Strategy (in priority order):
|
|
10
|
+
* 1. Delimiter parse — exact match of `<<<TASK_RESULT:id>>>` markers
|
|
11
|
+
* 2. Section heading parse — `### Task N of M` / `## Task N` headers
|
|
12
|
+
* 3. Whole-output broadcast — assign full raw output to ALL taskIds
|
|
13
|
+
* (safe fallback for read-only roles where identical context is OK)
|
|
14
|
+
*
|
|
15
|
+
* Returns an array of { taskId, text } records in input-order. When the
|
|
16
|
+
* delimiter strategy succeeds, each entry contains that task's delimited
|
|
17
|
+
* text. When broadcast fallback is used, all entries contain the full
|
|
18
|
+
* raw output.
|
|
19
|
+
*
|
|
20
|
+
* Note: pure function — no I/O, no LLM calls, deterministic. This is
|
|
21
|
+
* deliberately the simplest possible splitter; we don't try fuzzy
|
|
22
|
+
* matching, NL extraction, or retry-the-LLM. The MVP trusts workers
|
|
23
|
+
* to follow delimiters 99% of the time and broadcasts the rest.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
export interface SplitResult {
|
|
27
|
+
taskId: string;
|
|
28
|
+
text: string;
|
|
29
|
+
/** Which strategy produced this entry. */
|
|
30
|
+
strategy: "delimiter" | "section" | "broadcast";
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Split a raw worker output into N per-task result texts.
|
|
35
|
+
*
|
|
36
|
+
* @param rawOutput — the worker's combined output text
|
|
37
|
+
* @param taskIds — ordered list of task IDs (matches the dispatch order)
|
|
38
|
+
*/
|
|
39
|
+
export function splitCoalescedOutput(rawOutput: string, taskIds: string[]): SplitResult[] {
|
|
40
|
+
if (taskIds.length === 0) return [];
|
|
41
|
+
if (taskIds.length === 1) {
|
|
42
|
+
// Single-task group: return the whole output as the one task's result.
|
|
43
|
+
return [{ taskId: taskIds[0]!, text: rawOutput, strategy: "delimiter" }];
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const byId = new Map<string, string>();
|
|
47
|
+
const delimiterHits = new Set<string>();
|
|
48
|
+
|
|
49
|
+
// Strategy 1: delimiter parse.
|
|
50
|
+
// Pattern: <<<TASK_RESULT:{id}>>> ... <<<END_TASK_RESULT>>>
|
|
51
|
+
// We match greedily, allowing nested markers between start and end.
|
|
52
|
+
const delimiterRegex = /<<<TASK_RESULT:([^\s>]+)>>>([\s\S]*?)<<<END_TASK_RESULT>>>/g;
|
|
53
|
+
let match: RegExpExecArray | null;
|
|
54
|
+
while ((match = delimiterRegex.exec(rawOutput)) !== null) {
|
|
55
|
+
const id = match[1]!;
|
|
56
|
+
const body = match[2]!.trim();
|
|
57
|
+
if (taskIds.includes(id) && !byId.has(id)) {
|
|
58
|
+
byId.set(id, body);
|
|
59
|
+
delimiterHits.add(id);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (delimiterHits.size === taskIds.length) {
|
|
64
|
+
// All tasks got delimiter hits — return in input order.
|
|
65
|
+
return taskIds.map((id) => ({
|
|
66
|
+
taskId: id,
|
|
67
|
+
text: byId.get(id) ?? "",
|
|
68
|
+
strategy: "delimiter" as const,
|
|
69
|
+
}));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Strategy 2: section heading parse.
|
|
73
|
+
// Look for `### Task N of M` or `## Task {id}` markers. We try both.
|
|
74
|
+
if (delimiterHits.size === 0) {
|
|
75
|
+
const bySection = parseBySectionHeadings(rawOutput, taskIds);
|
|
76
|
+
if (bySection.size === taskIds.length) {
|
|
77
|
+
return taskIds.map((id) => ({
|
|
78
|
+
taskId: id,
|
|
79
|
+
text: bySection.get(id) ?? "",
|
|
80
|
+
strategy: "section" as const,
|
|
81
|
+
}));
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Strategy 3: broadcast fallback. All tasks get the full raw output.
|
|
86
|
+
// This is safe for read-only roles (explorers, reviewers) where
|
|
87
|
+
// downstream consumers care about findings, not strict per-task partitioning.
|
|
88
|
+
return taskIds.map((id) => ({
|
|
89
|
+
taskId: id,
|
|
90
|
+
text: rawOutput,
|
|
91
|
+
strategy: "broadcast" as const,
|
|
92
|
+
}));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Strategy 2 implementation: parse sections by heading patterns.
|
|
97
|
+
*
|
|
98
|
+
* Matches `### Task N of M` (N=1..M) or `### Task N` headers, then
|
|
99
|
+
* captures text up to the next header or end-of-input.
|
|
100
|
+
*
|
|
101
|
+
* Falls back to "first heading wins all text" if no N-of-M numbering is
|
|
102
|
+
* present, which is common in worker output that just labels sections.
|
|
103
|
+
*/
|
|
104
|
+
function parseBySectionHeadings(rawOutput: string, taskIds: string[]): Map<string, string> {
|
|
105
|
+
const result = new Map<string, string>();
|
|
106
|
+
// First try numbered: "### Task 1 of N" / "## Task 1" / "### Task 1"
|
|
107
|
+
const numberedRegex = /^(#{2,3})\s+Task\s+(\d+)\s+of\s+\d+.*$/gm;
|
|
108
|
+
const sections: { num: number; start: number }[] = [];
|
|
109
|
+
let m: RegExpExecArray | null;
|
|
110
|
+
while ((m = numberedRegex.exec(rawOutput)) !== null) {
|
|
111
|
+
sections.push({ num: Number(m[2]), start: m.index + m[0].length });
|
|
112
|
+
}
|
|
113
|
+
if (sections.length >= taskIds.length) {
|
|
114
|
+
sections.sort((a, b) => a.start - b.start);
|
|
115
|
+
for (let i = 0; i < sections.length && i < taskIds.length; i += 1) {
|
|
116
|
+
const section = sections[i]!;
|
|
117
|
+
const end = sections[i + 1]?.start ?? rawOutput.length;
|
|
118
|
+
const text = rawOutput.slice(section.start, end).trim();
|
|
119
|
+
const taskId = taskIds[i];
|
|
120
|
+
if (taskId) result.set(taskId, text);
|
|
121
|
+
}
|
|
122
|
+
return result;
|
|
123
|
+
}
|
|
124
|
+
// Try "### Task {taskId}" headers — direct ID matching.
|
|
125
|
+
const idHeaderRegex = /^(#{2,3})\s+Task\s+([^\s].*?)$/gm;
|
|
126
|
+
while ((m = idHeaderRegex.exec(rawOutput)) !== null) {
|
|
127
|
+
const headerText = m[2]!.trim();
|
|
128
|
+
const matchedId = taskIds.find((id) => headerText.includes(id));
|
|
129
|
+
if (matchedId && !result.has(matchedId)) {
|
|
130
|
+
result.set(matchedId, ""); // placeholder; filled below
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
if (result.size === taskIds.length) {
|
|
134
|
+
// Re-scan to extract body per matched header
|
|
135
|
+
const headerPositions: { taskId: string; start: number }[] = [];
|
|
136
|
+
const idHeaderRegex2 = /^(#{2,3})\s+Task\s+([^\s].*?)$/gm;
|
|
137
|
+
while ((m = idHeaderRegex2.exec(rawOutput)) !== null) {
|
|
138
|
+
const headerText = m[2]!.trim();
|
|
139
|
+
const matchedId = taskIds.find((id) => headerText.includes(id));
|
|
140
|
+
if (matchedId) headerPositions.push({ taskId: matchedId, start: m.index + m[0].length });
|
|
141
|
+
}
|
|
142
|
+
headerPositions.sort((a, b) => a.start - b.start);
|
|
143
|
+
for (let i = 0; i < headerPositions.length; i += 1) {
|
|
144
|
+
const cur = headerPositions[i]!;
|
|
145
|
+
const next = headerPositions[i + 1];
|
|
146
|
+
const end = next ? rawOutput.lastIndexOf("\n#", next.start) : rawOutput.length;
|
|
147
|
+
const text = rawOutput.slice(cur.start, end > 0 ? end : rawOutput.length).trim();
|
|
148
|
+
result.set(cur.taskId, text);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return result;
|
|
152
|
+
}
|