@posthog/wizard 2.60.0 → 2.62.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.
Files changed (106) hide show
  1. package/dist/{add-mcp-server-to-clients-CM30npkB.js → add-mcp-server-to-clients-Bzl7_wB3.js} +190 -60
  2. package/dist/add-mcp-server-to-clients-Bzl7_wB3.js.map +1 -0
  3. package/dist/{agent-interface-CybBFwnk.js → agent-interface-C90hyvs1.js} +7 -7
  4. package/dist/{agent-interface-CybBFwnk.js.map → agent-interface-C90hyvs1.js.map} +1 -1
  5. package/dist/{agent-prompt-loader-DL32ioJX.js → agent-prompt-loader-CBj2DWAJ.js} +38 -11
  6. package/dist/agent-prompt-loader-CBj2DWAJ.js.map +1 -0
  7. package/dist/{agent-runner-DUyxA1TQ.js → agent-runner-DA5YfjOD.js} +147 -24
  8. package/dist/agent-runner-DA5YfjOD.js.map +1 -0
  9. package/dist/{analytics-B9V7x1Ma.js → analytics-BdKBzz4M.js} +2 -2
  10. package/dist/{analytics-B9V7x1Ma.js.map → analytics-BdKBzz4M.js.map} +1 -1
  11. package/dist/analytics-CijpxQFN.js +2 -0
  12. package/dist/{api-OHLXhKTy.js → api-aTkzJ9vG.js} +3 -3
  13. package/dist/{api-OHLXhKTy.js.map → api-aTkzJ9vG.js.map} +1 -1
  14. package/dist/bin.js +288 -134
  15. package/dist/bin.js.map +1 -1
  16. package/dist/{bounded-fs-xkhfF3JS.js → bounded-fs-BU2L5mjO.js} +3 -3
  17. package/dist/{bounded-fs-xkhfF3JS.js.map → bounded-fs-BU2L5mjO.js.map} +1 -1
  18. package/dist/{ci-install-B31ciXo4.js → ci-install-BnTAUOz8.js} +4 -4
  19. package/dist/{ci-install-B31ciXo4.js.map → ci-install-BnTAUOz8.js.map} +1 -1
  20. package/dist/{debug-D3Ucw2y1.js → debug-BTPYy9p7.js} +10 -4
  21. package/dist/debug-BTPYy9p7.js.map +1 -0
  22. package/dist/{debug-Cx9Delbc.js → debug-D2L-fM_I.js} +1 -1
  23. package/dist/{defaults-BWLIffh5.js → defaults-mrAre0xM.js} +28 -2
  24. package/dist/defaults-mrAre0xM.js.map +1 -0
  25. package/dist/{environment-BN8ROaHv.js → environment-lV2X1gS-.js} +4 -4
  26. package/dist/{environment-BN8ROaHv.js.map → environment-lV2X1gS-.js.map} +1 -1
  27. package/dist/{file-watcher-CzBnjben.js → file-watcher-qqQBl5Em.js} +2 -2
  28. package/dist/{file-watcher-CzBnjben.js.map → file-watcher-qqQBl5Em.js.map} +1 -1
  29. package/dist/{headless-ui-DoQlIoeh.js → headless-ui-TSoOsa3j.js} +2 -2
  30. package/dist/{headless-ui-DoQlIoeh.js.map → headless-ui-TSoOsa3j.js.map} +1 -1
  31. package/dist/{interactive-DeFFwXME.js → interactive-DMoXEiKo.js} +2 -2
  32. package/dist/{interactive-DeFFwXME.js.map → interactive-DMoXEiKo.js.map} +1 -1
  33. package/dist/{mcp-CBskrEsK.js → mcp-Dqu0_QzN.js} +2 -2
  34. package/dist/{mcp-CBskrEsK.js.map → mcp-Dqu0_QzN.js.map} +1 -1
  35. package/dist/{mcp-prompt-streaming-B1upRE9N.js → mcp-prompt-streaming-B4cYVDVP.js} +3 -3
  36. package/dist/{mcp-prompt-streaming-B1upRE9N.js.map → mcp-prompt-streaming-B4cYVDVP.js.map} +1 -1
  37. package/dist/{non-interactive-BUmW9f9P.js → non-interactive-EG_lII4R.js} +2 -2
  38. package/dist/{non-interactive-BUmW9f9P.js.map → non-interactive-EG_lII4R.js.map} +1 -1
  39. package/dist/{orchestrator-tools-bM9GOq3c.js → orchestrator-tools-DrhpNOKK.js} +3 -3
  40. package/dist/{orchestrator-tools-bM9GOq3c.js.map → orchestrator-tools-DrhpNOKK.js.map} +1 -1
  41. package/dist/{package-manager-ByVEmFPR.js → package-manager-z33XHEWO.js} +2 -2
  42. package/dist/{package-manager-ByVEmFPR.js.map → package-manager-z33XHEWO.js.map} +1 -1
  43. package/dist/{pi-C7wbP2z-.js → pi-CVJB0Ban.js} +11 -11
  44. package/dist/{pi-C7wbP2z-.js.map → pi-CVJB0Ban.js.map} +1 -1
  45. package/dist/{playground-Df_ZzalF.js → playground-BjWqoWhf.js} +25 -788
  46. package/dist/playground-BjWqoWhf.js.map +1 -0
  47. package/dist/{posthog-DLklk2yT.js → posthog-3ijs_66W.js} +2 -2
  48. package/dist/{posthog-DLklk2yT.js.map → posthog-3ijs_66W.js.map} +1 -1
  49. package/dist/{posthog-integration-CxIj49T4.js → posthog-integration-C3wuB5B1.js} +110 -33
  50. package/dist/posthog-integration-C3wuB5B1.js.map +1 -0
  51. package/dist/{provisioning-BpqrbURn.js → provisioning-IKacrvWB.js} +3 -3
  52. package/dist/{provisioning-BpqrbURn.js.map → provisioning-IKacrvWB.js.map} +1 -1
  53. package/dist/{queue-tools-QVKYMX_C.js → queue-tools-zM8_mxx6.js} +39 -8
  54. package/dist/queue-tools-zM8_mxx6.js.map +1 -0
  55. package/dist/{registry-CboWk-Ny.js → registry-DF_aKyS0.js} +5 -5
  56. package/dist/{registry-CboWk-Ny.js.map → registry-DF_aKyS0.js.map} +1 -1
  57. package/dist/{security-aWRzd8V1.js → security-CVFKNYBn.js} +5 -5
  58. package/dist/{security-aWRzd8V1.js.map → security-CVFKNYBn.js.map} +1 -1
  59. package/dist/{setup-utils-VtxhrSx8.js → setup-utils-iINkc0xu.js} +9 -9
  60. package/dist/setup-utils-iINkc0xu.js.map +1 -0
  61. package/dist/{start-tui-CzMiitZJ.js → start-tui-CjtL-ls7.js} +137 -42
  62. package/dist/start-tui-CjtL-ls7.js.map +1 -0
  63. package/dist/{steps-9PddZ-BV.js → steps-DzUGHdfY.js} +7 -7
  64. package/dist/{steps-9PddZ-BV.js.map → steps-DzUGHdfY.js.map} +1 -1
  65. package/dist/{store-V71P5KpB.js → store-DtckpbSC.js} +25 -5
  66. package/dist/store-DtckpbSC.js.map +1 -0
  67. package/dist/{subagent-CcBKBSR-.js → subagent-cD_bF490.js} +2 -2
  68. package/dist/{subagent-CcBKBSR-.js.map → subagent-cD_bF490.js.map} +1 -1
  69. package/dist/{task-BRktXvCV.js → task-eIt2iATF.js} +36 -23
  70. package/dist/task-eIt2iATF.js.map +1 -0
  71. package/dist/{task-stream-CFAXlJLv.js → task-stream-DGBUveUD.js} +5 -5
  72. package/dist/{task-stream-CFAXlJLv.js.map → task-stream-DGBUveUD.js.map} +1 -1
  73. package/dist/{tasks-CyLSHCmC.js → tasks-wQ3V6Ft6.js} +2 -2
  74. package/dist/{tasks-CyLSHCmC.js.map → tasks-wQ3V6Ft6.js.map} +1 -1
  75. package/dist/{telemetry-mi4dua6_.js → telemetry-BWYDFAwf.js} +3 -3
  76. package/dist/{telemetry-mi4dua6_.js.map → telemetry-BWYDFAwf.js.map} +1 -1
  77. package/dist/{terminal-B-37htZb.js → terminal-yKJZx1UC.js} +978 -71
  78. package/dist/terminal-yKJZx1UC.js.map +1 -0
  79. package/dist/{tools-BWaoKBAO.js → tools-CDlaJb_e.js} +6 -6
  80. package/dist/{tools-BWaoKBAO.js.map → tools-CDlaJb_e.js.map} +1 -1
  81. package/dist/{wizard-abort-D0HFMYCV.js → wizard-abort-Cjk5z73h.js} +1 -1
  82. package/dist/{wizard-abort-Bgx_JOfw.js → wizard-abort-CztG5WTv.js} +4 -4
  83. package/dist/{wizard-abort-Bgx_JOfw.js.map → wizard-abort-CztG5WTv.js.map} +1 -1
  84. package/dist/{wizard-session-CwgR5y3-.js → wizard-session-BUhlJ1b8.js} +2 -1
  85. package/dist/wizard-session-BUhlJ1b8.js.map +1 -0
  86. package/dist/{wizard-session-DsK16SGs.js → wizard-session-DZUDtS5d.js} +1 -1
  87. package/dist/yara-hooks-DVGKhwaz.js +2 -0
  88. package/dist/{yara-hooks-Cj8x2YV4.js → yara-hooks-DeLjTIiJ.js} +4 -4
  89. package/dist/{yara-hooks-Cj8x2YV4.js.map → yara-hooks-DeLjTIiJ.js.map} +1 -1
  90. package/package.json +2 -1
  91. package/dist/add-mcp-server-to-clients-CM30npkB.js.map +0 -1
  92. package/dist/agent-prompt-loader-DL32ioJX.js.map +0 -1
  93. package/dist/agent-runner-DUyxA1TQ.js.map +0 -1
  94. package/dist/analytics-HdW5e8_o.js +0 -2
  95. package/dist/debug-D3Ucw2y1.js.map +0 -1
  96. package/dist/defaults-BWLIffh5.js.map +0 -1
  97. package/dist/playground-Df_ZzalF.js.map +0 -1
  98. package/dist/posthog-integration-CxIj49T4.js.map +0 -1
  99. package/dist/queue-tools-QVKYMX_C.js.map +0 -1
  100. package/dist/setup-utils-VtxhrSx8.js.map +0 -1
  101. package/dist/start-tui-CzMiitZJ.js.map +0 -1
  102. package/dist/store-V71P5KpB.js.map +0 -1
  103. package/dist/task-BRktXvCV.js.map +0 -1
  104. package/dist/terminal-B-37htZb.js.map +0 -1
  105. package/dist/wizard-session-CwgR5y3-.js.map +0 -1
  106. package/dist/yara-hooks-CIQRywtg.js +0 -2
