pi-crew 0.10.6 → 0.11.1

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.
Files changed (88) hide show
  1. package/CHANGELOG.md +215 -0
  2. package/README.md +0 -1
  3. package/dist/index.mjs +30623 -29844
  4. package/package.json +170 -169
  5. package/schema.json +10 -0
  6. package/scripts/watch-agent-transcript.mjs +120 -0
  7. package/skills/real-test-pi-crew/REPORT-TEMPLATE.md +2 -0
  8. package/skills/real-test-pi-crew/SKILL.md +181 -1
  9. package/src/config/config-validation.ts +0 -2
  10. package/src/config/defaults.ts +0 -1
  11. package/src/config/types.ts +0 -5
  12. package/src/extension/crew-input-router.ts +2 -0
  13. package/src/extension/crew-vibes/config.ts +1 -77
  14. package/src/extension/crew-vibes/index.ts +36 -330
  15. package/src/extension/crew-vibes/render.ts +1 -106
  16. package/src/extension/help.ts +1 -2
  17. package/src/extension/register.ts +7 -2
  18. package/src/extension/registration/command-registration.ts +5 -1
  19. package/src/extension/registration/commands/manage.ts +5 -4
  20. package/src/extension/registration/commands/schedules.ts +212 -0
  21. package/src/extension/registration/commands/shared.ts +56 -2
  22. package/src/extension/registration/lifecycle-handlers.ts +16 -2
  23. package/src/extension/registration/schedule-toast-bridge.ts +109 -0
  24. package/src/extension/registration/subagent-tools.ts +16 -6
  25. package/src/extension/registration/team-tool.ts +10 -3
  26. package/src/extension/registration/terminal-status-wiring.ts +172 -0
  27. package/src/extension/registration/viewers.ts +72 -1
  28. package/src/extension/team-tool/handle-schedule.ts +120 -1
  29. package/src/extension/team-tool/handle-settings.ts +14 -2
  30. package/src/runtime/scheduling/scheduler.ts +120 -6
  31. package/src/runtime/settings-store.ts +28 -2
  32. package/src/runtime/task-display.ts +1 -1
  33. package/src/schema/config-schema.ts +4 -0
  34. package/src/state/coordination/locks.ts +17 -2
  35. package/src/ui/adaptive-card.ts +65 -0
  36. package/src/ui/agents-jobs-browser.ts +791 -0
  37. package/src/ui/card-colors.ts +36 -7
  38. package/src/ui/dashboard-panes/agents-pane.ts +52 -17
  39. package/src/ui/dashboard-panes/cancellation-pane.ts +0 -42
  40. package/src/ui/dashboard-panes/health-pane.ts +7 -5
  41. package/src/ui/dashboard-panes/mailbox-pane.ts +22 -6
  42. package/src/ui/dashboard-panes/metrics-pane.ts +15 -7
  43. package/src/ui/dashboard-panes/pane-theme.ts +21 -0
  44. package/src/ui/dashboard-panes/plan-pane.ts +63 -30
  45. package/src/ui/dashboard-panes/progress-pane.ts +3 -2
  46. package/src/ui/dashboard-panes/schedules-pane.ts +177 -0
  47. package/src/ui/dashboard-panes/transcript-pane.ts +11 -5
  48. package/src/ui/dwf-phase-display.ts +3 -20
  49. package/src/ui/format-helpers.ts +22 -0
  50. package/src/ui/inline-panel/crew-editor.ts +32 -9
  51. package/src/ui/inline-panel/index.ts +66 -4
  52. package/src/ui/key-utils.ts +3 -0
  53. package/src/ui/keybinding-map.ts +286 -34
  54. package/src/ui/live-conversation-overlay.ts +176 -46
  55. package/src/ui/live-run-sidebar.ts +134 -55
  56. package/src/ui/mascot.ts +34 -17
  57. package/src/ui/overlays/agent-picker-overlay.ts +81 -26
  58. package/src/ui/overlays/confirm-overlay.ts +55 -28
  59. package/src/ui/overlays/help-overlay.ts +108 -53
  60. package/src/ui/overlays/mailbox-compose-overlay.ts +89 -49
  61. package/src/ui/overlays/mailbox-detail-overlay.ts +137 -57
  62. package/src/ui/powerbar-publisher.ts +0 -1
  63. package/src/ui/rail.ts +333 -0
  64. package/src/ui/run-dashboard.ts +344 -72
  65. package/src/ui/settings-overlay.ts +84 -42
  66. package/src/ui/terminal-status.ts +7 -1
  67. package/src/ui/theme-adapter.ts +0 -45
  68. package/src/ui/theme-discovery.ts +12 -6
  69. package/src/ui/tool-progress-formatter.ts +126 -8
  70. package/src/ui/tool-renderers/brief-mode.ts +8 -66
  71. package/src/ui/tool-renderers/index.ts +372 -521
  72. package/src/ui/transcript-viewer.ts +33 -14
  73. package/src/ui/widget/index.ts +86 -133
  74. package/src/ui/widget/task-list.ts +64 -32
  75. package/src/ui/widget/widget-formatters.ts +3 -399
  76. package/src/ui/widget/widget-model.ts +28 -7
  77. package/src/ui/widget/widget-renderer.ts +298 -265
  78. package/src/ui/widget/widget-types.ts +0 -9
  79. package/src/utils/relative-time.ts +33 -0
  80. package/src/utils/visual.ts +0 -4
  81. package/src/extension/crew-vibes/figures.ts +0 -101
  82. package/src/extension/crew-vibes/font-detect.ts +0 -71
  83. package/src/extension/crew-vibes/footer.ts +0 -313
  84. package/src/extension/crew-vibes/speed.ts +0 -286
  85. package/src/ui/dock-footer.ts +0 -49
  86. package/src/ui/dynamic-border.ts +0 -35
  87. package/src/ui/loaders.ts +0 -6
  88. package/src/ui/overlay-stack.ts +0 -148
