pi-crew 0.2.2 → 0.2.4
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/AGENTS.md +57 -32
- package/CHANGELOG.md +466 -413
- package/LICENSE +21 -21
- package/NOTICE.md +16 -16
- package/README.md +323 -323
- package/docs/FEATURE_INTAKE.md +126 -0
- package/docs/HARNESS.md +86 -0
- package/docs/HARNESS_BACKLOG.md +41 -0
- package/docs/TEST_MATRIX.md +49 -0
- package/docs/actions-reference.md +595 -595
- package/docs/architecture.md +180 -180
- package/docs/code-review-2026-05-11.md +592 -0
- package/docs/commands-reference.md +347 -347
- package/docs/comparison-pi-subagents-vs-pi-crew.md +303 -0
- package/docs/decisions/0001-durable-state.md +41 -0
- package/docs/decisions/0002-child-process-for-async.md +42 -0
- package/docs/decisions/0003-depth-guard.md +36 -0
- package/docs/decisions/0004-execfile-over-exec.md +34 -0
- package/docs/decisions/0005-no-parameter-properties.md +49 -0
- package/docs/decisions/0006-publish-bundled-esm.md +63 -0
- package/docs/decisions/0007-active-run-binary-index.md +54 -0
- package/docs/decisions/0008-child-pi-warm-pool.md +61 -0
- package/docs/decisions/README.md +23 -0
- package/docs/followup-plan-2026-05-12.md +463 -0
- package/docs/followup-review-2026-05-12.md +297 -0
- package/docs/followup-review-round3-2026-05-12.md +342 -0
- package/docs/followup-review-round4-2026-05-13.md +107 -0
- package/docs/implementation-plan-top3.md +333 -0
- package/docs/live-mailbox-runtime.md +36 -36
- package/docs/next-upgrade-roadmap.md +808 -808
- package/docs/oh-my-pi-research.md +509 -0
- package/docs/perf/baseline-2026-05.md +113 -0
- package/docs/perf/final-report-2026-05.md +206 -0
- package/docs/perf/sprint-1-report.md +71 -0
- package/docs/perf/sprint-2-report.md +81 -0
- package/docs/perf/sprint-2.5-report.md +53 -0
- package/docs/perf/sprint-3-report.md +36 -0
- package/docs/perf/sprint-4-report.md +47 -0
- package/docs/perf/sprint-5-report.md +51 -0
- package/docs/perf/sprint-6-report.md +94 -0
- package/docs/perf/sprint-7-report.md +74 -0
- package/docs/perf/upgrade-plan-2026-05.md +147 -0
- package/docs/pi-subagents3-deep-analysis.md +508 -0
- package/docs/product/README.md +31 -0
- package/docs/product/platform.md +27 -0
- package/docs/product/runtime-safety.md +37 -0
- package/docs/product/team-run.md +39 -0
- package/docs/product/team-tool.md +37 -0
- package/docs/publishing.md +65 -65
- package/docs/resource-formats.md +134 -134
- package/docs/runtime-analysis-child-vs-live.md +171 -0
- package/docs/runtime-flow.md +148 -148
- package/docs/runtime-migration-in-process-analysis.md +250 -0
- package/docs/stories/README.md +30 -0
- package/docs/stories/backlog.md +36 -0
- package/docs/templates/decision.md +27 -0
- package/docs/templates/story.md +44 -0
- package/docs/templates/validation-report.md +32 -0
- package/docs/usage.md +238 -238
- package/index.ts +7 -6
- package/install.mjs +65 -65
- package/package.json +107 -99
- package/schema.json +222 -222
- package/skills/child-pi-spawning/SKILL.md +213 -0
- package/skills/context-artifact-hygiene/SKILL.md +32 -0
- package/skills/event-log-tracing/SKILL.md +299 -0
- package/skills/git-master/SKILL.md +225 -24
- package/skills/live-agent-lifecycle/SKILL.md +192 -0
- package/skills/mailbox-interactive/SKILL.md +300 -19
- package/skills/model-routing-context/SKILL.md +94 -0
- package/skills/multi-perspective-review/SKILL.md +88 -0
- package/skills/read-only-explorer/SKILL.md +250 -26
- package/skills/safe-bash/SKILL.md +307 -21
- package/skills/verification-before-done/SKILL.md +11 -2
- package/skills/widget-rendering/SKILL.md +258 -0
- package/skills/workspace-isolation/SKILL.md +202 -0
- package/skills/worktree-isolation/SKILL.md +202 -18
- package/src/adapters/claude-adapter.ts +25 -25
- package/src/adapters/codex-adapter.ts +21 -21
- package/src/adapters/cursor-adapter.ts +17 -17
- package/src/adapters/export-util.ts +137 -137
- package/src/adapters/index.ts +15 -15
- package/src/adapters/registry.ts +18 -18
- package/src/adapters/types.ts +23 -23
- package/src/agents/agent-config.ts +38 -38
- package/src/agents/agent-serializer.ts +38 -38
- package/src/agents/discover-agents.ts +121 -118
- package/src/config/config.ts +740 -858
- package/src/config/defaults.ts +96 -96
- package/src/config/drift-detector.ts +211 -211
- package/src/config/markers.ts +327 -327
- package/src/config/resilient-parser.ts +109 -108
- package/src/config/suggestions.ts +74 -74
- package/src/config/types.ts +199 -0
- package/src/extension/async-notifier.ts +123 -89
- package/src/extension/autonomous-policy.ts +169 -169
- package/src/extension/cross-extension-rpc.ts +104 -103
- package/src/extension/help.ts +47 -47
- package/src/extension/import-index.ts +69 -69
- package/src/extension/management.ts +395 -382
- package/src/extension/notification-router.ts +116 -116
- package/src/extension/notification-sink.ts +51 -51
- package/src/extension/project-init.ts +168 -168
- package/src/extension/register.ts +859 -668
- package/src/extension/registration/artifact-cleanup.ts +15 -15
- package/src/extension/registration/command-utils.ts +54 -54
- package/src/extension/registration/commands.ts +559 -452
- package/src/extension/registration/compaction-guard.ts +125 -125
- package/src/extension/registration/subagent-helpers.ts +102 -102
- package/src/extension/registration/subagent-tools.ts +220 -158
- package/src/extension/registration/team-tool.ts +159 -98
- package/src/extension/registration/viewers.ts +29 -0
- package/src/extension/result-watcher.ts +128 -128
- package/src/extension/run-bundle-schema.ts +89 -89
- package/src/extension/run-export.ts +73 -73
- package/src/extension/run-import.ts +84 -84
- package/src/extension/run-index.ts +94 -94
- package/src/extension/run-maintenance.ts +142 -142
- package/src/extension/session-summary.ts +8 -8
- package/src/extension/team-manager-command.ts +96 -95
- package/src/extension/team-recommendation.ts +188 -188
- package/src/extension/team-tool/api.ts +5 -2
- package/src/extension/team-tool/cancel.ts +224 -209
- package/src/extension/team-tool/config-patch.ts +36 -36
- package/src/extension/team-tool/context.ts +60 -60
- package/src/extension/team-tool/doctor.ts +242 -242
- package/src/extension/team-tool/handle-settings.ts +421 -195
- package/src/extension/team-tool/inspect.ts +41 -41
- package/src/extension/team-tool/lifecycle-actions.ts +139 -139
- package/src/extension/team-tool/parallel-dispatch.ts +156 -156
- package/src/extension/team-tool/plan.ts +19 -19
- package/src/extension/team-tool/respond.ts +112 -111
- package/src/extension/team-tool/run.ts +246 -228
- package/src/extension/team-tool/status.ts +110 -110
- package/src/extension/team-tool-types.ts +13 -13
- package/src/extension/team-tool.ts +16 -4
- package/src/extension/tool-result.ts +16 -16
- package/src/extension/validate-resources.ts +77 -77
- package/src/hooks/registry.ts +61 -61
- package/src/hooks/types.ts +40 -40
- package/src/i18n.ts +184 -184
- package/src/observability/correlation.ts +35 -35
- package/src/observability/event-to-metric.ts +68 -68
- package/src/observability/exporters/adapter.ts +30 -30
- package/src/observability/exporters/otlp-exporter.ts +106 -92
- package/src/observability/exporters/prometheus-exporter.ts +54 -54
- package/src/observability/metric-registry.ts +87 -87
- package/src/observability/metric-retention.ts +54 -54
- package/src/observability/metric-sink.ts +81 -56
- package/src/observability/metrics-primitives.ts +167 -167
- package/src/prompt/prompt-runtime.ts +72 -72
- package/src/runtime/adaptive-plan.ts +338 -0
- package/src/runtime/agent-control.ts +169 -169
- package/src/runtime/agent-memory.ts +72 -72
- package/src/runtime/agent-observability.ts +114 -114
- package/src/runtime/async-marker.ts +26 -26
- package/src/runtime/async-runner.ts +153 -79
- package/src/runtime/attention-events.ts +28 -28
- package/src/runtime/auto-resume.ts +100 -100
- package/src/runtime/background-runner.ts +122 -88
- package/src/runtime/cancellation.ts +61 -61
- package/src/runtime/capability-inventory.ts +116 -116
- package/src/runtime/child-pi-pool.ts +68 -0
- package/src/runtime/child-pi.ts +541 -463
- package/src/runtime/code-summary.ts +247 -247
- package/src/runtime/compaction-summary.ts +271 -271
- package/src/runtime/concurrency.ts +58 -58
- package/src/runtime/crash-recovery.ts +317 -301
- package/src/runtime/crew-agent-records.ts +379 -281
- package/src/runtime/crew-agent-runtime.ts +60 -60
- package/src/runtime/cross-extension-rpc.ts +72 -0
- package/src/runtime/custom-tools/irc-tool.ts +201 -201
- package/src/runtime/custom-tools/submit-result-tool.ts +90 -90
- package/src/runtime/deadletter.ts +47 -47
- package/src/runtime/delivery-coordinator.ts +176 -176
- package/src/runtime/delta-conflict.ts +360 -360
- package/src/runtime/diagnostic-export.ts +102 -102
- package/src/runtime/direct-run.ts +35 -35
- package/src/runtime/effectiveness.ts +82 -81
- package/src/runtime/errors/crew-errors.ts +166 -0
- package/src/runtime/event-stream-bridge.ts +92 -92
- package/src/runtime/foreground-control.ts +82 -82
- package/src/runtime/green-contract.ts +46 -46
- package/src/runtime/group-join.ts +234 -106
- package/src/runtime/heartbeat-watcher.ts +145 -124
- package/src/runtime/iteration-hooks.ts +267 -264
- package/src/runtime/live-agent-control.ts +88 -88
- package/src/runtime/live-agent-manager.ts +377 -179
- package/src/runtime/live-control-realtime.ts +36 -36
- package/src/runtime/live-session-runtime.ts +676 -599
- package/src/runtime/loop-gates.ts +129 -129
- package/src/runtime/manifest-cache.ts +263 -263
- package/src/runtime/mcp-proxy.ts +113 -113
- package/src/runtime/metric-parser.ts +40 -40
- package/src/runtime/model-fallback.ts +282 -274
- package/src/runtime/model-resolver.ts +118 -0
- package/src/runtime/output-validator.ts +187 -187
- package/src/runtime/overflow-recovery.ts +175 -175
- package/src/runtime/parallel-research.ts +44 -44
- package/src/runtime/parallel-utils.ts +156 -156
- package/src/runtime/parent-guard.ts +80 -80
- package/src/runtime/phase-progress.ts +217 -217
- package/src/runtime/pi-args.ts +165 -165
- package/src/runtime/pi-json-output.ts +111 -111
- package/src/runtime/pi-spawn.ts +167 -167
- package/src/runtime/policy-engine.ts +79 -79
- package/src/runtime/post-checks.ts +125 -122
- package/src/runtime/post-exit-stdio-guard.ts +86 -86
- package/src/runtime/process-status.ts +97 -73
- package/src/runtime/progress-event-coalescer.ts +43 -43
- package/src/runtime/recovery-recipes.ts +74 -74
- package/src/runtime/retry-executor.ts +81 -81
- package/src/runtime/role-permission.ts +39 -39
- package/src/runtime/run-tracker.ts +99 -0
- package/src/runtime/runtime-policy.ts +21 -0
- package/src/runtime/runtime-resolver.ts +94 -90
- package/src/runtime/scheduler.ts +294 -0
- package/src/runtime/semaphore.ts +131 -131
- package/src/runtime/sensitive-paths.ts +92 -92
- package/src/runtime/session-usage.ts +79 -79
- package/src/runtime/settings-store.ts +103 -0
- package/src/runtime/sidechain-output.ts +29 -29
- package/src/runtime/skill-instructions.ts +222 -222
- package/src/runtime/stale-reconciler.ts +198 -189
- package/src/runtime/streaming-output.ts +47 -0
- package/src/runtime/subagent-manager.ts +404 -395
- package/src/runtime/subprocess-tool-registry.ts +67 -67
- package/src/runtime/task-display.ts +38 -38
- package/src/runtime/task-graph-scheduler.ts +122 -122
- package/src/runtime/task-graph.ts +207 -207
- package/src/runtime/task-output-context.ts +177 -177
- package/src/runtime/task-packet.ts +93 -93
- package/src/runtime/task-quality.ts +207 -207
- package/src/runtime/task-runner/capabilities.ts +78 -78
- package/src/runtime/task-runner/live-executor.ts +131 -113
- package/src/runtime/task-runner/progress.ts +119 -119
- package/src/runtime/task-runner/prompt-builder.ts +139 -139
- package/src/runtime/task-runner/prompt-pipeline.ts +64 -64
- package/src/runtime/task-runner/result-utils.ts +14 -14
- package/src/runtime/task-runner/run-projection.ts +103 -103
- package/src/runtime/task-runner/state-helpers.ts +22 -22
- package/src/runtime/task-runner.ts +469 -458
- package/src/runtime/team-runner.ts +693 -945
- package/src/runtime/usage-tracker.ts +71 -0
- package/src/runtime/worker-heartbeat.ts +21 -21
- package/src/runtime/worker-startup.ts +57 -57
- package/src/runtime/workflow-state.ts +187 -187
- package/src/runtime/yield-handler.ts +190 -189
- package/src/schema/config-schema.ts +172 -168
- package/src/schema/team-tool-schema.ts +126 -125
- package/src/schema/validation-types.ts +151 -148
- package/src/skills/discover-skills.ts +67 -67
- package/src/skills/skill-templates.ts +374 -374
- package/src/state/active-run-registry.ts +227 -191
- package/src/state/artifact-store.ts +130 -129
- package/src/state/atomic-write.ts +262 -178
- package/src/state/blob-store.ts +116 -116
- package/src/state/contracts.ts +111 -111
- package/src/state/event-log-rotation.ts +161 -158
- package/src/state/event-log.ts +383 -240
- package/src/state/event-reconstructor.ts +217 -217
- package/src/state/jsonl-writer.ts +82 -82
- package/src/state/locks.ts +146 -148
- package/src/state/mailbox.ts +446 -405
- package/src/state/state-store.ts +364 -351
- package/src/state/task-claims.ts +44 -44
- package/src/state/types.ts +285 -285
- package/src/state/usage.ts +29 -29
- package/src/subagents/async-entry.ts +1 -1
- package/src/subagents/index.ts +3 -3
- package/src/subagents/live/control.ts +1 -1
- package/src/subagents/live/manager.ts +1 -1
- package/src/subagents/live/realtime.ts +1 -1
- package/src/subagents/live/session-runtime.ts +1 -1
- package/src/subagents/manager.ts +1 -1
- package/src/subagents/spawn.ts +1 -1
- package/src/teams/discover-teams.ts +116 -116
- package/src/teams/team-config.ts +27 -27
- package/src/teams/team-serializer.ts +38 -38
- package/src/types/diff.d.ts +18 -18
- package/src/ui/agent-management-overlay.ts +144 -144
- package/src/ui/crew-widget.ts +487 -370
- package/src/ui/dashboard-panes/agents-pane.ts +109 -28
- package/src/ui/dashboard-panes/cancellation-pane.ts +42 -42
- package/src/ui/dashboard-panes/capability-pane.ts +59 -59
- package/src/ui/dashboard-panes/health-pane.ts +30 -30
- package/src/ui/dashboard-panes/mailbox-pane.ts +35 -35
- package/src/ui/dashboard-panes/progress-pane.ts +30 -30
- package/src/ui/dashboard-panes/transcript-pane.ts +10 -10
- package/src/ui/heartbeat-aggregator.ts +63 -63
- package/src/ui/keybinding-map.ts +97 -94
- package/src/ui/live-conversation-overlay.ts +152 -0
- package/src/ui/live-run-sidebar.ts +180 -180
- package/src/ui/mascot.ts +442 -442
- package/src/ui/overlays/agent-picker-overlay.ts +57 -57
- package/src/ui/overlays/confirm-overlay.ts +58 -58
- package/src/ui/overlays/mailbox-compose-overlay.ts +144 -144
- package/src/ui/overlays/mailbox-compose-preview.ts +63 -63
- package/src/ui/overlays/mailbox-detail-overlay.ts +122 -122
- package/src/ui/pi-ui-compat.ts +57 -57
- package/src/ui/powerbar-publisher.ts +221 -197
- package/src/ui/render-scheduler.ts +216 -143
- package/src/ui/run-action-dispatcher.ts +118 -117
- package/src/ui/run-dashboard.ts +526 -464
- package/src/ui/run-event-bus.ts +208 -208
- package/src/ui/run-snapshot-cache.ts +826 -777
- package/src/ui/settings-overlay.ts +721 -0
- package/src/ui/snapshot-types.ts +86 -70
- package/src/ui/theme-adapter.ts +190 -190
- package/src/ui/tool-progress-formatter.ts +89 -0
- package/src/ui/transcript-cache.ts +94 -94
- package/src/ui/transcript-viewer.ts +335 -335
- package/src/utils/conflict-detect.ts +662 -0
- package/src/utils/env-filter.ts +30 -0
- package/src/utils/file-coalescer.ts +86 -86
- package/src/utils/frontmatter.ts +68 -68
- package/src/utils/fs-watch.ts +88 -31
- package/src/utils/gh-protocol.ts +479 -0
- package/src/utils/ids.ts +17 -17
- package/src/utils/incremental-reader.ts +104 -104
- package/src/utils/internal-error.ts +6 -6
- package/src/utils/names.ts +27 -27
- package/src/utils/paths.ts +102 -63
- package/src/utils/redaction.ts +44 -44
- package/src/utils/resolve-shell.ts +34 -0
- package/src/utils/safe-paths.ts +47 -47
- package/src/utils/scan-cache.ts +136 -136
- package/src/utils/sleep.ts +2 -1
- package/src/utils/sse-parser.ts +134 -134
- package/src/utils/task-name-generator.ts +337 -337
- package/src/utils/timings.ts +33 -33
- package/src/utils/visual.ts +243 -198
- package/src/workflows/discover-workflows.ts +139 -139
- package/src/workflows/validate-workflow.ts +40 -40
- package/src/workflows/workflow-config.ts +26 -26
- package/src/workflows/workflow-serializer.ts +32 -32
- package/src/worktree/branch-freshness.ts +45 -45
- package/src/worktree/cleanup.ts +75 -72
- package/src/worktree/worktree-manager.ts +188 -146
- package/teams/default.team.md +12 -12
- package/teams/fast-fix.team.md +11 -11
- package/teams/implementation.team.md +18 -18
- package/teams/parallel-research.team.md +14 -14
- package/teams/research.team.md +11 -11
- package/teams/review.team.md +12 -12
- package/tsconfig.json +19 -19
- package/workflows/default.workflow.md +30 -30
- package/workflows/fast-fix.workflow.md +23 -23
- package/workflows/implementation.workflow.md +43 -43
- package/workflows/parallel-research.workflow.md +46 -46
- package/workflows/research.workflow.md +22 -22
- package/workflows/review.workflow.md +30 -30
- package/skills/task-packet/SKILL.md +0 -28
- package/skills/verify-evidence/SKILL.md +0 -27
|
@@ -1,28 +1,109 @@
|
|
|
1
|
-
import type { RunDashboardOptions } from "../run-dashboard.ts";
|
|
2
|
-
import { iconForStatus } from "../status-colors.ts";
|
|
3
|
-
import type { RunUiSnapshot } from "../snapshot-types.ts";
|
|
4
|
-
import { spinnerFrame } from "../spinner.ts";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
return
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
1
|
+
import type { RunDashboardOptions } from "../run-dashboard.ts";
|
|
2
|
+
import { iconForStatus } from "../status-colors.ts";
|
|
3
|
+
import type { RunUiSnapshot } from "../snapshot-types.ts";
|
|
4
|
+
import { spinnerFrame } from "../spinner.ts";
|
|
5
|
+
import type { CrewAgentRecord } from "../../runtime/crew-agent-runtime.ts";
|
|
6
|
+
import { listLiveAgents, type LiveAgentHandle } from "../../runtime/live-agent-manager.ts";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Returns true if this agent did real work (LLM call, tool use, or non-trivial duration).
|
|
10
|
+
* Scaffold-only agents (no tokens, no tools, no turns) are skipped in the agents pane —
|
|
11
|
+
* they represent pipeline infrastructure steps, not actual agent execution.
|
|
12
|
+
*/
|
|
13
|
+
function isRealAgent(agent: CrewAgentRecord, liveHandle?: LiveAgentHandle): boolean {
|
|
14
|
+
if (agent.runtime === "live-session" || agent.runtime === "child-process") return true;
|
|
15
|
+
// Scaffold agents with real work done are still worth showing
|
|
16
|
+
const tokens = (agent.usage?.input ?? 0) + (agent.usage?.output ?? 0) + (agent.usage?.cacheRead ?? 0) + (agent.usage?.cacheWrite ?? 0);
|
|
17
|
+
if (tokens > 0) return true;
|
|
18
|
+
const turns = (agent.usage as { turns?: number } | undefined)?.turns;
|
|
19
|
+
if (turns != null && turns > 0) return true;
|
|
20
|
+
if ((agent.progress?.toolCount ?? 0) > 0) return true;
|
|
21
|
+
// If it's still running and has been alive for > 30s, it might be real
|
|
22
|
+
if (liveHandle) {
|
|
23
|
+
const ms = Date.now() - liveHandle.activity.startedAtMs;
|
|
24
|
+
if (ms > 30_000) return true;
|
|
25
|
+
}
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const TOOL_LABELS: Record<string, string> = {
|
|
30
|
+
read: "reading",
|
|
31
|
+
bash: "cmd",
|
|
32
|
+
edit: "editing",
|
|
33
|
+
write: "writing",
|
|
34
|
+
grep: "searching",
|
|
35
|
+
find: "finding",
|
|
36
|
+
ls: "listing",
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
function describeActivity(handle: LiveAgentHandle): string {
|
|
40
|
+
const act = handle.activity;
|
|
41
|
+
if (act.activeTools.size > 0) {
|
|
42
|
+
const tools = [...new Set([...act.activeTools.values()])].map(t => TOOL_LABELS[t] ?? t);
|
|
43
|
+
return tools.join(", ") + "…";
|
|
44
|
+
}
|
|
45
|
+
if (act.responseText?.trim()) {
|
|
46
|
+
const line = act.responseText.split("\n").find((l) => l.trim())?.trim() ?? "";
|
|
47
|
+
return line.length > 40 ? line.slice(0, 40) + "…" : line;
|
|
48
|
+
}
|
|
49
|
+
return "thinking…";
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function renderAgentsPane(snapshot: RunUiSnapshot | undefined, options: RunDashboardOptions = {}): string[] {
|
|
53
|
+
if (!snapshot) return ["(snapshot unavailable)"];
|
|
54
|
+
if (!snapshot.agents.length) return ["(no agents)"];
|
|
55
|
+
const liveForRun = listLiveAgents().filter(h => h.runId === snapshot.runId);
|
|
56
|
+
const { completed, total } = snapshot.progress;
|
|
57
|
+
|
|
58
|
+
const lines: string[] = [];
|
|
59
|
+
|
|
60
|
+
const realAgents = snapshot.agents.filter(a => isRealAgent(a, liveForRun.find(h => h.taskId === a.taskId)));
|
|
61
|
+
const lineCount = Math.min(realAgents.length, 12);
|
|
62
|
+
const label = realAgents.length !== snapshot.agents.length
|
|
63
|
+
? `${realAgents.length} real agents (${snapshot.agents.length} total)`
|
|
64
|
+
: `${realAgents.length} agents`;
|
|
65
|
+
|
|
66
|
+
lines.push(`${completed}/${total} tasks · ${label}`);
|
|
67
|
+
|
|
68
|
+
for (const agent of realAgents.slice(0, 12)) {
|
|
69
|
+
const liveHandle = liveForRun.find(h => h.taskId === agent.taskId);
|
|
70
|
+
const icon = iconForStatus(agent.status, { runningGlyph: spinnerFrame(agent.taskId) });
|
|
71
|
+
const role = `${agent.role}`;
|
|
72
|
+
|
|
73
|
+
// Compact activity line
|
|
74
|
+
const activity = liveHandle ? describeActivity(liveHandle)
|
|
75
|
+
: agent.progress?.currentTool ? `${TOOL_LABELS[agent.progress.currentTool] ?? agent.progress.currentTool}…`
|
|
76
|
+
: agent.status === "running" ? "thinking…"
|
|
77
|
+
: agent.status === "queued" ? "queued"
|
|
78
|
+
: agent.status === "failed" ? (agent.error ?? "failed")
|
|
79
|
+
: "done";
|
|
80
|
+
|
|
81
|
+
// Stats: tokens + duration only
|
|
82
|
+
const stats: string[] = [];
|
|
83
|
+
const tokenTotal = (agent.usage?.input ?? 0) + (agent.usage?.output ?? 0) + (agent.usage?.cacheRead ?? 0) + (agent.usage?.cacheWrite ?? 0);
|
|
84
|
+
if (tokenTotal > 0) {
|
|
85
|
+
const tok = tokenTotal >= 1000 ? `${(tokenTotal / 1000).toFixed(1)}k` : `${tokenTotal}`;
|
|
86
|
+
stats.push(tok);
|
|
87
|
+
}
|
|
88
|
+
if (liveHandle) {
|
|
89
|
+
const ms = (liveHandle.activity.completedAtMs ?? Date.now()) - liveHandle.activity.startedAtMs;
|
|
90
|
+
stats.push(`${(ms / 1000).toFixed(1)}s`);
|
|
91
|
+
if (options.showModel !== false && liveHandle.modelName && liveHandle.modelName !== "default") {
|
|
92
|
+
stats.push(liveHandle.modelName);
|
|
93
|
+
}
|
|
94
|
+
} else if (agent.startedAt) {
|
|
95
|
+
const ms = Date.now() - new Date(agent.startedAt).getTime();
|
|
96
|
+
if (Number.isFinite(ms)) stats.push(`${(ms / 1000).toFixed(1)}s`);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const statsStr = stats.length ? ` · ${stats.join(" ")}` : "";
|
|
100
|
+
lines.push(` ${icon} ${agent.taskId} ${role}${statsStr}`);
|
|
101
|
+
lines.push(` ${activity}`);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (snapshot.agents.length > 12) {
|
|
105
|
+
lines.push(` … +${snapshot.agents.length - 12} more`);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return lines;
|
|
109
|
+
}
|
|
@@ -1,43 +1,43 @@
|
|
|
1
|
-
import type { TeamRunManifest, TeamTaskState } from "../../state/types.ts";
|
|
2
|
-
|
|
3
|
-
export interface CancellationPaneOptions {
|
|
4
|
-
maxReasons?: number;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export function renderCancellationPane(manifest: TeamRunManifest, tasks: TeamTaskState[], opts: CancellationPaneOptions = {}): string[] {
|
|
8
|
-
const maxReasons = opts.maxReasons ?? 5;
|
|
9
|
-
if (manifest.status !== "cancelled" && manifest.status !== "blocked") {
|
|
10
|
-
const cancellingTasks = tasks.filter((t) => t.status === "cancelled");
|
|
11
|
-
if (cancellingTasks.length === 0) return ["Cancellation pane: no active cancellations"];
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const lines: string[] = ["Cancellation pane"];
|
|
15
|
-
|
|
16
|
-
if (manifest.status === "cancelled") {
|
|
17
|
-
lines.push(` Run status: cancelled`);
|
|
18
|
-
} else if (manifest.status === "blocked") {
|
|
19
|
-
lines.push(` Run status: blocked`);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const cancelledTasks = tasks.filter((t) => t.status === "cancelled");
|
|
23
|
-
if (cancelledTasks.length > 0) {
|
|
24
|
-
lines.push(` Cancelled tasks (${cancelledTasks.length}):`);
|
|
25
|
-
for (const task of cancelledTasks.slice(0, maxReasons)) {
|
|
26
|
-
const reason = task.error ?? "unknown";
|
|
27
|
-
lines.push(` ✗ ${task.id}: ${reason}`);
|
|
28
|
-
}
|
|
29
|
-
if (cancelledTasks.length > maxReasons) {
|
|
30
|
-
lines.push(` ... and ${cancelledTasks.length - maxReasons} more`);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
if (manifest.policyDecisions?.length) {
|
|
35
|
-
const decisions = manifest.policyDecisions.slice(0, maxReasons);
|
|
36
|
-
lines.push(` Policy decisions (${manifest.policyDecisions.length}):`);
|
|
37
|
-
for (const d of decisions) {
|
|
38
|
-
lines.push(` ${d.action}: ${d.message}`);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
return lines;
|
|
1
|
+
import type { TeamRunManifest, TeamTaskState } from "../../state/types.ts";
|
|
2
|
+
|
|
3
|
+
export interface CancellationPaneOptions {
|
|
4
|
+
maxReasons?: number;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function renderCancellationPane(manifest: TeamRunManifest, tasks: TeamTaskState[], opts: CancellationPaneOptions = {}): string[] {
|
|
8
|
+
const maxReasons = opts.maxReasons ?? 5;
|
|
9
|
+
if (manifest.status !== "cancelled" && manifest.status !== "blocked") {
|
|
10
|
+
const cancellingTasks = tasks.filter((t) => t.status === "cancelled");
|
|
11
|
+
if (cancellingTasks.length === 0) return ["Cancellation pane: no active cancellations"];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const lines: string[] = ["Cancellation pane"];
|
|
15
|
+
|
|
16
|
+
if (manifest.status === "cancelled") {
|
|
17
|
+
lines.push(` Run status: cancelled`);
|
|
18
|
+
} else if (manifest.status === "blocked") {
|
|
19
|
+
lines.push(` Run status: blocked`);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const cancelledTasks = tasks.filter((t) => t.status === "cancelled");
|
|
23
|
+
if (cancelledTasks.length > 0) {
|
|
24
|
+
lines.push(` Cancelled tasks (${cancelledTasks.length}):`);
|
|
25
|
+
for (const task of cancelledTasks.slice(0, maxReasons)) {
|
|
26
|
+
const reason = task.error ?? "unknown";
|
|
27
|
+
lines.push(` ✗ ${task.id}: ${reason}`);
|
|
28
|
+
}
|
|
29
|
+
if (cancelledTasks.length > maxReasons) {
|
|
30
|
+
lines.push(` ... and ${cancelledTasks.length - maxReasons} more`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (manifest.policyDecisions?.length) {
|
|
35
|
+
const decisions = manifest.policyDecisions.slice(0, maxReasons);
|
|
36
|
+
lines.push(` Policy decisions (${manifest.policyDecisions.length}):`);
|
|
37
|
+
for (const d of decisions) {
|
|
38
|
+
lines.push(` ${d.action}: ${d.message}`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return lines;
|
|
43
43
|
}
|
|
@@ -1,60 +1,60 @@
|
|
|
1
|
-
import { buildCapabilityInventory } from "../../runtime/capability-inventory.ts";
|
|
2
|
-
import type { PiTeamsConfig } from "../../config/config.ts";
|
|
3
|
-
import type { CapabilityItem } from "../../runtime/capability-inventory.ts";
|
|
4
|
-
|
|
5
|
-
export interface CapabilityPaneOptions {
|
|
6
|
-
config?: PiTeamsConfig;
|
|
7
|
-
filter?: string;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
function kindIcon(kind: string): string {
|
|
11
|
-
switch (kind) {
|
|
12
|
-
case "team": return "👥";
|
|
13
|
-
case "workflow": return "📋";
|
|
14
|
-
case "agent": return "🤖";
|
|
15
|
-
case "skill": return "🔧";
|
|
16
|
-
case "tool": return "🛠";
|
|
17
|
-
case "runtime": return "⚙";
|
|
18
|
-
default: return "•";
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
function stateLabel(state: string): string {
|
|
23
|
-
switch (state) {
|
|
24
|
-
case "active": return "";
|
|
25
|
-
case "disabled": return " [DISABLED]";
|
|
26
|
-
case "shadowed": return " [SHADOWED]";
|
|
27
|
-
case "missing": return " [MISSING]";
|
|
28
|
-
default: return "";
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export function renderCapabilityPane(cwd: string, opts: CapabilityPaneOptions = {}): string[] {
|
|
33
|
-
const inventory = buildCapabilityInventory(cwd, opts.config);
|
|
34
|
-
const filtered = opts.filter
|
|
35
|
-
? inventory.filter((item) => item.kind.includes(opts.filter!.toLowerCase()) || item.name.toLowerCase().includes(opts.filter!.toLowerCase()) || item.id.toLowerCase().includes(opts.filter!.toLowerCase()))
|
|
36
|
-
: inventory;
|
|
37
|
-
|
|
38
|
-
if (filtered.length === 0) return ["Capability pane: no items found"];
|
|
39
|
-
|
|
40
|
-
const byKind = new Map<string, CapabilityItem[]>();
|
|
41
|
-
for (const item of filtered) {
|
|
42
|
-
const group = byKind.get(item.kind) ?? [];
|
|
43
|
-
group.push(item);
|
|
44
|
-
byKind.set(item.kind, group);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
const lines = [`Capability pane: ${filtered.length} item(s) (filter: ${opts.filter ?? "none"})`];
|
|
48
|
-
for (const [kind, items] of byKind) {
|
|
49
|
-
lines.push(` ${kindIcon(kind)} ${kind} (${items.length}):`);
|
|
50
|
-
for (const item of items.slice(0, 10)) {
|
|
51
|
-
const icon = item.state === "active" ? "✓" : "✗";
|
|
52
|
-
lines.push(` ${icon} ${item.name}${stateLabel(item.state)} [${item.source}]`);
|
|
53
|
-
}
|
|
54
|
-
if (items.length > 10) lines.push(` ... and ${items.length - 10} more`);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const disabled = filtered.filter((i) => i.state === "disabled").length;
|
|
58
|
-
if (disabled > 0) lines.push(` Disabled: ${disabled}`);
|
|
59
|
-
return lines;
|
|
1
|
+
import { buildCapabilityInventory } from "../../runtime/capability-inventory.ts";
|
|
2
|
+
import type { PiTeamsConfig } from "../../config/config.ts";
|
|
3
|
+
import type { CapabilityItem } from "../../runtime/capability-inventory.ts";
|
|
4
|
+
|
|
5
|
+
export interface CapabilityPaneOptions {
|
|
6
|
+
config?: PiTeamsConfig;
|
|
7
|
+
filter?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function kindIcon(kind: string): string {
|
|
11
|
+
switch (kind) {
|
|
12
|
+
case "team": return "👥";
|
|
13
|
+
case "workflow": return "📋";
|
|
14
|
+
case "agent": return "🤖";
|
|
15
|
+
case "skill": return "🔧";
|
|
16
|
+
case "tool": return "🛠";
|
|
17
|
+
case "runtime": return "⚙";
|
|
18
|
+
default: return "•";
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function stateLabel(state: string): string {
|
|
23
|
+
switch (state) {
|
|
24
|
+
case "active": return "";
|
|
25
|
+
case "disabled": return " [DISABLED]";
|
|
26
|
+
case "shadowed": return " [SHADOWED]";
|
|
27
|
+
case "missing": return " [MISSING]";
|
|
28
|
+
default: return "";
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function renderCapabilityPane(cwd: string, opts: CapabilityPaneOptions = {}): string[] {
|
|
33
|
+
const inventory = buildCapabilityInventory(cwd, opts.config);
|
|
34
|
+
const filtered = opts.filter
|
|
35
|
+
? inventory.filter((item) => item.kind.includes(opts.filter!.toLowerCase()) || item.name.toLowerCase().includes(opts.filter!.toLowerCase()) || item.id.toLowerCase().includes(opts.filter!.toLowerCase()))
|
|
36
|
+
: inventory;
|
|
37
|
+
|
|
38
|
+
if (filtered.length === 0) return ["Capability pane: no items found"];
|
|
39
|
+
|
|
40
|
+
const byKind = new Map<string, CapabilityItem[]>();
|
|
41
|
+
for (const item of filtered) {
|
|
42
|
+
const group = byKind.get(item.kind) ?? [];
|
|
43
|
+
group.push(item);
|
|
44
|
+
byKind.set(item.kind, group);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const lines = [`Capability pane: ${filtered.length} item(s) (filter: ${opts.filter ?? "none"})`];
|
|
48
|
+
for (const [kind, items] of byKind) {
|
|
49
|
+
lines.push(` ${kindIcon(kind)} ${kind} (${items.length}):`);
|
|
50
|
+
for (const item of items.slice(0, 10)) {
|
|
51
|
+
const icon = item.state === "active" ? "✓" : "✗";
|
|
52
|
+
lines.push(` ${icon} ${item.name}${stateLabel(item.state)} [${item.source}]`);
|
|
53
|
+
}
|
|
54
|
+
if (items.length > 10) lines.push(` ... and ${items.length - 10} more`);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const disabled = filtered.filter((i) => i.state === "disabled").length;
|
|
58
|
+
if (disabled > 0) lines.push(` Disabled: ${disabled}`);
|
|
59
|
+
return lines;
|
|
60
60
|
}
|
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
import { summarizeHeartbeats } from "../heartbeat-aggregator.ts";
|
|
2
|
-
import type { RunUiSnapshot } from "../snapshot-types.ts";
|
|
3
|
-
|
|
4
|
-
export interface HealthPaneOptions {
|
|
5
|
-
staleMs?: number;
|
|
6
|
-
deadMs?: number;
|
|
7
|
-
isForeground?: boolean;
|
|
8
|
-
now?: number | Date;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
function seconds(ms: number): string {
|
|
12
|
-
return `${Math.round(ms / 1000)}s`;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function renderHealthPane(snapshot: RunUiSnapshot | undefined, opts: HealthPaneOptions = {}): string[] {
|
|
16
|
-
if (!snapshot) return ["Health pane: snapshot unavailable"];
|
|
17
|
-
const summary = summarizeHeartbeats(snapshot, opts);
|
|
18
|
-
const lines = [
|
|
19
|
-
`Health pane: ${summary.healthy}/${summary.totalTasks} healthy · stale=${summary.stale} · dead=${summary.dead} · missing=${summary.missing}`,
|
|
20
|
-
];
|
|
21
|
-
if (summary.worstStaleMs > 0) lines.push(`Worst stale: ${seconds(summary.worstStaleMs)} ago`);
|
|
22
|
-
const hints: string[] = [];
|
|
23
|
-
const foreground = opts.isForeground !== false;
|
|
24
|
-
if ((summary.dead > 0 || summary.missing > 0) && foreground) hints.push("R recovery");
|
|
25
|
-
if ((summary.dead > 0 || summary.stale > 0) && foreground) hints.push("K kill stale");
|
|
26
|
-
hints.push("D diagnostic export");
|
|
27
|
-
lines.push(`Actions: ${hints.join(" · ")}`);
|
|
28
|
-
if (!foreground && (summary.dead > 0 || summary.missing > 0 || summary.stale > 0)) lines.push("Async run: R/K disabled — inspect process manually or use /team-api.");
|
|
29
|
-
return lines;
|
|
30
|
-
}
|
|
1
|
+
import { summarizeHeartbeats } from "../heartbeat-aggregator.ts";
|
|
2
|
+
import type { RunUiSnapshot } from "../snapshot-types.ts";
|
|
3
|
+
|
|
4
|
+
export interface HealthPaneOptions {
|
|
5
|
+
staleMs?: number;
|
|
6
|
+
deadMs?: number;
|
|
7
|
+
isForeground?: boolean;
|
|
8
|
+
now?: number | Date;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function seconds(ms: number): string {
|
|
12
|
+
return `${Math.round(ms / 1000)}s`;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function renderHealthPane(snapshot: RunUiSnapshot | undefined, opts: HealthPaneOptions = {}): string[] {
|
|
16
|
+
if (!snapshot) return ["Health pane: snapshot unavailable"];
|
|
17
|
+
const summary = summarizeHeartbeats(snapshot, opts);
|
|
18
|
+
const lines = [
|
|
19
|
+
`Health pane: ${summary.healthy}/${summary.totalTasks} healthy · stale=${summary.stale} · dead=${summary.dead} · missing=${summary.missing}`,
|
|
20
|
+
];
|
|
21
|
+
if (summary.worstStaleMs > 0) lines.push(`Worst stale: ${seconds(summary.worstStaleMs)} ago`);
|
|
22
|
+
const hints: string[] = [];
|
|
23
|
+
const foreground = opts.isForeground !== false;
|
|
24
|
+
if ((summary.dead > 0 || summary.missing > 0) && foreground) hints.push("R recovery");
|
|
25
|
+
if ((summary.dead > 0 || summary.stale > 0) && foreground) hints.push("K kill stale");
|
|
26
|
+
hints.push("D diagnostic export");
|
|
27
|
+
lines.push(`Actions: ${hints.join(" · ")}`);
|
|
28
|
+
if (!foreground && (summary.dead > 0 || summary.missing > 0 || summary.stale > 0)) lines.push("Async run: R/K disabled — inspect process manually or use /team-api.");
|
|
29
|
+
return lines;
|
|
30
|
+
}
|
|
@@ -1,35 +1,35 @@
|
|
|
1
|
-
import type { RunUiSnapshot } from "../snapshot-types.ts";
|
|
2
|
-
|
|
3
|
-
export function renderMailboxPane(snapshot: RunUiSnapshot | undefined): string[] {
|
|
4
|
-
if (!snapshot) return ["Mailbox pane: snapshot unavailable"];
|
|
5
|
-
const mailbox = snapshot.mailbox;
|
|
6
|
-
const approx = mailbox.approximate ? " · approximate (tail)" : "";
|
|
7
|
-
const lines: string[] = [
|
|
8
|
-
`Mailbox pane: inbox unread=${mailbox.inboxUnread} · outbox pending=${mailbox.outboxPending} · attention=${mailbox.needsAttention}${approx}`,
|
|
9
|
-
];
|
|
10
|
-
// Kind-separated breakdown
|
|
11
|
-
const kindParts: string[] = [];
|
|
12
|
-
const steer = mailbox.steerUnread ?? 0;
|
|
13
|
-
const followUp = mailbox.followUpUnread ?? 0;
|
|
14
|
-
const response = mailbox.responseUnread ?? 0;
|
|
15
|
-
const message = mailbox.messageUnread ?? 0;
|
|
16
|
-
if (steer > 0) kindParts.push(`steer=${steer}`);
|
|
17
|
-
if (followUp > 0) kindParts.push(`follow-up=${followUp}`);
|
|
18
|
-
if (response > 0) kindParts.push(`response=${response}`);
|
|
19
|
-
if (message > 0) kindParts.push(`message=${message}`);
|
|
20
|
-
if (kindParts.length > 0) {
|
|
21
|
-
lines.push(` Breakdown: ${kindParts.join(" · ")}`);
|
|
22
|
-
if (steer > 0) {
|
|
23
|
-
lines.push(" ⚠ Urgent: steering messages require immediate attention.");
|
|
24
|
-
}
|
|
25
|
-
if (followUp > 0) {
|
|
26
|
-
lines.push(` 📋 ${followUp} follow-up(s) pending review.`);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
if (mailbox.needsAttention > 0) {
|
|
30
|
-
lines.push("Needs attention: press Enter for detail · A ack · N nudge · C compose · X ack all.");
|
|
31
|
-
} else {
|
|
32
|
-
lines.push("No mailbox items need attention. Press Enter for detail or C compose.");
|
|
33
|
-
}
|
|
34
|
-
return lines;
|
|
35
|
-
}
|
|
1
|
+
import type { RunUiSnapshot } from "../snapshot-types.ts";
|
|
2
|
+
|
|
3
|
+
export function renderMailboxPane(snapshot: RunUiSnapshot | undefined): string[] {
|
|
4
|
+
if (!snapshot) return ["Mailbox pane: snapshot unavailable"];
|
|
5
|
+
const mailbox = snapshot.mailbox;
|
|
6
|
+
const approx = mailbox.approximate ? " · approximate (tail)" : "";
|
|
7
|
+
const lines: string[] = [
|
|
8
|
+
`Mailbox pane: inbox unread=${mailbox.inboxUnread} · outbox pending=${mailbox.outboxPending} · attention=${mailbox.needsAttention}${approx}`,
|
|
9
|
+
];
|
|
10
|
+
// Kind-separated breakdown
|
|
11
|
+
const kindParts: string[] = [];
|
|
12
|
+
const steer = mailbox.steerUnread ?? 0;
|
|
13
|
+
const followUp = mailbox.followUpUnread ?? 0;
|
|
14
|
+
const response = mailbox.responseUnread ?? 0;
|
|
15
|
+
const message = mailbox.messageUnread ?? 0;
|
|
16
|
+
if (steer > 0) kindParts.push(`steer=${steer}`);
|
|
17
|
+
if (followUp > 0) kindParts.push(`follow-up=${followUp}`);
|
|
18
|
+
if (response > 0) kindParts.push(`response=${response}`);
|
|
19
|
+
if (message > 0) kindParts.push(`message=${message}`);
|
|
20
|
+
if (kindParts.length > 0) {
|
|
21
|
+
lines.push(` Breakdown: ${kindParts.join(" · ")}`);
|
|
22
|
+
if (steer > 0) {
|
|
23
|
+
lines.push(" ⚠ Urgent: steering messages require immediate attention.");
|
|
24
|
+
}
|
|
25
|
+
if (followUp > 0) {
|
|
26
|
+
lines.push(` 📋 ${followUp} follow-up(s) pending review.`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
if (mailbox.needsAttention > 0) {
|
|
30
|
+
lines.push("Needs attention: press Enter for detail · A ack · N nudge · C compose · X ack all.");
|
|
31
|
+
} else {
|
|
32
|
+
lines.push("No mailbox items need attention. Press Enter for detail or C compose.");
|
|
33
|
+
}
|
|
34
|
+
return lines;
|
|
35
|
+
}
|
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
import type { RunUiSnapshot } from "../snapshot-types.ts";
|
|
2
|
-
import { computePhaseProgress, formatPhaseProgressLine } from "../../runtime/phase-progress.ts";
|
|
3
|
-
|
|
4
|
-
export function renderProgressPane(snapshot: RunUiSnapshot | undefined): string[] {
|
|
5
|
-
if (!snapshot) return ["Progress pane: snapshot unavailable"];
|
|
6
|
-
const progress = snapshot.progress;
|
|
7
|
-
const groupJoins = snapshot.groupJoins ?? [];
|
|
8
|
-
const groupJoinLines = groupJoins.length ? groupJoins.map((item) => `group join ${item.partial ? "partial" : "completed"}: ${item.requestId} ack=${item.ack}`) : ["group joins: none"];
|
|
9
|
-
const cancellationLine = snapshot.cancellationReason ? [`cancelled: reason=${snapshot.cancellationReason}`] : [];
|
|
10
|
-
const runProgress = computePhaseProgress(snapshot.tasks);
|
|
11
|
-
const phaseLines = runProgress.phases.length > 0
|
|
12
|
-
? runProgress.phases.map((p) => {
|
|
13
|
-
const done = p.completed + p.failed;
|
|
14
|
-
const status = p.running > 0 ? "running" : p.queued > 0 ? "queued" : done >= p.total ? "done" : "waiting";
|
|
15
|
-
return ` Phase ${p.index + 1} ${p.phase}: ${p.percentage}% (${done}/${p.total}) [${status}]`;
|
|
16
|
-
})
|
|
17
|
-
: [];
|
|
18
|
-
const phaseHeader = phaseLines.length > 0 ? [formatPhaseProgressLine(runProgress), ...phaseLines] : [];
|
|
19
|
-
return [
|
|
20
|
-
`Progress pane: ${progress.completed}/${progress.total} completed · running=${progress.running} queued=${progress.queued} failed=${progress.failed}`,
|
|
21
|
-
...phaseHeader,
|
|
22
|
-
...cancellationLine,
|
|
23
|
-
...groupJoinLines,
|
|
24
|
-
...snapshot.recentEvents.slice(-10).map((event) => {
|
|
25
|
-
const seq = event.metadata?.seq !== undefined ? `#${event.metadata.seq}` : "#?";
|
|
26
|
-
return `${seq} ${event.time} ${event.type}${event.taskId ? ` ${event.taskId}` : ""}${event.message ? ` · ${event.message}` : ""}`;
|
|
27
|
-
}),
|
|
28
|
-
...(snapshot.recentEvents.length ? [] : ["No recent events"]),
|
|
29
|
-
];
|
|
30
|
-
}
|
|
1
|
+
import type { RunUiSnapshot } from "../snapshot-types.ts";
|
|
2
|
+
import { computePhaseProgress, formatPhaseProgressLine } from "../../runtime/phase-progress.ts";
|
|
3
|
+
|
|
4
|
+
export function renderProgressPane(snapshot: RunUiSnapshot | undefined): string[] {
|
|
5
|
+
if (!snapshot) return ["Progress pane: snapshot unavailable"];
|
|
6
|
+
const progress = snapshot.progress;
|
|
7
|
+
const groupJoins = snapshot.groupJoins ?? [];
|
|
8
|
+
const groupJoinLines = groupJoins.length ? groupJoins.map((item) => `group join ${item.partial ? "partial" : "completed"}: ${item.requestId} ack=${item.ack}`) : ["group joins: none"];
|
|
9
|
+
const cancellationLine = snapshot.cancellationReason ? [`cancelled: reason=${snapshot.cancellationReason}`] : [];
|
|
10
|
+
const runProgress = computePhaseProgress(snapshot.tasks);
|
|
11
|
+
const phaseLines = runProgress.phases.length > 0
|
|
12
|
+
? runProgress.phases.map((p) => {
|
|
13
|
+
const done = p.completed + p.failed;
|
|
14
|
+
const status = p.running > 0 ? "running" : p.queued > 0 ? "queued" : done >= p.total ? "done" : "waiting";
|
|
15
|
+
return ` Phase ${p.index + 1} ${p.phase}: ${p.percentage}% (${done}/${p.total}) [${status}]`;
|
|
16
|
+
})
|
|
17
|
+
: [];
|
|
18
|
+
const phaseHeader = phaseLines.length > 0 ? [formatPhaseProgressLine(runProgress), ...phaseLines] : [];
|
|
19
|
+
return [
|
|
20
|
+
`Progress pane: ${progress.completed}/${progress.total} completed · running=${progress.running} queued=${progress.queued} failed=${progress.failed}`,
|
|
21
|
+
...phaseHeader,
|
|
22
|
+
...cancellationLine,
|
|
23
|
+
...groupJoinLines,
|
|
24
|
+
...snapshot.recentEvents.slice(-10).map((event) => {
|
|
25
|
+
const seq = event.metadata?.seq !== undefined ? `#${event.metadata.seq}` : "#?";
|
|
26
|
+
return `${seq} ${event.time} ${event.type}${event.taskId ? ` ${event.taskId}` : ""}${event.message ? ` · ${event.message}` : ""}`;
|
|
27
|
+
}),
|
|
28
|
+
...(snapshot.recentEvents.length ? [] : ["No recent events"]),
|
|
29
|
+
];
|
|
30
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import type { RunUiSnapshot } from "../snapshot-types.ts";
|
|
2
|
-
|
|
3
|
-
export function renderTranscriptPane(snapshot: RunUiSnapshot | undefined): string[] {
|
|
4
|
-
if (!snapshot) return ["Output pane: snapshot unavailable"];
|
|
5
|
-
return [
|
|
6
|
-
`Output pane: ${snapshot.recentOutputLines.length} recent lines · press v for transcript viewer · o for raw output`,
|
|
7
|
-
...snapshot.recentOutputLines.slice(-12).map((line) => `⎿ ${line}`),
|
|
8
|
-
...(snapshot.recentOutputLines.length ? [] : ["No recent output"]),
|
|
9
|
-
];
|
|
10
|
-
}
|
|
1
|
+
import type { RunUiSnapshot } from "../snapshot-types.ts";
|
|
2
|
+
|
|
3
|
+
export function renderTranscriptPane(snapshot: RunUiSnapshot | undefined): string[] {
|
|
4
|
+
if (!snapshot) return ["Output pane: snapshot unavailable"];
|
|
5
|
+
return [
|
|
6
|
+
`Output pane: ${snapshot.recentOutputLines.length} recent lines · press v for transcript viewer · o for raw output`,
|
|
7
|
+
...snapshot.recentOutputLines.slice(-12).map((line) => `⎿ ${line}`),
|
|
8
|
+
...(snapshot.recentOutputLines.length ? [] : ["No recent output"]),
|
|
9
|
+
];
|
|
10
|
+
}
|