@@ -1,14 +1,14 @@
1
- import { ht as VERSION, l as WIZARD_LOG_FILE, v as getBlockingServiceKeys } from "./debug-D3Ucw2y1.js";
2
- import { s as HostResolution } from "./setup-utils-VtxhrSx8.js";
3
- import "./wizard-session-CwgR5y3-.js";
4
- import { h as Icons, m as Colors } from "./posthog-integration-CxIj49T4.js";
5
- import { T as getContentBlocks, d as PROGRAM_REGISTRY, o as ConfirmButton, p as getProgramConfig, t as PickerMenu } from "./bin.js";
6
- import { t as WizardStore } from "./store-V71P5KpB.js";
7
- import { A as LogViewer, C as TipsCard, D as TabContainer, E as HNViewer, F as GroupedPickerMenu, I as ProgressList, L as LoadingBox, N as ModalOverlay, O as ScreenContainer, P as ConfirmationInput, R as SplitView, S as ServiceHealthList, T as ContentSequencer, _ as TAILORED_ROLES, c as SlackConnectScreen, d as AuditChecksViewer, h as assembleProfile, k as EventPlanViewer, l as AUDIT_AREA_SLIDES, m as McpSuggestedPromptsScreen, n as releaseTerminal, o as OutroScreen, p as seededProfile, r as AiOptInRequiredScreen, t as enterDarkTerminal, v as McpScreen, w as LearnCard, y as IssueTable, z as CardLayout } from "./terminal-B-37htZb.js";
1
+ import { gt as VERSION, l as WIZARD_LOG_FILE, v as getBlockingServiceKeys } from "./debug-BTPYy9p7.js";
2
+ import { s as HostResolution } from "./setup-utils-iINkc0xu.js";
3
+ import "./wizard-session-BUhlJ1b8.js";
4
+ import { h as Icons, m as Colors } from "./posthog-integration-C3wuB5B1.js";
5
+ import { O as getContentBlocks, d as PROGRAM_REGISTRY, o as ConfirmButton, p as getProgramConfig, t as PickerMenu } from "./bin.js";
6
+ import { t as WizardStore } from "./store-DtckpbSC.js";
7
+ import { A as EventPlanViewer, B as CardLayout, C as VisualizerTab, D as HNViewer, E as ContentSequencer, F as ConfirmationInput, I as GroupedPickerMenu, L as ProgressList, O as TabContainer, P as ModalOverlay, R as LoadingBox, S as ServiceHealthList, T as LearnCard, _ as TAILORED_ROLES, c as SlackConnectScreen, d as AuditChecksViewer, h as assembleProfile, j as LogViewer, k as ScreenContainer, l as AUDIT_AREA_SLIDES, m as McpSuggestedPromptsScreen, n as releaseTerminal, o as OutroScreen, p as seededProfile, r as AiOptInRequiredScreen, t as enterDarkTerminal, v as McpScreen, w as TipsCard, y as IssueTable, z as SplitView } from "./terminal-yKJZx1UC.js";
8
8
  import * as fs$1 from "fs";