@@ -47,6 +47,6 @@ export function formatTaskGraphLines(tasks: TeamTaskState[]): string[] {
47
47
  ? "⚠"
48
48
  : "◦";
49
49
  const wait = waitingReason(task, tasks);
50
- return `- ${icon} ${task.id} [${task.status}] ${task.role}->${task.agent}${wait && wait !== "ready" ? ` (${wait})` : ""}`;
50
+ return `- ${icon} ${task.id} [${task.status}] ${task.role}▸${task.agent}${wait && wait !== "ready" ? ` (${wait})` : ""}`;
51
51
  });
52
52
  }
@@ -298,6 +298,10 @@ export const PiTeamsUiConfigSchema = Type.Object(
298
298
  {
299
299
  widgetPlacement: Type.Optional(Type.Union([Type.Literal("aboveEditor"), Type.Literal("belowEditor"), Type.Literal("bottom")])),
300
300
  widgetMaxLines: Type.Optional(Type.Integer({ minimum: 1, maximum: 50 })),
301
+ /** Inline panel (editor-wrapper agent rows). M1-9/P1-8: parsed + read
302
+ * (src/ui/inline-panel/index.ts) + defaulted (true), but absent from this
303
+ * schema → same unknown-key warning. */
304
+ inlinePanel: Type.Optional(Type.Boolean()),
301
305
  powerbar: Type.Optional(Type.Boolean()),
302
306
  dashboardPlacement: Type.Optional(Type.Union([Type.Literal("center"), Type.Literal("right")])),
303
307
  dashboardWidth: Type.Optional(Type.Integer({ minimum: 32, maximum: 120 })),
@@ -307,6 +307,21 @@ function releaseLock(filePath: string, token: string): void {
307
307
  // (probably stale and overtaken). Do not touch it — the new holder owns it.
308
308
  }
309
309
 
310
+ /**
311
+ * Error codes that mean "the lock file exists / is momentarily un-creatable
312
+ * because another process holds it" rather than "something is broken".
313
+ *
314
+ * EEXIST is the POSIX O_CREAT|O_EXCL loser signal. On Windows (libuv),
315
+ * CREATE_NEW against a file that another process has open mid-create can
316
+ * surface as EPERM (ERROR_ACCESS_DENIED) or EBUSY instead of EEXIST —
317
+ * observed on the windows-latest CI runner (ST-3 cross-process flock test).
318
+ * Retrying these is correct: the holder always closes/releases within the
319
+ * stale-deadline budget, and the deadline still bounds the wait.
320
+ */
321
+ function isLockContention(code: string | undefined): boolean {
322
+ return code === "EEXIST" || code === "EPERM" || code === "EBUSY";
323
+ }
324
+
310
325
  function acquireLockWithRetry(filePath: string, staleMs: number, kind: LockKind = "file"): string {
311
326
  let attempt = 0;
312
327
  const deadline = Date.now() + staleMs * 2;
@@ -317,7 +332,7 @@ function acquireLockWithRetry(filePath: string, staleMs: number, kind: LockKind
317
332
  return token;
318
333
  } catch (error) {
319
334
  const code = (error as NodeJS.ErrnoException).code;
320
- if (code !== "EEXIST") throw error;
335
+ if (!isLockContention(code)) throw error;
321
336
  if (Date.now() > deadline) {
322
337
  throw new Error(`Run '${path.basename(filePath)}' is locked by another operation.`);
323
338
  }
@@ -355,7 +370,7 @@ async function acquireLockWithRetryAsync(filePath: string, staleMs: number, kind
355
370
  return token;
356
371
  } catch (error) {
357
372
  const code = (error as NodeJS.ErrnoException).code;
358
- if (code !== "EEXIST") throw error;
373
+ if (!isLockContention(code)) throw error;
359
374
  if (Date.now() > deadline) {
360
375
  throw new Error(`Run '${path.basename(filePath)}' is locked by another operation.`);
361
376
  }
@@ -0,0 +1,65 @@
1
+ /**
2
+ * AdaptiveCard — a width-deferred card component (R2, 2026-09-16).
3
+ *
4
+ * Problem it fixes: pi-crew's tool-renderer cards used to be BUILT as a
5
+ * pre-formatted string at a guessed width (`ctx.width || process.stdout.columns
6
+ * || 116`) and handed to `new Text(...)`. Pi's ToolRenderContext carries NO
7
+ * width field — neither the TUI nor export-html pass one — so the guess could
8
+ * never match the real render column. `Text.render(width)` WRAPS lines wider
9
+ * than the column, which tore the box frame apart (top border split mid-line,
10
+ * right border vanished). This hit HTML export hardest: export renders every
11
+ * card at width=100 while a non-TTY export process builds at the 116 fallback.
12
+ *
13
+ * Design: build the frame at RENDER time, at the width the caller actually
14
+ * provides. The card receives a `builder(width) => string`; `render(width)`
15
+ * invokes it and delegates line-wrapping/padding to a zero-padding `Text`.
16
+ * Results are cached per width (mirroring Text's own cache) so repeated
17
+ * renders of an unchanged card cost nothing.
18
+ *
19
+ * Fail-visible: a builder exception surfaces as a red `✖ card render error`
20
+ * line instead of propagating into the TUI render loop (which has no per-
21
+ * component catch). Construction-time errors in the ToolRenderer wrappers
22
+ * keep their own catch — this is the third and final layer.
23
+ */
24
+
25
+ import { Text } from "@earendil-works/pi-tui";
26
+ import type { CrewComponent } from "./component.ts";
27
+
28
+ export class AdaptiveCard implements CrewComponent {
29
+ #builder: (width: number) => string;
30
+ #errorStyle: (text: string) => string;
31
+ #text = new Text("", 0, 0);
32
+ #cachedWidth: number | undefined;
33
+ #cachedLines: string[] | null = null;
34
+
35
+ /**
36
+ * @param builder produces the full card text (frame included) for a width.
37
+ * Must keep every line within `width` visual columns — the same contract
38
+ * the old fixed-width builders already obeyed for their baked width.
39
+ * @param errorStyle theme.fg("error", …) adapter for the fail-visible line.
40
+ */
41
+ constructor(builder: (width: number) => string, errorStyle: (text: string) => string = (t) => t) {
42
+ this.#builder = builder;
43
+ this.#errorStyle = errorStyle;
44
+ }
45
+
46
+ invalidate(): void {
47
+ this.#cachedLines = null;
48
+ this.#cachedWidth = undefined;
49
+ }
50
+
51
+ render(width: number): string[] {
52
+ if (this.#cachedLines !== null && this.#cachedWidth === width) return this.#cachedLines;
53
+ let text: string;
54
+ try {
55
+ text = this.#builder(width);
56
+ } catch (e) {
57
+ const msg = e instanceof Error ? e.message : String(e);
58
+ text = this.#errorStyle(`✖ card render error: ${msg.slice(0, 60)}`);
59
+ }
60
+ this.#text.setText(text);
61
+ this.#cachedLines = this.#text.render(width);
62
+ this.#cachedWidth = width;
63
+ return this.#cachedLines;
64
+ }
65
+ }