pi-crew 0.10.6 → 0.11.0
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 +99 -0
- package/dist/index.mjs +34850 -34889
- package/package.json +170 -169
- package/scripts/watch-agent-transcript.mjs +120 -0
- package/src/extension/crew-input-router.ts +2 -0
- package/src/extension/crew-vibes/config.ts +1 -56
- package/src/extension/crew-vibes/figures.ts +5 -84
- package/src/extension/crew-vibes/font-detect.ts +1 -1
- package/src/extension/crew-vibes/index.ts +36 -328
- package/src/extension/crew-vibes/render.ts +2 -58
- package/src/extension/help.ts +1 -0
- package/src/extension/registration/command-registration.ts +5 -1
- package/src/extension/registration/commands/schedules.ts +212 -0
- package/src/extension/registration/commands/shared.ts +56 -1
- package/src/extension/registration/lifecycle-handlers.ts +16 -2
- package/src/extension/registration/schedule-toast-bridge.ts +109 -0
- package/src/extension/registration/viewers.ts +66 -1
- package/src/extension/team-tool/handle-schedule.ts +120 -1
- package/src/runtime/scheduling/scheduler.ts +120 -6
- package/src/runtime/settings-store.ts +28 -2
- package/src/state/coordination/locks.ts +17 -2
- package/src/ui/agents-jobs-browser.ts +785 -0
- package/src/ui/dashboard-panes/agents-pane.ts +7 -4
- package/src/ui/dashboard-panes/schedules-pane.ts +154 -0
- package/src/ui/inline-panel/crew-editor.ts +19 -6
- package/src/ui/inline-panel/index.ts +6 -0
- package/src/ui/key-utils.ts +3 -0
- package/src/ui/keybinding-map.ts +56 -2
- package/src/ui/mascot.ts +2 -1
- package/src/ui/overlays/agent-picker-overlay.ts +3 -3
- package/src/ui/overlays/confirm-overlay.ts +3 -2
- package/src/ui/overlays/mailbox-compose-overlay.ts +4 -3
- package/src/ui/overlays/mailbox-detail-overlay.ts +3 -3
- package/src/ui/run-dashboard.ts +257 -6
- package/src/ui/settings-overlay.ts +3 -3
- package/src/ui/transcript-viewer.ts +3 -2
- package/src/ui/widget/index.ts +61 -88
- package/src/ui/widget/widget-formatters.ts +7 -4
- package/src/ui/widget/widget-renderer.ts +134 -174
- package/src/ui/widget/widget-types.ts +0 -7
- package/src/utils/relative-time.ts +33 -0
- package/src/extension/crew-vibes/footer.ts +0 -313
- package/src/extension/crew-vibes/speed.ts +0 -286
- package/src/ui/dock-footer.ts +0 -49
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,105 @@
|
|
|
2
2
|
|
|
3
3
|
> **Note:** `atomic-write-v2.ts` / `AtomicWriter` mentioned in historical entries below was consolidated into `atomic-write.ts` as of v0.9.42. This changelog is preserved as historical record — the migration was completed (the v2 class was never adopted; v1 won on simplicity + symlink-safety + link+unlink atomicity). See `docs/migration/atomic-write-v2-migration.md` for the decision rationale.
|
|
4
4
|
|
|
5
|
+
## [0.11.0] — Scheduled Jobs UI + Agents & Jobs browser + kitty CSI-u hardening (2026-09-15)
|
|
6
|
+
|
|
7
|
+
### feat(ui): Agents & Jobs browser — the crew widget's ↓+Enter popup
|
|
8
|
+
|
|
9
|
+
- The crew widget is now ONE screen line (`Crew agents 3/5 · 1 running · 24m · ↓·enter`); pressing `↓` or Enter opens the Agents & Jobs browser — a framed modal (border box with live counts in the top frame, key hints in the bottom frame) listing every widget-visible agent and scheduled job from the SAME data source as the widget counts (`activeWidgetRuns()` over `.crew/state/runs/*/agents.json` + `recordTokPerSec()` usage snapshots), so the browser and the widget can never disagree.
|
|
10
|
+
- Agent rows show role/status/duration/tok-per-sec live; job rows show cron/interval + next run. Focus modes cycle Agents → Jobs; jobs keep their inline detail view.
|
|
11
|
+
- Pressing Enter on an agent row opens the full transcript overlay (`DurableTranscriptViewer` — the same experience as `/crew transcript`). For RUNNING agents the transcript path resolves through a 3-tier fallback (record.transcriptPath → status.json → artifacts-root `transcripts/<taskId>.attempt-N.jsonl` convention), because records only carry the path after completion.
|
|
12
|
+
- The legacy `p` key (spawn a mux pane tailing the watcher-formatted log) is retired: a log tail is not a real pi session. The retired code stays as commented blocks for a future "focus the existing surface pane" key.
|
|
13
|
+
|
|
14
|
+
### feat(agents): live surface panes — watch a worker's REAL pi TUI
|
|
15
|
+
|
|
16
|
+
- New `runtime.surface` config (`~/.pi/agent/pi-crew.json`): `{ mode: "herdr" | "tmux", visibleAgents: ["agent", ...] }` boots eligible workers inside a real mux pane running the pi TUI (the worker's `--mode json -p` args are stripped for the pane) — watch the worker's actual footer/model/widget live instead of log tails. The pane closes itself when the worker finishes; resume is never used (resuming would kill the subagent).
|
|
17
|
+
- Surface spawns emit `worker.surface_spawned` (+ `surfacePaneId` on `worker.started`); gate rejections emit `worker.surface_gate_blocked` with the reason. Async workers forward TERM/HERDR_*/mux env into the child.
|
|
18
|
+
|
|
19
|
+
### fix(ui): kitty CSI-u hardening — matchesKey everywhere
|
|
20
|
+
|
|
21
|
+
- Every overlay now routes Enter/Escape through `@earendil-works/pi-tui`'s `matchesKey` instead of raw byte compare: kitty's disambiguate-codes protocol sends `\x1b[13u`/`\x1b[27u`, so raw `\r`/`\x1b` compares silently swallowed keys. Sweep covered the agents browser, confirm, agent-picker, mailbox detail, mailbox compose, live-conversation overlays, transcript viewer, mascot, and settings overlay (backspace ×2).
|
|
22
|
+
- `src/ui/key-utils.ts` re-exports `matchesKey` for overlays that cannot import pi-tui directly.
|
|
23
|
+
|
|
24
|
+
### fix(ci-windows): the two real flakes behind windows-latest failures
|
|
25
|
+
|
|
26
|
+
- Broker integration helpers compressed EVERY client timer to 100ms (intent: only the 1s hello deadline) — the 15s request timeout and the explicit 2s escalate budget fired before slow NTFS durable writes could land, nondeterministically killing clients with fallback-sticky `request-timeout` (broadcast/DM/escalate tests). Timers ≤1s compress; real request budgets stay real.
|
|
27
|
+
- `O_CREAT|O_EXCL` against a `.flock` held mid-create by another process surfaces as EPERM/EBUSY (not EEXIST) on Windows — both lock retry loops now treat EPERM/EBUSY as contention (deadline still bounds the wait). Fixes the ST-3 cross-process flock EPERM crash.
|
|
28
|
+
- Also in this release: `npm run lint` (biome) added to the pre-push gate — three unused members left by the p retirement had slipped past a tsc+format-only gate.
|
|
29
|
+
|
|
30
|
+
### Scheduled Jobs UI (tiers A/C/D/E — previously unreleased)
|
|
31
|
+
|
|
32
|
+
### feat(vibes): tok/s speed UI REMOVED — pi's built-in working indicator always used
|
|
33
|
+
|
|
34
|
+
- Maintainer decision: the entire speed subsystem is deleted, not toggled off — custom spinner frames (`setWorkingIndicator`), the `Working N tok/s` message (`setWorkingMessage`), SpeedTracker/SpeedAnimator, the speed config block, and every speed event handler (agent_start/turn_start/message_*/turn_end/agent_end wiring). crew-vibes is now a single-purpose module: fetch the provider rate-limit quota and publish it as a status entry on pi's native footer. `/team-vibes` shrinks to `[on|off]`.
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
### feat(footer): restore pi's NATIVE footer — custom footer replacement retired (UI-review option 1)
|
|
38
|
+
|
|
39
|
+
- Maintainer decision: the crew-vibes custom footer (setFooter replacement that re-implemented pi's pwd/stats/status lines to guarantee the quota a never-truncated line) is REMOVED — pi's built-in footer is always shown. The re-implementation had drifted from native (missing `CH%` cache-hit, missing `xp` segment, totals ignoring toolResult/branch-summary/compaction usage, hardcoded `(auto)`), and composing pi's native FooterComponent is impossible by design (extensions only receive ReadonlySessionManager, not AgentSession).
|
|
40
|
+
- Provider quota (`z.ai 5h ━ 37% 46m Wk …`) now publishes through `ctx.ui.setStatus` and joins pi's native status line (right-truncates on very narrow terminals — accepted).
|
|
41
|
+
- The crew widget ALWAYS renders through pi's widget slots now (`bottom` placement maps to belowEditor): FooterDockHost, the dock-footer registry, slotInstalled/dockedInFooter state, and WidgetRenderOptions.noSchedulesLine are deleted. The ⏰ schedules line and all run rows paint in the belowEditor slot exactly as the pre-footer design; the keep-alive fix is preserved.
|
|
42
|
+
- Clock-injection sweep (D6-T4) in the render path: compactDockLines/detailed rows/agents-pane now pin ONE clock per render (options.now / options.nowMs) threaded into orderWidgetAgents, dockUsageText, agentStats, computeLiveDurationMs — no more scattered Date.now() reads that could straddle a tick.
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
### feat(footer): retire the capacity stage meter; the ⏰ schedules segment takes its slot
|
|
46
|
+
|
|
47
|
+
- Maintainer decision after the full UI review: the capacity meter (context token count `74k` + `○ Orbit/Cruise/Warp/…` stage glyph) duplicated the context percent already shown on the stats line and carried no actionable signal — removed from the footer composition (`renderCapacity` remains exported for its unit tests).
|
|
48
|
+
- The meter line now carries the Tier-C schedules segment on the LEFT (`⏰ N sched · next …`) with the provider quota right-aligned on the SAME line (wraps to two lines only on narrow terminals). Net effect: one screen line saved — the schedules line no longer paints as its own dock line when the crew-vibes footer is active.
|
|
49
|
+
- `CrewWidgetModel.dockedInFooter` + `WidgetRenderOptions.noSchedulesLine`: in the dock path the widget no longer paints `⏰` itself (the footer owns it — no duplicate painter); slot mode (no footer sink) keeps painting it unchanged.
|
|
50
|
+
|
|
51
|
+
### fix(scheduler): cron jobs never fired — arm() had no `cron` branch (P1-1 from UI review)
|
|
52
|
+
|
|
53
|
+
- Root cause of the live "next 7h ago" symptom: `arm()` only handled `interval`/`once`, so cron jobs were persisted with a `nextRun` but never got a timer — silent death. `nextRunTime()`/`nextCronDate` (already in the same file) were simply never wired into arming.
|
|
54
|
+
- `arm()` now arms cron via a chained `setTimeout` hop toward the next occurrence, clamped below the 2^31-1 ms timer ceiling (`MAX_TIMER_DELAY_MS`) so yearly crons cannot mis-fire on overflow; `disarm()` clears the cron handle on the right branch.
|
|
55
|
+
- After each cron fire, `advanceCronNextRun()` recomputes and persists the next occurrence (previously `nextRun` was written exactly once, at job creation); jobs whose next occurrence is not computable self-disable with an `error` event explaining why.
|
|
56
|
+
- Scheduler constructor takes an injectable clock (`now?: () => Date`, default `Date.now`) per the D6-T4 clock-injection convention — cron firing tests run on a fake clock, no real sleeps.
|
|
57
|
+
- New suite `test/unit/runtime/scheduling/scheduler-cron-arm.test.ts` (first fire, re-arm + nextRun advance, mid-flight disable, overflow chaining, disarm) — red on the pre-fix HEAD, green with the fix.
|
|
58
|
+
|
|
59
|
+
### feat(ui): B2 gate hint — "N project-tier jobs hidden" on all three surfaces (P2-1)
|
|
60
|
+
|
|
61
|
+
- The Wave B2 opt-in gate (`schedulingEnabled` + `allowProjectScheduledJobs`, both required in user-tier `~/.pi/crew-settings.json`) was completely invisible: gated-out jobs made every surface fall into the plain empty state, looking like the jobs were lost.
|
|
62
|
+
- New companion getter `getScheduledJobsHiddenCount()` / pure `scheduledJobsHiddenCountOf(tiers)` in `settings-store.ts` (no signature change to `getScheduledJobs`); the paint path reuses the registration-time tiers stash — no new disk reads on render.
|
|
63
|
+
- Schedules pane + `/schedules` (via the shared renderer, parity test kept) append one dim hint line, the widget line appends a compact `· N hidden` — all three surfaces, EN-only per project convention, shown only when hiddenCount > 0.
|
|
64
|
+
|
|
65
|
+
### test: settings-store tests are now hermetic
|
|
66
|
+
|
|
67
|
+
- `loadCrewSettings()` gained an optional `globalFile` param (default unchanged). The three affected tests previously read the developer's REAL `~/.pi/crew-settings.json` ("defaults when file missing" failed the moment that file exists with scheduling flags) — they now pin an absent temp global file.
|
|
68
|
+
|
|
69
|
+
Full Scheduled Jobs UI stack over the existing scheduler/settings layer. No version bump yet — no schema or persistence changes; reads a single provider, mutations go through the existing extension channel.
|
|
70
|
+
|
|
71
|
+
### feat(ui): schedules dashboard pane (tier A)
|
|
72
|
+
|
|
73
|
+
- New pane 8 in the run dashboard (`src/ui/dashboard-panes/schedules-pane.ts`, pure string renderer): one main line per job (enabled glyph ●/○ · name truncate · humanized schedule · relative next-run · last status ✓/✗/⟳ · runCount) plus a sub line (subagentType · lastRun · id in headless mode). Empty state: `No scheduled jobs — create via team tool action='schedule'`.
|
|
74
|
+
- Keys `T/N/V/X/R` (pane-scoped in `keybinding-map.ts`): toggle-enabled, run-now, details toggle (goal + ScheduleSpec + spawnedRunIds), delete with a **2-step confirm-gate** (first X arms + warning line, any other key disarms), refresh (drops the provider cache). Job cursor up/down while pane 8 owns input.
|
|
75
|
+
- Mutations never touch the scheduler from the UI layer: they leave the dashboard only as `done()` selections carrying `schedule-*` actions + `jobId`, routed by `commands/shared.ts openTeamDashboard` through `handleTeamTool({action:'schedule', subAction, jobId})` → `handle-schedule.ts` (the same channel as the chat tool), then the result surfaces as an info/error toast and the dashboard reopens.
|
|
76
|
+
|
|
77
|
+
### feat(ui): schedules line in the crew widget (tier C)
|
|
78
|
+
|
|
79
|
+
- One lowest-priority widget row (`src/ui/widget/widget-renderer.ts`): `⏰ N sched · next Xm` — painted ONLY when ≥1 enabled job exists, always last (below active-run info). The line joins the widget cache signature so add/remove/toggle repaints immediately. Survives the no-runs collapse (scheduled jobs are exactly what runs while nothing interactive is active). One clock read per render feeds both the signature and the painted line.
|
|
80
|
+
|
|
81
|
+
### feat(extension): scheduler event toasts (tier D)
|
|
82
|
+
|
|
83
|
+
- New `schedule-toast-bridge.ts` wired into the scheduler's `emit` in `lifecycle-handlers.ts`: `fired` → `⏰ <name> fired → <agentId>` (info); failures → red. Failure has two producers — the scheduler's synchronous `error` event and the (common) async executor rejection recorded as a `running→error` lastStatus transition — deduped per attempt so one failed attempt = one notice. Success surfaces as `⏰ <name> ✓ succeeded` on a tracked lastStatus transition only (no drip on patches). Bounded like the hung-notice pattern; headless no-ops; all interpolated fields sanitized.
|
|
84
|
+
|
|
85
|
+
### feat(commands): /schedules + /schedules log (tier E, headless-compatible)
|
|
86
|
+
|
|
87
|
+
- New `/schedules` command re-uses the SAME pane renderer (text-block variant — no copied table logic) so command and dashboard can never drift. Natural-language phrases `crew schedule` / `scheduled jobs` rewrite via the crew-input-router.
|
|
88
|
+
- `/schedules log <jobId-or-name>` resolves a job by id or name, tails the most recent output artifact of its latest spawned run (32KB bound, traversal-guarded via `resolveRealContainedPath`; unsafe-charset runIds degrade to an error result). Works under `pi -p` — the handler touches only `ctx.cwd` + `ctx.ui.notify`.
|
|
89
|
+
|
|
90
|
+
### fix(scheduling): run-now on a once job consumes it
|
|
91
|
+
|
|
92
|
+
- `CrewScheduler.runNow()` on a `once` job now self-disables after the forced fire (mirroring the timer-driven path). Previously the still-armed timer would fire the job a SECOND time at its scheduled time — a one-shot executing twice.
|
|
93
|
+
|
|
94
|
+
### Constraints honored
|
|
95
|
+
|
|
96
|
+
- **Single source of truth (G17)** — every consumer (pane, command, widget, autocomplete) reads jobs through one provider `getScheduledJobs()` (scheduler singleton, gated settings-tier fallback). No defaults copies anywhere.
|
|
97
|
+
- **Injectable clock (D6-T4)** — renderers take `now: Date` as a parameter; no `Date.now()` on any render path (pane, widget, command, and the provider TTL timestamp).
|
|
98
|
+
- **Extension channel only** — toggle/run-now/delete dispatch through `handle-schedule.ts` subActions; persisted `scheduledJobs` shape unchanged.
|
|
99
|
+
|
|
100
|
+
### Tests
|
|
101
|
+
|
|
102
|
+
- New: `schedules-pane`, `schedules-dashboard`, `widget-schedules-line`, `relative-time`, `schedules-command`, `schedule-toast-bridge`, `team-tool-schedule-provider`, `scheduler-run-now`, `dashboard-schedule-routing` (155+ assertions across render parity, injected clock, confirm-gate, toast bounds/dedup, traversal guards, once-job run-now regression, shared.ts routing integration).
|
|
103
|
+
|
|
5
104
|
## [0.10.6] — agent/skill resource layer + broker coordination fixes (2026-09-12)
|
|
6
105
|
|
|
7
106
|
### fix(bundle): PACKAGE_SKILLS_DIR resolves via `packageRoot()` instead of broken `import.meta.url` walk-up
|