pi-crew 0.6.3 → 0.6.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/CHANGELOG.md +34 -0
- package/README.md +12 -1
- package/docs/ui-optimization-plan.md +447 -0
- package/package.json +1 -1
- package/src/extension/register.ts +19 -1
- package/src/extension/registration/brief-tool-overrides.ts +400 -0
- package/src/extension/registration/commands.ts +25 -0
- package/src/extension/registration/subagent-tools.ts +8 -3
- package/src/extension/registration/team-tool.ts +18 -11
- package/src/extension/team-tool/run.ts +4 -3
- package/src/extension/team-tool-types.ts +2 -0
- package/src/state/session-state-map.ts +51 -0
- package/src/ui/powerbar-publisher.ts +1 -1
- package/src/ui/status-colors.ts +5 -1
- package/src/ui/theme-adapter.ts +80 -1
- package/src/ui/tool-progress-formatter.ts +9 -5
- package/src/ui/tool-render.ts +4 -0
- package/src/ui/tool-renderers/brief-mode.ts +207 -0
- package/src/ui/tool-renderers/index.ts +627 -0
- package/src/ui/widget/index.ts +224 -0
- package/src/ui/widget/widget-formatters.ts +148 -0
- package/src/ui/widget/widget-model.ts +90 -0
- package/src/ui/widget/widget-renderer.ts +130 -0
- package/src/ui/widget/widget-types.ts +37 -0
- package/src/utils/guards.ts +110 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,39 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.6.4] — Visually Rich Tool Rendering: Merged Frames, Live Progress Bars (2026-06-14)
|
|
4
|
+
|
|
5
|
+
### Highlights
|
|
6
|
+
- **Visually rich team & agent tool rendering** — framed cards with box-drawing borders, colored status badges, and structured layouts for `team` and `Agent` tool calls in the Pi TUI
|
|
7
|
+
- **Merged call+result into ONE connected frame** — previously `renderCall` and `renderResult` each drew a complete box, producing two disconnected frames. Now they split a single frame (top border + header from `renderCall`, content + bottom border from `renderResult`) that merge seamlessly in Pi's `Box(1,1)` container
|
|
8
|
+
- **Animated live progress bar during runs** — real-time task progress (`tasks completed=N/M`) parsed from streaming updates and rendered as a `████░░░░ N/M` bar with elapsed time, DURING the run (not after completion). Indeterminate "starting" phase uses an animated scanning bar
|
|
9
|
+
- **Compact summary after completion** — collapsed cards show `✓ crew run 3/3 done · 1m2s · 26k tok · $0.068` with expand hint (`⌘E`) and agent briefs (`✓ explorer · 45.0s · 8.0k tok`)
|
|
10
|
+
- **Crash fix on session resume** — `renderCall` was returning a `string` (from `buildFrame`), causing `TypeError: child.render is not a function` when Pi re-rendered stored tool calls on resume. Now wraps in `new Text(...)`
|
|
11
|
+
|
|
12
|
+
### Bug Fixes
|
|
13
|
+
- **`5613ecc`** — **Critical crash fix**: `teamToolRenderer.renderCall` and `agentToolRenderer.renderCall` returned `buildFrame(...)` (a string), not a Component. Pi's `addChild(string)` stored the string in `children[]`, then `Box.render()` called `child.render(width)` on the string → crash. Only surfaced on resume because fast-completing tools got their `Text` result frame painted before the string call frame was rendered. Fixed by wrapping both renderers in `new Text(..., 0, 0)`.
|
|
14
|
+
- **`58ba6e5`** — Elapsed time miscalculation: Pi's `ctx.executionStarted` is a **boolean** flag (not a timestamp), so `Date.now() - true` produced ~56-year durations. Now timing is tracked via `ctx.state.briefStartedAt`.
|
|
15
|
+
- **`1c2cf71`** — Reverted `lastComponent` reuse: returning `ctx.lastComponent` and mutating its private `.text` field crashed on session resume (deserialized components lose prototype methods). Pi already calls `renderContainer.clear()` before each `updateDisplay()`, so single-frame streaming is guaranteed without reuse.
|
|
16
|
+
- **`7d01ebb`** — Typecheck fix: `agentToolRenderer.renderCall` had parameter named `_ctx` (unused convention) but `borderFromContext(ctx)` referenced `ctx` (`error TS2552`).
|
|
17
|
+
|
|
18
|
+
### Reverts
|
|
19
|
+
- **`0763e67`** — **Disabled brief tool overrides**. Re-registering built-in tools (read/bash/edit/write/find/grep/ls) replaced Pi's superior native renderers (syntax highlighting, diff views, full file content) with inferior custom `fullRender()` output, and caused `renderCall`/`renderResult` to duplicate path/command info. The file is retained for reference; re-enable by uncommenting one line in `register.ts`.
|
|
20
|
+
|
|
21
|
+
### Test Fixes
|
|
22
|
+
- **`39d1dc7`** — `AnimatedMascot` timing tests were flaky under CI load. The animation advances via `setInterval(20ms)` which is `unref()`'d; under `--test-concurrency=4` the unref'd timers get delayed, so a fixed 70ms wait wasn't always enough for one tick. Replaced fixed waits with polling loops (retry until the frame advances, up to 600ms). Applied to both cat and armin animation tests. Robust: finishes fast normally (~40ms), tolerates heavy load.
|
|
23
|
+
|
|
24
|
+
### Features (UI)
|
|
25
|
+
- **`a7b703b`** — `parseStreamingProgress()` parses `tasks completed=N running=M` and `N/M done` formats from streaming progress text; `renderScanBar()` renders an animated bouncing bar for the indeterminate "starting" phase.
|
|
26
|
+
- **`9b1de38`** — `onRunStarted` now called in the async path of `run.ts` (was only in foreground path), so background runs attach the progress binder and show real-time progress instead of stuck "starting".
|
|
27
|
+
- **`5741d73`** — `formatCompactToolProgress` always includes the `tasks N/M done status=X` line even when an active agent is present (was skipped via `else if` bug).
|
|
28
|
+
- **`22d8132`** — `extractContentText` returns only the LAST text block (was `.join("\n")` on all blocks, causing stacked progress frames during streaming).
|
|
29
|
+
- **`3777fbc`** — `buildFrameTop()` / `buildFrameBottom()` split rendering so `renderCall` + `renderResult` merge into one connected frame; `borderFromContext(ctx)` keeps top and bottom border colors consistent (accent while running, green on success, red on error).
|
|
30
|
+
- **`9fa5153`** — Cost display in collapsed cards (`computeTotalCost()`), `⌘E` expand hint, agent briefs with duration/tokens, `shortenPath()` (`$HOME` → `~`), OSC 8 clickable paths (`linkPath()`).
|
|
31
|
+
- **`f9c9803`** — Frame width auto-adjusts to terminal via `process.stdout.columns`.
|
|
32
|
+
|
|
33
|
+
### Stats
|
|
34
|
+
- 9 commits since v0.6.3
|
|
35
|
+
- CI green on Ubuntu, macOS, and Windows
|
|
36
|
+
|
|
3
37
|
## [0.6.3] — Cross-Platform CI, 87 Test Fixes, Worktree Validation, Heartbeat & Crash Fixes (2026-06-12)
|
|
4
38
|
|
|
5
39
|
### Highlights
|
package/README.md
CHANGED
|
@@ -9,7 +9,18 @@ npm: pi-crew
|
|
|
9
9
|
repo: https://github.com/baphuongna/pi-crew
|
|
10
10
|
```
|
|
11
11
|
|
|
12
|
-
**v0.6.
|
|
12
|
+
**v0.6.4**: See [CHANGELOG.md](CHANGELOG.md).
|
|
13
|
+
|
|
14
|
+
### Highlights (v0.6.3 → v0.6.4)
|
|
15
|
+
|
|
16
|
+
- **Visually rich tool rendering** — `team` and `Agent` tool calls now render as framed cards in the Pi TUI with box-drawing borders, colored status badges, and structured layouts
|
|
17
|
+
- **Merged call+result into ONE connected frame** — the call header and result body now form a single seamless frame instead of two disconnected boxes
|
|
18
|
+
- **Animated live progress bar during runs** — real-time `████░░░░ N/M` task progress with elapsed time, rendered DURING the run; indeterminate "starting" phase uses an animated scanning bar
|
|
19
|
+
- **Compact completion summary** — collapsed cards show `✓ crew run 3/3 done · 1m2s · 26k tok · $0.068` with expand hint and per-agent briefs
|
|
20
|
+
- **Critical crash fix on session resume** — `renderCall` was returning a `string` instead of a `Text` component, causing `TypeError: child.render is not a function` when Pi re-rendered stored tool calls
|
|
21
|
+
- **Disabled brief tool overrides** — reverted the experimental brief mode that replaced Pi's superior native renderers (syntax highlighting, diff views, full content)
|
|
22
|
+
- **Flaky test fix** — `AnimatedMascot` timing tests made CI-load-robust via polling loops
|
|
23
|
+
- **CI green** — 0 failures on Ubuntu, macOS, and Windows
|
|
13
24
|
|
|
14
25
|
### Highlights (v0.6.2 → v0.6.3)
|
|
15
26
|
|
|
@@ -0,0 +1,447 @@
|
|
|
1
|
+
# pi-crew UI Optimization & Beautification Plan
|
|
2
|
+
|
|
3
|
+
> Based on deep analysis of oh-my-pi patterns + pi-crew current UI state.
|
|
4
|
+
> Date: 2026-06-12
|
|
5
|
+
> Status: Draft — awaiting approval
|
|
6
|
+
|
|
7
|
+
## Current State
|
|
8
|
+
|
|
9
|
+
### pi-crew UI (~7,800 lines across 45 files)
|
|
10
|
+
|
|
11
|
+
| Component | Lines | Status |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| `run-snapshot-cache.ts` | 827 | Complex, over-engineered |
|
|
14
|
+
| `settings-overlay.ts` | 723 | Functional |
|
|
15
|
+
| `crew-widget.ts` | 544 | **High complexity, hard to read** |
|
|
16
|
+
| `run-dashboard.ts` | 536 | Dense, many responsibilities |
|
|
17
|
+
| `mascot.ts` | 444 | Cute but bloated |
|
|
18
|
+
| `tool-render.ts` | 380 | **Needs pattern overhaul** |
|
|
19
|
+
| `theme-adapter.ts` | 190 | Defensive but verbose |
|
|
20
|
+
|
|
21
|
+
### Key Problems
|
|
22
|
+
|
|
23
|
+
1. **No theme color consistency** — `CrewThemeColor` has ~22 slots vs oh-my-pi's 40+
|
|
24
|
+
2. **Tool rendering reimplements logic** — pi-brief's delegate-execute pattern is cleaner
|
|
25
|
+
3. **Widget is monolithic** — 544 lines doing state management, rendering, caching, and formatting
|
|
26
|
+
4. **No structured interaction** — `respond` action is free-text only; no `ask_user`-style schema
|
|
27
|
+
5. **Raw ANSI codes in places** — mixing `theme.fg()` with `\x1b[38;5;2m`
|
|
28
|
+
6. **No brief/compact mode** — all output is verbose, no toggle for condensed display
|
|
29
|
+
7. **Checkpoint display is text-heavy** — run history shows full text vs compact stats
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Phase 1: Theme System Upgrade
|
|
34
|
+
|
|
35
|
+
**Priority**: HIGH — foundation for all other UI work
|
|
36
|
+
**Effort**: 2-3 days
|
|
37
|
+
**Risk**: LOW (additive changes, no breaking API)
|
|
38
|
+
|
|
39
|
+
### 1.1 Expand Theme Color Slots
|
|
40
|
+
|
|
41
|
+
**Current** (`src/ui/theme-adapter.ts`):
|
|
42
|
+
```typescript
|
|
43
|
+
export type CrewThemeColor =
|
|
44
|
+
| "accent" | "border" | "borderAccent" | "borderMuted"
|
|
45
|
+
| "success" | "error" | "warning" | "muted" | "dim" | "text"
|
|
46
|
+
| "toolDiffAdded" | "toolDiffRemoved" | "toolDiffContext"
|
|
47
|
+
| "syntaxKeyword" | "syntaxString" | "syntaxNumber"
|
|
48
|
+
| "syntaxComment" | "syntaxFunction" | "syntaxVariable"
|
|
49
|
+
| "syntaxType" | "syntaxOperator" | "syntaxPunctuation"
|
|
50
|
+
| "mdCodeBlock";
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**Target** — add from oh-my-pi's 40+ slots:
|
|
54
|
+
```typescript
|
|
55
|
+
export type CrewThemeColor =
|
|
56
|
+
// Existing (keep)
|
|
57
|
+
| "accent" | "border" | "borderAccent" | "borderMuted"
|
|
58
|
+
| "success" | "error" | "warning" | "muted" | "dim" | "text"
|
|
59
|
+
| "toolDiffAdded" | "toolDiffRemoved" | "toolDiffContext"
|
|
60
|
+
| "syntaxKeyword" | "syntaxString" | "syntaxNumber"
|
|
61
|
+
| "syntaxComment" | "syntaxFunction" | "syntaxVariable"
|
|
62
|
+
| "syntaxType" | "syntaxOperator" | "syntaxPunctuation"
|
|
63
|
+
| "mdCodeBlock"
|
|
64
|
+
// NEW — message display
|
|
65
|
+
| "userMessageText" | "customMessageLabel"
|
|
66
|
+
// NEW — tool rendering
|
|
67
|
+
| "toolTitle" // already used in tool-render.ts but missing from type
|
|
68
|
+
| "toolOutput"
|
|
69
|
+
| "toolPending" | "toolSuccess" | "toolError"
|
|
70
|
+
// NEW — markdown
|
|
71
|
+
| "mdHeading" | "mdLink" | "mdCode" | "mdQuote" | "mdHr" | "mdListBullet"
|
|
72
|
+
// NEW — thinking gradient (6 levels)
|
|
73
|
+
| "thinkingOff" | "thinkingMinimal" | "thinkingLow"
|
|
74
|
+
| "thinkingMedium" | "thinkingHigh" | "thinkingXhigh"
|
|
75
|
+
// NEW — special
|
|
76
|
+
| "bashMode" | "thinkingText";
|
|
77
|
+
|
|
78
|
+
export type CrewThemeBg =
|
|
79
|
+
// Existing
|
|
80
|
+
| "selectedBg" | "userMessageBg" | "toolPendingBg" | "toolSuccessBg" | "toolErrorBg"
|
|
81
|
+
// NEW
|
|
82
|
+
| "customMessageBg";
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
**Files to change**: `src/ui/theme-adapter.ts`
|
|
86
|
+
|
|
87
|
+
### 1.2 Theme Color Fallback Map
|
|
88
|
+
|
|
89
|
+
Add default ANSI values for all new slots so widgets work even with minimal themes:
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
const THEME_FALLBACKS: Record<CrewThemeColor, string> = {
|
|
93
|
+
toolTitle: "\x1b[36m", // cyan
|
|
94
|
+
toolOutput: "\x1b[38;5;245m", // gray
|
|
95
|
+
toolPending: "\x1b[38;5;240m",
|
|
96
|
+
toolSuccess: "\x1b[32m",
|
|
97
|
+
toolError: "\x1b[31m",
|
|
98
|
+
mdHeading: "\x1b[33m", // yellow
|
|
99
|
+
mdLink: "\x1b[35m", // indigo
|
|
100
|
+
mdCode: "\x1b[32m", // green
|
|
101
|
+
// ... all new slots
|
|
102
|
+
};
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### 1.3 Remove Raw ANSI from Business Logic
|
|
106
|
+
|
|
107
|
+
Find and replace all raw `\x1b[38;5;XXXm` in non-UI files with `theme.fg("slot", text)` calls.
|
|
108
|
+
|
|
109
|
+
**Files to audit**:
|
|
110
|
+
- `src/ui/tool-render.ts` — check for raw ANSI
|
|
111
|
+
- `src/extension/registration/commands.ts` — status line rendering
|
|
112
|
+
- `src/runtime/task-display.ts` — display formatting
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Phase 2: Tool Rendering Overhaul
|
|
117
|
+
|
|
118
|
+
**Priority**: HIGH — visible improvement to every tool call display
|
|
119
|
+
**Effort**: 2-3 days
|
|
120
|
+
**Risk**: MEDIUM (changes how tool calls look)
|
|
121
|
+
|
|
122
|
+
### 2.1 Adopt Rendering-Only Override Pattern
|
|
123
|
+
|
|
124
|
+
**From oh-my-pi's pi-brief**: Register tool rendering that delegates execution to original.
|
|
125
|
+
|
|
126
|
+
**Current pi-crew approach** (`src/ui/tool-render.ts`):
|
|
127
|
+
- 380 lines of monolithic rendering functions
|
|
128
|
+
- Separate `renderTeamToolCall`, `renderAgentToolCall`, `renderTeamToolResult`, `renderAgentToolResult`
|
|
129
|
+
- Each function handles both collapsed and expanded mode internally
|
|
130
|
+
|
|
131
|
+
**Target**: Split into focused renderers using a registry pattern:
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
// src/ui/tool-renderers/index.ts
|
|
135
|
+
export interface ToolRenderer {
|
|
136
|
+
renderCall(args: unknown, theme: CrewTheme, expanded: boolean): Component;
|
|
137
|
+
renderResult(result: unknown, theme: CrewTheme, expanded: boolean): Component;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// src/ui/tool-renderers/team-renderer.ts
|
|
141
|
+
export const teamToolRenderer: ToolRenderer = {
|
|
142
|
+
renderCall(args, theme, expanded) { ... },
|
|
143
|
+
renderResult(result, theme, expanded) { ... },
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
// src/ui/tool-renderers/agent-renderer.ts
|
|
147
|
+
export const agentToolRenderer: ToolRenderer = { ... };
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### 2.2 Compact Brief Mode for Tool Output
|
|
151
|
+
|
|
152
|
+
**From pi-brief**: Add a configurable "brief" toggle that shows one-line summaries.
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
// New: src/ui/tool-renderers/brief-mode.ts
|
|
156
|
+
export function briefResult(result: ToolResult, theme: CrewTheme): string {
|
|
157
|
+
// read → "→ 142 lines"
|
|
158
|
+
// bash → "→ done" or "→ 12 lines"
|
|
159
|
+
// edit → "→ edited +3 -1"
|
|
160
|
+
// write → "→ written"
|
|
161
|
+
// team → "→ 3/3 tasks · 1.2m · 45k tok"
|
|
162
|
+
// agent → "✓ explorer · 8 tools · 23.4s"
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Add `/crew-brief on|off` command and persist state via `pi.appendEntry()`.
|
|
167
|
+
|
|
168
|
+
### 2.3 Team Tool Result — Compact Stats Display
|
|
169
|
+
|
|
170
|
+
**From pi-rewind's checkpoint display**: Show goal + task stats in one line.
|
|
171
|
+
|
|
172
|
+
**Current**:
|
|
173
|
+
```
|
|
174
|
+
team action='run' (implementation) · status=completed · runId=team_2026... · goal="Investigate failing..."
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
**Target** (compact):
|
|
178
|
+
```
|
|
179
|
+
✓ team/implementation · 3/3 tasks · 1.2m · ↑45k ↓12k · $0.042
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
With expanded (Ctrl+O):
|
|
183
|
+
```
|
|
184
|
+
✓ team/implementation · 3/3 tasks · 1.2m · ↑45k ↓12k · $0.042
|
|
185
|
+
├─ ✓ explorer · 8 tools · 23.4s · ↑12k ↓4k
|
|
186
|
+
├─ ✓ executor · 15 tools · 41.2s · ↑22k ↓6k
|
|
187
|
+
└─ ✓ verifier · 5 tools · 12.1s · ↑11k ↓2k
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## Phase 3: Widget Refactor
|
|
193
|
+
|
|
194
|
+
**Priority**: MEDIUM — internal cleanup, same visual output
|
|
195
|
+
**Effort**: 3-4 days
|
|
196
|
+
**Risk**: MEDIUM (core display component)
|
|
197
|
+
|
|
198
|
+
### 3.1 Split crew-widget.ts into Modules
|
|
199
|
+
|
|
200
|
+
**Current**: 544 lines monolith doing everything.
|
|
201
|
+
|
|
202
|
+
**Target structure**:
|
|
203
|
+
```
|
|
204
|
+
src/ui/widget/
|
|
205
|
+
├── index.ts # Public API: updateCrewWidget, stopCrewWidget
|
|
206
|
+
├── widget-component.ts # CrewWidgetComponent class (~100 lines)
|
|
207
|
+
├── widget-model.ts # Data fetching + caching (~100 lines)
|
|
208
|
+
├── widget-renderer.ts # Line building + colorizing (~150 lines)
|
|
209
|
+
├── widget-formatters.ts # formatTokens, formatDuration, agentStats (~100 lines)
|
|
210
|
+
└── widget-types.ts # Shared types
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### 3.2 Adopt SessionStateMap Pattern
|
|
214
|
+
|
|
215
|
+
**From oh-my-pi**: Generic session-scoped state container instead of scattered maps.
|
|
216
|
+
|
|
217
|
+
```typescript
|
|
218
|
+
// src/state/session-state-map.ts (new)
|
|
219
|
+
export class SessionStateMap<T> {
|
|
220
|
+
private map = new Map<string, T>();
|
|
221
|
+
getOrUndefined(sessionId: string): T | undefined { ... }
|
|
222
|
+
set(sessionId: string, value: T): void { ... }
|
|
223
|
+
delete(sessionId: string): void { ... }
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
Use this in widget, dashboard, and live-agent-manager instead of separate `Map<string, ...>` instances.
|
|
228
|
+
|
|
229
|
+
### 3.3 Render Coalescing Optimization
|
|
230
|
+
|
|
231
|
+
The widget currently rebuilds signature strings on every render call. Optimize:
|
|
232
|
+
- Pre-compute signatures when data changes, not on render
|
|
233
|
+
- Use a simple counter-based invalidation instead of string concatenation
|
|
234
|
+
- Eliminate `this.cacheSignature` string comparison in hot path
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## Phase 4: Dashboard Polish
|
|
239
|
+
|
|
240
|
+
**Priority**: MEDIUM
|
|
241
|
+
**Effort**: 3-4 days
|
|
242
|
+
**Risk**: LOW
|
|
243
|
+
|
|
244
|
+
### 4.1 Run History — Compact Checkpoint Style
|
|
245
|
+
|
|
246
|
+
**From pi-rewind**: Show runs with file-change statistics.
|
|
247
|
+
|
|
248
|
+
**Current** (status command output):
|
|
249
|
+
```
|
|
250
|
+
Run: team_20260612100313...
|
|
251
|
+
Status: completed
|
|
252
|
+
Team: implementation
|
|
253
|
+
Goal: Fix failing tests
|
|
254
|
+
Tasks: 3/3
|
|
255
|
+
Duration: 5m23s
|
|
256
|
+
Tokens: 45.2k
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
**Target** (compact):
|
|
260
|
+
```
|
|
261
|
+
✓ team_...3d7f implementation · Fix failing tests
|
|
262
|
+
3/3 tasks · 5m23s · ↑45k ↓12k
|
|
263
|
+
14 files +342 -87
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### 4.2 Agent Progress — Thinking Level Visualization
|
|
267
|
+
|
|
268
|
+
**From oh-my-pi's thinking gradient**: Show thinking intensity with color gradient.
|
|
269
|
+
|
|
270
|
+
```typescript
|
|
271
|
+
function thinkingColor(level: number, theme: CrewTheme): CrewThemeColor {
|
|
272
|
+
// level 0-5 → off, minimal, low, medium, high, xhigh
|
|
273
|
+
return ["thinkingOff", "thinkingMinimal", "thinkingLow",
|
|
274
|
+
"thinkingMedium", "thinkingHigh", "thinkingXhigh"][level];
|
|
275
|
+
}
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
Apply to agent activity line when agent is "thinking..." (no tool call, just LLM processing).
|
|
279
|
+
|
|
280
|
+
### 4.3 Dashboard Pane Improvements
|
|
281
|
+
|
|
282
|
+
**Agents pane**: Add compact/expanded toggle per agent
|
|
283
|
+
**Progress pane**: Use brief mode rendering from Phase 2
|
|
284
|
+
**Mailbox pane**: Add structured response schema option
|
|
285
|
+
**Health pane**: Color-code issues by severity
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
## Phase 5: Structured Interaction
|
|
290
|
+
|
|
291
|
+
**Priority**: MEDIUM
|
|
292
|
+
**Effort**: 4-5 days
|
|
293
|
+
**Risk**: MEDIUM (new feature)
|
|
294
|
+
|
|
295
|
+
### 5.1 Structured Respond Action
|
|
296
|
+
|
|
297
|
+
**From pi-clarify**: Add schema validation to `respond` action.
|
|
298
|
+
|
|
299
|
+
```typescript
|
|
300
|
+
// In team-tool/respond.ts
|
|
301
|
+
interface RespondOptions {
|
|
302
|
+
message: string;
|
|
303
|
+
// NEW: structured answer option
|
|
304
|
+
answer?: {
|
|
305
|
+
type: "select" | "text" | "confirm";
|
|
306
|
+
value: string | boolean;
|
|
307
|
+
label?: string;
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### 5.2 Secret Rejection in Tool Inputs
|
|
313
|
+
|
|
314
|
+
**From pi-clarify's SECRET_WORDS**: Add to all tool inputs that accept user text.
|
|
315
|
+
|
|
316
|
+
```typescript
|
|
317
|
+
const SECRET_PATTERNS = [
|
|
318
|
+
"api key", "apikey", "auth token", "cookie", "credential",
|
|
319
|
+
"password", "private key", "secret", "token",
|
|
320
|
+
];
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
Already partially done in `env-filter.ts`, but should extend to `goal`, `message`, `task` parameters.
|
|
324
|
+
|
|
325
|
+
---
|
|
326
|
+
|
|
327
|
+
## Phase 6: Code Quality from oh-my-pi
|
|
328
|
+
|
|
329
|
+
**Priority**: LOW-MEDIUM (foundation for long-term)
|
|
330
|
+
**Effort**: 2-3 days
|
|
331
|
+
**Risk**: LOW
|
|
332
|
+
|
|
333
|
+
### 6.1 Type Guard Library
|
|
334
|
+
|
|
335
|
+
**From runtime-core**: Create `src/utils/guards.ts` with systematic type guards.
|
|
336
|
+
|
|
337
|
+
```typescript
|
|
338
|
+
// src/utils/guards.ts
|
|
339
|
+
export function isRecord(value: unknown): value is Record<string, unknown> { ... }
|
|
340
|
+
export function isString(value: unknown): value is string { ... }
|
|
341
|
+
export function isNumber(value: unknown): value is number { ... }
|
|
342
|
+
export function isNonEmptyString(value: unknown): value is string { ... }
|
|
343
|
+
export function isArrayOf<T>(guard: (v: unknown) => v is T): (v: unknown) => v is readonly T[] { ... }
|
|
344
|
+
export function getStringField(value: unknown, key: string): string | undefined { ... }
|
|
345
|
+
export function getNumberField(value: unknown, key: number): number | undefined { ... }
|
|
346
|
+
export function errorMessage(err: unknown): string { ... }
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
Replace scattered `typeof x === "string"` checks across codebase.
|
|
350
|
+
|
|
351
|
+
### 6.2 No-Any Lint Rule
|
|
352
|
+
|
|
353
|
+
Add ESLint rule to enforce `unknown` over `any`:
|
|
354
|
+
|
|
355
|
+
```javascript
|
|
356
|
+
// .eslintrc
|
|
357
|
+
{
|
|
358
|
+
"rules": {
|
|
359
|
+
"@typescript-eslint/no-explicit-any": "error",
|
|
360
|
+
"@typescript-eslint/no-unsafe-assignment": "error",
|
|
361
|
+
"@typescript-eslint/no-unsafe-call": "error"
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
### 6.3 mkdir-Based Locking (Optional)
|
|
367
|
+
|
|
368
|
+
**From pi-checkpoint**: Replace JSON token-based locks with `mkdir` atomic locks.
|
|
369
|
+
|
|
370
|
+
This is a bigger change — could be Phase 7 if needed.
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
374
|
+
## Implementation Order & Timeline
|
|
375
|
+
|
|
376
|
+
| Phase | Duration | Depends On | Impact |
|
|
377
|
+
|---|---|---|---|
|
|
378
|
+
| **Phase 1**: Theme System | 2-3 days | Nothing | Foundation for all UI |
|
|
379
|
+
| **Phase 2**: Tool Rendering | 2-3 days | Phase 1 | Every tool call looks better |
|
|
380
|
+
| **Phase 3**: Widget Refactor | 3-4 days | Phase 1 | Internal cleanup |
|
|
381
|
+
| **Phase 4**: Dashboard Polish | 3-4 days | Phase 1, 2 | Visible improvement |
|
|
382
|
+
| **Phase 5**: Structured Interaction | 4-5 days | Phase 2 | New feature |
|
|
383
|
+
| **Phase 6**: Code Quality | 2-3 days | Nothing | Long-term maintainability |
|
|
384
|
+
|
|
385
|
+
**Total estimated**: 16-22 days (can parallelize Phase 1+6, Phase 2+3)
|
|
386
|
+
|
|
387
|
+
### Recommended Execution
|
|
388
|
+
|
|
389
|
+
```
|
|
390
|
+
Week 1: Phase 1 (Theme) + Phase 6 (Code Quality) [parallel]
|
|
391
|
+
Week 2: Phase 2 (Tool Rendering)
|
|
392
|
+
Week 3: Phase 3 (Widget) + Phase 4 (Dashboard) [sequential]
|
|
393
|
+
Week 4: Phase 5 (Structured Interaction) + polish
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
---
|
|
397
|
+
|
|
398
|
+
## Success Metrics
|
|
399
|
+
|
|
400
|
+
| Metric | Current | Target |
|
|
401
|
+
|---|---|---|
|
|
402
|
+
| Theme color slots | 22 | 40+ |
|
|
403
|
+
| Raw ANSI in business logic | ~15 instances | 0 |
|
|
404
|
+
| Widget lines of code | 544 | ~150 (per module) |
|
|
405
|
+
| Tool result compact display | N/A | All 7 tool types |
|
|
406
|
+
| Structured respond | Free text only | Schema-validated |
|
|
407
|
+
| `any` in production code | ~40 instances | 0 |
|
|
408
|
+
| Type guard reuse | Scattered | Centralized in guards.ts |
|
|
409
|
+
|
|
410
|
+
---
|
|
411
|
+
|
|
412
|
+
## Risks & Mitigations
|
|
413
|
+
|
|
414
|
+
| Risk | Mitigation |
|
|
415
|
+
|---|---|
|
|
416
|
+
| Theme slot additions break existing themes | All new slots have fallback ANSI values |
|
|
417
|
+
| Widget refactor breaks live updates | Keep same public API, refactor internals only |
|
|
418
|
+
| Brief mode confuses users | Default OFF, toggle via `/crew-brief on` |
|
|
419
|
+
| Structured respond breaks existing workflows | `message` field still accepts free text; `answer` is optional |
|
|
420
|
+
| No-any lint produces too many errors | Incremental: start with new files, then expand |
|
|
421
|
+
|
|
422
|
+
---
|
|
423
|
+
|
|
424
|
+
## Files to Create/Modify
|
|
425
|
+
|
|
426
|
+
### New Files
|
|
427
|
+
- `src/ui/tool-renderers/index.ts`
|
|
428
|
+
- `src/ui/tool-renderers/team-renderer.ts`
|
|
429
|
+
- `src/ui/tool-renderers/agent-renderer.ts`
|
|
430
|
+
- `src/ui/tool-renderers/brief-mode.ts`
|
|
431
|
+
- `src/ui/widget/index.ts`
|
|
432
|
+
- `src/ui/widget/widget-component.ts`
|
|
433
|
+
- `src/ui/widget/widget-model.ts`
|
|
434
|
+
- `src/ui/widget/widget-renderer.ts`
|
|
435
|
+
- `src/ui/widget/widget-formatters.ts`
|
|
436
|
+
- `src/ui/widget/widget-types.ts`
|
|
437
|
+
- `src/state/session-state-map.ts`
|
|
438
|
+
- `src/utils/guards.ts`
|
|
439
|
+
|
|
440
|
+
### Modified Files
|
|
441
|
+
- `src/ui/theme-adapter.ts` — expand color types + fallbacks
|
|
442
|
+
- `src/ui/tool-render.ts` — slim down, delegate to renderers
|
|
443
|
+
- `src/ui/crew-widget.ts` — split into widget/ modules
|
|
444
|
+
- `src/ui/run-dashboard.ts` — compact display + thinking gradient
|
|
445
|
+
- `src/ui/status-colors.ts` — add new status colors
|
|
446
|
+
- `src/extension/team-tool/respond.ts` — structured response option
|
|
447
|
+
- `src/extension/registration/commands.ts` — add `/crew-brief` command
|
package/package.json
CHANGED
|
@@ -61,7 +61,7 @@ import {
|
|
|
61
61
|
type CrewWidgetState,
|
|
62
62
|
stopCrewWidget,
|
|
63
63
|
updateCrewWidget,
|
|
64
|
-
} from "../ui/
|
|
64
|
+
} from "../ui/widget/index.ts";
|
|
65
65
|
import { summarizeHeartbeats } from "../ui/heartbeat-aggregator.ts";
|
|
66
66
|
import {
|
|
67
67
|
requestRender,
|
|
@@ -100,6 +100,7 @@ import {
|
|
|
100
100
|
import { createJsonlSink, type NotificationSink } from "./notification-sink.ts";
|
|
101
101
|
import { runArtifactCleanup } from "./registration/artifact-cleanup.ts";
|
|
102
102
|
import { registerTeamCommands } from "./registration/commands.ts";
|
|
103
|
+
import { registerBriefToolOverrides } from "./registration/brief-tool-overrides.ts";
|
|
103
104
|
import { registerCompactionGuard } from "./registration/compaction-guard.ts";
|
|
104
105
|
import {
|
|
105
106
|
__test__subagentSpawnParams,
|
|
@@ -1194,6 +1195,17 @@ export function registerPiTeams(pi: ExtensionAPI): void {
|
|
|
1194
1195
|
|
|
1195
1196
|
pi.on("session_start", (_event, ctx) => {
|
|
1196
1197
|
runArtifactCleanup(ctx.cwd);
|
|
1198
|
+
|
|
1199
|
+
// Restore brief mode state from session entries
|
|
1200
|
+
try {
|
|
1201
|
+
const entries = ctx.sessionManager?.getEntries?.();
|
|
1202
|
+
if (entries) {
|
|
1203
|
+
import("../ui/tool-renderers/brief-mode.ts").then(({ restoreBriefState }) => {
|
|
1204
|
+
restoreBriefState(entries);
|
|
1205
|
+
}).catch(() => {/* non-critical */});
|
|
1206
|
+
}
|
|
1207
|
+
} catch { /* non-critical */ }
|
|
1208
|
+
|
|
1197
1209
|
time("register.session-start");
|
|
1198
1210
|
cleanedUp = false;
|
|
1199
1211
|
sessionGeneration++;
|
|
@@ -1974,6 +1986,12 @@ export function registerPiTeams(pi: ExtensionAPI): void {
|
|
|
1974
1986
|
|
|
1975
1987
|
registerCleanupHandler(pi);
|
|
1976
1988
|
|
|
1989
|
+
// Brief tool overrides DISABLED: re-registering built-in tools replaced Pi's
|
|
1990
|
+
// superior native renderers (syntax highlighting, diff views, full file
|
|
1991
|
+
// content) with inferior custom ones, and caused renderCall/renderResult
|
|
1992
|
+
// to duplicate path/command info. Pi's native rendering is better.
|
|
1993
|
+
// To re-enable, uncomment: registerBriefToolOverrides(pi, process.cwd());
|
|
1994
|
+
|
|
1977
1995
|
registerTeamCommands(pi, {
|
|
1978
1996
|
startForegroundRun,
|
|
1979
1997
|
abortForegroundRun,
|