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,380 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
4
|
+
import { startChildBrokerClient } from "../runtime/crew-broker-child.ts";
|
|
5
|
+
import { logInternalError } from "../utils/internal-error.ts";
|
|
6
|
+
import { resolveRealContainedPath } from "../utils/safe-paths.ts";
|
|
7
|
+
|
|
8
|
+
export const PI_TEAMS_INHERIT_PROJECT_CONTEXT_ENV = "PI_TEAMS_INHERIT_PROJECT_CONTEXT";
|
|
9
|
+
export const PI_TEAMS_INHERIT_SKILLS_ENV = "PI_TEAMS_INHERIT_SKILLS";
|
|
10
|
+
export const PI_CREW_INHERIT_PROJECT_CONTEXT_ENV = "PI_CREW_INHERIT_PROJECT_CONTEXT";
|
|
11
|
+
export const PI_CREW_INHERIT_SKILLS_ENV = "PI_CREW_INHERIT_SKILLS";
|
|
12
|
+
const PI_CREW_MAX_OUTPUT_ENV = "PI_CREW_MAX_OUTPUT";
|
|
13
|
+
const PI_CREW_STEERING_FILE_ENV = "PI_CREW_STEERING_FILE";
|
|
14
|
+
|
|
15
|
+
const PROJECT_CONTEXT_HEADER = "\n\n# Project Context\n\nProject-specific instructions and guidelines:\n\n";
|
|
16
|
+
const SKILLS_HEADER = "\n\nThe following skills provide specialized instructions for specific tasks.";
|
|
17
|
+
const DATE_HEADER = "\nCurrent date:";
|
|
18
|
+
|
|
19
|
+
// ── FIX-02: Steering content sanitization limits ──────────────────────────
|
|
20
|
+
// Bounded to keep a malformed/malicious steer entry from blowing up the
|
|
21
|
+
// worker's prompt budget or smuggling control sequences into the agent.
|
|
22
|
+
const MAX_STEER_MESSAGE_LENGTH = 4096;
|
|
23
|
+
const MAX_STEER_MESSAGE_NEWLINES = 50;
|
|
24
|
+
// C0 control characters minus the printable whitespace (\t \n \r). These
|
|
25
|
+
// are the bytes most useful for ANSI escapes, terminal-control tricks, and
|
|
26
|
+
// NUL-injection attacks when steer content reaches the worker's UI.
|
|
27
|
+
const STEER_CONTROL_CHAR_PATTERN = /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/;
|
|
28
|
+
|
|
29
|
+
export interface SteerSanitizeResult {
|
|
30
|
+
valid: boolean;
|
|
31
|
+
reason?: string;
|
|
32
|
+
message?: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface SteerEntry {
|
|
36
|
+
type?: string;
|
|
37
|
+
message?: string;
|
|
38
|
+
/** Message id. Present in entries the broker writes; absent in legacy
|
|
39
|
+
* entries pre-dating the broker id-forwarding change. */
|
|
40
|
+
id?: string;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// ── FIX-S1: Cross-channel steer dedup state ──────────────────────────────
|
|
44
|
+
// Both the live broker push (mailbox.message → onSteer) and the durable
|
|
45
|
+
// file poll (pollSteering JSONL) can deliver the SAME steer to the worker
|
|
46
|
+
// for two reasons:
|
|
47
|
+
// 1. The broker writes to BOTH the mailbox AND the steering JSONL for
|
|
48
|
+
// durability. A connected child receives the broker push FIRST, then
|
|
49
|
+
// file-poll sees the JSONL shortly after (the broker's own write is
|
|
50
|
+
// what populates that file).
|
|
51
|
+
// 2. A reconnect / catch-up from a previously-disconnected child can
|
|
52
|
+
// re-deliver the same mailbox.message id a second time.
|
|
53
|
+
//
|
|
54
|
+
// We dedup at the recipient (worker) by tracking steer ids across BOTH
|
|
55
|
+
// channels in a single bounded FIFO set. Entries without an id (legacy
|
|
56
|
+
// JSONL rows written before S1) are NOT deduped, because they lack a
|
|
57
|
+
// stable identity — the file-poll path is their only delivery route.
|
|
58
|
+
const SEEN_STEER_ID_CAP = 1024;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Bounded FIFO seen-set for steer message ids.
|
|
62
|
+
*
|
|
63
|
+
* - `markOrSkip(undefined)` returns true (the file-poll path may emit
|
|
64
|
+
* legacy id-less entries; forward them).
|
|
65
|
+
* - `markOrSkip('a')` first call returns true; the same call again returns
|
|
66
|
+
* false (id already seen → drop the duplicate deliver).
|
|
67
|
+
* - When the cap is exceeded, the oldest id is evicted so the set stays
|
|
68
|
+
* bounded under long-running workers with high steer churn.
|
|
69
|
+
*
|
|
70
|
+
* Factory-shaped so multiple prompt-runtime instances (tests, parallel
|
|
71
|
+
* workers) get independent sets.
|
|
72
|
+
*/
|
|
73
|
+
export function createSeenSteerIdSet(): { markOrSkip: (id?: string) => boolean; size: () => number } {
|
|
74
|
+
const seen: string[] = [];
|
|
75
|
+
const set = new Set<string>();
|
|
76
|
+
return {
|
|
77
|
+
markOrSkip(id?: string): boolean {
|
|
78
|
+
if (id === undefined) return true; // legacy steers have no id; only file-poll path can produce these
|
|
79
|
+
if (set.has(id)) return false;
|
|
80
|
+
set.add(id);
|
|
81
|
+
seen.push(id);
|
|
82
|
+
// FIFO eviction: when the cap is exceeded, drop the oldest entry.
|
|
83
|
+
while (seen.length > SEEN_STEER_ID_CAP) {
|
|
84
|
+
const oldest = seen.shift();
|
|
85
|
+
if (oldest !== undefined) set.delete(oldest);
|
|
86
|
+
}
|
|
87
|
+
return true;
|
|
88
|
+
},
|
|
89
|
+
size: () => set.size,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Validate a single steering-file entry before forwarding it to
|
|
95
|
+
* `pi.sendMessage`. FIX-02: reject oversized payloads, excessive newlines,
|
|
96
|
+
* or control characters that could be used to confuse the worker UI.
|
|
97
|
+
*/
|
|
98
|
+
export function sanitizeSteerMessage(entry: SteerEntry): SteerSanitizeResult {
|
|
99
|
+
const message = entry.message;
|
|
100
|
+
if (typeof message !== "string" || message.length === 0) {
|
|
101
|
+
return { valid: false, reason: "missing-or-empty-message" };
|
|
102
|
+
}
|
|
103
|
+
if (message.length > MAX_STEER_MESSAGE_LENGTH) {
|
|
104
|
+
return { valid: false, reason: `message-too-long:${message.length}` };
|
|
105
|
+
}
|
|
106
|
+
const newlineCount = (message.match(/\n/g) ?? []).length;
|
|
107
|
+
if (newlineCount > MAX_STEER_MESSAGE_NEWLINES) {
|
|
108
|
+
return { valid: false, reason: `too-many-newlines:${newlineCount}` };
|
|
109
|
+
}
|
|
110
|
+
if (STEER_CONTROL_CHAR_PATTERN.test(message)) {
|
|
111
|
+
return { valid: false, reason: "contains-control-characters" };
|
|
112
|
+
}
|
|
113
|
+
return { valid: true, message };
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// ── FIX-03: Steering file path containment validation ─────────────────────
|
|
117
|
+
// The steering file path is inherited from the parent via env, so we
|
|
118
|
+
// defensively re-validate it before the first read to catch symlink
|
|
119
|
+
// redirection or paths that escape the session's artifacts root.
|
|
120
|
+
export interface SteeringFileValidation {
|
|
121
|
+
valid: boolean;
|
|
122
|
+
reason?: string;
|
|
123
|
+
resolvedPath?: string;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Validate `PI_CREW_STEERING_FILE` before first read. FIX-03:
|
|
128
|
+
* 1. `lstatSync` rejects a symlink at the steering file itself.
|
|
129
|
+
* 2. `resolveRealContainedPath` walks the ancestor chain with O_NOFOLLOW
|
|
130
|
+
* to reject any symlinked parent (e.g. a redirected `artifactsRoot`)
|
|
131
|
+
* and to verify the resolved path stays inside the derived artifacts
|
|
132
|
+
* root (`<artifactsRoot>/steering/<taskId>.jsonl` → `<artifactsRoot>`).
|
|
133
|
+
*
|
|
134
|
+
* Returns `{ valid: false }` with a reason on any violation. Callers must
|
|
135
|
+
* log + skip steering on failure rather than abort the worker.
|
|
136
|
+
*/
|
|
137
|
+
export function validateSteeringFile(steeringFile: string): SteeringFileValidation {
|
|
138
|
+
try {
|
|
139
|
+
const lst = fs.lstatSync(steeringFile);
|
|
140
|
+
if (lst.isSymbolicLink()) {
|
|
141
|
+
return { valid: false, reason: "steering-file-is-symlink" };
|
|
142
|
+
}
|
|
143
|
+
} catch (error) {
|
|
144
|
+
const errCode = (error as NodeJS.ErrnoException).code;
|
|
145
|
+
if (errCode && errCode !== "ENOENT") {
|
|
146
|
+
return { valid: false, reason: `lstat-failed:${errCode}` };
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
// Layout invariant from task-runner.ts: `steeringFile` is built as
|
|
150
|
+
// `<artifactsRoot>/steering/<taskId>.jsonl`. We don't trust the caller
|
|
151
|
+
// to pass `artifactsRoot`, so derive it as 2 levels up. `resolveRealContainedPath`
|
|
152
|
+
// then enforces both containment AND ancestor-symlink safety in one shot.
|
|
153
|
+
const artifactsRoot = path.resolve(steeringFile, "..", "..");
|
|
154
|
+
try {
|
|
155
|
+
const resolved = resolveRealContainedPath(artifactsRoot, steeringFile);
|
|
156
|
+
return { valid: true, resolvedPath: resolved };
|
|
157
|
+
} catch (error) {
|
|
158
|
+
return {
|
|
159
|
+
valid: false,
|
|
160
|
+
reason: `path-validation-failed:${error instanceof Error ? error.message : String(error)}`,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function readBooleanEnv(name: string): boolean | undefined {
|
|
166
|
+
const value = process.env[name];
|
|
167
|
+
if (value === undefined) return undefined;
|
|
168
|
+
const normalized = value.trim().toLowerCase();
|
|
169
|
+
if (normalized === "1" || normalized === "true" || normalized === "yes") return true;
|
|
170
|
+
if (normalized === "0" || normalized === "false" || normalized === "no") return false;
|
|
171
|
+
// Ambiguous value — treat as undefined so callers apply their default.
|
|
172
|
+
return undefined;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function readBooleanEnvAny(...names: string[]): boolean | undefined {
|
|
176
|
+
for (const name of names) {
|
|
177
|
+
const value = readBooleanEnv(name);
|
|
178
|
+
if (value !== undefined) return value;
|
|
179
|
+
}
|
|
180
|
+
return undefined;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function findSectionEnd(prompt: string, startIndex: number, nextHeaders: string[]): number {
|
|
184
|
+
let endIndex = prompt.length;
|
|
185
|
+
for (const header of nextHeaders) {
|
|
186
|
+
const index = prompt.indexOf(header, startIndex);
|
|
187
|
+
if (index !== -1 && index < endIndex) endIndex = index;
|
|
188
|
+
}
|
|
189
|
+
return endIndex;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export function stripProjectContext(prompt: string): string {
|
|
193
|
+
const startIndex = prompt.indexOf(PROJECT_CONTEXT_HEADER);
|
|
194
|
+
if (startIndex === -1) return prompt;
|
|
195
|
+
const endIndex = findSectionEnd(prompt, startIndex + PROJECT_CONTEXT_HEADER.length, [SKILLS_HEADER, DATE_HEADER]);
|
|
196
|
+
return `${prompt.slice(0, startIndex)}${prompt.slice(endIndex)}`;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export function stripInheritedSkills(prompt: string): string {
|
|
200
|
+
const startIndex = prompt.indexOf(SKILLS_HEADER);
|
|
201
|
+
if (startIndex === -1) return prompt;
|
|
202
|
+
const endIndex = findSectionEnd(prompt, startIndex + SKILLS_HEADER.length, [DATE_HEADER]);
|
|
203
|
+
return `${prompt.slice(0, startIndex)}${prompt.slice(endIndex)}`;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export function rewriteTeamWorkerPrompt(prompt: string, options: { inheritProjectContext: boolean; inheritSkills: boolean }): string {
|
|
207
|
+
let rewritten = prompt;
|
|
208
|
+
if (!options.inheritProjectContext) rewritten = stripProjectContext(rewritten);
|
|
209
|
+
if (!options.inheritSkills) rewritten = stripInheritedSkills(rewritten);
|
|
210
|
+
return rewritten;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export default function registerPiTeamsPromptRuntime(pi: ExtensionAPI): void {
|
|
214
|
+
// ── FIX-S1: cross-channel steer dedup state ────────────────────────────
|
|
215
|
+
// Both the broker push (mailbox.message → onSteer callback below) and the
|
|
216
|
+
// file poll (pollSteering below) are wired to sendMessage. The broker
|
|
217
|
+
// writes to BOTH the mailbox observer (live fanout) AND the steering
|
|
218
|
+
// JSONL (durable fallback) so a connected worker will see the same steer
|
|
219
|
+
// twice: once via the broker, once via the next poll tick. We dedup at the
|
|
220
|
+
// consumer by tracking steer ids in a bounded FIFO set shared by both
|
|
221
|
+
// delivery paths. Without id-bearing entries (legacy producer), pollSteering
|
|
222
|
+
// is the only delivery channel and dedup is a no-op for id-less entries.
|
|
223
|
+
const seenSteers = createSeenSteerIdSet();
|
|
224
|
+
// ── Feature 1: maxTokens cap ──────────────────────────────────────────
|
|
225
|
+
// Cap output tokens per API call for background workers. Reads
|
|
226
|
+
// PI_CREW_MAX_OUTPUT_TOKENS env (set by pi-args.ts from agent.maxTokens).
|
|
227
|
+
const maxTokensEnv = process.env[PI_CREW_MAX_OUTPUT_ENV];
|
|
228
|
+
const maxTokensCap = maxTokensEnv ? Number.parseInt(maxTokensEnv, 10) : undefined;
|
|
229
|
+
if (maxTokensCap && maxTokensCap > 0) {
|
|
230
|
+
pi.on("before_provider_request", (event) => {
|
|
231
|
+
const payload = event.payload as Record<string, unknown> | undefined;
|
|
232
|
+
if (!payload || typeof payload !== "object") return;
|
|
233
|
+
// Cap both OpenAI-style max_tokens and Anthropic-style max_tokens
|
|
234
|
+
if (typeof payload.max_tokens === "number" && payload.max_tokens > maxTokensCap) {
|
|
235
|
+
payload.max_tokens = maxTokensCap;
|
|
236
|
+
}
|
|
237
|
+
// Also cap newer field names used by some providers
|
|
238
|
+
if (typeof payload.max_completion_tokens === "number" && payload.max_completion_tokens > maxTokensCap) {
|
|
239
|
+
payload.max_completion_tokens = maxTokensCap;
|
|
240
|
+
}
|
|
241
|
+
if (typeof payload.max_output_tokens === "number" && payload.max_output_tokens > maxTokensCap) {
|
|
242
|
+
payload.max_output_tokens = maxTokensCap;
|
|
243
|
+
}
|
|
244
|
+
const generationConfig = payload.generationConfig as Record<string, unknown> | undefined;
|
|
245
|
+
if (
|
|
246
|
+
generationConfig &&
|
|
247
|
+
typeof generationConfig.max_output_tokens === "number" &&
|
|
248
|
+
generationConfig.max_output_tokens > maxTokensCap
|
|
249
|
+
) {
|
|
250
|
+
generationConfig.max_output_tokens = maxTokensCap;
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// ── Feature 2: real-time steering ──────────────────────────────────────
|
|
256
|
+
// Poll the steering JSONL file for new steer messages. The parent (team
|
|
257
|
+
// tool) writes steers here in real-time; this reader injects them into
|
|
258
|
+
// the active session via pi.sendMessage with deliverAs:"steer".
|
|
259
|
+
const steeringFile = process.env[PI_CREW_STEERING_FILE_ENV];
|
|
260
|
+
if (steeringFile) {
|
|
261
|
+
// FIX-03: validate the steering file path once before first read.
|
|
262
|
+
const validation = validateSteeringFile(steeringFile);
|
|
263
|
+
if (!validation.valid) {
|
|
264
|
+
logInternalError(
|
|
265
|
+
"prompt-runtime.steering-file-rejected",
|
|
266
|
+
new Error(validation.reason ?? "steering-file-validation-failed"),
|
|
267
|
+
`path=${steeringFile}`,
|
|
268
|
+
"warn",
|
|
269
|
+
);
|
|
270
|
+
} else {
|
|
271
|
+
const safeSteeringFile = validation.resolvedPath ?? steeringFile;
|
|
272
|
+
let lastOffset = 0;
|
|
273
|
+
const pollSteering = (): void => {
|
|
274
|
+
try {
|
|
275
|
+
const stat = fs.statSync(safeSteeringFile, { throwIfNoEntry: false });
|
|
276
|
+
if (!stat || stat.size <= lastOffset) return;
|
|
277
|
+
const fd = fs.openSync(safeSteeringFile, "r");
|
|
278
|
+
try {
|
|
279
|
+
const buf = Buffer.alloc(stat.size - lastOffset);
|
|
280
|
+
fs.readSync(fd, buf, 0, buf.length, lastOffset);
|
|
281
|
+
lastOffset = stat.size;
|
|
282
|
+
const lines = buf.toString("utf8").split("\n").filter(Boolean);
|
|
283
|
+
for (const line of lines) {
|
|
284
|
+
try {
|
|
285
|
+
const entry = JSON.parse(line) as SteerEntry;
|
|
286
|
+
if (entry.type !== "steer") continue;
|
|
287
|
+
// FIX-S1: cross-channel dedup. The broker writes the
|
|
288
|
+
// same steer to both the mailbox (live fanout via the
|
|
289
|
+
// onSteer callback below) and this JSONL file. A
|
|
290
|
+
// connected worker receives it via the broker first
|
|
291
|
+
// and via this poll second; the seen-id set ensures
|
|
292
|
+
// only the first arrival reaches pi.sendMessage.
|
|
293
|
+
const entryId =
|
|
294
|
+
typeof (entry as { id?: unknown }).id === "string" ? (entry as { id: string }).id : undefined;
|
|
295
|
+
if (!seenSteers.markOrSkip(entryId)) continue;
|
|
296
|
+
// FIX-02: sanitize each steer entry before forwarding
|
|
297
|
+
// to pi.sendMessage. Reject oversized payloads,
|
|
298
|
+
// excessive newlines, and control characters.
|
|
299
|
+
const sanitized = sanitizeSteerMessage(entry);
|
|
300
|
+
if (!sanitized.valid || sanitized.message === undefined) {
|
|
301
|
+
logInternalError(
|
|
302
|
+
"prompt-runtime.steer-rejected",
|
|
303
|
+
new Error(sanitized.reason ?? "steer-sanitization-failed"),
|
|
304
|
+
`line-preview=${line.slice(0, 64)}`,
|
|
305
|
+
"warn",
|
|
306
|
+
);
|
|
307
|
+
continue;
|
|
308
|
+
}
|
|
309
|
+
pi.sendMessage(
|
|
310
|
+
{ customType: "crew-steer", content: sanitized.message, display: false },
|
|
311
|
+
{ deliverAs: "steer" },
|
|
312
|
+
);
|
|
313
|
+
} catch {
|
|
314
|
+
// Malformed line — skip
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
} finally {
|
|
318
|
+
try {
|
|
319
|
+
fs.closeSync(fd);
|
|
320
|
+
} catch {
|
|
321
|
+
/* already closed */
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
} catch {
|
|
325
|
+
// File doesn't exist yet or read error — will retry next tick
|
|
326
|
+
}
|
|
327
|
+
};
|
|
328
|
+
const timer = setInterval(pollSteering, 500);
|
|
329
|
+
timer.unref?.();
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// ── Feature 2b: broker push steering (opt-in, layered on the file poll) ──
|
|
334
|
+
// When the parent injected broker credentials, connect a broker client and
|
|
335
|
+
// deliver pushed steers with the SAME sanitize + pi.sendMessage path as the
|
|
336
|
+
// file poll above. The file poll remains the durable fallback; a broker
|
|
337
|
+
// connect failure is invisible to the worker.
|
|
338
|
+
const brokerHandle = startChildBrokerClient({
|
|
339
|
+
onSteer: (rawMessage, id) => {
|
|
340
|
+
// FIX-S1: cross-channel dedup. The broker persists every steer to
|
|
341
|
+
// the steering JSONL (durable) AND pushes it via the mailbox
|
|
342
|
+
// observer (live). This callback sees the live push; the
|
|
343
|
+
// pollSteering path above will see the same steer on its next
|
|
344
|
+
// tick. Keying on `id` (a stable identifier emitted by the broker)
|
|
345
|
+
// guarantees a single pi.sendMessage per steer.
|
|
346
|
+
if (!seenSteers.markOrSkip(id)) return;
|
|
347
|
+
const sanitized = sanitizeSteerMessage({ type: "steer", message: rawMessage });
|
|
348
|
+
if (!sanitized.valid || sanitized.message === undefined) {
|
|
349
|
+
logInternalError(
|
|
350
|
+
"prompt-runtime.broker-steer-rejected",
|
|
351
|
+
new Error(sanitized.reason ?? "steer-sanitization-failed"),
|
|
352
|
+
undefined,
|
|
353
|
+
"warn",
|
|
354
|
+
);
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
pi.sendMessage({ customType: "crew-steer", content: sanitized.message, display: false }, { deliverAs: "steer" });
|
|
358
|
+
},
|
|
359
|
+
});
|
|
360
|
+
// Close the broker connection on session shutdown to avoid leaking the
|
|
361
|
+
// persistent socket / reconnect timer. Fire-and-forget: the socket is
|
|
362
|
+
// already .unref()'d so it never blocks event-loop exit; errors are
|
|
363
|
+
// swallowed because teardown failures during shutdown are harmless.
|
|
364
|
+
pi.on("session_shutdown", () => {
|
|
365
|
+
void brokerHandle.close().catch(() => {});
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
// ── Prompt rewriting (existing) ────────────────────────────────────────
|
|
369
|
+
pi.on("before_agent_start", (event) => {
|
|
370
|
+
const inheritProjectContext = readBooleanEnvAny(PI_CREW_INHERIT_PROJECT_CONTEXT_ENV, PI_TEAMS_INHERIT_PROJECT_CONTEXT_ENV);
|
|
371
|
+
const inheritSkills = readBooleanEnvAny(PI_CREW_INHERIT_SKILLS_ENV, PI_TEAMS_INHERIT_SKILLS_ENV);
|
|
372
|
+
if (inheritProjectContext === undefined && inheritSkills === undefined) return;
|
|
373
|
+
const rewritten = rewriteTeamWorkerPrompt(event.systemPrompt, {
|
|
374
|
+
inheritProjectContext: inheritProjectContext ?? true,
|
|
375
|
+
inheritSkills: inheritSkills ?? true,
|
|
376
|
+
});
|
|
377
|
+
if (rewritten === event.systemPrompt) return;
|
|
378
|
+
return { systemPrompt: rewritten };
|
|
379
|
+
});
|
|
380
|
+
}
|