9
9
  import * as path$1 from "path";
10
10
  import * as os from "os";
11
- import { Box, Text, measureElement, render, useInput } from "ink";
11
+ import { Box, Text, render, useInput } from "ink";
12
12
  import { createElement, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
13
13
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
14
14
  //#region src/ui/tui/playground/demos/WelcomeDemo.tsx
@@ -485,782 +485,6 @@ const LogDemo = () => {
485
485
  });
486
486
  };
487
487
  //#endregion
488
- //#region src/ui/tui/hooks/useTick.ts
489
- /**
490
- * useTick — forces a re-render every `intervalMs`. Returns a monotonically
491
- * increasing counter, which is rarely needed — most callers just want the
492
- * re-render side effect.
493
- */
494
- function useTick(intervalMs) {
495
- const [tick, setTick] = useState(0);
496
- useEffect(() => {
497
- const id = setInterval(() => setTick((t) => t + 1), intervalMs);
498
- return () => clearInterval(id);
499
- }, [intervalMs]);
500
- return tick;
501
- }
502
- //#endregion
503
- //#region src/ui/tui/components/visualizer/palette.ts
504
- const VISUALIZER_PALETTE = {
505
- fade: "#0E7A0E",
506
- bright: "#7CFF7C",
507
- mid: "#22D622",
508
- head: "#E6FFE6",
509
- book: [
510
- "#22D622",
511
- "#7CFF7C",
512
- "#5BE05B",
513
- "#A0F0A0",
514
- "#36B536"
515
- ],
516
- deleteRed: "#D63B22",
517
- upGreen: "#7CFF7C"
518
- };
519
- //#endregion
520
- //#region src/ui/tui/components/visualizer/panel.tsx
521
- /**
522
- * Shared scaffolding for the phase visuals — Matrix-green color, common
523
- * VisualProps shape, and the rounded `Panel` shell every visual sits in.
524
- *
525
- * Visuals each render their own grid then wrap it in `<Panel>` so phase
526
- * transitions stay visually continuous.
527
- */
528
- const MATRIX_FADE = VISUALIZER_PALETTE.fade;
529
- const Panel = ({ children }) => /* @__PURE__ */ jsx(Box, {
530
- flexDirection: "column",
531
- borderStyle: "round",
532
- borderColor: MATRIX_FADE,
533
- children
534
- });
535
- //#endregion
536
- //#region src/ui/tui/components/visualizer/MatrixRain.tsx
537
- /**
538
- * MatrixRain — code-rain visual used for the codebase-scan phase.
539
- *
540
- * Independent of the phase orchestrator so it can be reused elsewhere
541
- * (e.g. standalone in a demo). `bordered` toggles the rounded green frame.
542
- */
543
- const { head: MATRIX_HEAD, bright: MATRIX_BRIGHT, mid: MATRIX_MID } = VISUALIZER_PALETTE;
544
- const DEFAULT_TICK_MS = 110;
545
- const DEFAULT_MAX_TAIL = 7;
546
- const RAIN_GLYPHS = "ヲァィゥェォャュョッアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン0123456789Z<>=*+:.";
547
- function pickGlyph() {
548
- return RAIN_GLYPHS[Math.floor(Math.random() * 73)];
549
- }
550
- function makeRainColumn(height, maxTail) {
551
- return {
552
- headY: -Math.random() * height,
553
- speed: .3 + Math.random() * .9,
554
- tail: 3 + Math.floor(Math.random() * (maxTail - 2)),
555
- glyphs: /* @__PURE__ */ new Map(),
556
- dormant: Math.floor(Math.random() * 18)
557
- };
558
- }
559
- function tickRainColumn(col, height, maxTail) {
560
- if (col.dormant > 0) return {
561
- ...col,
562
- dormant: col.dormant - 1
563
- };
564
- const next = col.headY + col.speed;
565
- if (next > height + col.tail) return makeRainColumn(height, maxTail);
566
- const glyphs = new Map(col.glyphs);
567
- for (let y = Math.max(0, Math.ceil(col.headY)); y <= Math.min(Math.floor(next), height - 1); y++) glyphs.set(y, pickGlyph());
568
- if (glyphs.size > 0 && Math.random() < .22) {
569
- const keys = [...glyphs.keys()];
570
- const k = keys[Math.floor(Math.random() * keys.length)];
571
- glyphs.set(k, pickGlyph());
572
- }
573
- return {
574
- ...col,
575
- headY: next,
576
- glyphs
577
- };
578
- }
579
- const MatrixRain = ({ width, height, tickMs = DEFAULT_TICK_MS, maxTail = DEFAULT_MAX_TAIL, bordered = true }) => {
580
- const columnsRef = useRef(Array.from({ length: width }, () => makeRainColumn(height, maxTail)));
581
- const [, setTick] = useState(0);
582
- useEffect(() => {
583
- const interval = setInterval(() => {
584
- columnsRef.current = columnsRef.current.map((c) => tickRainColumn(c, height, maxTail));
585
- setTick((t) => t + 1);
586
- }, tickMs);
587
- return () => clearInterval(interval);
588
- }, [
589
- height,
590
- maxTail,
591
- tickMs
592
- ]);
593
- const columns = columnsRef.current;
594
- const body = Array.from({ length: height }).map((_, y) => /* @__PURE__ */ jsx(Box, { children: columns.map((col, x) => {
595
- const glyph = col.glyphs.get(y);
596
- if (!glyph) return /* @__PURE__ */ jsx(Text, { children: " " }, x);
597
- const dist = col.headY - y;
598
- if (dist < 0 || dist > col.tail) return /* @__PURE__ */ jsx(Text, { children: " " }, x);
599
- if (dist < 1) return /* @__PURE__ */ jsx(Text, {
600
- bold: true,
601
- color: MATRIX_HEAD,
602
- children: glyph
603
- }, x);
604
- if (dist < 2) return /* @__PURE__ */ jsx(Text, {
605
- color: MATRIX_BRIGHT,
606
- children: glyph
607
- }, x);
608
- if (dist < col.tail * .55) return /* @__PURE__ */ jsx(Text, {
609
- color: MATRIX_MID,
610
- children: glyph
611
- }, x);
612
- return /* @__PURE__ */ jsx(Text, {
613
- color: MATRIX_FADE,
614
- dimColor: true,
615
- children: glyph
616
- }, x);
617
- }) }, y));
618
- if (!bordered) return /* @__PURE__ */ jsx(Box, {
619
- flexDirection: "column",
620
- children: body
621
- });
622
- return /* @__PURE__ */ jsx(Box, {
623
- flexDirection: "column",
624
- borderStyle: "round",
625
- borderColor: MATRIX_FADE,
626
- children: body
627
- });
628
- };
629
- //#endregion
630
- //#region src/ui/tui/components/visualizer/LibraryShelf.tsx
631
- /**
632
- * LibraryShelf — skill-selection phase.
633
- *
634
- * A row of book spines. One spine peels forward each cycle, the chosen
635
- * title hovers next to it, then it slides home and the next one is picked.
636
- */
637
- const BOOK_LABELS = [
638
- "nx",
639
- "rt",
640
- "sv",
641
- "fl",
642
- "jg",
643
- "rb",
644
- "go",
645
- "dj",
646
- "fa",
647
- "lv",
648
- "ts",
649
- "py"
650
- ];
651
- const BOOK_COLORS = VISUALIZER_PALETTE.book;
652
- const LibraryShelf = ({ width, height }) => {
653
- const tick = useTick(380);
654
- const bookCount = Math.min(Math.floor((width - 2) / 2), BOOK_LABELS.length);
655
- const cyclePos = tick % (bookCount * 4);
656
- const selectedIdx = Math.floor(cyclePos / 4);
657
- const phase = cyclePos % 4;
658
- const offset = phase === 0 ? 0 : phase === 1 ? 1 : phase === 2 ? 2 : 1;
659
- const wobble = phase === 2 && tick % 2 === 0 ? 1 : 0;
660
- const shelfY = Math.floor(height / 2) - 1;
661
- const rows = Array.from({ length: height }, () => new Array(width).fill(" "));
662
- for (let i = 0; i < bookCount; i++) {
663
- const x = 1 + i * 2;
664
- const isSelected = i === selectedIdx;
665
- const shift = isSelected ? offset : 0;
666
- const wob = isSelected && wobble ? -1 : 0;
667
- if (x + shift >= width) continue;
668
- rows[shelfY - 1][x + shift] = "█";
669
- rows[shelfY][x + shift] = BOOK_LABELS[i][0];
670
- rows[shelfY + 1][x + shift] = BOOK_LABELS[i][1];
671
- rows[shelfY + 2 + wob]?.[x + shift] !== void 0 && (rows[shelfY + 2 + wob][x + shift] = "█");
672
- }
673
- const boardY = shelfY + 3;
674
- if (boardY < height) for (let x = 0; x < width; x++) rows[boardY][x] = "─";
675
- if (phase === 2) {
676
- const labelStartX = 1 + selectedIdx * 2 + 4;
677
- const labelText = BOOK_LABELS[selectedIdx] + "-app";
678
- for (let c = 0; c < labelText.length && labelStartX + c < width; c++) rows[shelfY][labelStartX + c] = labelText[c];
679
- if (labelStartX - 1 < width && labelStartX - 1 >= 0) rows[shelfY][labelStartX - 1] = "▶";
680
- }
681
- return /* @__PURE__ */ jsx(Panel, { children: rows.map((row, y) => /* @__PURE__ */ jsx(Box, { children: row.map((ch, x) => {
682
- if (ch === " ") return /* @__PURE__ */ jsx(Text, { children: " " }, x);
683
- if (ch === "─") return /* @__PURE__ */ jsx(Text, {
684
- color: MATRIX_FADE,
685
- dimColor: true,
686
- children: "─"
687
- }, x);
688
- if (ch === "▶") return /* @__PURE__ */ jsx(Text, {
689
- bold: true,
690
- color: VISUALIZER_PALETTE.head,
691
- children: "▶"
692
- }, x);
693
- const booksColor = BOOK_COLORS[(Math.floor((x - 1) / 2) + 17 * y) % BOOK_COLORS.length];
694
- const isSel = x === 1 + selectedIdx * 2 + offset;
695
- return /* @__PURE__ */ jsx(Text, {
696
- bold: isSel,
697
- color: isSel ? VISUALIZER_PALETTE.head : booksColor,
698
- children: ch
699
- }, x);
700
- }) }, y)) });
701
- };
702
- //#endregion
703
- //#region src/ui/tui/components/visualizer/CrateStack.tsx
704
- /**
705
- * CrateStack — dependency-install phase.
706
- *
707
- * Boxes drop from the top and stack at the bottom. Each new arrival lands
708
- * with a tiny shake.
709
- */
710
- const PACKAGE_NAMES = [
711
- "posthog-js",
712
- "posthog-py",
713
- "posthog-rb",
714
- "posthog-go",
715
- "posthog-node",
716
- "react-ph",
717
- "next-ph",
718
- "svelte-ph",
719
- "ph-mcp",
720
- "ph-ai"
721
- ];
722
- const CRATE_W = Math.max(...PACKAGE_NAMES.map((n) => n.length)) + 2;
723
- const CrateStack = ({ width, height }) => {
724
- const tick = useTick(95);
725
- const state = useRef({
726
- stack: [],
727
- falling: null,
728
- spawnCooldown: 0
729
- }).current;
730
- const crateW = CRATE_W;
731
- const crateH = 1;
732
- const floorY = height - 1;
733
- if (state.falling) {
734
- state.falling.y += 1;
735
- const collisionStackHeight = state.stack.filter((c) => Math.abs(c.x - state.falling.x) < crateW - 1).length * crateH;
736
- if (state.falling.y >= floorY - collisionStackHeight) {
737
- state.stack.push({
738
- label: state.falling.label,
739
- x: state.falling.x,
740
- landedAt: tick
741
- });
742
- state.falling = null;
743
- state.spawnCooldown = 3;
744
- }
745
- } else if (state.spawnCooldown > 0) state.spawnCooldown -= 1;
746
- else if (state.stack.length < Math.floor(height / crateH) - 1) state.falling = {
747
- label: PACKAGE_NAMES[Math.floor(Math.random() * PACKAGE_NAMES.length)],
748
- x: 2 + Math.floor(Math.random() * Math.max(1, width - crateW - 4)),
749
- y: -1
750
- };
751
- else if (tick % 20 === 0) state.stack = [];
752
- const grid = Array.from({ length: height }, () => new Array(width).fill(" "));
753
- const drawCrate = (cx, cy, label, shake) => {
754
- const x = cx + shake;
755
- if (cy < 0 || cy >= height) return;
756
- const padded = `[${label.slice(0, crateW - 2)}]`.padEnd(crateW, " ");
757
- for (let i = 0; i < crateW && x + i < width; i++) if (x + i >= 0) grid[cy][x + i] = padded[i];
758
- };
759
- state.stack.forEach((c, idx) => {
760
- const cy = floorY - idx;
761
- const shake = tick - c.landedAt === 0 ? 1 : tick - c.landedAt === 1 ? -1 : 0;
762
- drawCrate(c.x, cy, c.label, shake);
763
- });
764
- if (state.falling) drawCrate(state.falling.x, state.falling.y, state.falling.label, 0);
765
- return /* @__PURE__ */ jsx(Panel, { children: grid.map((row, y) => /* @__PURE__ */ jsx(Box, { children: row.map((ch, x) => {
766
- if (ch === " ") return /* @__PURE__ */ jsx(Text, { children: " " }, x);
767
- const isFalling = state.falling && y === state.falling.y && Math.abs(x - state.falling.x) < crateW;
768
- return /* @__PURE__ */ jsx(Text, {
769
- bold: isFalling,
770
- color: isFalling ? VISUALIZER_PALETTE.head : VISUALIZER_PALETTE.mid,
771
- children: ch
772
- }, x);
773
- }) }, y)) });
774
- };
775
- //#endregion
776
- //#region src/ui/tui/components/visualizer/DiffCascade.tsx
777
- /**
778
- * DiffCascade — code-edits phase.
779
- *
780
- * + and - code lines scroll upward continuously. Occasional comment-rewrite
781
- * gag: a "// hmm…" line appears, gets - struck out, then a + replaces it.
782
- */
783
- const CODE_SNIPPETS = [
784
- "import posthog from 'posthog-js'",
785
- "posthog.init(KEY, { host: HOST })",
786
- "<PostHogProvider client={posthog}>",
787
- " {children}",
788
- "</PostHogProvider>",
789
- "posthog.capture('page_viewed')",
790
- "posthog.capture('signup_started')",
791
- "posthog.identify(user.id, { email })",
792
- "if (process.env.NODE_ENV !== 'test') posthog.init(KEY)",
793
- "export const posthog = new PostHog(KEY)",
794
- "// TODO: enable replay",
795
- "window.posthog = posthog"
796
- ];
797
- const WHIMSY_COMMENTS = [
798
- "// hmm — that should be a hook",
799
- "// wait, refactor incoming",
800
- "// posthog says hi"
801
- ];
802
- const DiffCascade = ({ width, height }) => {
803
- const tick = useTick(280);
804
- const linesRef = useRef([]);
805
- if (linesRef.current.length === 0) for (let i = 0; i < height; i++) linesRef.current.push({
806
- sign: Math.random() < .75 ? "+" : "-",
807
- text: CODE_SNIPPETS[Math.floor(Math.random() * CODE_SNIPPETS.length)]
808
- });
809
- linesRef.current.shift();
810
- const whimsy = tick % 23 === 0;
811
- linesRef.current.push({
812
- sign: whimsy ? "-" : Math.random() < .78 ? "+" : "-",
813
- text: whimsy ? WHIMSY_COMMENTS[Math.floor(Math.random() * WHIMSY_COMMENTS.length)] : CODE_SNIPPETS[Math.floor(Math.random() * CODE_SNIPPETS.length)]
814
- });
815
- const lines = linesRef.current;
816
- return /* @__PURE__ */ jsx(Panel, { children: Array.from({ length: height }).map((_, y) => {
817
- const line = lines[y];
818
- const cap = width - 2;
819
- const text = `${line.sign} ${line.text}`.slice(0, cap);
820
- return /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Text, {
821
- color: line.sign === "+" ? VISUALIZER_PALETTE.mid : line.sign === "-" ? VISUALIZER_PALETTE.deleteRed : MATRIX_FADE,
822
- children: text.padEnd(cap, " ")
823
- }) }, y);
824
- }) });
825
- };
826
- //#endregion
827
- //#region src/ui/tui/components/visualizer/Tumblers.tsx
828
- /**
829
- * Tumblers — env-setup phase.
830
- *
831
- * Pins fall into a lock cylinder one by one; when all six align the bolt
832
- * pulses green for a beat, then the cycle restarts.
833
- */
834
- const Tumblers = ({ width, height }) => {
835
- const tick = useTick(80);
836
- const pinCount = Math.min(Math.floor((width - 2) / 2), 6);
837
- const state = useRef({
838
- heights: new Array(pinCount).fill(0),
839
- current: 0,
840
- fallY: 0,
841
- pulse: 0
842
- }).current;
843
- const cylinderTop = 1;
844
- const cylinderBottom = height - 2;
845
- const targetForPin = (i) => cylinderBottom - 1 - i % 3 - Math.floor(i / 2);
846
- if (state.pulse > 0) {
847
- state.pulse -= 1;
848
- if (state.pulse === 0) {
849
- state.heights = new Array(pinCount).fill(0);
850
- state.current = 0;
851
- state.fallY = 0;
852
- }
853
- } else if (state.current < pinCount) {
854
- state.fallY += 1;
855
- if (state.fallY >= targetForPin(state.current)) {
856
- state.heights[state.current] = targetForPin(state.current);
857
- state.current += 1;
858
- state.fallY = cylinderTop;
859
- }
860
- } else state.pulse = 14;
861
- const grid = Array.from({ length: height }, () => new Array(width).fill(" "));
862
- for (let y = 0; y < height; y++) {
863
- grid[y][0] = "│";
864
- grid[y][width - 1] = "│";
865
- }
866
- for (let i = 0; i < pinCount; i++) {
867
- const x = 1 + i * 2 + 1;
868
- if (x < width) grid[0][x] = "▼";
869
- }
870
- for (let x = 1; x < width - 1; x++) grid[height - 1][x] = "─";
871
- for (let i = 0; i < pinCount; i++) {
872
- const pinX = 1 + i * 2 + 1;
873
- if (pinX >= width) continue;
874
- const top = state.heights[i] || cylinderTop;
875
- for (let y = top; y <= cylinderBottom; y++) grid[y][pinX] = "█";
876
- }
877
- if (state.pulse === 0 && state.current < pinCount) {
878
- const pinX = 1 + state.current * 2 + 1;
879
- if (pinX < width) grid[state.fallY][pinX] = "█";
880
- }
881
- const pulsing = state.pulse > 0;
882
- const pulseBright = pulsing && tick % 2 === 0;
883
- return /* @__PURE__ */ jsx(Panel, { children: grid.map((row, y) => /* @__PURE__ */ jsx(Box, { children: row.map((ch, x) => {
884
- if (ch === " ") return /* @__PURE__ */ jsx(Text, { children: " " }, x);
885
- if (ch === "│" || ch === "─" || ch === "▼") return /* @__PURE__ */ jsx(Text, {
886
- color: pulsing ? pulseBright ? VISUALIZER_PALETTE.bright : MATRIX_FADE : MATRIX_FADE,
887
- dimColor: !pulsing,
888
- children: ch
889
- }, x);
890
- const isFalling = state.pulse === 0 && state.current < pinCount && y === state.fallY && x === 1 + state.current * 2 + 1;
891
- const color = pulsing ? pulseBright ? VISUALIZER_PALETTE.head : VISUALIZER_PALETTE.bright : isFalling ? VISUALIZER_PALETTE.head : VISUALIZER_PALETTE.mid;
892
- return /* @__PURE__ */ jsx(Text, {
893
- bold: pulsing || isFalling,
894
- color,
895
- children: ch
896
- }, x);
897
- }) }, y)) });
898
- };
899
- //#endregion
900
- //#region src/ui/tui/components/visualizer/DashboardGrid.tsx
901
- /**
902
- * DashboardGrid — dashboards phase.
903
- *
904
- * 2×2 grid of mini-charts to evoke a real PostHog dashboard. When the area
905
- * is too small, the layout collapses to 1×2 or 1×1 so something always
906
- * renders.
907
- */
908
- const DASHBOARD_TILES = [
909
- {
910
- title: "Visitors",
911
- kind: "bars"
912
- },
913
- {
914
- title: "Sessions",
915
- kind: "line"
916
- },
917
- {
918
- title: "Revenue",
919
- kind: "gauge"
920
- },
921
- {
922
- title: "Errors",
923
- kind: "pulse"
924
- }
925
- ];
926
- const SPARK_GLYPHS = "▁▂▃▄▅▆▇█";
927
- const DashboardGrid = ({ width, height }) => {
928
- const tick = useTick(220);
929
- const grid = Array.from({ length: height }, () => new Array(width).fill(" "));
930
- const cols = width >= 22 ? 2 : 1;
931
- const rows = height >= 7 ? 2 : 1;
932
- const vSplit = cols === 2 ? Math.floor(width / 2) : -1;
933
- const hSplit = rows === 2 ? Math.floor(height / 2) : -1;
934
- if (vSplit >= 0) for (let y = 0; y < height; y++) grid[y][vSplit] = "│";
935
- if (hSplit >= 0) {
936
- for (let x = 0; x < width; x++) grid[hSplit][x] = "─";
937
- if (vSplit >= 0) grid[hSplit][vSplit] = "┼";
938
- }
939
- const writeText = (x0, y0, maxW, text) => {
940
- if (y0 < 0 || y0 >= height) return;
941
- const slice = text.slice(0, Math.max(0, maxW));
942
- for (let i = 0; i < slice.length; i++) if (x0 + i >= 0 && x0 + i < width) grid[y0][x0 + i] = slice[i];
943
- };
944
- for (let r = 0; r < rows; r++) for (let c = 0; c < cols; c++) {
945
- const tile = DASHBOARD_TILES[r * cols + c];
946
- const tileX = c === 0 ? 0 : vSplit + 1;
947
- const tileY = r === 0 ? 0 : hSplit + 1;
948
- const tileW = cols === 2 ? c === 0 ? vSplit : width - vSplit - 1 : width;
949
- const tileH = rows === 2 ? r === 0 ? hSplit : height - hSplit - 1 : height;
950
- const innerX = tileX;
951
- const innerW = Math.max(1, tileW);
952
- const titleY = tileY;
953
- const valueY = tileY + tileH - 1;
954
- const chartY0 = tileY + 1;
955
- const chartY1 = Math.max(chartY0, valueY - 1);
956
- const chartH = Math.max(1, chartY1 - chartY0 + 1);
957
- const seed = (r * cols + c) * 13;
958
- writeText(innerX, titleY, innerW, tile.title);
959
- renderTile(grid, tile.kind, innerX, chartY0, innerW, chartH, tick, seed, width);
960
- writeText(innerX, valueY, innerW, tileValue(tile.kind, tick, seed));
961
- }
962
- return /* @__PURE__ */ jsx(Panel, { children: grid.map((row, y) => /* @__PURE__ */ jsx(Box, { children: row.map((ch, x) => {
963
- if (ch === " ") return /* @__PURE__ */ jsx(Text, { children: " " }, x);
964
- if (ch === "│" || ch === "─" || ch === "┼") return /* @__PURE__ */ jsx(Text, {
965
- color: MATRIX_FADE,
966
- dimColor: true,
967
- children: ch
968
- }, x);
969
- if (SPARK_GLYPHS.includes(ch) || ch === "█") return /* @__PURE__ */ jsx(Text, {
970
- color: VISUALIZER_PALETTE.mid,
971
- children: ch
972
- }, x);
973
- if (ch === "●" || ch === "∙" || ch === "·") {
974
- const color = ch === "●" ? VISUALIZER_PALETTE.head : ch === "∙" ? VISUALIZER_PALETTE.bright : VISUALIZER_PALETTE.mid;
975
- return /* @__PURE__ */ jsx(Text, {
976
- bold: ch === "●",
977
- color,
978
- children: ch
979
- }, x);
980
- }
981
- if (ch === "▲" || ch === "▼") return /* @__PURE__ */ jsx(Text, {
982
- bold: true,
983
- color: ch === "▲" ? VISUALIZER_PALETTE.upGreen : VISUALIZER_PALETTE.deleteRed,
984
- children: ch
985
- }, x);
986
- return /* @__PURE__ */ jsx(Text, {
987
- color: VISUALIZER_PALETTE.bright,
988
- children: ch
989
- }, x);
990
- }) }, y)) });
991
- };
992
- function renderTile(grid, kind, x0, y0, w, h, tick, seed, gridW) {
993
- const set = (x, y, ch) => {
994
- if (y < 0 || y >= grid.length) return;
995
- if (x < 0 || x >= gridW) return;
996
- grid[y][x] = ch;
997
- };
998
- if (kind === "bars") for (let i = 0; i < w; i++) {
999
- const t = tick * .18 + (i + seed) * .6;
1000
- const level = .55 + .35 * Math.sin(t) + .1 * Math.sin(t * 2.7);
1001
- const filled = Math.max(0, Math.min(h, Math.round(level * h)));
1002
- for (let j = 0; j < filled; j++) set(x0 + i, y0 + h - 1 - j, "█");
1003
- if (filled > 0 && filled < h) {
1004
- const frac = level * h - Math.floor(level * h);
1005
- const glyph = SPARK_GLYPHS[Math.floor(frac * 7)];
1006
- set(x0 + i, y0 + h - filled, glyph);
1007
- }
1008
- }
1009
- else if (kind === "line") {
1010
- const spikeAt = ((tick / 12 | 0) + seed) % Math.max(1, w);
1011
- for (let i = 0; i < w; i++) {
1012
- const norm = i / Math.max(1, w - 1);
1013
- const base = h - 1 - norm * (h - 1);
1014
- let yf = base + .6 * Math.sin(i * .7 + seed + tick * .05);
1015
- if (i === spikeAt) yf = Math.max(0, base - 1.5);
1016
- const y = Math.max(0, Math.min(h - 1, Math.round(yf)));
1017
- const dist = Math.abs(i - (w - 1));
1018
- const ch = dist === 0 ? "●" : dist < 3 ? "∙" : "·";
1019
- set(x0 + i, y0 + y, ch);
1020
- }
1021
- } else if (kind === "gauge") {
1022
- const cycle = (tick + seed) % 40;
1023
- const pct = cycle < 30 ? cycle / 30 : 1 - (cycle - 30) / 10;
1024
- const midY = y0 + Math.floor(h / 2);
1025
- const filled = Math.max(0, Math.min(w, Math.round(pct * w)));
1026
- for (let i = 0; i < w; i++) set(x0 + i, midY, i < filled ? "█" : "·");
1027
- } else if (kind === "pulse") for (let i = 0; i < w; i++) {
1028
- const t = (i + seed + Math.floor(tick / 3)) % 17;
1029
- let level;
1030
- if (t === 0) level = .9;
1031
- else if (t === 1 || t === 16) level = .5;
1032
- else level = .12 + .06 * Math.sin((i + tick) * .5);
1033
- const filled = Math.max(1, Math.min(h, Math.round(level * h)));
1034
- for (let j = 0; j < filled; j++) set(x0 + i, y0 + h - 1 - j, "█");
1035
- }
1036
- }
1037
- function tileValue(kind, tick, seed) {
1038
- const wave = .5 + .5 * Math.sin(tick * .05 + seed);
1039
- if (kind === "bars") return `${(Math.round(8e3 + wave * 6e3) / 1e3).toFixed(1)}k ▲`;
1040
- if (kind === "line") return `${(2 + wave * 4).toFixed(1)}% ▲`;
1041
- if (kind === "gauge") return `$${Math.round(20 + wave * 60)}k`;
1042
- return `${Math.round(1 + wave * 5)} ▼`;
1043
- }
1044
- //#endregion
1045
- //#region src/ui/tui/components/PhaseVisuals.tsx
1046
- /**
1047
- * Phase visuals — ambient ASCII visualizations of what the agent is currently
1048
- * doing. The active phase is derived from the in-progress task labels (best-
1049
- * effort heuristic). Each phase has its own component (under ./visualizer);
1050
- * the orchestrator `PhaseVisual` picks which one to render.
1051
- *
1052
- * Width and height are passed in from the parent so visuals adapt to the
1053
- * column they're placed in.
1054
- */
1055
- const PHASE_LABELS = {
1056
- ["codebase-scan"]: "Reading the Code",
1057
- ["skill-install"]: "Picking the Right Skill",
1058
- ["dep-install"]: "Installing Packages",
1059
- ["code-edits"]: "Editing Source",
1060
- ["env-setup"]: "Wiring Up Secrets",
1061
- ["dashboards"]: "Building Dashboards"
1062
- };
1063
- /** Reads the active phase from the store. The agent loop pushes it in via
1064
- * `getUI().setStage(...)` whenever a new tool fires. */
1065
- function useAgentPhase(store) {
1066
- useSyncExternalStore((cb) => store.subscribe(cb), () => store.getSnapshot());
1067
- return store.currentStage?.stage ?? "codebase-scan";
1068
- }
1069
- /**
1070
- * VisualizerTab — Winamp-style fullscreen take on the phase visual.
1071
- * "NOW PLAYING" header, centered visual, transport bar with elapsed time.
1072
- *
1073
- * Sizes itself off the *measured* container rather than the raw terminal so
1074
- * the tab bar / hints / status panel above don't get pushed off-screen on
1075
- * short terminals. When height runs out, chrome rows drop in order:
1076
- * transport bar first, then track title, then the NOW PLAYING header.
1077
- */
1078
- const VisualizerTab = ({ store }) => {
1079
- const phase = useAgentPhase(store);
1080
- const containerRef = useRef(null);
1081
- const [size, setSize] = useState({
1082
- width: 0,
1083
- height: 0
1084
- });
1085
- useEffect(() => {
1086
- if (!containerRef.current) return;
1087
- const m = measureElement(containerRef.current);
1088
- if (m.width !== size.width || m.height !== size.height) setSize({
1089
- width: m.width,
1090
- height: m.height
1091
- });
1092
- }, [
1093
- useTick(EQ_TICK_MS),
1094
- size.width,
1095
- size.height
1096
- ]);
1097
- const HEADER_ROWS = 2;
1098
- const TITLE_ROWS = 2;
1099
- const TRANSPORT_ROWS = 2;
1100
- const BORDER_ROWS = 2;
1101
- const MIN_VISUAL_H = 5;
1102
- const availH = size.height;
1103
- const availW = size.width;
1104
- let chromeBudget = BORDER_ROWS + HEADER_ROWS + TITLE_ROWS + TRANSPORT_ROWS;
1105
- let showHeader = true;
1106
- let showTitle = true;
1107
- let showTransport = true;
1108
- if (availH > 0 && availH - chromeBudget < MIN_VISUAL_H) {
1109
- showTransport = false;
1110
- chromeBudget -= TRANSPORT_ROWS;
1111
- }
1112
- if (availH > 0 && availH - chromeBudget < MIN_VISUAL_H) {
1113
- showTitle = false;
1114
- chromeBudget -= TITLE_ROWS;
1115
- }
1116
- if (availH > 0 && availH - chromeBudget < MIN_VISUAL_H) {
1117
- showHeader = false;
1118
- chromeBudget -= HEADER_ROWS;
1119
- }
1120
- const visualH = availH > 0 ? Math.max(MIN_VISUAL_H, Math.min(18, availH - chromeBudget)) : MIN_VISUAL_H;
1121
- const visualW = availW > 0 ? Math.max(20, Math.min(64, availW - 12)) : 40;
1122
- const now = Date.now();
1123
- const beatTimeMs = now - (store.currentStage?.startedAt ?? now);
1124
- const timeStr = formatElapsed(Math.max(0, Math.floor(beatTimeMs / 1e3)));
1125
- const equalizer = renderMiniEqualizer(beatTimeMs, useRef(new Array(EQ_BARS).fill(0)).current);
1126
- return /* @__PURE__ */ jsxs(Box, {
1127
- ref: containerRef,
1128
- flexDirection: "column",
1129
- flexGrow: 1,
1130
- alignItems: "center",
1131
- justifyContent: "center",
1132
- overflow: "hidden",
1133
- children: [
1134
- showHeader && /* @__PURE__ */ jsxs(Box, {
1135
- flexDirection: "row",
1136
- marginBottom: 1,
1137
- children: [
1138
- /* @__PURE__ */ jsx(Text, {
1139
- color: MATRIX_FADE,
1140
- children: "┌─"
1141
- }),
1142
- /* @__PURE__ */ jsx(Text, {
1143
- bold: true,
1144
- color: VISUALIZER_PALETTE.bright,
1145
- children: " ► NOW PLAYING "
1146
- }),
1147
- /* @__PURE__ */ jsx(Text, {
1148
- color: MATRIX_FADE,
1149
- children: "─┐"
1150
- })
1151
- ]
1152
- }),
1153
- showTitle && /* @__PURE__ */ jsx(Box, {
1154
- marginBottom: 1,
1155
- children: /* @__PURE__ */ jsxs(Text, {
1156
- bold: true,
1157
- color: VISUALIZER_PALETTE.head,
1158
- children: [PHASE_LABELS[phase], " - PostHog"]
1159
- })
1160
- }),
1161
- /* @__PURE__ */ jsx(PhaseBody, {
1162
- phase,
1163
- width: visualW,
1164
- height: visualH
1165
- }),
1166
- showTransport && /* @__PURE__ */ jsxs(Box, {
1167
- flexDirection: "row",
1168
- marginTop: 1,
1169
- gap: 2,
1170
- children: [
1171
- /* @__PURE__ */ jsxs(Text, {
1172
- color: VISUALIZER_PALETTE.mid,
1173
- children: [
1174
- "[",
1175
- timeStr,
1176
- "]"
1177
- ]
1178
- }),
1179
- /* @__PURE__ */ jsx(Text, {
1180
- color: MATRIX_FADE,
1181
- children: equalizer
1182
- }),
1183
- /* @__PURE__ */ jsx(Text, {
1184
- color: VISUALIZER_PALETTE.mid,
1185
- children: "WizardAmp"
1186
- })
1187
- ]
1188
- })
1189
- ]
1190
- });
1191
- };
1192
- function formatElapsed(totalSec) {
1193
- const m = Math.floor(totalSec / 60);
1194
- const s = totalSec % 60;
1195
- return `${String(m).padStart(2, "0")}:${String(s).padStart(2, "0")}`;
1196
- }
1197
- const BEAT_MS = 60 / 120 * 1e3;
1198
- const EQ_BARS = 12;
1199
- const EQ_TICK_MS = 67;
1200
- const EQ_FALL_PER_FRAME = .08;
1201
- function pulse(t, periodMs, decay, phaseMs = 0) {
1202
- const since = (t - phaseMs + periodMs * 100) % periodMs;
1203
- return Math.exp(-decay * since / periodMs);
1204
- }
1205
- const EQ_GLYPHS = "▁▂▃▄▅▆▇█";
1206
- function renderMiniEqualizer(beatTimeMs, levels) {
1207
- const kick = pulse(beatTimeMs, BEAT_MS, 4);
1208
- const bass = pulse(beatTimeMs, BEAT_MS, 1.5);
1209
- const clap = pulse(beatTimeMs, BEAT_MS * 2, 5, BEAT_MS);
1210
- const hat8 = pulse(beatTimeMs, BEAT_MS / 2, 8);
1211
- const hat16 = pulse(beatTimeMs, BEAT_MS / 4, 12);
1212
- const pad = .2 + .15 * Math.sin(2 * Math.PI * beatTimeMs / 4e3);
1213
- const mix = [
1214
- bass * .7 + kick * .5 + pad,
1215
- bass * .6 + kick * .6 + pad * .9,
1216
- bass * .4 + kick * .7 + pad * .8,
1217
- kick * .6 + clap * .3 + pad * .7,
1218
- kick * .4 + clap * .5 + pad * .7,
1219
- clap * .7 + hat8 * .3 + pad * .6,
1220
- clap * .6 + hat8 * .5 + pad * .5,
1221
- hat8 * .7 + clap * .3 + pad * .5,
1222
- hat8 * .5 + hat16 * .4 + pad * .4,
1223
- hat8 * .4 + hat16 * .5 + pad * .4,
1224
- hat16 * .6 + hat8 * .3 + pad * .3,
1225
- hat16 * .7 + pad * .3
1226
- ];
1227
- let out = "";
1228
- for (let i = 0; i < EQ_BARS; i++) {
1229
- const target = Math.min(1, mix[i]);
1230
- levels[i] = Math.max(target, levels[i] - EQ_FALL_PER_FRAME);
1231
- out += EQ_GLYPHS[Math.floor(levels[i] * 7)];
1232
- }
1233
- return out;
1234
- }
1235
- const PhaseBody = ({ phase, width, height }) => {
1236
- switch (phase) {
1237
- case "codebase-scan": return /* @__PURE__ */ jsx(MatrixRain, {
1238
- width,
1239
- height
1240
- });
1241
- case "skill-install": return /* @__PURE__ */ jsx(LibraryShelf, {
1242
- width,
1243
- height
1244
- });
1245
- case "dep-install": return /* @__PURE__ */ jsx(CrateStack, {
1246
- width,
1247
- height
1248
- });
1249
- case "code-edits": return /* @__PURE__ */ jsx(DiffCascade, {
1250
- width,
1251
- height
1252
- });
1253
- case "env-setup": return /* @__PURE__ */ jsx(Tumblers, {
1254
- width,
1255
- height
1256
- });
1257
- case "dashboards": return /* @__PURE__ */ jsx(DashboardGrid, {
1258
- width,
1259
- height
1260
- });
1261
- }
1262
- };
1263
- //#endregion
1264
488
  //#region src/ui/tui/playground/demos/RunScreenDemo.tsx
