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
|
@@ -6,13 +6,12 @@
|
|
|
6
6
|
* Uses visibleWidth() for ANSI-aware padding so borders align correctly.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import { Container, Text } from "@earendil-works/pi-tui";
|
|
10
|
-
import { visibleWidth } from "@earendil-works/pi-tui";
|
|
11
|
-
import type { CrewTheme } from "../theme-adapter.ts";
|
|
12
|
-
import { truncLine, formatTokens, formatDuration } from "../tool-render.ts";
|
|
9
|
+
import { type Container, Text, visibleWidth } from "@earendil-works/pi-tui";
|
|
13
10
|
import type { CrewAgentRecord } from "../../runtime/crew-agent-runtime.ts";
|
|
14
|
-
import { isBrief, briefToolResult } from "./brief-mode.ts";
|
|
15
11
|
import { truncateToWidth } from "../../utils/visual.ts";
|
|
12
|
+
import type { CrewTheme } from "../theme-adapter.ts";
|
|
13
|
+
import { formatDuration, formatTokens, truncLine } from "../tool-render.ts";
|
|
14
|
+
import { briefToolResult, isBrief } from "./brief-mode.ts";
|
|
16
15
|
|
|
17
16
|
// ── Types ──────────────────────────────────────────────────────────────
|
|
18
17
|
|
|
@@ -55,22 +54,30 @@ function truncVisual(str: string, maxWidth: number): string {
|
|
|
55
54
|
/** Status icon with color */
|
|
56
55
|
function statusBadge(status: string, theme: CrewTheme): string {
|
|
57
56
|
switch (status) {
|
|
58
|
-
case "completed":
|
|
57
|
+
case "completed":
|
|
58
|
+
return theme.fg("success", "●");
|
|
59
59
|
case "failed":
|
|
60
|
-
case "cancelled":
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
case "cancelled":
|
|
61
|
+
return theme.fg("error", "✖");
|
|
62
|
+
case "running":
|
|
63
|
+
return theme.fg("warning", "◉");
|
|
64
|
+
default:
|
|
65
|
+
return theme.fg("dim", "○");
|
|
63
66
|
}
|
|
64
67
|
}
|
|
65
68
|
|
|
66
69
|
/** Status icon — compact */
|
|
67
70
|
export function statusIcon(status: string, theme: CrewTheme): string {
|
|
68
71
|
switch (status) {
|
|
69
|
-
case "completed":
|
|
72
|
+
case "completed":
|
|
73
|
+
return theme.fg("success", "✓");
|
|
70
74
|
case "failed":
|
|
71
|
-
case "cancelled":
|
|
72
|
-
|
|
73
|
-
|
|
75
|
+
case "cancelled":
|
|
76
|
+
return theme.fg("error", "✗");
|
|
77
|
+
case "running":
|
|
78
|
+
return theme.fg("warning", "⟳");
|
|
79
|
+
default:
|
|
80
|
+
return theme.fg("dim", "○");
|
|
74
81
|
}
|
|
75
82
|
}
|
|
76
83
|
|
|
@@ -82,10 +89,13 @@ function shortId(id: string | undefined): string {
|
|
|
82
89
|
/** Border color based on status */
|
|
83
90
|
function borderColorForStatus(status: string): "success" | "error" | "border" {
|
|
84
91
|
switch (status) {
|
|
85
|
-
case "completed":
|
|
92
|
+
case "completed":
|
|
93
|
+
return "success";
|
|
86
94
|
case "failed":
|
|
87
|
-
case "cancelled":
|
|
88
|
-
|
|
95
|
+
case "cancelled":
|
|
96
|
+
return "error";
|
|
97
|
+
default:
|
|
98
|
+
return "border";
|
|
89
99
|
}
|
|
90
100
|
}
|
|
91
101
|
|
|
@@ -113,9 +123,15 @@ import { deriveCardBackground, padWithBackground } from "../card-colors.ts";
|
|
|
113
123
|
* When bgSlot is provided, the interior is filled with a subtle status-tinted
|
|
114
124
|
* background derived from the theme (mixBg at 8% intensity).
|
|
115
125
|
*/
|
|
116
|
-
function buildFrame(
|
|
126
|
+
function buildFrame(
|
|
127
|
+
contentLines: string[],
|
|
128
|
+
totalWidth: number,
|
|
129
|
+
theme: CrewTheme,
|
|
130
|
+
borderSlot: "success" | "error" | "border" | "borderAccent" = "border",
|
|
131
|
+
bgSlot?: "success" | "error" | "border" | "borderAccent",
|
|
132
|
+
): string {
|
|
117
133
|
const frameW = totalWidth - 2; // available after Box(1,1) padding
|
|
118
|
-
const innerW = frameW - 2;
|
|
134
|
+
const innerW = frameW - 2; // │ chars
|
|
119
135
|
const top = theme.fg(borderSlot, `╭${"─".repeat(innerW)}╮`);
|
|
120
136
|
const bottom = theme.fg(borderSlot, `╰${"─".repeat(innerW)}╯`);
|
|
121
137
|
const v = theme.fg(borderSlot, "│");
|
|
@@ -132,7 +148,13 @@ function buildFrame(contentLines: string[], totalWidth: number, theme: CrewTheme
|
|
|
132
148
|
|
|
133
149
|
/** Build frame TOP: top border + content lines, NO bottom border.
|
|
134
150
|
* Pairs with buildFrameBottom() so renderCall + renderResult merge into ONE frame. */
|
|
135
|
-
function buildFrameTop(
|
|
151
|
+
function buildFrameTop(
|
|
152
|
+
contentLines: string[],
|
|
153
|
+
totalWidth: number,
|
|
154
|
+
theme: CrewTheme,
|
|
155
|
+
borderSlot: "success" | "error" | "border" | "borderAccent" = "border",
|
|
156
|
+
bgSlot?: "success" | "error" | "border" | "borderAccent",
|
|
157
|
+
): string {
|
|
136
158
|
const frameW = totalWidth - 2;
|
|
137
159
|
const innerW = frameW - 2;
|
|
138
160
|
const top = theme.fg(borderSlot, `╭${"─".repeat(innerW)}╮`);
|
|
@@ -148,7 +170,13 @@ function buildFrameTop(contentLines: string[], totalWidth: number, theme: CrewTh
|
|
|
148
170
|
|
|
149
171
|
/** Build frame BOTTOM: content lines + bottom border, NO top border.
|
|
150
172
|
* Pairs with buildFrameTop() so renderCall + renderResult merge into ONE frame. */
|
|
151
|
-
function buildFrameBottom(
|
|
173
|
+
function buildFrameBottom(
|
|
174
|
+
contentLines: string[],
|
|
175
|
+
totalWidth: number,
|
|
176
|
+
theme: CrewTheme,
|
|
177
|
+
borderSlot: "success" | "error" | "border" | "borderAccent" = "border",
|
|
178
|
+
bgSlot?: "success" | "error" | "border" | "borderAccent",
|
|
179
|
+
): string {
|
|
152
180
|
const frameW = totalWidth - 2;
|
|
153
181
|
const innerW = frameW - 2;
|
|
154
182
|
const v = theme.fg(borderSlot, "│");
|
|
@@ -174,10 +202,10 @@ function borderFromContext(ctx: ToolRenderContext): "success" | "error" | "borde
|
|
|
174
202
|
|
|
175
203
|
export const teamToolRenderer: ToolRenderer = {
|
|
176
204
|
renderCall(args, theme, ctx) {
|
|
177
|
-
const action = args.action as string ?? "";
|
|
178
|
-
const goal = args.goal as string ?? "";
|
|
205
|
+
const action = (args.action as string) ?? "";
|
|
206
|
+
const goal = (args.goal as string) ?? "";
|
|
179
207
|
const team = args.team as string | undefined;
|
|
180
|
-
const w =
|
|
208
|
+
const w = ctx.width || process.stdout.columns || 116;
|
|
181
209
|
const innerW = w - 4;
|
|
182
210
|
|
|
183
211
|
const contentLines: string[] = [];
|
|
@@ -215,7 +243,7 @@ function renderTeamResult(result: Record<string, unknown>, options: unknown, the
|
|
|
215
243
|
const action = typeof d.action === "string" ? d.action : "";
|
|
216
244
|
const status = typeof d.status === "string" ? d.status : "";
|
|
217
245
|
const runId = typeof d.runId === "string" ? d.runId : "";
|
|
218
|
-
const w =
|
|
246
|
+
const w = ctx.width || process.stdout.columns || 116;
|
|
219
247
|
const innerW = w - 4;
|
|
220
248
|
const bColor = borderColorForStatus(status);
|
|
221
249
|
const contentLines: string[] = [];
|
|
@@ -238,7 +266,9 @@ function renderTeamResult(result: Record<string, unknown>, options: unknown, the
|
|
|
238
266
|
const barW = Math.min(innerW - 22, 30);
|
|
239
267
|
const bar = progressBar(ratio, barW, theme);
|
|
240
268
|
const count = theme.fg("muted", ` ${parsed.completed}/${parsed.total}`);
|
|
241
|
-
contentLines.push(
|
|
269
|
+
contentLines.push(
|
|
270
|
+
padVisual(` ${spinner} ${theme.fg("toolTitle", theme.bold("crew run"))} ${theme.fg("dim", elapsed)}`, innerW),
|
|
271
|
+
);
|
|
242
272
|
contentLines.push(padVisual(` ${bar}${count}`, innerW));
|
|
243
273
|
if (parsed.activeAgent) contentLines.push(padVisual(` ${theme.fg("dim", parsed.activeAgent)}`, innerW));
|
|
244
274
|
} else {
|
|
@@ -300,9 +330,9 @@ function renderTeamResult(result: Record<string, unknown>, options: unknown, the
|
|
|
300
330
|
|
|
301
331
|
export const agentToolRenderer: ToolRenderer = {
|
|
302
332
|
renderCall(args, theme, ctx) {
|
|
303
|
-
const agentName = args.agent as string ?? args.subagent_type as string ?? "";
|
|
333
|
+
const agentName = (args.agent as string) ?? (args.subagent_type as string) ?? "";
|
|
304
334
|
const prompt = (args.prompt ?? args.task ?? "") as string;
|
|
305
|
-
const w =
|
|
335
|
+
const w = ctx.width || process.stdout.columns || 116;
|
|
306
336
|
const innerW = w - 4;
|
|
307
337
|
|
|
308
338
|
const contentLines: string[] = [];
|
|
@@ -333,7 +363,7 @@ export const agentToolRenderer: ToolRenderer = {
|
|
|
333
363
|
function renderAgentResult(result: Record<string, unknown>, options: unknown, theme: CrewTheme, ctx: ToolRenderContext): string {
|
|
334
364
|
const d = (result.details ?? result) as Record<string, unknown>;
|
|
335
365
|
const results = d.results as Array<Record<string, unknown>> | undefined;
|
|
336
|
-
const w =
|
|
366
|
+
const w = ctx.width || process.stdout.columns || 116;
|
|
337
367
|
const innerW = w - 4;
|
|
338
368
|
const status = ((d.status ?? (results?.[0] as Record<string, unknown>)?.status ?? "") as string) || "completed";
|
|
339
369
|
const bColor: "success" | "error" | "border" = status === "completed" ? "success" : status === "failed" ? "error" : "border";
|
|
@@ -359,7 +389,7 @@ function renderAgentResult(result: Record<string, unknown>, options: unknown, th
|
|
|
359
389
|
if (!ctx.expanded) {
|
|
360
390
|
// Collapsed: compact card
|
|
361
391
|
const badge = statusBadge(status, theme);
|
|
362
|
-
const agentId = (d.agentId as string) ?? (results?.[0] as Record<string, unknown>)?.agentId as string ?? "agent";
|
|
392
|
+
const agentId = (d.agentId as string) ?? ((results?.[0] as Record<string, unknown>)?.agentId as string) ?? "agent";
|
|
363
393
|
const nameTag = theme.fg("toolTitle", theme.bold(agentId));
|
|
364
394
|
contentLines.push(padVisual(` ${badge} ${nameTag}`, innerW));
|
|
365
395
|
|
|
@@ -378,7 +408,7 @@ function renderAgentResult(result: Record<string, unknown>, options: unknown, th
|
|
|
378
408
|
if (results?.length) {
|
|
379
409
|
for (let i = 0; i < results.length; i++) {
|
|
380
410
|
const item = results[i]!;
|
|
381
|
-
const icon = statusIcon(item.status as string ?? "", theme);
|
|
411
|
+
const icon = statusIcon((item.status as string) ?? "", theme);
|
|
382
412
|
const label = theme.fg("toolTitle", theme.bold((item.agentId as string) ?? "agent"));
|
|
383
413
|
contentLines.push(padVisual(` ${icon} ${label}`, innerW));
|
|
384
414
|
|
|
@@ -396,7 +426,7 @@ function renderAgentResult(result: Record<string, unknown>, options: unknown, th
|
|
|
396
426
|
}
|
|
397
427
|
}
|
|
398
428
|
} else if (d.agentId) {
|
|
399
|
-
const icon = statusIcon(d.status as string ?? "", theme);
|
|
429
|
+
const icon = statusIcon((d.status as string) ?? "", theme);
|
|
400
430
|
contentLines.push(padVisual(` ${icon} ${theme.fg("toolTitle", theme.bold(d.agentId as string))}`, innerW));
|
|
401
431
|
if (d.error) {
|
|
402
432
|
contentLines.push(padVisual(` ${theme.fg("error", truncLine(String(d.error), innerW - 6))}`, innerW));
|
|
@@ -473,7 +503,15 @@ function appendSimpleCard(lines: string[], status: string, runId: string, theme:
|
|
|
473
503
|
lines.push(padVisual(` ${badge} ${theme.fg("text", parts.join(" · ") || "done")}`, innerW));
|
|
474
504
|
}
|
|
475
505
|
|
|
476
|
-
function appendExpandedRun(
|
|
506
|
+
function appendExpandedRun(
|
|
507
|
+
lines: string[],
|
|
508
|
+
records: CrewAgentRecord[],
|
|
509
|
+
status: string,
|
|
510
|
+
runId: string,
|
|
511
|
+
theme: CrewTheme,
|
|
512
|
+
w: number,
|
|
513
|
+
innerW: number,
|
|
514
|
+
): void {
|
|
477
515
|
const completed = records.filter((r) => r.status === "completed").length;
|
|
478
516
|
const total = records.length;
|
|
479
517
|
const ratio = total > 0 ? completed / total : 0;
|
|
@@ -491,10 +529,9 @@ function appendExpandedRun(lines: string[], records: CrewAgentRecord[], status:
|
|
|
491
529
|
lines.push(padVisual(` ${theme.fg("muted", "Progress")} ${bar}${count}`, innerW));
|
|
492
530
|
|
|
493
531
|
// Metrics
|
|
494
|
-
const metricLine = [
|
|
495
|
-
theme.fg("
|
|
496
|
-
|
|
497
|
-
].join(theme.fg("dim", " · "));
|
|
532
|
+
const metricLine = [theme.fg("muted", formatDuration(duration)), theme.fg("muted", `${formatTokens(tokens)} tok`)].join(
|
|
533
|
+
theme.fg("dim", " · "),
|
|
534
|
+
);
|
|
498
535
|
lines.push(padVisual(` ${metricLine}`, innerW));
|
|
499
536
|
lines.push(padVisual(theme.fg("borderMuted", "─".repeat(innerW - 2)), innerW));
|
|
500
537
|
|
|
@@ -517,7 +554,15 @@ function appendExpandedRun(lines: string[], records: CrewAgentRecord[], status:
|
|
|
517
554
|
}
|
|
518
555
|
}
|
|
519
556
|
|
|
520
|
-
function appendExpandedMetrics(
|
|
557
|
+
function appendExpandedMetrics(
|
|
558
|
+
lines: string[],
|
|
559
|
+
m: Metrics | undefined,
|
|
560
|
+
status: string,
|
|
561
|
+
runId: string,
|
|
562
|
+
theme: CrewTheme,
|
|
563
|
+
w: number,
|
|
564
|
+
innerW: number,
|
|
565
|
+
): void {
|
|
521
566
|
lines.push(padVisual(` ${theme.fg("toolTitle", theme.bold("CREW RUN RESULT"))} ${theme.fg("dim", shortId(runId))}`, innerW));
|
|
522
567
|
lines.push(padVisual(theme.fg("borderMuted", "─".repeat(innerW - 2)), innerW));
|
|
523
568
|
if (m) {
|
|
@@ -538,8 +583,9 @@ function appendExpandedMetrics(lines: string[], m: Metrics | undefined, status:
|
|
|
538
583
|
function extractContentText(content: unknown): string {
|
|
539
584
|
if (!Array.isArray(content)) return typeof content === "string" ? content : "";
|
|
540
585
|
// onUpdate appends text blocks — only use the LAST one to avoid stacking
|
|
541
|
-
const texts = content
|
|
542
|
-
|
|
586
|
+
const texts = content.filter(
|
|
587
|
+
(c): c is Record<string, unknown> => typeof c === "object" && c !== null && (c as Record<string, unknown>).type === "text",
|
|
588
|
+
);
|
|
543
589
|
if (texts.length === 0) return "";
|
|
544
590
|
return String((texts[texts.length - 1]! as Record<string, unknown>).text ?? "");
|
|
545
591
|
}
|
|
@@ -573,17 +619,35 @@ function parseStreamingProgress(text: string): StreamingProgress | null {
|
|
|
573
619
|
const toolInfo = toolMatch ? ` · ${toolMatch[1]}` : "";
|
|
574
620
|
|
|
575
621
|
if (doneMatch) {
|
|
576
|
-
return {
|
|
622
|
+
return {
|
|
623
|
+
elapsedMs,
|
|
624
|
+
completed: parseInt(doneMatch[1]!, 10),
|
|
625
|
+
total: parseInt(doneMatch[2]!, 10),
|
|
626
|
+
status: null,
|
|
627
|
+
activeAgent: (activeAgent ?? "") + toolInfo,
|
|
628
|
+
};
|
|
577
629
|
}
|
|
578
630
|
if (taskMatch) {
|
|
579
631
|
const done = parseInt(taskMatch[1]!, 10);
|
|
580
632
|
const running = parseInt(taskMatch[2]!, 10);
|
|
581
633
|
const total = done + running;
|
|
582
|
-
return {
|
|
634
|
+
return {
|
|
635
|
+
elapsedMs,
|
|
636
|
+
completed: done,
|
|
637
|
+
total,
|
|
638
|
+
status: null,
|
|
639
|
+
activeAgent: (activeAgent ?? "") + toolInfo,
|
|
640
|
+
};
|
|
583
641
|
}
|
|
584
642
|
if (elapsedMs > 0) {
|
|
585
643
|
const statusMatch = text.match(/status=(\w+)/);
|
|
586
|
-
return {
|
|
644
|
+
return {
|
|
645
|
+
elapsedMs,
|
|
646
|
+
completed: null,
|
|
647
|
+
total: null,
|
|
648
|
+
status: statusMatch?.[1] ?? null,
|
|
649
|
+
activeAgent,
|
|
650
|
+
};
|
|
587
651
|
}
|
|
588
652
|
|
|
589
653
|
return null;
|
|
@@ -617,7 +681,9 @@ function computeRecordDuration(r: CrewAgentRecord): number {
|
|
|
617
681
|
|
|
618
682
|
function computeTotalCost(records: CrewAgentRecord[]): number {
|
|
619
683
|
let total = 0;
|
|
620
|
-
for (const r of records) {
|
|
684
|
+
for (const r of records) {
|
|
685
|
+
if (r.usage?.cost) total += r.usage.cost;
|
|
686
|
+
}
|
|
621
687
|
return total;
|
|
622
688
|
}
|
|
623
689
|
|
|
@@ -22,7 +22,12 @@ const DEFAULT_TAIL_BYTES = 256 * 1024;
|
|
|
22
22
|
const MAX_CACHE_SIZE = 100;
|
|
23
23
|
const transcriptCache = new Map<string, TranscriptCacheEntry>();
|
|
24
24
|
|
|
25
|
-
function cacheKey(
|
|
25
|
+
function cacheKey(
|
|
26
|
+
path: string,
|
|
27
|
+
options: Required<Pick<TranscriptReadOptions, "full">> & {
|
|
28
|
+
maxTailBytes: number;
|
|
29
|
+
},
|
|
30
|
+
): string {
|
|
26
31
|
return `${path}:${options.full ? "full" : `tail:${options.maxTailBytes}`}`;
|
|
27
32
|
}
|
|
28
33
|
|
|
@@ -35,13 +40,26 @@ export function clearTranscriptCache(path?: string): void {
|
|
|
35
40
|
}
|
|
36
41
|
|
|
37
42
|
export function getTranscriptCacheEntry(path: string, options: TranscriptReadOptions = {}): TranscriptCacheEntry | undefined {
|
|
38
|
-
const normalized = {
|
|
43
|
+
const normalized = {
|
|
44
|
+
full: options.full === true,
|
|
45
|
+
maxTailBytes: options.maxTailBytes ?? DEFAULT_TAIL_BYTES,
|
|
46
|
+
};
|
|
39
47
|
return transcriptCache.get(cacheKey(path, normalized)) ?? transcriptCache.get(path);
|
|
40
48
|
}
|
|
41
49
|
|
|
42
|
-
function readTranscriptText(
|
|
50
|
+
function readTranscriptText(
|
|
51
|
+
path: string,
|
|
52
|
+
stat: fs.Stats,
|
|
53
|
+
options: Required<Pick<TranscriptReadOptions, "full">> & {
|
|
54
|
+
maxTailBytes: number;
|
|
55
|
+
},
|
|
56
|
+
): { text: string; bytesRead: number; truncated: boolean } {
|
|
43
57
|
if (options.full || stat.size <= options.maxTailBytes) {
|
|
44
|
-
return {
|
|
58
|
+
return {
|
|
59
|
+
text: fs.readFileSync(path, "utf-8"),
|
|
60
|
+
bytesRead: stat.size,
|
|
61
|
+
truncated: false,
|
|
62
|
+
};
|
|
45
63
|
}
|
|
46
64
|
const bytesToRead = Math.min(stat.size, options.maxTailBytes);
|
|
47
65
|
const fd = fs.openSync(path, "r");
|
|
@@ -57,8 +75,16 @@ function readTranscriptText(path: string, stat: fs.Stats, options: Required<Pick
|
|
|
57
75
|
}
|
|
58
76
|
}
|
|
59
77
|
|
|
60
|
-
export function readTranscriptLinesCached(
|
|
61
|
-
|
|
78
|
+
export function readTranscriptLinesCached(
|
|
79
|
+
path: string,
|
|
80
|
+
parse: (text: string) => string[],
|
|
81
|
+
now = Date.now(),
|
|
82
|
+
options: TranscriptReadOptions = {},
|
|
83
|
+
): string[] {
|
|
84
|
+
const normalized = {
|
|
85
|
+
full: options.full === true,
|
|
86
|
+
maxTailBytes: Math.max(1024, options.maxTailBytes ?? DEFAULT_TAIL_BYTES),
|
|
87
|
+
};
|
|
62
88
|
const key = cacheKey(path, normalized);
|
|
63
89
|
const previous = transcriptCache.get(key);
|
|
64
90
|
let stat: fs.Stats;
|
|
@@ -30,9 +30,7 @@ function textFromContent(content: unknown): string {
|
|
|
30
30
|
|
|
31
31
|
/** Safely cast unknown to a record for property access. */
|
|
32
32
|
function asRecord(value: unknown): Record<string, unknown> | undefined {
|
|
33
|
-
return value && typeof value === "object" && !Array.isArray(value)
|
|
34
|
-
? (value as Record<string, unknown>)
|
|
35
|
-
: undefined;
|
|
33
|
+
return value && typeof value === "object" && !Array.isArray(value) ? (value as Record<string, unknown>) : undefined;
|
|
36
34
|
}
|
|
37
35
|
|
|
38
36
|
/** Detect if an event type is a tool invocation (call/use/start). */
|
|
@@ -48,10 +46,13 @@ function isToolResultType(type: string): boolean {
|
|
|
48
46
|
/** Extract tool name from various event shapes. */
|
|
49
47
|
function extractToolName(obj: Record<string, unknown>): string | undefined {
|
|
50
48
|
const name =
|
|
51
|
-
typeof obj.toolName === "string"
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
49
|
+
typeof obj.toolName === "string"
|
|
50
|
+
? obj.toolName
|
|
51
|
+
: typeof obj.name === "string"
|
|
52
|
+
? obj.name
|
|
53
|
+
: typeof obj.tool === "string"
|
|
54
|
+
? obj.tool
|
|
55
|
+
: undefined;
|
|
55
56
|
return name;
|
|
56
57
|
}
|
|
57
58
|
|
|
@@ -105,9 +106,7 @@ export function parseTranscriptEntries(lines: string[]): TranscriptEntry[] {
|
|
|
105
106
|
if (isToolCallType(type)) {
|
|
106
107
|
// Look ahead for matching tool_result
|
|
107
108
|
const toolName = extractToolName(obj) ?? "unknown";
|
|
108
|
-
const inputText =
|
|
109
|
-
typeof obj.input === "string" ? obj.input :
|
|
110
|
-
obj.input !== undefined ? JSON.stringify(obj.input) : "";
|
|
109
|
+
const inputText = typeof obj.input === "string" ? obj.input : obj.input !== undefined ? JSON.stringify(obj.input) : "";
|
|
111
110
|
let resultText = "";
|
|
112
111
|
let isError = false;
|
|
113
112
|
let resultTimestamp = timestamp;
|
|
@@ -120,9 +119,13 @@ export function parseTranscriptEntries(lines: string[]): TranscriptEntry[] {
|
|
|
120
119
|
if (isToolResultType(nextType) || /tool/i.test(nextType)) {
|
|
121
120
|
const robj = parsed[j]!.obj;
|
|
122
121
|
const rt =
|
|
123
|
-
typeof robj.text === "string"
|
|
124
|
-
|
|
125
|
-
|
|
122
|
+
typeof robj.text === "string"
|
|
123
|
+
? robj.text
|
|
124
|
+
: typeof robj.result === "string"
|
|
125
|
+
? robj.result
|
|
126
|
+
: robj.result !== undefined
|
|
127
|
+
? JSON.stringify(robj.result)
|
|
128
|
+
: "";
|
|
126
129
|
resultText = rt;
|
|
127
130
|
isError = robj.isError === true;
|
|
128
131
|
resultTimestamp = typeof robj.timestamp === "number" ? robj.timestamp : resultTimestamp;
|
|
@@ -159,15 +162,16 @@ export function parseTranscriptEntries(lines: string[]): TranscriptEntry[] {
|
|
|
159
162
|
const toolName = extractToolName(obj) ?? "unknown";
|
|
160
163
|
const isError = obj.isError === true;
|
|
161
164
|
const text =
|
|
162
|
-
typeof obj.text === "string"
|
|
163
|
-
|
|
164
|
-
|
|
165
|
+
typeof obj.text === "string"
|
|
166
|
+
? obj.text
|
|
167
|
+
: typeof obj.result === "string"
|
|
168
|
+
? obj.result
|
|
169
|
+
: obj.result !== undefined
|
|
170
|
+
? JSON.stringify(obj.result)
|
|
171
|
+
: "";
|
|
165
172
|
|
|
166
173
|
const summary = summarize(`${isError ? "✗" : "✓"} ${toolName}${text ? ": " + summarize(text, 60) : ""}`, SUMMARY_MAX);
|
|
167
|
-
const content = [
|
|
168
|
-
`[Tool Result: ${toolName}${isError ? " (error)" : ""}]`,
|
|
169
|
-
text || "(no output)",
|
|
170
|
-
].join("\n");
|
|
174
|
+
const content = [`[Tool Result: ${toolName}${isError ? " (error)" : ""}]`, text || "(no output)"].join("\n");
|
|
171
175
|
|
|
172
176
|
entries.push({
|
|
173
177
|
id: id++,
|
|
@@ -225,9 +229,7 @@ export function parseTranscriptEntries(lines: string[]): TranscriptEntry[] {
|
|
|
225
229
|
|
|
226
230
|
/** Toggle expand/collapse for an entry by index. Returns a new array. */
|
|
227
231
|
export function toggleEntry(entries: TranscriptEntry[], index: number): TranscriptEntry[] {
|
|
228
|
-
return entries.map((entry, i) =>
|
|
229
|
-
i === index ? { ...entry, expanded: !entry.expanded } : entry,
|
|
230
|
-
);
|
|
232
|
+
return entries.map((entry, i) => (i === index ? { ...entry, expanded: !entry.expanded } : entry));
|
|
231
233
|
}
|
|
232
234
|
|
|
233
235
|
/** Render entries into display lines, respecting expand/collapse.
|
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
|
-
import type { TeamRunManifest } from "../state/types.ts";
|
|
3
2
|
import { agentOutputPath, readCrewAgents } from "../runtime/crew-agent-records.ts";
|
|
4
|
-
import type {
|
|
5
|
-
import {
|
|
6
|
-
import { renderDiff } from "./render-diff.ts";
|
|
7
|
-
import { highlightCode, highlightJson } from "./syntax-highlight.ts";
|
|
3
|
+
import type { TeamRunManifest } from "../state/types.ts";
|
|
4
|
+
import { resolveRealContainedPath } from "../utils/safe-paths.ts";
|
|
8
5
|
import { pad, truncate, truncateToVisualLines } from "../utils/visual.ts";
|
|
6
|
+
import { renderDiff } from "./render-diff.ts";
|
|
9
7
|
import { colorForStatus, iconForStatus, type RunStatus } from "./status-colors.ts";
|
|
8
|
+
import { highlightCode, highlightJson } from "./syntax-highlight.ts";
|
|
9
|
+
import type { CrewTheme } from "./theme-adapter.ts";
|
|
10
|
+
import { asCrewTheme, subscribeThemeChange } from "./theme-adapter.ts";
|
|
10
11
|
import { DEFAULT_TRANSCRIPT_TAIL_BYTES, getTranscriptCacheEntry, readTranscriptLinesCached } from "./transcript-cache.ts";
|
|
11
|
-
import { resolveRealContainedPath } from "../utils/safe-paths.ts";
|
|
12
12
|
|
|
13
|
-
type Component = {
|
|
13
|
+
type Component = {
|
|
14
|
+
invalidate(): void;
|
|
15
|
+
render(width: number): string[];
|
|
16
|
+
handleInput(data: string): void;
|
|
17
|
+
};
|
|
14
18
|
|
|
15
19
|
type TranscriptTheme = CrewTheme;
|
|
16
20
|
|
|
@@ -71,7 +75,10 @@ export function formatTranscriptEvent(event: unknown, themeLike: unknown = undef
|
|
|
71
75
|
const isError = obj.isError === true || result?.isError === true;
|
|
72
76
|
const isPartial = obj.isPartial === true;
|
|
73
77
|
const status: RunStatus = isError ? "failed" : isPartial ? "running" : "completed";
|
|
74
|
-
const header = theme.fg(
|
|
78
|
+
const header = theme.fg(
|
|
79
|
+
colorForStatus(status),
|
|
80
|
+
`${iconForStatus(status, { runningGlyph: "⋯" })} [Tool${toolName ? `: ${toolName}` : ""}] ${type}`,
|
|
81
|
+
);
|
|
75
82
|
const text = (content || (typeof obj.text === "string" ? obj.text : typeof obj.result === "string" ? obj.result : "")).trim();
|
|
76
83
|
if (!text) return [header, "(no output)"];
|
|
77
84
|
if (isLikelyDiff(text)) {
|
|
@@ -83,7 +90,13 @@ export function formatTranscriptEvent(event: unknown, themeLike: unknown = undef
|
|
|
83
90
|
if (text.includes("```") && text.includes("```")) {
|
|
84
91
|
return [header, ...highlightCodeBlocks(text, theme)];
|
|
85
92
|
}
|
|
86
|
-
return [
|
|
93
|
+
return [
|
|
94
|
+
header,
|
|
95
|
+
...text
|
|
96
|
+
.split(/\r?\n/)
|
|
97
|
+
.filter(Boolean)
|
|
98
|
+
.map((line) => theme.fg("muted", line)),
|
|
99
|
+
];
|
|
87
100
|
}
|
|
88
101
|
const message = asRecord(obj.message);
|
|
89
102
|
if (message) {
|
|
@@ -97,9 +110,7 @@ export function formatTranscriptEvent(event: unknown, themeLike: unknown = undef
|
|
|
97
110
|
return [theme.fg("accent", header), ...highlightCodeBlocks(text, theme)];
|
|
98
111
|
}
|
|
99
112
|
if (lines.length > 1) {
|
|
100
|
-
const block = lines
|
|
101
|
-
.map((line) => (role === "assistant" ? theme.bold(line) : line))
|
|
102
|
-
.join("\n");
|
|
113
|
+
const block = lines.map((line) => (role === "assistant" ? theme.bold(line) : line)).join("\n");
|
|
103
114
|
return [theme.fg("accent", header), ...block.split(/\r?\n/).filter(Boolean)];
|
|
104
115
|
}
|
|
105
116
|
return [theme.fg("accent", header), ...lines.filter(Boolean)];
|
|
@@ -125,9 +136,22 @@ export function formatTranscriptText(text: string, themeLike: unknown = undefine
|
|
|
125
136
|
return lines.length ? lines : ["(no transcript content)"];
|
|
126
137
|
}
|
|
127
138
|
|
|
128
|
-
export function readRunTranscript(
|
|
139
|
+
export function readRunTranscript(
|
|
140
|
+
manifest: TeamRunManifest,
|
|
141
|
+
taskId?: string,
|
|
142
|
+
options: { full?: boolean; maxTailBytes?: number } = {},
|
|
143
|
+
): {
|
|
144
|
+
title: string;
|
|
145
|
+
path: string;
|
|
146
|
+
lines: string[];
|
|
147
|
+
bytesRead: number;
|
|
148
|
+
size: number;
|
|
149
|
+
truncated: boolean;
|
|
150
|
+
} {
|
|
129
151
|
const agents = readCrewAgents(manifest);
|
|
130
|
-
const agent = taskId
|
|
152
|
+
const agent = taskId
|
|
153
|
+
? agents.find((item) => item.taskId === taskId || item.id === taskId)
|
|
154
|
+
: (agents.find((item) => item.transcriptPath) ?? agents[0]);
|
|
131
155
|
const selectedTaskId = agent?.taskId ?? taskId ?? "unknown";
|
|
132
156
|
let transcriptPath = "";
|
|
133
157
|
try {
|
|
@@ -148,10 +172,20 @@ export function readRunTranscript(manifest: TeamRunManifest, taskId?: string, op
|
|
|
148
172
|
// Ignore untrusted transcript paths from mutable agent state and fall back to durable agent output.
|
|
149
173
|
}
|
|
150
174
|
}
|
|
151
|
-
const readOptions = {
|
|
175
|
+
const readOptions = {
|
|
176
|
+
full: options.full === true,
|
|
177
|
+
maxTailBytes: options.maxTailBytes ?? DEFAULT_TRANSCRIPT_TAIL_BYTES,
|
|
178
|
+
};
|
|
152
179
|
const lines = readTranscriptLinesCached(transcriptPath, (text) => formatTranscriptText(text), Date.now(), readOptions);
|
|
153
180
|
const entry = getTranscriptCacheEntry(transcriptPath, readOptions);
|
|
154
|
-
return {
|
|
181
|
+
return {
|
|
182
|
+
title: `${manifest.runId}:${selectedTaskId}`,
|
|
183
|
+
path: transcriptPath,
|
|
184
|
+
lines: lines.length ? lines : ["(no transcript content)"],
|
|
185
|
+
bytesRead: entry?.bytesRead ?? 0,
|
|
186
|
+
size: entry?.size ?? 0,
|
|
187
|
+
truncated: entry?.truncated ?? false,
|
|
188
|
+
};
|
|
155
189
|
}
|
|
156
190
|
|
|
157
191
|
interface ViewerState {
|
|
@@ -161,13 +195,7 @@ interface ViewerState {
|
|
|
161
195
|
scroll: number;
|
|
162
196
|
}
|
|
163
197
|
|
|
164
|
-
function renderViewerBase(
|
|
165
|
-
state: ViewerState,
|
|
166
|
-
width: number,
|
|
167
|
-
lines: string[],
|
|
168
|
-
title: string,
|
|
169
|
-
subtitle: string,
|
|
170
|
-
): string[] {
|
|
198
|
+
function renderViewerBase(state: ViewerState, width: number, lines: string[], title: string, subtitle: string): string[] {
|
|
171
199
|
const inner = Math.max(20, width - 4);
|
|
172
200
|
const bodyText = lines.join("\n");
|
|
173
201
|
const { visualLines, skippedCount } = truncateToVisualLines(bodyText, state.lastHeight, inner);
|
|
@@ -194,7 +222,6 @@ function renderViewerBase(
|
|
|
194
222
|
return linesOut.map((line) => truncate(line, width));
|
|
195
223
|
}
|
|
196
224
|
|
|
197
|
-
|
|
198
225
|
export class DurableTextViewer implements Component {
|
|
199
226
|
private scroll = 0;
|
|
200
227
|
private lastHeight = 16;
|
|
@@ -252,7 +279,12 @@ export class DurableTextViewer implements Component {
|
|
|
252
279
|
|
|
253
280
|
render(width: number): string[] {
|
|
254
281
|
return renderViewerBase(
|
|
255
|
-
{
|
|
282
|
+
{
|
|
283
|
+
theme: this.theme,
|
|
284
|
+
autoScroll: this.autoScroll,
|
|
285
|
+
lastHeight: this.lastHeight,
|
|
286
|
+
scroll: this.scroll,
|
|
287
|
+
},
|
|
256
288
|
width,
|
|
257
289
|
this.lines,
|
|
258
290
|
this.title,
|
|
@@ -273,7 +305,13 @@ export class DurableTranscriptViewer implements Component {
|
|
|
273
305
|
private maxTailBytes: number;
|
|
274
306
|
private readonly unsubscribeTheme: () => void;
|
|
275
307
|
|
|
276
|
-
constructor(
|
|
308
|
+
constructor(
|
|
309
|
+
manifest: TeamRunManifest,
|
|
310
|
+
theme: unknown,
|
|
311
|
+
done: (result: undefined) => void,
|
|
312
|
+
taskId?: string,
|
|
313
|
+
options: { maxTailBytes?: number } = {},
|
|
314
|
+
) {
|
|
277
315
|
this.manifest = manifest;
|
|
278
316
|
this.theme = asCrewTheme(theme);
|
|
279
317
|
this.done = done;
|
|
@@ -293,7 +331,10 @@ export class DurableTranscriptViewer implements Component {
|
|
|
293
331
|
this.done(undefined);
|
|
294
332
|
return;
|
|
295
333
|
}
|
|
296
|
-
const content = readRunTranscript(this.manifest, this.taskId, {
|
|
334
|
+
const content = readRunTranscript(this.manifest, this.taskId, {
|
|
335
|
+
full: this.fullTranscript,
|
|
336
|
+
maxTailBytes: this.maxTailBytes,
|
|
337
|
+
}).lines;
|
|
297
338
|
const maxScroll = Math.max(0, content.length - this.lastHeight);
|
|
298
339
|
if (data === "k" || data === "\u001b[A") {
|
|
299
340
|
this.scroll = Math.max(0, this.scroll - 1);
|
|
@@ -323,9 +364,17 @@ export class DurableTranscriptViewer implements Component {
|
|
|
323
364
|
}
|
|
324
365
|
|
|
325
366
|
render(width: number): string[] {
|
|
326
|
-
const data = readRunTranscript(this.manifest, this.taskId, {
|
|
367
|
+
const data = readRunTranscript(this.manifest, this.taskId, {
|
|
368
|
+
full: this.fullTranscript,
|
|
369
|
+
maxTailBytes: this.maxTailBytes,
|
|
370
|
+
});
|
|
327
371
|
return renderViewerBase(
|
|
328
|
-
{
|
|
372
|
+
{
|
|
373
|
+
theme: this.theme,
|
|
374
|
+
autoScroll: this.autoScroll,
|
|
375
|
+
lastHeight: this.lastHeight,
|
|
376
|
+
scroll: this.scroll,
|
|
377
|
+
},
|
|
329
378
|
width,
|
|
330
379
|
data.lines,
|
|
331
380
|
"pi-crew transcript",
|