pi-crew 0.9.16 → 0.9.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +130 -0
- package/README.md +19 -0
- package/dist/build-meta.json +21784 -0
- package/dist/index.mjs +83169 -0
- package/dist/index.mjs.map +7 -0
- package/docs/A +358 -0
- package/docs/M-A +357 -0
- package/docs/REVIEW-FINDINGS-2026-06 +357 -0
- package/docs/Y +357 -0
- package/docs/a +357 -0
- package/docs/aA +358 -0
- package/docs/archive/README.md +91 -0
- package/docs/migration/atomic-write-v2-migration.md +297 -0
- package/docs/patterns/command-agent-skill.md +1 -1
- package/docs/perf/performance-review-2026-07.md +287 -0
- package/docs/skills/REFERENCE.md +0 -17
- package/docs//303/242mmaAAA/303/242 +357 -0
- package/index.bundle.ts +25 -0
- package/index.ts +95 -4
- package/package.json +15 -4
- package/skills/iterative-audit/SKILL.md +0 -1
- package/skills/widget-rendering/SKILL.md +17 -0
- package/src/adapters/claude-adapter.ts +1 -3
- package/src/adapters/export-util.ts +16 -16
- package/src/adapters/index.ts +5 -5
- package/src/agents/agent-config.ts +20 -14
- package/src/agents/agent-serializer.ts +1 -1
- package/src/agents/discover-agents.ts +83 -39
- package/src/benchmark/benchmark-runner.ts +51 -51
- package/src/benchmark/feedback-loop.ts +1 -1
- package/src/config/config.ts +303 -591
- package/src/config/defaults.ts +28 -2
- package/src/config/drift-detector.ts +11 -14
- package/src/config/markers.ts +201 -203
- package/src/config/resilient-parser.ts +14 -6
- package/src/config/role-tools.ts +3 -3
- package/src/config/suggestions.ts +5 -12
- package/src/config/types.ts +9 -25
- package/src/errors.ts +151 -157
- package/src/extension/action-suggestions.ts +54 -9
- package/src/extension/async-notifier.ts +43 -13
- package/src/extension/autonomous-policy.ts +77 -37
- package/src/extension/command-completions.ts +9 -8
- package/src/extension/context-status-injection.ts +14 -12
- package/src/extension/crew-autocomplete.ts +8 -16
- package/src/extension/crew-cleanup.ts +2 -1
- package/src/extension/crew-shortcuts.ts +9 -6
- package/src/extension/cross-extension-rpc.ts +136 -42
- package/src/extension/help.ts +1 -1
- package/src/extension/import-index.ts +10 -5
- package/src/extension/knowledge-injection.ts +88 -15
- package/src/extension/management.ts +89 -349
- package/src/extension/message-renderers.ts +3 -4
- package/src/extension/notification-router.ts +22 -5
- package/src/extension/notification-sink.ts +6 -3
- package/src/extension/pi-api.ts +17 -8
- package/src/extension/plan-orchestrate.ts +8 -27
- package/src/extension/project-init.ts +21 -6
- package/src/extension/register.ts +329 -975
- package/src/extension/registration/artifact-cleanup.ts +9 -4
- package/src/extension/registration/command-utils.ts +5 -1
- package/src/extension/registration/commands.ts +806 -314
- package/src/extension/registration/compaction-guard.ts +15 -15
- package/src/extension/registration/lifecycle.ts +259 -0
- package/src/extension/registration/observability.ts +293 -0
- package/src/extension/registration/subagent-helpers.ts +29 -7
- package/src/extension/registration/subagent-tools.ts +253 -44
- package/src/extension/registration/team-tool.ts +19 -84
- package/src/extension/registration/ui.ts +168 -0
- package/src/extension/registration/viewers.ts +64 -24
- package/src/extension/result-watcher.ts +18 -7
- package/src/extension/run-bundle-schema.ts +21 -6
- package/src/extension/run-export.ts +15 -6
- package/src/extension/run-import.ts +64 -29
- package/src/extension/run-index.ts +28 -9
- package/src/extension/run-maintenance.ts +32 -12
- package/src/extension/session-summary.ts +1 -1
- package/src/extension/team-manager-command.ts +64 -7
- package/src/extension/team-onboard.ts +149 -150
- package/src/extension/team-recommendation.ts +121 -21
- package/src/extension/team-tool/anchor.ts +31 -64
- package/src/extension/team-tool/api.ts +929 -141
- package/src/extension/team-tool/auto-summarize.ts +14 -26
- package/src/extension/team-tool/cache-control.ts +1 -5
- package/src/extension/team-tool/cancel.ts +138 -38
- package/src/extension/team-tool/chain-dispatch.ts +5 -13
- package/src/extension/team-tool/chain-executor.ts +29 -51
- package/src/extension/team-tool/config-patch.ts +1 -1
- package/src/extension/team-tool/context.ts +40 -20
- package/src/extension/team-tool/destructive-gate.ts +10 -5
- package/src/extension/team-tool/doctor.ts +170 -51
- package/src/extension/team-tool/explain.ts +228 -214
- package/src/extension/team-tool/failure-patterns.ts +3 -9
- package/src/extension/team-tool/goal-wrap.ts +71 -29
- package/src/extension/team-tool/goal.ts +185 -35
- package/src/extension/team-tool/handle-schedule.ts +34 -15
- package/src/extension/team-tool/handle-settings.ts +94 -56
- package/src/extension/team-tool/health-monitor.ts +27 -108
- package/src/extension/team-tool/inspect.ts +42 -9
- package/src/extension/team-tool/intent-policy.ts +4 -1
- package/src/extension/team-tool/lifecycle-actions.ts +244 -48
- package/src/extension/team-tool/orchestrate.ts +7 -18
- package/src/extension/team-tool/parallel-dispatch.ts +51 -29
- package/src/extension/team-tool/plan.ts +29 -5
- package/src/extension/team-tool/respond.ts +49 -16
- package/src/extension/team-tool/run-not-found.ts +3 -8
- package/src/extension/team-tool/run.ts +80 -317
- package/src/extension/team-tool/status.ts +135 -43
- package/src/extension/team-tool/workflow-manage.ts +92 -25
- package/src/extension/team-tool-types.ts +8 -1
- package/src/extension/team-tool.ts +142 -551
- package/src/extension/validate-resources.ts +39 -8
- package/src/hooks/registry.ts +66 -17
- package/src/hooks/types.ts +1 -1
- package/src/i18n.ts +25 -11
- package/src/observability/correlation.ts +17 -3
- package/src/observability/event-bus.ts +51 -56
- package/src/observability/event-to-metric.ts +117 -15
- package/src/observability/exporters/otlp-exporter.ts +56 -17
- package/src/observability/exporters/prometheus-exporter.ts +1 -1
- package/src/observability/metric-registry.ts +16 -4
- package/src/observability/metric-retention.ts +8 -2
- package/src/observability/metric-sink.ts +11 -3
- package/src/observability/metrics-primitives.ts +42 -9
- package/src/plugins/plugin-define.ts +2 -2
- package/src/plugins/plugin-registry.ts +25 -25
- package/src/plugins/plugins/index.ts +1 -1
- package/src/plugins/plugins/nextjs.ts +16 -16
- package/src/plugins/plugins/vite.ts +7 -11
- package/src/plugins/plugins/vitest.ts +6 -11
- package/src/runtime/adaptive-plan.ts +225 -40
- package/src/runtime/agent-control.ts +58 -15
- package/src/runtime/agent-memory.ts +15 -9
- package/src/runtime/agent-observability.ts +10 -2
- package/src/runtime/anchor-manager.ts +27 -25
- package/src/runtime/async-marker.ts +7 -1
- package/src/runtime/async-runner.ts +39 -24
- package/src/runtime/auto-summarize.ts +7 -13
- package/src/runtime/background-runner.ts +189 -251
- package/src/runtime/batch-barrier.ts +18 -16
- package/src/runtime/cancellation-token.ts +16 -6
- package/src/runtime/cancellation.ts +46 -8
- package/src/runtime/capability-inventory.ts +6 -4
- package/src/runtime/chain-parser.ts +44 -11
- package/src/runtime/chain-runner.ts +63 -69
- package/src/runtime/checkpoint.ts +12 -56
- package/src/runtime/child-pi.ts +344 -79
- package/src/runtime/coalesce-tasks.ts +268 -0
- package/src/runtime/code-summary.ts +71 -26
- package/src/runtime/compact-stages/index.ts +15 -5
- package/src/runtime/compact-stages/tail-capture-stage.ts +7 -2
- package/src/runtime/compact-stages/truncation-stage.ts +4 -1
- package/src/runtime/compaction-summary.ts +17 -10
- package/src/runtime/completion-guard.ts +33 -16
- package/src/runtime/crash-classification.ts +28 -7
- package/src/runtime/crash-recovery.ts +177 -37
- package/src/runtime/crew-agent-records.ts +145 -47
- package/src/runtime/crew-hooks.ts +9 -24
- package/src/runtime/cross-extension-rpc.ts +25 -23
- package/src/runtime/custom-tools/irc-tool.ts +43 -15
- package/src/runtime/custom-tools/submit-result-tool.ts +16 -5
- package/src/runtime/delivery-coordinator.ts +34 -7
- package/src/runtime/delta-conflict.ts +9 -21
- package/src/runtime/deterministic-ast.ts +1 -1
- package/src/runtime/diagnostic-export.ts +53 -20
- package/src/runtime/direct-run.ts +12 -2
- package/src/runtime/dwf-state-store.ts +1 -1
- package/src/runtime/dynamic-workflow-context.ts +187 -59
- package/src/runtime/dynamic-workflow-runner.ts +42 -20
- package/src/runtime/effectiveness.ts +16 -8
- package/src/runtime/errors/crew-errors.ts +7 -11
- package/src/runtime/event-stream-bridge.ts +9 -3
- package/src/runtime/foreground-control.ts +54 -14
- package/src/runtime/foreground-watchdog.ts +9 -6
- package/src/runtime/goal-achievement.ts +27 -10
- package/src/runtime/goal-evaluator.ts +54 -19
- package/src/runtime/goal-loop-runner.ts +280 -99
- package/src/runtime/goal-state-store.ts +27 -17
- package/src/runtime/green-contract.ts +11 -2
- package/src/runtime/group-join.ts +64 -31
- package/src/runtime/handoff-manager.ts +37 -42
- package/src/runtime/heartbeat-gradient.ts +10 -2
- package/src/runtime/heartbeat-watcher.ts +32 -6
- package/src/runtime/hidden-handoff.ts +13 -31
- package/src/runtime/important-line-classifier.ts +12 -2
- package/src/runtime/iteration-hooks.ts +25 -15
- package/src/runtime/live-agent-control.ts +55 -7
- package/src/runtime/live-agent-manager.ts +130 -27
- package/src/runtime/live-control-realtime.ts +23 -3
- package/src/runtime/live-irc.ts +4 -1
- package/src/runtime/live-session-health.ts +12 -4
- package/src/runtime/live-session-runtime.ts +379 -117
- package/src/runtime/manifest-cache.ts +28 -12
- package/src/runtime/mcp-proxy.ts +10 -18
- package/src/runtime/metric-parser.ts +1 -5
- package/src/runtime/model-fallback.ts +55 -18
- package/src/runtime/model-resolver.ts +2 -6
- package/src/runtime/model-scope.ts +19 -3
- package/src/runtime/notebook-helpers.ts +60 -62
- package/src/runtime/orphan-worker-registry.ts +37 -26
- package/src/runtime/output-validator.ts +18 -3
- package/src/runtime/overflow-recovery.ts +5 -4
- package/src/runtime/parallel-research.ts +29 -5
- package/src/runtime/parallel-utils.ts +9 -11
- package/src/runtime/path-overlap.ts +150 -0
- package/src/runtime/peer-dep.ts +12 -17
- package/src/runtime/per-write-validator.ts +1 -3
- package/src/runtime/phase-tracker.ts +342 -330
- package/src/runtime/pi-args.ts +26 -8
- package/src/runtime/pi-json-output.ts +1 -1
- package/src/runtime/pi-spawn.ts +30 -19
- package/src/runtime/pipeline-runner.ts +56 -55
- package/src/runtime/plan-templates.ts +5 -6
- package/src/runtime/policy-engine.ts +43 -7
- package/src/runtime/post-checks.ts +12 -4
- package/src/runtime/post-exit-stdio-guard.ts +2 -2
- package/src/runtime/process-lifecycle.ts +20 -10
- package/src/runtime/process-status.ts +16 -5
- package/src/runtime/progress-event-coalescer.ts +2 -1
- package/src/runtime/progress-tracker.ts +103 -103
- package/src/runtime/prose-compressor.ts +9 -11
- package/src/runtime/recovery-recipes.ts +118 -24
- package/src/runtime/replace.ts +25 -10
- package/src/runtime/resilient-edit.ts +10 -25
- package/src/runtime/result-extractor.ts +2 -6
- package/src/runtime/retry-executor.ts +20 -4
- package/src/runtime/retry-runner.ts +27 -51
- package/src/runtime/role-permission.ts +6 -1
- package/src/runtime/run-coalesced-task-group.ts +256 -0
- package/src/runtime/run-drift.ts +14 -15
- package/src/runtime/run-tracker.ts +6 -28
- package/src/runtime/runtime-policy.ts +1 -6
- package/src/runtime/runtime-resolver.ts +80 -15
- package/src/runtime/scheduler.ts +47 -18
- package/src/runtime/semaphore.ts +5 -7
- package/src/runtime/sensitive-paths.ts +2 -1
- package/src/runtime/session-usage.ts +1 -1
- package/src/runtime/settings-store.ts +16 -12
- package/src/runtime/sidechain-output.ts +6 -2
- package/src/runtime/single-agent-compose.ts +1 -4
- package/src/runtime/skill-effectiveness.ts +29 -97
- package/src/runtime/skill-instructions.ts +40 -83
- package/src/runtime/stale-reconciler.ts +73 -197
- package/src/runtime/stream-preview.ts +1 -1
- package/src/runtime/streaming-output.ts +1 -1
- package/src/runtime/subagent-manager.ts +44 -169
- package/src/runtime/subprocess-tool-registry.ts +4 -1
- package/src/runtime/supervisor-contact.ts +10 -5
- package/src/runtime/task-display.ts +19 -5
- package/src/runtime/task-graph-scheduler.ts +95 -21
- package/src/runtime/task-graph.ts +5 -11
- package/src/runtime/task-health.ts +54 -47
- package/src/runtime/task-id.ts +12 -19
- package/src/runtime/task-output-context.ts +265 -81
- package/src/runtime/task-packet.ts +12 -20
- package/src/runtime/task-quality.ts +6 -14
- package/src/runtime/task-runner/context-retrieval.ts +4 -13
- package/src/runtime/task-runner/live-executor.ts +114 -36
- package/src/runtime/task-runner/output-splitter.ts +152 -0
- package/src/runtime/task-runner/progress.ts +50 -12
- package/src/runtime/task-runner/prompt-builder.ts +31 -7
- package/src/runtime/task-runner/prompt-pipeline.ts +31 -7
- package/src/runtime/task-runner/result-utils.ts +3 -1
- package/src/runtime/task-runner/retrieval-orchestrator.ts +310 -0
- package/src/runtime/task-runner/run-projection.ts +27 -8
- package/src/runtime/task-runner/state-helpers.ts +50 -14
- package/src/runtime/task-runner/tail-read.ts +2 -6
- package/src/runtime/task-runner.ts +180 -326
- package/src/runtime/team-runner-artifacts.ts +13 -0
- package/src/runtime/team-runner.ts +456 -974
- package/src/runtime/tool-output-pruner.ts +6 -9
- package/src/runtime/tool-progress.ts +11 -21
- package/src/runtime/verification-gates.ts +33 -24
- package/src/runtime/verification-integrity.ts +2 -7
- package/src/runtime/verification-worktree.ts +62 -12
- package/src/runtime/worker-heartbeat.ts +5 -1
- package/src/runtime/worker-startup.ts +29 -5
- package/src/runtime/workflow-state.ts +17 -9
- package/src/runtime/workspace-lock.ts +30 -35
- package/src/runtime/workspace-tree.ts +20 -32
- package/src/runtime/yield-handler.ts +43 -9
- package/src/runtime/zombie-scanner.ts +5 -4
- package/src/schema/config-schema.ts +266 -172
- package/src/schema/team-tool-schema.ts +29 -74
- package/src/schema/validation-types.ts +25 -17
- package/src/skills/discover-skills.ts +35 -10
- package/src/skills/skill-templates.ts +109 -27
- package/src/skills/validate.ts +26 -8
- package/src/state/active-run-registry.ts +87 -28
- package/src/state/artifact-store.ts +9 -5
- package/src/state/atomic-write-v2.ts +85 -63
- package/src/state/atomic-write.ts +106 -27
- package/src/state/blob-store.ts +47 -20
- package/src/state/contracts.ts +20 -5
- package/src/state/crew-init.ts +5 -22
- package/src/state/decision-ledger.ts +19 -73
- package/src/state/event-log-rotation.ts +41 -15
- package/src/state/event-log.ts +168 -53
- package/src/state/event-reconstructor.ts +11 -1
- package/src/state/gitignore-manager.ts +2 -8
- package/src/state/health-store.ts +57 -57
- package/src/state/hook-instinct-bridge.ts +1 -1
- package/src/state/hook-integrations.ts +1 -1
- package/src/state/instinct-store.ts +17 -5
- package/src/state/jsonl-writer.ts +1 -1
- package/src/state/locks.ts +23 -9
- package/src/state/mailbox.ts +151 -28
- package/src/state/observation-store.ts +20 -14
- package/src/state/run-cache.ts +142 -135
- package/src/state/run-graph.ts +6 -15
- package/src/state/run-metrics.ts +5 -18
- package/src/state/schedule.ts +15 -9
- package/src/state/state-store.ts +137 -47
- package/src/state/task-claims.ts +12 -2
- package/src/state/tiered-eval.ts +52 -43
- package/src/state/types-eval.ts +2 -2
- package/src/state/types.ts +24 -20
- package/src/state/usage.ts +20 -4
- package/src/state/worker-atomic-writer.ts +6 -3
- package/src/subagents/index.ts +2 -2
- package/src/teams/discover-teams.ts +21 -6
- package/src/tools/safe-bash-extension.ts +5 -6
- package/src/tools/safe-bash.ts +10 -11
- package/src/types/new-api-types.ts +6 -10
- package/src/ui/agent-management-overlay.ts +52 -40
- package/src/ui/card-colors.ts +13 -4
- package/src/ui/crew-footer.ts +8 -7
- package/src/ui/crew-select-list.ts +1 -1
- package/src/ui/dashboard-panes/agents-pane.ts +41 -25
- package/src/ui/dashboard-panes/cancellation-pane.ts +1 -1
- package/src/ui/dashboard-panes/capability-pane.ts +32 -15
- package/src/ui/dashboard-panes/health-pane.ts +2 -1
- package/src/ui/dashboard-panes/metrics-pane.ts +4 -1
- package/src/ui/dashboard-panes/progress-pane.ts +12 -9
- package/src/ui/heartbeat-aggregator.ts +15 -4
- package/src/ui/keybinding-map.ts +40 -7
- package/src/ui/live-conversation-overlay.ts +36 -20
- package/src/ui/live-duration.ts +1 -4
- package/src/ui/live-run-sidebar.ts +88 -25
- package/src/ui/loaders.ts +2 -8
- package/src/ui/mascot.ts +20 -36
- package/src/ui/overlays/agent-picker-overlay.ts +11 -3
- package/src/ui/overlays/confirm-overlay.ts +4 -2
- package/src/ui/overlays/help-overlay.ts +25 -14
- package/src/ui/overlays/mailbox-compose-overlay.ts +48 -11
- package/src/ui/overlays/mailbox-compose-preview.ts +20 -5
- package/src/ui/overlays/mailbox-detail-overlay.ts +27 -6
- package/src/ui/pi-ui-compat.ts +7 -7
- package/src/ui/powerbar-publisher.ts +120 -42
- package/src/ui/render-diff.ts +10 -3
- package/src/ui/render-scheduler.ts +12 -4
- package/src/ui/run-action-dispatcher.ts +81 -18
- package/src/ui/run-dashboard.ts +172 -76
- package/src/ui/run-event-bus.ts +59 -37
- package/src/ui/run-snapshot-cache.ts +276 -86
- package/src/ui/settings-overlay.ts +361 -74
- package/src/ui/status-colors.ts +12 -1
- package/src/ui/syntax-highlight.ts +1 -1
- package/src/ui/terminal-status.ts +1 -3
- package/src/ui/theme-adapter.ts +16 -14
- package/src/ui/theme-discovery.ts +13 -2
- package/src/ui/tool-progress-formatter.ts +7 -7
- package/src/ui/tool-render.ts +128 -56
- package/src/ui/tool-renderers/brief-mode.ts +45 -27
- package/src/ui/tool-renderers/index.ts +109 -43
- package/src/ui/transcript-cache.ts +32 -6
- package/src/ui/transcript-entries.ts +25 -23
- package/src/ui/transcript-viewer.ts +78 -29
- package/src/ui/widget/index.ts +99 -40
- package/src/ui/widget/widget-formatters.ts +13 -6
- package/src/ui/widget/widget-model.ts +19 -8
- package/src/ui/widget/widget-renderer.ts +23 -13
- package/src/ui/widget/widget-types.ts +1 -1
- package/src/utils/bm25-search.ts +199 -199
- package/src/utils/conflict-detect.ts +22 -21
- package/src/utils/env-filter.ts +14 -7
- package/src/utils/file-coalescer.ts +5 -1
- package/src/utils/fingerprint.ts +3 -6
- package/src/utils/frontmatter.ts +3 -1
- package/src/utils/fs-watch.ts +2 -6
- package/src/utils/gh-protocol.ts +119 -44
- package/src/utils/git.ts +13 -15
- package/src/utils/guards.ts +2 -5
- package/src/utils/ids.ts +9 -2
- package/src/utils/incremental-reader.ts +14 -3
- package/src/utils/internal-error.ts +2 -1
- package/src/utils/names.ts +12 -3
- package/src/utils/paths.ts +49 -5
- package/src/utils/project-detector.ts +2 -2
- package/src/utils/redaction.ts +29 -19
- package/src/utils/resolve-shell.ts +9 -7
- package/src/utils/run-watcher-registry.ts +19 -31
- package/src/utils/safe-paths.ts +46 -29
- package/src/utils/scan-cache.ts +9 -2
- package/src/utils/session-utils.ts +2 -4
- package/src/utils/sleep.ts +12 -5
- package/src/utils/sse-parser.ts +5 -17
- package/src/utils/visual.ts +52 -32
- package/src/workflows/discover-workflows.ts +41 -109
- package/src/workflows/intermediate-store.ts +5 -21
- package/src/workflows/preflight-validator.ts +6 -33
- package/src/workflows/topology-analyzer.ts +5 -21
- package/src/workflows/workflow-config.ts +7 -6
- package/src/worktree/branch-freshness.ts +66 -8
- package/src/worktree/cleanup.ts +130 -20
- package/src/worktree/worktree-manager.ts +212 -69
- package/skills/artifact-analysis-loop/SKILL.md +0 -303
- package/skills/detection-pipeline-design/SKILL.md +0 -286
- package/skills/hunting-investigation-loop/SKILL.md +0 -402
- package/skills/incident-playbook-construction/SKILL.md +0 -384
- package/skills/security-review/SKILL.md +0 -561
- package/skills/threat-hypothesis-framework/SKILL.md +0 -176
- package/skills/ui-render-performance/SKILL.md +0 -58
- /package/docs/{followup-review-round3-2026-05-12.md → archive/followup-review-round3-2026-05-12.md} +0 -0
- /package/docs/{followup-review-round4-2026-05-13.md → archive/followup-review-round4-2026-05-13.md} +0 -0
- /package/docs/{pi-crew-bugs.md → archive/pi-crew-bugs.md} +0 -0
- /package/docs/{pi-crew-test-final.md → archive/pi-crew-test-final.md} +0 -0
- /package/docs/{pi-crew-test-results.md → archive/pi-crew-test-results.md} +0 -0
- /package/docs/{pi-crew-test-round2.md → archive/pi-crew-test-round2.md} +0 -0
- /package/docs/{pi-crew-test-round4.md → archive/pi-crew-test-round4.md} +0 -0
- /package/docs/{pi-crew-test-round5.md → archive/pi-crew-test-round5.md} +0 -0
- /package/docs/{pi-crew-test-round6.md → archive/pi-crew-test-round6.md} +0 -0
- /package/docs/{pi-crew-v0.5.10-audit-fix-plan.md → archive/pi-crew-v0.5.10-audit-fix-plan.md} +0 -0
- /package/docs/{pi-crew-v0.5.11-audit-fix-plan.md → archive/pi-crew-v0.5.11-audit-fix-plan.md} +0 -0
- /package/docs/{pi-crew-v0.5.12-audit-fix-plan.md → archive/pi-crew-v0.5.12-audit-fix-plan.md} +0 -0
- /package/docs/{pi-crew-v0.5.13-audit-fix-plan.md → archive/pi-crew-v0.5.13-audit-fix-plan.md} +0 -0
- /package/docs/{pi-crew-v0.5.14-audit-fix-plan.md → archive/pi-crew-v0.5.14-audit-fix-plan.md} +0 -0
- /package/docs/{pi-crew-v0.5.16-audit-fix-plan.md → archive/pi-crew-v0.5.16-audit-fix-plan.md} +0 -0
- /package/docs/{pi-crew-v0.5.17-audit-fix-plan.md → archive/pi-crew-v0.5.17-audit-fix-plan.md} +0 -0
- /package/docs/{pi-crew-v0.5.5-audit-fix-plan.md → archive/pi-crew-v0.5.5-audit-fix-plan.md} +0 -0
- /package/docs/{pi-crew-v0.5.9-audit-fix-plan.md → archive/pi-crew-v0.5.9-audit-fix-plan.md} +0 -0
- /package/docs/{pi-mono-opportunities.md → archive/pi-mono-opportunities.md} +0 -0
- /package/docs/{pi-mono-review.md → archive/pi-mono-review.md} +0 -0
- /package/docs/{pi-subagent4-comparison.md → archive/pi-subagent4-comparison.md} +0 -0
- /package/docs/{pi-subagents3-deep-analysis.md → archive/pi-subagents3-deep-analysis.md} +0 -0
|
@@ -1,41 +1,59 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
3
|
import type { AgentConfig } from "../agents/agent-config.ts";
|
|
4
|
+
import { resolveToolPolicy } from "../agents/agent-config.ts";
|
|
4
5
|
import type { CrewRuntimeConfig } from "../config/config.ts";
|
|
5
|
-
import
|
|
6
|
+
import { loadConfig } from "../config/config.ts";
|
|
7
|
+
import { DEFAULT_LIVE_SESSION } from "../config/defaults.ts";
|
|
6
8
|
import { appendEvent } from "../state/event-log.ts";
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
// in a single place: the shared user prompt. See G3 fix.
|
|
14
|
-
import { createStreamingOutput, type StreamingOutputHandle } from "./streaming-output.ts";
|
|
15
|
-
import { registerLiveAgent, disposeLiveAgentSession, terminateLiveAgent, updateLiveAgentStatus, trackLiveAgentToolStart, trackLiveAgentToolEnd, trackLiveAgentTurnEnd, trackLiveAgentResponseText, markLiveAgentCompleted } from "./live-agent-manager.ts";
|
|
9
|
+
import type { TeamRunManifest, TeamTaskState, UsageState } from "../state/types.ts";
|
|
10
|
+
import { logInternalError } from "../utils/internal-error.ts";
|
|
11
|
+
import { redactSecrets } from "../utils/redaction.ts";
|
|
12
|
+
import type { WorkflowStep } from "../workflows/workflow-config.ts";
|
|
13
|
+
import { createIrcTool } from "./custom-tools/irc-tool.ts";
|
|
14
|
+
import { createSubmitResultTool } from "./custom-tools/submit-result-tool.ts";
|
|
16
15
|
import { applyLiveAgentControlRequest, applyLiveAgentControlRequests, type LiveAgentControlCursor } from "./live-agent-control.ts";
|
|
16
|
+
import {
|
|
17
|
+
disposeLiveAgentSession,
|
|
18
|
+
listLiveAgents,
|
|
19
|
+
markLiveAgentCompleted,
|
|
20
|
+
registerLiveAgent,
|
|
21
|
+
terminateLiveAgent,
|
|
22
|
+
trackLiveAgentResponseText,
|
|
23
|
+
trackLiveAgentToolEnd,
|
|
24
|
+
trackLiveAgentToolStart,
|
|
25
|
+
trackLiveAgentTurnEnd,
|
|
26
|
+
updateLiveAgentStatus,
|
|
27
|
+
} from "./live-agent-manager.ts";
|
|
17
28
|
import { subscribeLiveControlRealtime } from "./live-control-realtime.ts";
|
|
18
|
-
import {
|
|
19
|
-
import type
|
|
20
|
-
import {
|
|
21
|
-
import { redactSecrets } from "../utils/redaction.ts";
|
|
29
|
+
import { buildExtensionBridge } from "./live-extension-bridge.ts";
|
|
30
|
+
import { collectLiveSessionHealth, formatLiveSessionDiagnostics, type LiveSessionHealth } from "./live-session-health.ts";
|
|
31
|
+
import { buildMcpProxyFromSession } from "./mcp-proxy.ts";
|
|
22
32
|
import { buildConfiguredModelRouting } from "./model-fallback.ts";
|
|
23
33
|
import { readEnabledModelsPatterns } from "./model-scope.ts";
|
|
24
|
-
import {
|
|
25
|
-
import { loadConfig } from "../config/config.ts";
|
|
34
|
+
import { isLiveSessionRuntimeAvailable } from "./runtime-resolver.ts";
|
|
26
35
|
import { awaitRuntimeWarmup } from "./runtime-warmup.ts";
|
|
27
|
-
import { DEFAULT_LIVE_SESSION } from "../config/defaults.ts";
|
|
28
|
-
import { buildYieldReminder, hasYieldInOutput, isYieldEvent, extractYieldResult, validateYieldData, DEFAULT_YIELD_CONFIG, type YieldResult } from "./yield-handler.ts";
|
|
29
|
-
import { buildMcpProxyFromSession } from "./mcp-proxy.ts";
|
|
30
|
-
import { createSubmitResultTool } from "./custom-tools/submit-result-tool.ts";
|
|
31
|
-
import { createIrcTool } from "./custom-tools/irc-tool.ts";
|
|
32
|
-
import { buildExtensionBridge } from "./live-extension-bridge.ts";
|
|
33
|
-
import { logInternalError } from "../utils/internal-error.ts";
|
|
34
36
|
// prose-compressor imported for custom tool descriptions below;
|
|
35
37
|
// tool description compression for SDK-managed tools awaits SDK support.
|
|
36
38
|
import { buildSensitivePathConstraint } from "./sensitive-paths.ts";
|
|
37
|
-
import {
|
|
38
|
-
|
|
39
|
+
import { eventToSidechainType, sidechainOutputPath, writeSidechainEntry } from "./sidechain-output.ts";
|
|
40
|
+
// NOTE: buildMemoryBlock is intentionally NOT imported here. The agent memory
|
|
41
|
+
// block is injected via renderTaskPrompt().full (the USER prompt), which is
|
|
42
|
+
// shared by both the child-pi path (no system prompt) and the live-session
|
|
43
|
+
// path. Adding it to liveSystemPrompt() too duplicated the entire memory
|
|
44
|
+
// block (up to 200 lines) in both the user and system prompts. Keep memory
|
|
45
|
+
// in a single place: the shared user prompt. See G3 fix.
|
|
46
|
+
import { createStreamingOutput, type StreamingOutputHandle } from "./streaming-output.ts";
|
|
47
|
+
import { trackTaskUsage } from "./usage-tracker.ts";
|
|
48
|
+
import {
|
|
49
|
+
buildYieldReminder,
|
|
50
|
+
DEFAULT_YIELD_CONFIG,
|
|
51
|
+
extractYieldResult,
|
|
52
|
+
hasYieldInOutput,
|
|
53
|
+
isYieldEvent,
|
|
54
|
+
validateYieldData,
|
|
55
|
+
type YieldResult,
|
|
56
|
+
} from "./yield-handler.ts";
|
|
39
57
|
|
|
40
58
|
/**
|
|
41
59
|
* Module-scoped latch for the optional peer dependency import. When N
|
|
@@ -110,13 +128,16 @@ export interface LiveSessionPlannedResult {
|
|
|
110
128
|
type LiveSessionModule = Record<string, unknown> & {
|
|
111
129
|
createAgentSession?: (options?: Record<string, unknown>) => Promise<{ session: LiveSessionLike; modelFallbackMessage?: string }>;
|
|
112
130
|
DefaultResourceLoader?: new (options: Record<string, unknown>) => { reload?: () => Promise<void> };
|
|
113
|
-
SessionManager?: {
|
|
131
|
+
SessionManager?: {
|
|
132
|
+
inMemory?: (cwd?: string) => unknown;
|
|
133
|
+
create?: (cwd?: string, sessionDir?: string) => unknown;
|
|
134
|
+
};
|
|
114
135
|
SettingsManager?: { create?: (cwd?: string, agentDir?: string) => unknown };
|
|
115
136
|
getAgentDir?: () => string;
|
|
116
137
|
};
|
|
117
138
|
|
|
118
139
|
type LiveSessionLike = {
|
|
119
|
-
subscribe?: (listener: (event: unknown) => void) => (
|
|
140
|
+
subscribe?: (listener: (event: unknown) => void) => () => void;
|
|
120
141
|
prompt?: (text: string, options?: Record<string, unknown>) => Promise<void>;
|
|
121
142
|
steer?: (text: string) => Promise<void>;
|
|
122
143
|
abort?: () => Promise<void> | void;
|
|
@@ -135,7 +156,7 @@ function appendTranscript(filePath: string | undefined, event: unknown): void {
|
|
|
135
156
|
}
|
|
136
157
|
|
|
137
158
|
function asRecord(value: unknown): Record<string, unknown> | undefined {
|
|
138
|
-
return value && typeof value === "object" && !Array.isArray(value) ? value as Record<string, unknown> : undefined;
|
|
159
|
+
return value && typeof value === "object" && !Array.isArray(value) ? (value as Record<string, unknown>) : undefined;
|
|
139
160
|
}
|
|
140
161
|
|
|
141
162
|
function isString(value: unknown): value is string {
|
|
@@ -157,7 +178,7 @@ function extractMessageRole(obj: Record<string, unknown> | undefined): string |
|
|
|
157
178
|
*/
|
|
158
179
|
function extractMessageUsage(obj: Record<string, unknown> | undefined): Record<string, unknown> | undefined {
|
|
159
180
|
const message = obj?.message ? asRecord(obj.message) : undefined;
|
|
160
|
-
return message?.usage && typeof message.usage === "object" ? message.usage as Record<string, unknown> : undefined;
|
|
181
|
+
return message?.usage && typeof message.usage === "object" ? (message.usage as Record<string, unknown>) : undefined;
|
|
161
182
|
}
|
|
162
183
|
|
|
163
184
|
/**
|
|
@@ -260,21 +281,18 @@ function modelFromRegistry(modelRegistry: unknown, modelId: string | undefined):
|
|
|
260
281
|
* model (e.g. minimax/MiniMax-M3, zai/glm-5.2); otherwise returns the
|
|
261
282
|
* raw `parentModel` unchanged so the caller surfaces E008.
|
|
262
283
|
*/
|
|
263
|
-
export function resolveParentModelFromRegistry(
|
|
264
|
-
modelRegistry: unknown,
|
|
265
|
-
rawParentModel: unknown,
|
|
266
|
-
): string | undefined {
|
|
284
|
+
export function resolveParentModelFromRegistry(modelRegistry: unknown, rawParentModel: unknown): string | undefined {
|
|
267
285
|
const raw = typeof rawParentModel === "string" ? rawParentModel.trim() : undefined;
|
|
268
286
|
if (raw) {
|
|
269
287
|
const candidate = raw.includes("/")
|
|
270
288
|
? raw
|
|
271
289
|
: (() => {
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
290
|
+
const m = modelFromRegistry(modelRegistry, raw);
|
|
291
|
+
if (m && typeof m === "object" && "fullId" in m) {
|
|
292
|
+
return String((m as { fullId?: unknown }).fullId ?? raw);
|
|
293
|
+
}
|
|
294
|
+
return undefined;
|
|
295
|
+
})();
|
|
278
296
|
if (candidate && modelFromRegistry(modelRegistry, candidate)) return candidate;
|
|
279
297
|
}
|
|
280
298
|
const registry = modelRegistry as { getAvailable?: () => unknown[] } | undefined;
|
|
@@ -311,15 +329,16 @@ const ROLE_INTENSITY: Record<string, "lite" | "full" | "ultra"> = {
|
|
|
311
329
|
function buildCommunicationStyle(role: string): string {
|
|
312
330
|
const intensity = ROLE_INTENSITY[role] ?? "full";
|
|
313
331
|
if (intensity === "lite") return "## Communication\nProfessional concise. No filler/hedging. Full sentences OK.";
|
|
314
|
-
if (intensity === "ultra")
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
332
|
+
if (intensity === "ultra")
|
|
333
|
+
return [
|
|
334
|
+
"## Communication (ultra-compressed)",
|
|
335
|
+
"Drop: articles, filler, hedging, pleasantries. Fragments OK.",
|
|
336
|
+
"Pattern: [thing] [action] [reason].",
|
|
337
|
+
"Code/paths/symbols: exact, never abbreviated. Errors quoted exact.",
|
|
338
|
+
"Abbreviate prose words: DB/auth/config/req/res/fn/impl.",
|
|
339
|
+
"Arrows for causality: X → Y. One word when one word enough.",
|
|
340
|
+
"Security/destructive: write normal English. Resume compressed after.",
|
|
341
|
+
].join("\n");
|
|
323
342
|
return [
|
|
324
343
|
"## Communication (compressed)",
|
|
325
344
|
"Drop: articles (a/an/the), filler (just/really/basically/actually/simply), hedging, pleasantries.",
|
|
@@ -330,32 +349,36 @@ function buildCommunicationStyle(role: string): string {
|
|
|
330
349
|
}
|
|
331
350
|
|
|
332
351
|
function buildOutputContract(role: string): string {
|
|
333
|
-
if (role === "explorer")
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
"
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
"
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
352
|
+
if (role === "explorer")
|
|
353
|
+
return [
|
|
354
|
+
"## Output Contract",
|
|
355
|
+
"<path>:<line> — `<symbol>` — <≤6 word note>",
|
|
356
|
+
"Group: Defs: / Refs: / Callers: / Tests: / Sites:",
|
|
357
|
+
'Zero hits → "No match."',
|
|
358
|
+
"Last line → totals: N defs, M refs.",
|
|
359
|
+
].join("\n");
|
|
360
|
+
if (role === "executor")
|
|
361
|
+
return [
|
|
362
|
+
"## Output Contract",
|
|
363
|
+
"<path>:<line-range> — <change ≤10 words>.",
|
|
364
|
+
"verified: <re-read OK | mismatch @ path:line>.",
|
|
365
|
+
"Refusal tokens: too-big. / needs-confirm. / ambiguous. / regressed.",
|
|
366
|
+
].join("\n");
|
|
367
|
+
if (role === "reviewer" || role === "security-reviewer")
|
|
368
|
+
return [
|
|
369
|
+
"## Output Contract",
|
|
370
|
+
"<path>:<line>: <emoji> <severity>: <problem>. <fix>.",
|
|
371
|
+
"Severity: 🔴 bug, 🟡 risk, 🔵 nit, ❓ question.",
|
|
372
|
+
'Zero findings → "No issues."',
|
|
373
|
+
"Sorted: file order → ascending line numbers.",
|
|
374
|
+
].join("\n");
|
|
375
|
+
if (role === "verifier")
|
|
376
|
+
return [
|
|
377
|
+
"## Output Contract",
|
|
378
|
+
"PASS: <what verified> — <evidence ≤20 words>.",
|
|
379
|
+
"FAIL: <what failed> — <reason>. <expected vs actual>.",
|
|
380
|
+
"Evidence: file paths, test output, or diffs.",
|
|
381
|
+
].join("\n");
|
|
359
382
|
if (role === "writer") return "## Output Contract\nWrite clear documentation. Full sentences. No compression.";
|
|
360
383
|
return ""; // planner, critic, analyst, test-engineer: no strict format
|
|
361
384
|
}
|
|
@@ -397,7 +420,9 @@ export function liveSystemPrompt(input: LiveSessionSpawnInput): string {
|
|
|
397
420
|
sensitiveConstraint,
|
|
398
421
|
"",
|
|
399
422
|
input.agent.systemPrompt || "Follow the user task exactly and report verification evidence.",
|
|
400
|
-
]
|
|
423
|
+
]
|
|
424
|
+
.filter(Boolean)
|
|
425
|
+
.join("\n");
|
|
401
426
|
}
|
|
402
427
|
|
|
403
428
|
function filterActiveTools(session: LiveSessionLike, agent: AgentConfig, role?: string): void {
|
|
@@ -411,7 +436,9 @@ function filterActiveTools(session: LiveSessionLike, agent: AgentConfig, role?:
|
|
|
411
436
|
const policy = resolveToolPolicy(agent, role);
|
|
412
437
|
const disallowed = policy.excludeTools?.length ? new Set(policy.excludeTools) : undefined;
|
|
413
438
|
const allowed = policy.tools?.length ? new Set(policy.tools) : undefined;
|
|
414
|
-
const active = session
|
|
439
|
+
const active = session
|
|
440
|
+
.getActiveToolNames()
|
|
441
|
+
.filter((name) => !recursiveTools.has(name) && (!disallowed || !disallowed.has(name)) && (!allowed || allowed.has(name)));
|
|
415
442
|
session.setActiveToolsByName(active);
|
|
416
443
|
}
|
|
417
444
|
|
|
@@ -424,11 +451,16 @@ function usageFromStats(stats: unknown): UsageState | undefined {
|
|
|
424
451
|
const cacheWrite = numberField(obj, ["cacheWrite", "cache_write"]);
|
|
425
452
|
const cost = numberField(obj, ["cost"]);
|
|
426
453
|
const turns = numberField(obj, ["turns", "turnCount", "turn_count"]);
|
|
427
|
-
return [input, output, cacheRead, cacheWrite, cost, turns].some((value) => value !== undefined)
|
|
454
|
+
return [input, output, cacheRead, cacheWrite, cost, turns].some((value) => value !== undefined)
|
|
455
|
+
? { input, output, cacheRead, cacheWrite, cost, turns }
|
|
456
|
+
: undefined;
|
|
428
457
|
}
|
|
429
458
|
|
|
430
459
|
async function promptWithTimeout(session: LiveSessionLike, text: string, timeoutMs: number, label: string): Promise<boolean> {
|
|
431
|
-
const promptPromise = session.prompt?.(text, {
|
|
460
|
+
const promptPromise = session.prompt?.(text, {
|
|
461
|
+
source: "api",
|
|
462
|
+
expandPromptTemplates: false,
|
|
463
|
+
});
|
|
432
464
|
if (!promptPromise) return false;
|
|
433
465
|
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
434
466
|
try {
|
|
@@ -447,8 +479,15 @@ async function promptWithTimeout(session: LiveSessionLike, text: string, timeout
|
|
|
447
479
|
|
|
448
480
|
export async function probeLiveSessionRuntime(): Promise<LiveSessionUnavailableResult | LiveSessionPlannedResult> {
|
|
449
481
|
const availability = await isLiveSessionRuntimeAvailable();
|
|
450
|
-
if (!availability.available)
|
|
451
|
-
|
|
482
|
+
if (!availability.available)
|
|
483
|
+
return {
|
|
484
|
+
available: false,
|
|
485
|
+
reason: availability.reason ?? "Live-session runtime is unavailable.",
|
|
486
|
+
};
|
|
487
|
+
return {
|
|
488
|
+
available: true,
|
|
489
|
+
reason: "Live-session SDK exports are available. pi-crew can run in-process live agents when runtime.mode=live-session.",
|
|
490
|
+
};
|
|
452
491
|
}
|
|
453
492
|
|
|
454
493
|
export async function runLiveSessionTask(input: LiveSessionSpawnInput): Promise<LiveSessionRunResult> {
|
|
@@ -464,29 +503,91 @@ export async function runLiveSessionTask(input: LiveSessionSpawnInput): Promise<
|
|
|
464
503
|
let customToolYieldResolved = false;
|
|
465
504
|
if (process.env.PI_CREW_MOCK_LIVE_SESSION === "success") {
|
|
466
505
|
const agentId = `${input.manifest.runId}:${input.task.id}`;
|
|
467
|
-
const inherited =
|
|
468
|
-
|
|
469
|
-
const
|
|
470
|
-
|
|
506
|
+
const inherited =
|
|
507
|
+
input.runtimeConfig?.inheritContext === true && input.parentContext ? ` with inherited context: ${input.parentContext}` : "";
|
|
508
|
+
const event = {
|
|
509
|
+
type: "message_end",
|
|
510
|
+
message: {
|
|
511
|
+
role: "assistant",
|
|
512
|
+
content: [
|
|
513
|
+
{
|
|
514
|
+
type: "text",
|
|
515
|
+
text: `Mock live-session success for ${input.agent.name}${inherited}`,
|
|
516
|
+
},
|
|
517
|
+
],
|
|
518
|
+
},
|
|
519
|
+
};
|
|
520
|
+
const mockSession = {
|
|
521
|
+
steer: async () => {},
|
|
522
|
+
prompt: async () => {},
|
|
523
|
+
abort: async () => {},
|
|
524
|
+
};
|
|
525
|
+
registerLiveAgent(
|
|
526
|
+
{
|
|
527
|
+
agentId,
|
|
528
|
+
runId: input.manifest.runId,
|
|
529
|
+
taskId: input.task.id,
|
|
530
|
+
role: input.task.role,
|
|
531
|
+
agent: input.agent?.name ?? "mock",
|
|
532
|
+
description: "mock",
|
|
533
|
+
session: mockSession,
|
|
534
|
+
status: "running",
|
|
535
|
+
workspaceId: input.workspaceId,
|
|
536
|
+
},
|
|
537
|
+
appendEvent,
|
|
538
|
+
input.manifest.eventsPath,
|
|
539
|
+
);
|
|
471
540
|
appendTranscript(input.transcriptPath, event);
|
|
472
541
|
const sidechainPath = sidechainOutputPath(input.manifest.stateRoot, input.task.id);
|
|
473
|
-
writeSidechainEntry(sidechainPath, {
|
|
474
|
-
|
|
542
|
+
writeSidechainEntry(sidechainPath, {
|
|
543
|
+
agentId,
|
|
544
|
+
type: "user",
|
|
545
|
+
message: { role: "user", content: input.prompt },
|
|
546
|
+
cwd: input.task.cwd,
|
|
547
|
+
});
|
|
548
|
+
writeSidechainEntry(sidechainPath, {
|
|
549
|
+
agentId,
|
|
550
|
+
type: "message",
|
|
551
|
+
message: event,
|
|
552
|
+
cwd: input.task.cwd,
|
|
553
|
+
});
|
|
475
554
|
if (isCurrent()) input.onEvent?.(event);
|
|
476
555
|
const stdout = `Mock live-session success for ${input.agent.name}${inherited}`;
|
|
477
556
|
if (isCurrent()) input.onOutput?.(stdout);
|
|
478
557
|
updateLiveAgentStatus(agentId, "completed");
|
|
479
558
|
markLiveAgentCompleted(agentId);
|
|
480
|
-
return {
|
|
559
|
+
return {
|
|
560
|
+
available: true,
|
|
561
|
+
exitCode: 0,
|
|
562
|
+
stdout,
|
|
563
|
+
stderr: "",
|
|
564
|
+
jsonEvents: 1,
|
|
565
|
+
};
|
|
481
566
|
}
|
|
482
567
|
const availability = await isLiveSessionRuntimeAvailable();
|
|
483
|
-
if (!availability.available)
|
|
568
|
+
if (!availability.available)
|
|
569
|
+
return {
|
|
570
|
+
available: true,
|
|
571
|
+
exitCode: 1,
|
|
572
|
+
stdout: "",
|
|
573
|
+
stderr: availability.reason ?? "Live-session runtime unavailable.",
|
|
574
|
+
jsonEvents: 0,
|
|
575
|
+
error: availability.reason,
|
|
576
|
+
};
|
|
484
577
|
// LAZY: optional peer dependency — only loaded when live-session runtime is
|
|
485
578
|
// chosen. Goes through the module-scoped latch (loadLiveSessionModule) so
|
|
486
579
|
// concurrent first-imports share ONE in-flight promise instead of racing
|
|
487
580
|
// module-record instantiation under the tsx loader.
|
|
488
581
|
const mod = await loadLiveSessionModule();
|
|
489
|
-
if (typeof mod.createAgentSession !== "function")
|
|
582
|
+
if (typeof mod.createAgentSession !== "function")
|
|
583
|
+
return {
|
|
584
|
+
available: true,
|
|
585
|
+
exitCode: 1,
|
|
586
|
+
stdout: "",
|
|
587
|
+
stderr: "createAgentSession export is unavailable.",
|
|
588
|
+
jsonEvents: 0,
|
|
589
|
+
error: "createAgentSession export is unavailable.",
|
|
590
|
+
};
|
|
490
591
|
let session: LiveSessionLike | undefined;
|
|
491
592
|
let unsubscribe: (() => void) | undefined;
|
|
492
593
|
let unsubscribeControlRealtime: (() => void) | undefined;
|
|
@@ -528,8 +629,19 @@ export async function runLiveSessionTask(input: LiveSessionSpawnInput): Promise<
|
|
|
528
629
|
await (resourceLoader as { reload?: () => Promise<void> }).reload?.();
|
|
529
630
|
}
|
|
530
631
|
const effectiveParentModel = resolveParentModelFromRegistry(input.modelRegistry, input.parentModel);
|
|
531
|
-
const modelRouting = buildConfiguredModelRouting({
|
|
532
|
-
|
|
632
|
+
const modelRouting = buildConfiguredModelRouting({
|
|
633
|
+
overrideModel: input.modelOverride,
|
|
634
|
+
stepModel: input.step.model,
|
|
635
|
+
teamRoleModel: input.teamRoleModel,
|
|
636
|
+
agentModel: input.agent.model,
|
|
637
|
+
fallbackModels: input.agent.fallbackModels,
|
|
638
|
+
parentModel: effectiveParentModel,
|
|
639
|
+
modelRegistry: input.modelRegistry,
|
|
640
|
+
cwd: input.manifest.cwd,
|
|
641
|
+
scopeModelsPatterns: await resolveScopeModelsPatterns(input.manifest.cwd),
|
|
642
|
+
});
|
|
643
|
+
const resolvedModel =
|
|
644
|
+
modelFromRegistry(input.modelRegistry, modelRouting.candidates[0] ?? modelRouting.requested) ?? input.parentModel;
|
|
533
645
|
// Phase 4: MCP proxy — will be determined after session creation
|
|
534
646
|
// (we check parent's MCP tools and share connections when available)
|
|
535
647
|
const mcpProxy = buildMcpProxyFromSession([], { shareMcp: true });
|
|
@@ -547,8 +659,16 @@ export async function runLiveSessionTask(input: LiveSessionSpawnInput): Promise<
|
|
|
547
659
|
cwd: input.task.cwd,
|
|
548
660
|
...(agentDir ? { agentDir } : {}),
|
|
549
661
|
...(resourceLoader ? { resourceLoader } : {}),
|
|
550
|
-
...(mod.SessionManager?.inMemory
|
|
551
|
-
|
|
662
|
+
...(mod.SessionManager?.inMemory
|
|
663
|
+
? {
|
|
664
|
+
sessionManager: mod.SessionManager.inMemory(input.task.cwd),
|
|
665
|
+
}
|
|
666
|
+
: {}),
|
|
667
|
+
...(mod.SettingsManager?.create && agentDir
|
|
668
|
+
? {
|
|
669
|
+
settingsManager: mod.SettingsManager.create(input.task.cwd, agentDir),
|
|
670
|
+
}
|
|
671
|
+
: {}),
|
|
552
672
|
...(input.modelRegistry ? { modelRegistry: input.modelRegistry } : {}),
|
|
553
673
|
...(resolvedModel ? { model: resolvedModel } : {}),
|
|
554
674
|
...(input.agent.thinking ? { thinkingLevel: input.agent.thinking } : {}),
|
|
@@ -556,7 +676,15 @@ export async function runLiveSessionTask(input: LiveSessionSpawnInput): Promise<
|
|
|
556
676
|
customTools,
|
|
557
677
|
});
|
|
558
678
|
session = created.session;
|
|
559
|
-
appendEvent(input.manifest.eventsPath, {
|
|
679
|
+
appendEvent(input.manifest.eventsPath, {
|
|
680
|
+
type: "live-session.session_created",
|
|
681
|
+
runId: input.manifest.runId,
|
|
682
|
+
taskId: input.task.id,
|
|
683
|
+
data: {
|
|
684
|
+
elapsedMs: Date.now() - sessionCreateStart,
|
|
685
|
+
modelFallbackMessage: created.modelFallbackMessage,
|
|
686
|
+
},
|
|
687
|
+
});
|
|
560
688
|
filterActiveTools(session, input.agent, input.task.role);
|
|
561
689
|
|
|
562
690
|
// Diagnostic: log before bindExtensions so we can identify extension-loading hangs
|
|
@@ -568,7 +696,15 @@ export async function runLiveSessionTask(input: LiveSessionSpawnInput): Promise<
|
|
|
568
696
|
]);
|
|
569
697
|
} catch (bindError) {
|
|
570
698
|
const msg = bindError instanceof Error ? bindError.message : String(bindError);
|
|
571
|
-
appendEvent(input.manifest.eventsPath, {
|
|
699
|
+
appendEvent(input.manifest.eventsPath, {
|
|
700
|
+
type: "live-session.bind_extensions_error",
|
|
701
|
+
runId: input.manifest.runId,
|
|
702
|
+
taskId: input.task.id,
|
|
703
|
+
data: {
|
|
704
|
+
elapsedMs: Date.now() - bindExtensionsStart,
|
|
705
|
+
error: msg,
|
|
706
|
+
},
|
|
707
|
+
});
|
|
572
708
|
// Continue without extensions — they should not block the session
|
|
573
709
|
}
|
|
574
710
|
|
|
@@ -583,9 +719,17 @@ export async function runLiveSessionTask(input: LiveSessionSpawnInput): Promise<
|
|
|
583
719
|
const extRunner = (session as Record<string, unknown>).extensionRunner;
|
|
584
720
|
if (extRunner && typeof (extRunner as Record<string, unknown>).initialize === "function") {
|
|
585
721
|
try {
|
|
586
|
-
(
|
|
722
|
+
(
|
|
723
|
+
extRunner as {
|
|
724
|
+
initialize: (apis: unknown, host: unknown) => void;
|
|
725
|
+
}
|
|
726
|
+
).initialize(extensionBridge.apis, extensionBridge.host);
|
|
587
727
|
if (typeof (extRunner as Record<string, unknown>).emit === "function") {
|
|
588
|
-
await (
|
|
728
|
+
await (
|
|
729
|
+
extRunner as {
|
|
730
|
+
emit: (event: unknown) => Promise<void>;
|
|
731
|
+
}
|
|
732
|
+
).emit({ type: "session_start" });
|
|
589
733
|
}
|
|
590
734
|
} catch {
|
|
591
735
|
// Extension runner initialization failure should not block the session
|
|
@@ -593,7 +737,22 @@ export async function runLiveSessionTask(input: LiveSessionSpawnInput): Promise<
|
|
|
593
737
|
}
|
|
594
738
|
}
|
|
595
739
|
|
|
596
|
-
registerLiveAgent(
|
|
740
|
+
registerLiveAgent(
|
|
741
|
+
{
|
|
742
|
+
agentId,
|
|
743
|
+
runId: input.manifest.runId,
|
|
744
|
+
taskId: input.task.id,
|
|
745
|
+
role: input.task.role,
|
|
746
|
+
agent: input.agent?.name ?? "unknown",
|
|
747
|
+
description: input.task.adaptive?.task ?? input.step?.task ?? "",
|
|
748
|
+
modelName: (resolvedModel as { name?: string })?.name,
|
|
749
|
+
session,
|
|
750
|
+
status: "running",
|
|
751
|
+
workspaceId: input.workspaceId,
|
|
752
|
+
},
|
|
753
|
+
appendEvent,
|
|
754
|
+
input.manifest.eventsPath,
|
|
755
|
+
);
|
|
597
756
|
streamOut = createStreamingOutput(input.manifest, input.task.id);
|
|
598
757
|
let controlCursor: LiveAgentControlCursor = { offset: 0 };
|
|
599
758
|
const seenControlRequestIds = new Set<string>();
|
|
@@ -602,14 +761,27 @@ export async function runLiveSessionTask(input: LiveSessionSpawnInput): Promise<
|
|
|
602
761
|
if (!isCurrent() || controlBusy || !session) return;
|
|
603
762
|
controlBusy = true;
|
|
604
763
|
try {
|
|
605
|
-
controlCursor = await applyLiveAgentControlRequests({
|
|
764
|
+
controlCursor = await applyLiveAgentControlRequests({
|
|
765
|
+
manifest: input.manifest,
|
|
766
|
+
taskId: input.task.id,
|
|
767
|
+
agentId,
|
|
768
|
+
session,
|
|
769
|
+
cursor: controlCursor,
|
|
770
|
+
seenRequestIds: seenControlRequestIds,
|
|
771
|
+
});
|
|
606
772
|
} finally {
|
|
607
773
|
controlBusy = false;
|
|
608
774
|
}
|
|
609
775
|
};
|
|
610
776
|
unsubscribeControlRealtime = subscribeLiveControlRealtime((request) => {
|
|
611
777
|
if (!isCurrent() || request.runId !== input.manifest.runId || request.taskId !== input.task.id || !session) return;
|
|
612
|
-
void applyLiveAgentControlRequest({
|
|
778
|
+
void applyLiveAgentControlRequest({
|
|
779
|
+
request,
|
|
780
|
+
taskId: input.task.id,
|
|
781
|
+
agentId,
|
|
782
|
+
session,
|
|
783
|
+
seenRequestIds: seenControlRequestIds,
|
|
784
|
+
});
|
|
613
785
|
});
|
|
614
786
|
await pollControl();
|
|
615
787
|
controlTimer = setInterval(() => {
|
|
@@ -620,14 +792,25 @@ export async function runLiveSessionTask(input: LiveSessionSpawnInput): Promise<
|
|
|
620
792
|
const maxTurns = input.runtimeConfig?.maxTurns;
|
|
621
793
|
const graceTurns = input.runtimeConfig?.graceTurns ?? 5;
|
|
622
794
|
const sidechainPath = sidechainOutputPath(input.manifest.stateRoot, input.task.id);
|
|
623
|
-
writeSidechainEntry(sidechainPath, {
|
|
795
|
+
writeSidechainEntry(sidechainPath, {
|
|
796
|
+
agentId,
|
|
797
|
+
type: "user",
|
|
798
|
+
message: { role: "user", content: input.prompt },
|
|
799
|
+
cwd: input.task.cwd,
|
|
800
|
+
});
|
|
624
801
|
if (typeof session.subscribe === "function") {
|
|
625
802
|
unsubscribe = session.subscribe((event) => {
|
|
626
803
|
if (!isCurrent()) return;
|
|
627
804
|
jsonEvents += 1;
|
|
628
805
|
appendTranscript(input.transcriptPath, event);
|
|
629
806
|
const sidechainType = eventToSidechainType(event);
|
|
630
|
-
if (sidechainType)
|
|
807
|
+
if (sidechainType)
|
|
808
|
+
writeSidechainEntry(sidechainPath, {
|
|
809
|
+
agentId,
|
|
810
|
+
type: sidechainType,
|
|
811
|
+
message: event,
|
|
812
|
+
cwd: input.task.cwd,
|
|
813
|
+
});
|
|
631
814
|
const obj = asRecord(event);
|
|
632
815
|
if (obj?.type === "turn_end") {
|
|
633
816
|
turnCount += 1;
|
|
@@ -670,24 +853,42 @@ export async function runLiveSessionTask(input: LiveSessionSpawnInput): Promise<
|
|
|
670
853
|
// Phase 1: collect events for yield detection
|
|
671
854
|
if (event && typeof event === "object" && !Array.isArray(event)) {
|
|
672
855
|
collectedJsonEvents.push(event as Record<string, unknown>);
|
|
673
|
-
if (collectedJsonEvents.length > maxCollectedJsonEvents)
|
|
856
|
+
if (collectedJsonEvents.length > maxCollectedJsonEvents)
|
|
857
|
+
collectedJsonEvents.splice(0, collectedJsonEvents.length - maxCollectedJsonEvents);
|
|
674
858
|
}
|
|
675
859
|
});
|
|
676
860
|
}
|
|
677
861
|
// Round 27 (BUG 4): named abort handler (removed in finally below).
|
|
678
|
-
onSignalAbort = (): void => {
|
|
862
|
+
onSignalAbort = (): void => {
|
|
863
|
+
void session?.abort?.();
|
|
864
|
+
};
|
|
679
865
|
if (input.signal) {
|
|
680
866
|
if (input.signal.aborted) await session.abort?.();
|
|
681
867
|
// Round 27 (BUG 4): named handler so the finally block can remove it.
|
|
682
868
|
// The previous anonymous listener leaked on normal completion (only
|
|
683
869
|
// auto-removed by { once: true } AFTER the signal fires).
|
|
684
|
-
else
|
|
870
|
+
else
|
|
871
|
+
input.signal.addEventListener("abort", onSignalAbort, {
|
|
872
|
+
once: true,
|
|
873
|
+
});
|
|
685
874
|
}
|
|
686
|
-
const effectivePrompt =
|
|
875
|
+
const effectivePrompt =
|
|
876
|
+
input.runtimeConfig?.inheritContext === true && input.parentContext
|
|
877
|
+
? `${input.parentContext}\n\n---\n# Live Subagent Task\n${input.prompt}`
|
|
878
|
+
: input.prompt;
|
|
687
879
|
|
|
688
880
|
// Diagnostic: log prompt size and timing
|
|
689
881
|
const promptStart = Date.now();
|
|
690
|
-
appendEvent(input.manifest.eventsPath, {
|
|
882
|
+
appendEvent(input.manifest.eventsPath, {
|
|
883
|
+
type: "live-session.prompt_start",
|
|
884
|
+
runId: input.manifest.runId,
|
|
885
|
+
taskId: input.task.id,
|
|
886
|
+
data: {
|
|
887
|
+
promptLength: effectivePrompt.length,
|
|
888
|
+
agent: input.agent.name,
|
|
889
|
+
role: input.task.role,
|
|
890
|
+
},
|
|
891
|
+
});
|
|
691
892
|
|
|
692
893
|
// Phase 3: Wrap session.prompt with timeout for graceful cancellation
|
|
693
894
|
const sessionTimeoutMs = DEFAULT_LIVE_SESSION.responseTimeoutMs;
|
|
@@ -695,20 +896,43 @@ export async function runLiveSessionTask(input: LiveSessionSpawnInput): Promise<
|
|
|
695
896
|
await promptWithTimeout(session, effectivePrompt, sessionTimeoutMs, "Live-session");
|
|
696
897
|
} catch (promptError) {
|
|
697
898
|
const msg = promptError instanceof Error ? promptError.message : String(promptError);
|
|
698
|
-
appendEvent(input.manifest.eventsPath, {
|
|
899
|
+
appendEvent(input.manifest.eventsPath, {
|
|
900
|
+
type: "live-session.prompt_error",
|
|
901
|
+
runId: input.manifest.runId,
|
|
902
|
+
taskId: input.task.id,
|
|
903
|
+
data: { elapsedMs: Date.now() - promptStart, error: msg },
|
|
904
|
+
});
|
|
699
905
|
if (msg.includes("timed out")) {
|
|
700
906
|
await session.abort?.();
|
|
701
907
|
updateLiveAgentStatus(agentId, "failed");
|
|
702
|
-
return {
|
|
908
|
+
return {
|
|
909
|
+
available: true,
|
|
910
|
+
exitCode: 1,
|
|
911
|
+
stdout: stdout.trim(),
|
|
912
|
+
stderr: msg,
|
|
913
|
+
jsonEvents,
|
|
914
|
+
error: msg,
|
|
915
|
+
};
|
|
703
916
|
}
|
|
704
917
|
throw promptError;
|
|
705
918
|
}
|
|
706
|
-
appendEvent(input.manifest.eventsPath, {
|
|
919
|
+
appendEvent(input.manifest.eventsPath, {
|
|
920
|
+
type: "live-session.prompt_done",
|
|
921
|
+
runId: input.manifest.runId,
|
|
922
|
+
taskId: input.task.id,
|
|
923
|
+
data: {
|
|
924
|
+
elapsedMs: Date.now() - promptStart,
|
|
925
|
+
jsonEvents,
|
|
926
|
+
outputLength: stdout.length,
|
|
927
|
+
},
|
|
928
|
+
});
|
|
707
929
|
|
|
708
930
|
// --- Phase 1: Yield enforcement loop ---
|
|
709
931
|
// After the initial prompt completes, check if the worker called submit_result.
|
|
710
932
|
// Priority: 1) custom tool callback (G1), 2) JSON event detection (legacy).
|
|
711
|
-
const yieldConfig = input.runtimeConfig?.yield ?? {
|
|
933
|
+
const yieldConfig = input.runtimeConfig?.yield ?? {
|
|
934
|
+
enabled: DEFAULT_YIELD_CONFIG.enabled,
|
|
935
|
+
};
|
|
712
936
|
const yieldEnabled = yieldConfig.enabled !== false;
|
|
713
937
|
if (yieldEnabled && session) {
|
|
714
938
|
// Check custom tool callback first (G1)
|
|
@@ -733,7 +957,12 @@ export async function runLiveSessionTask(input: LiveSessionSpawnInput): Promise<
|
|
|
733
957
|
customToolYieldResolved = false;
|
|
734
958
|
const schemaReminder = `Your submit_result data did not match the required schema: ${validation.error}. Please fix and call submit_result again with valid data.`;
|
|
735
959
|
try {
|
|
736
|
-
await promptWithTimeout(
|
|
960
|
+
await promptWithTimeout(
|
|
961
|
+
session,
|
|
962
|
+
schemaReminder,
|
|
963
|
+
Math.min(sessionTimeoutMs, DEFAULT_LIVE_SESSION.idleWaitTimeoutMs),
|
|
964
|
+
"Live-session schema reminder",
|
|
965
|
+
);
|
|
737
966
|
} catch {
|
|
738
967
|
/* ignore */
|
|
739
968
|
}
|
|
@@ -770,7 +999,12 @@ export async function runLiveSessionTask(input: LiveSessionSpawnInput): Promise<
|
|
|
770
999
|
if (typeof session.setActiveToolsByName === "function" && prevTools.length > 0) {
|
|
771
1000
|
session.setActiveToolsByName(["submit_result"]);
|
|
772
1001
|
}
|
|
773
|
-
await promptWithTimeout(
|
|
1002
|
+
await promptWithTimeout(
|
|
1003
|
+
session,
|
|
1004
|
+
reminder,
|
|
1005
|
+
Math.min(sessionTimeoutMs, DEFAULT_LIVE_SESSION.idleWaitTimeoutMs),
|
|
1006
|
+
"Live-session yield reminder",
|
|
1007
|
+
);
|
|
774
1008
|
} catch {
|
|
775
1009
|
break;
|
|
776
1010
|
} finally {
|
|
@@ -794,14 +1028,32 @@ export async function runLiveSessionTask(input: LiveSessionSpawnInput): Promise<
|
|
|
794
1028
|
}
|
|
795
1029
|
}
|
|
796
1030
|
if (!customToolYieldResolved && !yieldResult && !input.signal?.aborted && retryCount >= maxReminders) {
|
|
797
|
-
input.onEvent?.({
|
|
1031
|
+
input.onEvent?.({
|
|
1032
|
+
type: "task.attention",
|
|
1033
|
+
runId: input.manifest.runId,
|
|
1034
|
+
taskId: input.task.id,
|
|
1035
|
+
message: "Live-session worker completed without calling submit_result tool.",
|
|
1036
|
+
data: {
|
|
1037
|
+
activityState: "needs_attention",
|
|
1038
|
+
reason: "no_yield",
|
|
1039
|
+
attempts: retryCount,
|
|
1040
|
+
},
|
|
1041
|
+
});
|
|
798
1042
|
}
|
|
799
1043
|
}
|
|
800
1044
|
|
|
801
1045
|
const usage = usageFromStats(typeof session.getStats === "function" ? session.getStats() : session.stats);
|
|
802
1046
|
updateLiveAgentStatus(agentId, "completed");
|
|
803
1047
|
markLiveAgentCompleted(agentId);
|
|
804
|
-
return {
|
|
1048
|
+
return {
|
|
1049
|
+
available: true,
|
|
1050
|
+
exitCode: 0,
|
|
1051
|
+
stdout: stdout.trim(),
|
|
1052
|
+
stderr: created.modelFallbackMessage ?? "",
|
|
1053
|
+
jsonEvents,
|
|
1054
|
+
usage,
|
|
1055
|
+
yieldResult,
|
|
1056
|
+
};
|
|
805
1057
|
} catch (error) {
|
|
806
1058
|
const message = error instanceof Error ? error.message : String(error);
|
|
807
1059
|
|
|
@@ -810,13 +1062,23 @@ export async function runLiveSessionTask(input: LiveSessionSpawnInput): Promise<
|
|
|
810
1062
|
const agents = listLiveAgents();
|
|
811
1063
|
const health = collectLiveSessionHealth(agents, () => undefined);
|
|
812
1064
|
const diagnostics = formatLiveSessionDiagnostics(health);
|
|
813
|
-
input.onEvent?.({
|
|
1065
|
+
input.onEvent?.({
|
|
1066
|
+
type: "live-session.diagnostics",
|
|
1067
|
+
data: diagnostics,
|
|
1068
|
+
});
|
|
814
1069
|
} catch (diagError) {
|
|
815
1070
|
logInternalError("live-session.diagnostics", diagError);
|
|
816
1071
|
}
|
|
817
1072
|
|
|
818
1073
|
updateLiveAgentStatus(`${input.manifest.runId}:${input.task.id}`, "failed");
|
|
819
|
-
return {
|
|
1074
|
+
return {
|
|
1075
|
+
available: true,
|
|
1076
|
+
exitCode: 1,
|
|
1077
|
+
stdout: stdout.trim(),
|
|
1078
|
+
stderr: message,
|
|
1079
|
+
jsonEvents,
|
|
1080
|
+
error: message,
|
|
1081
|
+
};
|
|
820
1082
|
} finally {
|
|
821
1083
|
// H6: Unsubscribe listeners FIRST before clearing timer to prevent race
|
|
822
1084
|
unsubscribe?.();
|