1265
489
  /**
1266
490
  * RunScreenDemo — Playground demo for the agent run view.
@@ -1779,15 +1003,28 @@ function createMockInstaller() {
1779
1003
  },
1780
1004
  async install(clientNames) {
1781
1005
  await new Promise((r) => setTimeout(r, 1500));
1782
- return clientNames;
1006
+ return clientNames.map((name, i) => ({
1007
+ name,
1008
+ status: i === 1 ? "unchanged" : "changed"
1009
+ }));
1783
1010
  },
1784
1011
  async installPlugins(clientNames) {
1785
1012
  await new Promise((r) => setTimeout(r, 800));
1786
- return clientNames.filter((name) => MOCK_CLIENTS.find((c) => c.name === name)?.supportsPlugin);
1013
+ return clientNames.filter((name) => MOCK_CLIENTS.find((c) => c.name === name)?.supportsPlugin).map((name) => ({
1014
+ name,
1015
+ status: "changed"
1016
+ }));
1787
1017
  },
1788
1018
  async remove() {
1789
1019
  await new Promise((r) => setTimeout(r, 1e3));
1790
- return MOCK_CLIENTS.map((c) => c.name);
1020
+ return MOCK_CLIENTS.map((c, i) => i === 2 ? {
1021
+ name: c.name,
1022
+ status: "failed",
1023
+ detail: "EACCES: permission denied"
1024
+ } : {
1025
+ name: c.name,
1026
+ status: "changed"
1027
+ });
1791
1028
  }
1792
1029
  };
1793
1030
  }
@@ -3283,4 +2520,4 @@ function runPlayground() {
3283
2520
  //#endregion
3284
2521
  export { runPlayground };
3285
2522
 
3286
- //# sourceMappingURL=playground-Df_ZzalF.js.map
2523
+ //# sourceMappingURL=playground-BjWqoWhf.js.map