@posthog/wizard 2.13.1 → 2.14.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 (87) hide show
  1. package/LICENSE +0 -26
  2. package/README.md +1 -1
  3. package/dist/TextBlock-B3cm43YY.js +244 -0
  4. package/dist/TextBlock-B3cm43YY.js.map +1 -0
  5. package/dist/{add-mcp-server-to-clients-D1IyBa9u.js → add-mcp-server-to-clients-BTW9Ey5Z.js} +7 -7
  6. package/dist/{add-mcp-server-to-clients-D1IyBa9u.js.map → add-mcp-server-to-clients-BTW9Ey5Z.js.map} +1 -1
  7. package/dist/{agent-interface-D9DeIikl.js → agent-interface-gP4pkZgS.js} +533 -255
  8. package/dist/agent-interface-gP4pkZgS.js.map +1 -0
  9. package/dist/{agent-runner-B41-Iig3.js → agent-runner-Bxi71jnp.js} +102 -20
  10. package/dist/agent-runner-Bxi71jnp.js.map +1 -0
  11. package/dist/{analytics-Cek5hIwm.js → analytics-Dmnxu2zE.js} +2 -2
  12. package/dist/{analytics-Cek5hIwm.js.map → analytics-Dmnxu2zE.js.map} +1 -1
  13. package/dist/analytics-tslsXyf9.js +2 -0
  14. package/dist/bin.js +951 -141
  15. package/dist/bin.js.map +1 -1
  16. package/dist/{debug-B2BH87dh.js → debug-CYUB-urp.js} +26 -21
  17. package/dist/debug-CYUB-urp.js.map +1 -0
  18. package/dist/{debug-BNWsxaDm.js → debug-Du7qXlug.js} +1 -1
  19. package/dist/{defaults-GbLPuHxj.js → defaults-DgKAzsD1.js} +1 -1
  20. package/dist/{defaults-GbLPuHxj.js.map → defaults-DgKAzsD1.js.map} +1 -1
  21. package/dist/{detection-BFl2AYV6.js → detection-D651Eb5k.js} +4 -4
  22. package/dist/detection-D651Eb5k.js.map +1 -0
  23. package/dist/{file-8iNrXHkG.js → file-BKbKreWF.js} +1 -1
  24. package/dist/{file-8iNrXHkG.js.map → file-BKbKreWF.js.map} +1 -1
  25. package/dist/{file-utils-DnTSiTJw.js → file-utils-DPmgn9Vm.js} +1 -1
  26. package/dist/{file-utils-DnTSiTJw.js.map → file-utils-DPmgn9Vm.js.map} +1 -1
  27. package/dist/{package-json-F_7oktsp.js → package-json-DZpnf6vU.js} +8 -10
  28. package/dist/package-json-DZpnf6vU.js.map +1 -0
  29. package/dist/package-json-_4PEss19.js +2 -0
  30. package/dist/{package-manager-BBTvHn9i.js → package-manager-liwrN_aI.js} +2 -2
  31. package/dist/{package-manager-BBTvHn9i.js.map → package-manager-liwrN_aI.js.map} +1 -1
  32. package/dist/{posthog-vm0k9PKS.js → posthog-BbQf_Hzq.js} +1 -1
  33. package/dist/{posthog-vm0k9PKS.js.map → posthog-BbQf_Hzq.js.map} +1 -1
  34. package/dist/posthog-integration-C-FFV5ny.js +1012 -0
  35. package/dist/posthog-integration-C-FFV5ny.js.map +1 -0
  36. package/dist/provisioning-ByWo5KcQ.js +2 -0
  37. package/dist/{provisioning-DRwH4skH.js → provisioning-C4nHkz-O.js} +3 -3
  38. package/dist/{provisioning-DRwH4skH.js.map → provisioning-C4nHkz-O.js.map} +1 -1
  39. package/dist/{registry-CZjMhhsK.js → registry-B92uyoWK.js} +5 -5
  40. package/dist/{registry-CZjMhhsK.js.map → registry-B92uyoWK.js.map} +1 -1
  41. package/dist/setup-utils-D5aNKrba.js +2 -0
  42. package/dist/{setup-utils-DGUR4Djo.js → setup-utils-LvtZIY18.js} +77 -107
  43. package/dist/setup-utils-LvtZIY18.js.map +1 -0
  44. package/dist/{AuditChecksViewer-CjBCZjxG.js → slides-yyC_W0RZ.js} +626 -1058
  45. package/dist/slides-yyC_W0RZ.js.map +1 -0
  46. package/dist/smoke-test-ci.sh +4 -4
  47. package/dist/{start-playground-DPYl5WR-.js → start-playground-BhwBUq-a.js} +259 -10
  48. package/dist/start-playground-BhwBUq-a.js.map +1 -0
  49. package/dist/{start-tui-Cj_4BhK8.js → start-tui-BwQa3kmG.js} +288 -446
  50. package/dist/start-tui-BwQa3kmG.js.map +1 -0
  51. package/dist/{steps-BFD76-MP.js → steps-CGpfOAcr.js} +7 -7
  52. package/dist/{steps-BFD76-MP.js.map → steps-CGpfOAcr.js.map} +1 -1
  53. package/dist/{task-stream-CX7Uf6EM.js → task-stream-DUpUZmFQ.js} +8 -8
  54. package/dist/task-stream-DUpUZmFQ.js.map +1 -0
  55. package/dist/telemetry-Fmdx1AYv.js +13 -0
  56. package/dist/telemetry-Fmdx1AYv.js.map +1 -0
  57. package/dist/{wizard-abort-CZH03nD0.js → wizard-abort-BTBccRto.js} +1 -1
  58. package/dist/{wizard-abort-54DpTnUi.js → wizard-abort-D-t5yDkY.js} +3 -3
  59. package/dist/{wizard-abort-54DpTnUi.js.map → wizard-abort-D-t5yDkY.js.map} +1 -1
  60. package/dist/wizard-session-CPhhll4P.js +2 -0
  61. package/dist/{wizard-session-BcNJTl2I.js → wizard-session-CsI33S4_.js} +6 -3
  62. package/dist/wizard-session-CsI33S4_.js.map +1 -0
  63. package/dist/wizard-ui-YdGFRyu_.js.map +1 -1
  64. package/npm-shrinkwrap.json +2 -2
  65. package/package.json +3 -2
  66. package/dist/AuditChecksViewer-CjBCZjxG.js.map +0 -1
  67. package/dist/agent-interface-D9DeIikl.js.map +0 -1
  68. package/dist/agent-runner-B41-Iig3.js.map +0 -1
  69. package/dist/analytics-CpbY05Lf.js +0 -2
  70. package/dist/debug-B2BH87dh.js.map +0 -1
  71. package/dist/detection-BFl2AYV6.js.map +0 -1
  72. package/dist/package-json-BzVey4Bd.js +0 -2
  73. package/dist/package-json-F_7oktsp.js.map +0 -1
  74. package/dist/posthog-integration-vFBuSN5U.js +0 -259
  75. package/dist/posthog-integration-vFBuSN5U.js.map +0 -1
  76. package/dist/provisioning--RCv39tI.js +0 -2
  77. package/dist/router-COhhuIW3.js +0 -135
  78. package/dist/router-COhhuIW3.js.map +0 -1
  79. package/dist/setup-utils-DGUR4Djo.js.map +0 -1
  80. package/dist/setup-utils-eh1450iu.js +0 -2
  81. package/dist/start-playground-DPYl5WR-.js.map +0 -1
  82. package/dist/start-tui-Cj_4BhK8.js.map +0 -1
  83. package/dist/task-stream-CX7Uf6EM.js.map +0 -1
  84. package/dist/telemetry-DCyjsXhw.js +0 -13
  85. package/dist/telemetry-DCyjsXhw.js.map +0 -1
  86. package/dist/wizard-session-BQC9vy9Z.js +0 -2
  87. package/dist/wizard-session-BcNJTl2I.js.map +0 -1
@@ -1,17 +1,110 @@
1
- import { d as SERVICE_LABELS } from "./debug-B2BH87dh.js";
1
+ import { d as SERVICE_LABELS } from "./debug-CYUB-urp.js";
2
2
  import { n as isTaskStatus } from "./wizard-ui-YdGFRyu_.js";
3
- import { n as analytics, r as sessionProperties } from "./analytics-Cek5hIwm.js";
4
- import { r as buildSession } from "./wizard-session-BcNJTl2I.js";
5
- import { g as AUDIT_SEVERITY_STYLE } from "./agent-interface-D9DeIikl.js";
6
- import { r as getKindMeta } from "./bin.js";
7
- import { n as AVAILABLE_FEATURES, t as ALL_FEATURE_VALUES } from "./defaults-GbLPuHxj.js";
8
- import { i as WORKFLOW_STEPS, t as WizardRouter } from "./router-COhhuIW3.js";
3
+ import { n as analytics, r as sessionProperties } from "./analytics-Dmnxu2zE.js";
4
+ import { r as buildSession } from "./wizard-session-CsI33S4_.js";
5
+ import { _ as AUDIT_SEVERITY_STYLE } from "./agent-interface-gP4pkZgS.js";
6
+ import { a as isObjectBlock, i as isLinesBlock, n as computeVisibleRange, o as Colors, r as isClearBlock, s as Icons, t as TextBlock } from "./TextBlock-B3cm43YY.js";
7
+ import { a as getKindMeta, n as Program, r as getProgramConfig, t as PROGRAM_REGISTRY } from "./bin.js";
8
+ import { n as AVAILABLE_FEATURES, t as ALL_FEATURE_VALUES } from "./defaults-DgKAzsD1.js";
9
9
  import * as fs$1 from "fs";
10
10
  import { Box, Text, measureElement, useInput, useStdout } from "ink";
11
11
  import { Component, Fragment, createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
12
- import { atom, map } from "nanostores";
13
12
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
13
+ import { atom, map } from "nanostores";
14
14
  import { Spinner } from "@inkjs/ui";
15
+ //#region src/lib/programs/program-step.ts
16
+ /**
17
+ * Project program steps into the narrower Screen shape the router consumes.
18
+ *
19
+ * Two things happen here:
20
+ * 1. Headless steps (no `screenId`) are filtered out. The router walks
21
+ * visible screens; gate-only steps like `detect` are store concerns.
22
+ * 2. The step is narrowed to just { id, show, isComplete } — the
23
+ * router has no business touching gate, onInit, or label.
24
+ *
25
+ * This intentional separation keeps the router focused on one question:
26
+ * "Which screen should be rendered right now?"
27
+ */
28
+ function createProgramSequence(steps) {
29
+ const entries = steps.filter((step) => step.screenId != null).map((step) => ({
30
+ id: step.screenId,
31
+ show: step.show,
32
+ isComplete: step.isComplete ?? step.gate
33
+ }));
34
+ entries.push({
35
+ id: "exit",
36
+ show: void 0,
37
+ isComplete: void 0
38
+ });
39
+ return entries;
40
+ }
41
+ //#endregion
42
+ //#region src/ui/tui/screen-sequences.ts
43
+ /** All program screen sequences keyed by program id. */
44
+ const PROGRAM_SEQUENCES = Object.fromEntries(PROGRAM_REGISTRY.map((c) => [c.id, createProgramSequence(c.steps)]));
45
+ //#endregion
46
+ //#region src/ui/tui/router.ts
47
+ var WizardRouter = class {
48
+ sequence;
49
+ programId;
50
+ overlays = [];
51
+ constructor(programId = Program.PostHogIntegration) {
52
+ this.programId = programId;
53
+ this.sequence = PROGRAM_SEQUENCES[programId];
54
+ }
55
+ /**
56
+ * Resolve which screen should be active based on session state.
57
+ * Walks the program sequence, skipping hidden entries and completed entries,
58
+ * returns the first incomplete screen.
59
+ */
60
+ resolve(session) {
61
+ if (this.overlays.length > 0) return this.overlays[this.overlays.length - 1];
62
+ for (const entry of this.sequence) {
63
+ if (entry.show && !entry.show(session)) continue;
64
+ if (entry.isComplete && entry.isComplete(session)) continue;
65
+ return entry.id;
66
+ }
67
+ return this.sequence[this.sequence.length - 1].id;
68
+ }
69
+ /** The screen that should be rendered right now. */
70
+ get activeScreen() {
71
+ if (this.overlays.length > 0) return this.overlays[this.overlays.length - 1];
72
+ return this.sequence[0].id;
73
+ }
74
+ /** The id of the active program. */
75
+ get activeProgram() {
76
+ return this.programId;
77
+ }
78
+ /** Whether an overlay is currently active. */
79
+ get hasOverlay() {
80
+ return this.overlays.length > 0;
81
+ }
82
+ /**
83
+ * Push an overlay that interrupts the current program.
84
+ * The program resumes when the overlay is dismissed via popOverlay().
85
+ */
86
+ pushOverlay(overlay) {
87
+ this.overlays.push(overlay);
88
+ }
89
+ /**
90
+ * Dismiss the topmost overlay. The program screen underneath resumes.
91
+ */
92
+ popOverlay() {
93
+ this.overlays.pop();
94
+ }
95
+ /**
96
+ * Direction hint for screen transitions.
97
+ */
98
+ _lastDirection = null;
99
+ get lastNavDirection() {
100
+ return this._lastDirection;
101
+ }
102
+ /** @internal — called by store wrapper to track direction */
103
+ _setDirection(dir) {
104
+ this._lastDirection = dir;
105
+ }
106
+ };
107
+ //#endregion
15
108
  //#region src/ui/tui/store.ts
16
109
  /**
17
110
  * WizardStore — Nanostore-backed reactive store for the TUI.
@@ -41,7 +134,7 @@ var WizardStore = class {
41
134
  _lastScreen = null;
42
135
  /** Hooks run when transitioning onto a screen. */
43
136
  _enterScreenHooks = /* @__PURE__ */ new Map();
44
- /** Gate promises derived from workflow step definitions. */
137
+ /** Gate promises derived from program step definitions. */
45
138
  _gates = /* @__PURE__ */ new Map();
46
139
  version = "";
47
140
  /** Navigation router — resolves active screen from session state. */
@@ -51,17 +144,18 @@ var WizardStore = class {
51
144
  _backupAndFixSettings = null;
52
145
  /** Blocks OAuth flow until the port-conflict overlay is dismissed. */
53
146
  _resolvePortConflict = null;
54
- constructor(flow = "posthog-integration") {
55
- this.router = new WizardRouter(flow);
56
- this._initFromWorkflow(flow);
147
+ /** Resolves the in-flight wizard_ask request. */
148
+ _resolvePendingQuestion = null;
149
+ constructor(program = Program.PostHogIntegration) {
150
+ this.router = new WizardRouter(program);
151
+ this._initFromProgram(program);
57
152
  }
58
153
  /**
59
- * Scan workflow steps for gate predicates and onInit callbacks.
154
+ * Scan program steps for gate predicates and onInit callbacks.
60
155
  * Creates gate promises and fires init work.
61
156
  */
62
- _initFromWorkflow(flow) {
63
- const steps = WORKFLOW_STEPS[flow];
64
- if (!steps) return;
157
+ _initFromProgram(program) {
158
+ const steps = getProgramConfig(program).steps;
65
159
  for (const step of steps) if (step.gate) {
66
160
  let resolve;
67
161
  const promise = new Promise((r) => {
@@ -89,11 +183,10 @@ var WizardStore = class {
89
183
  * Run all `onReady` hooks declared by the current flow's steps, in
90
184
  * order. Must be called after `store.session = session` so hooks see
91
185
  * the real installDir. bin.ts calls this generically — it doesn't
92
- * need to know which workflow has which pre-flow work.
186
+ * need to know which program has which pre-flow work.
93
187
  */
94
188
  async runReadyHooks() {
95
- const steps = WORKFLOW_STEPS[this.router.activeFlow];
96
- if (!steps) return;
189
+ const steps = getProgramConfig(this.router.activeProgram).steps;
97
190
  const ctx = {
98
191
  session: this.session,
99
192
  setFrameworkContext: (k, v) => this.setFrameworkContext(k, v),
@@ -108,13 +201,13 @@ var WizardStore = class {
108
201
  /**
109
202
  * Get a gate promise by step ID — the primary blocking checkpoint API
110
203
  * for bin.ts. `await store.getGate('...')` parks the caller until the
111
- * corresponding workflow step's gate predicate flips to true (if the
204
+ * corresponding program step's gate predicate flips to true (if the
112
205
  * predicate stays false, the caller stays parked indefinitely — the
113
206
  * TUI keeps rendering so the user can resolve whatever is blocking).
114
207
  *
115
- * If the workflow doesn't define a step with this ID, or the step
208
+ * If the program doesn't define a step with this ID, or the step
116
209
  * has no `gate` predicate, this returns an already-resolved promise
117
- * so bin.ts flows straight through. This lets workflows opt in to
210
+ * so bin.ts flows straight through. This lets programs opt in to
118
211
  * gates on a per-step basis without bin.ts needing to know which
119
212
  * gates exist in which flow.
120
213
  */
@@ -244,6 +337,48 @@ var WizardStore = class {
244
337
  this._resolvePortConflict = null;
245
338
  }
246
339
  /**
340
+ * Open the WizardAsk overlay with a set of questions and return a promise
341
+ * that resolves once the user submits answers (or the request is cancelled).
342
+ *
343
+ * Only one request is in flight at a time — calling this while a request
344
+ * is already pending throws.
345
+ */
346
+ requestQuestion(question) {
347
+ if (this._resolvePendingQuestion) throw new Error("requestQuestion called while another wizard_ask request is pending");
348
+ this.$session.setKey("pendingQuestion", question);
349
+ this.pushOverlay("wizard-ask");
350
+ analytics.wizardCapture("wizard_ask shown", {
351
+ source: question.source,
352
+ question_count: question.questions.length,
353
+ kinds: question.questions.map((q) => q.kind)
354
+ });
355
+ return new Promise((resolve) => {
356
+ this._resolvePendingQuestion = resolve;
357
+ });
358
+ }
359
+ /**
360
+ * Resolve the in-flight wizard_ask request with the user's answers and
361
+ * dismiss the overlay. Answers flow back to the agent as the tool result.
362
+ */
363
+ resolvePendingQuestion(answers) {
364
+ const resolve = this._resolvePendingQuestion;
365
+ this._resolvePendingQuestion = null;
366
+ this.$session.setKey("pendingQuestion", null);
367
+ this.popOverlay();
368
+ resolve?.(answers);
369
+ }
370
+ /**
371
+ * Cancel the in-flight wizard_ask request — the bridge sends a sentinel
372
+ * answer ("__cancelled__") so the skill can decide how to handle it.
373
+ */
374
+ cancelPendingQuestion() {
375
+ const pending = this.session.pendingQuestion;
376
+ if (!pending) return;
377
+ const cancelled = {};
378
+ for (const q of pending.questions) cancelled[q.id] = "__cancelled__";
379
+ this.resolvePendingQuestion(cancelled);
380
+ }
381
+ /**
247
382
  * Back up .claude/settings.json. Dismisses the overlay on success.
248
383
  */
249
384
  backupAndFixSettingsOverride() {
@@ -259,7 +394,8 @@ var WizardStore = class {
259
394
  return ok;
260
395
  }
261
396
  /** Push the auth-error overlay (no dismiss — user must exit). */
262
- showAuthError() {
397
+ showAuthError(detail) {
398
+ this.$session.setKey("authErrorDetail", detail ?? null);
263
399
  this.pushOverlay("auth-error");
264
400
  }
265
401
  addDiscoveredFeature(feature) {
@@ -305,6 +441,10 @@ var WizardStore = class {
305
441
  this.$session.setKey("outroData", data);
306
442
  this.emitChange();
307
443
  }
444
+ setDashboardUrl(url) {
445
+ this.$session.setKey("dashboardUrl", url);
446
+ this.emitChange();
447
+ }
308
448
  setFrameworkContext(key, value) {
309
449
  const ctx = {
310
450
  ...this.$session.get().frameworkContext,
@@ -371,7 +511,7 @@ var WizardStore = class {
371
511
  if (hooks) for (const fn of hooks) fn();
372
512
  analytics.wizardCapture(`screen ${next}`, {
373
513
  from_screen: prev,
374
- workflow: this.router.activeFlow,
514
+ program_id: this.router.activeProgram,
375
515
  ...sessionProperties(this.session)
376
516
  });
377
517
  }
@@ -445,27 +585,6 @@ var WizardStore = class {
445
585
  }
446
586
  };
447
587
  //#endregion
448
- //#region src/ui/tui/styles.ts
449
- const Colors = {
450
- primary: "cyan",
451
- accent: "#DC9300",
452
- titleColor: "#3D2800",
453
- success: "green",
454
- error: "red",
455
- muted: "gray"
456
- };
457
- const Icons = {
458
- diamond: "◆",
459
- diamondOpen: "◇",
460
- check: "✔",
461
- warning: "⚠",
462
- squareFilled: "◼",
463
- squareOpen: "◻",
464
- triangleRight: "▶",
465
- triangleSmallRight: "▸",
466
- bullet: "•"
467
- };
468
- //#endregion
469
588
  //#region src/ui/tui/primitives/CardLayout.tsx
470
589
  /**
471
590
  * CardLayout — Aligns a single child within available space.
@@ -1835,223 +1954,6 @@ function openStory(input, stories) {
1835
1954
  });
1836
1955
  }
1837
1956
  //#endregion
1838
- //#region src/ui/tui/primitives/text-helpers.ts
1839
- /**
1840
- * Text-splitting helpers for sentence boundary detection.
1841
- * Used by TextBlock for animation pauses at punctuation.
1842
- */
1843
- /** Split text into sentences (keeps the delimiter attached) */
1844
- function splitSentences(text) {
1845
- const parts = [];
1846
- const re = /[^.!?]*[.!?]+\s*/g;
1847
- let match;
1848
- let lastIndex = 0;
1849
- while ((match = re.exec(text)) !== null) {
1850
- parts.push(match[0]);
1851
- lastIndex = re.lastIndex;
1852
- }
1853
- if (lastIndex < text.length) parts.push(text.slice(lastIndex));
1854
- return parts;
1855
- }
1856
- /** Build a set of character indices where sentences end (for typewriter pause) */
1857
- function sentenceEndChars(text) {
1858
- const ends = /* @__PURE__ */ new Set();
1859
- const sentences = splitSentences(text);
1860
- let pos = 0;
1861
- for (const s of sentences) {
1862
- pos += s.length;
1863
- ends.add(pos - 1);
1864
- }
1865
- return ends;
1866
- }
1867
- /** Build a set of word indices where sentences end (for word-by-word pause) */
1868
- function sentenceEndWords(text) {
1869
- const ends = /* @__PURE__ */ new Set();
1870
- const sentences = splitSentences(text);
1871
- let wordCount = 0;
1872
- for (const s of sentences) {
1873
- const words = s.trim().split(/\s+/).filter(Boolean);
1874
- wordCount += words.length;
1875
- ends.add(wordCount - 1);
1876
- }
1877
- return ends;
1878
- }
1879
- //#endregion
1880
- //#region src/ui/tui/primitives/content-types.ts
1881
- /** Type guard for lines blocks. */
1882
- function isLinesBlock(block) {
1883
- return typeof block !== "string" && "type" in block && block.type === "lines";
1884
- }
1885
- /** Type guard for clear blocks. */
1886
- function isClearBlock(block) {
1887
- return typeof block !== "string" && "type" in block && block.type === "clear";
1888
- }
1889
- /** Type guard for object blocks (text or node content). */
1890
- function isObjectBlock(block) {
1891
- return typeof block !== "string" && !("type" in block);
1892
- }
1893
- //#endregion
1894
- //#region src/ui/tui/primitives/layout-helpers.ts
1895
- /**
1896
- * Estimate the number of terminal rows a content block will occupy,
1897
- * including 1 row of marginBottom.
1898
- */
1899
- function estimateBlockHeight(block, availableWidth) {
1900
- if (typeof block === "string") return wordWrap(block, availableWidth).length + 1;
1901
- if (isClearBlock(block)) return 0;
1902
- if (isLinesBlock(block)) return block.lines.length + 1;
1903
- if (isObjectBlock(block)) {
1904
- if (typeof block.content === "string") return wordWrap(block.content, availableWidth).length + 1;
1905
- return 4;
1906
- }
1907
- return 1;
1908
- }
1909
- /**
1910
- * Given all blocks, the active index, available width, and a row budget,
1911
- * return [startIdx, endIdx] — the range of blocks to render.
1912
- *
1913
- * Always includes activeIdx. Walks backward to include as many completed
1914
- * blocks as fit within maxHeight.
1915
- */
1916
- function computeVisibleRange(blocks, activeIdx, availableWidth, maxHeight) {
1917
- const budget = Math.max(4, maxHeight - 2);
1918
- let totalHeight = estimateBlockHeight(blocks[activeIdx], availableWidth);
1919
- let start = activeIdx;
1920
- for (let i = activeIdx - 1; i >= 0; i--) {
1921
- if (isClearBlock(blocks[i])) break;
1922
- const h = estimateBlockHeight(blocks[i], availableWidth);
1923
- if (totalHeight + h > budget) break;
1924
- totalHeight += h;
1925
- start = i;
1926
- }
1927
- return [start, activeIdx];
1928
- }
1929
- /**
1930
- * Word-wrap text at clean word boundaries. Always returns pre-wrapped text
1931
- * joined with \n — this avoids Ink's native wrap which can leave leading
1932
- * spaces on continuation lines.
1933
- *
1934
- * Uses a 1-char safety margin so slight width estimate mismatches don't
1935
- * cause Ink to re-wrap our already-wrapped lines.
1936
- */
1937
- function wordWrap(text, availableWidth) {
1938
- const safeWidth = Math.max(10, availableWidth - 1);
1939
- const words = text.split(/\s+/);
1940
- const lines = [];
1941
- let currentLine = "";
1942
- for (const word of words) if (currentLine.length + word.length + 1 > safeWidth && currentLine.length > 0) {
1943
- lines.push(currentLine);
1944
- currentLine = word;
1945
- } else currentLine += (currentLine.length > 0 ? " " : "") + word;
1946
- if (currentLine.length > 0) lines.push(currentLine);
1947
- return lines;
1948
- }
1949
- /**
1950
- * Word-wrap text and return only the last `maxRows` lines.
1951
- * Used for intra-block truncation when a single text block exceeds the viewport.
1952
- * Also used for normal rendering to avoid Ink's leading-space wrap artifacts.
1953
- */
1954
- function wrapAndTruncate(text, availableWidth, maxRows) {
1955
- const lines = wordWrap(text, availableWidth);
1956
- if (lines.length <= maxRows) return lines.join("\n");
1957
- return lines.slice(-maxRows).join("\n");
1958
- }
1959
- //#endregion
1960
- //#region src/ui/tui/primitives/TextBlock.tsx
1961
- /**
1962
- * TextBlock — Animates a single string paragraph.
1963
- *
1964
- * Self-contained: owns its own animIdx and timer.
1965
- * Calls onComplete() when the animation finishes.
1966
- *
1967
- * Five animation modes:
1968
- * 1. Typewriter — character-by-character reveal
1969
- * 2. Word by word — each word appears in order
1970
- * 3. Sentence by sentence — sentences appear one at a time
1971
- * 4. Paragraph fade — paragraph appears at full opacity immediately
1972
- * 5. Sentence fade — paragraph dim, sentences light up in order
1973
- */
1974
- /** Default interval per mode (ms) */
1975
- const TEXT_REVEAL_MODE_DEFAULTS = {
1976
- [1]: 240,
1977
- [0]: 32,
1978
- [2]: 1800,
1979
- [3]: 4800,
1980
- [4]: 2400
1981
- };
1982
- const TextBlock = ({ text, active, completed, onComplete, mode, bullet, animationInterval, sentenceInterval = 1600, maxHeight, availableWidth }) => {
1983
- const speed = animationInterval ?? TEXT_REVEAL_MODE_DEFAULTS[mode];
1984
- const [animIdx, setAnimIdx] = useState(mode === 4 ? 1 : 0);
1985
- const resetRef = useRef(0);
1986
- const prevMode = useRef(mode);
1987
- if (prevMode.current !== mode) {
1988
- prevMode.current = mode;
1989
- resetRef.current += 1;
1990
- setAnimIdx(mode === 4 ? 1 : 0);
1991
- }
1992
- const words = text.split(/\s+/);
1993
- const sentences = splitSentences(text);
1994
- const sentenceCharEnds = useMemo(() => sentenceEndChars(text), [text]);
1995
- const sentenceWordEnds = useMemo(() => sentenceEndWords(text), [text]);
1996
- const isDone = mode === 0 ? animIdx >= text.length : mode === 3 ? true : mode === 1 ? animIdx >= words.length : mode === 4 || mode === 2 ? animIdx >= sentences.length : true;
1997
- useEffect(() => {
1998
- if (isDone && active) onComplete();
1999
- }, [
2000
- isDone,
2001
- active,
2002
- onComplete
2003
- ]);
2004
- useEffect(() => {
2005
- if (!active || mode === 3 || isDone) return;
2006
- const token = resetRef.current;
2007
- const isFirstTick = animIdx === 0;
2008
- let delay = isFirstTick ? 0 : speed;
2009
- if (!isFirstTick && mode === 0 && animIdx > 0 && sentenceCharEnds.has(animIdx - 1)) delay = sentenceInterval;
2010
- else if (!isFirstTick && mode === 1 && animIdx > 0 && sentenceWordEnds.has(animIdx - 1)) delay = sentenceInterval;
2011
- const timer = setTimeout(() => {
2012
- if (token !== resetRef.current) return;
2013
- setAnimIdx((c) => c + 1);
2014
- }, delay);
2015
- return () => clearTimeout(timer);
2016
- }, [
2017
- active,
2018
- mode,
2019
- animIdx,
2020
- isDone,
2021
- speed,
2022
- sentenceInterval,
2023
- sentenceCharEnds,
2024
- sentenceWordEnds
2025
- ]);
2026
- const wrap = (visibleText) => {
2027
- if (availableWidth == null) return visibleText;
2028
- if (maxHeight == null) return wrapAndTruncate(visibleText, availableWidth, Infinity);
2029
- return wrapAndTruncate(visibleText, availableWidth, maxHeight);
2030
- };
2031
- if (completed) return /* @__PURE__ */ jsxs(Text, {
2032
- dimColor: true,
2033
- children: [bullet, wrap(text)]
2034
- });
2035
- if (mode === 0) {
2036
- const revealed = text.slice(0, animIdx);
2037
- return /* @__PURE__ */ jsxs(Text, { children: [
2038
- bullet,
2039
- wrap(/[.!?]\s*$/.test(revealed) ? revealed.trimEnd() : revealed),
2040
- /* @__PURE__ */ jsx(Text, {
2041
- color: Colors.muted,
2042
- children: "▌"
2043
- })
2044
- ] });
2045
- }
2046
- if (mode === 1) return /* @__PURE__ */ jsxs(Text, { children: [bullet, wrap(words.slice(0, animIdx).join(" "))] });
2047
- if (mode === 3) return /* @__PURE__ */ jsxs(Text, { children: [bullet, wrap(text)] });
2048
- if (mode === 2) return /* @__PURE__ */ jsxs(Text, { children: [bullet, wrap(sentences.slice(0, animIdx).join(""))] });
2049
- return /* @__PURE__ */ jsxs(Text, { children: [bullet, sentences.map((s, si) => /* @__PURE__ */ jsx(Text, {
2050
- dimColor: si >= animIdx,
2051
- children: s
2052
- }, si))] });
2053
- };
2054
- //#endregion
2055
1957
  //#region src/ui/tui/primitives/LinesBlock.tsx
2056
1958
  /**
2057
1959
  * LinesBlock — Reveals ReactNode lines one at a time.
@@ -2261,809 +2163,99 @@ const BlockRenderer = ({ block, active, completed, onComplete, mode, bullet, ani
2261
2163
  //#endregion
2262
2164
  //#region src/ui/tui/components/LearnCard.tsx
2263
2165
  /**
2264
- * LearnCard — PostHog educational content with animated text reveal.
2265
- */
2266
- /**
2267
- * StatusPeekTrigger Fires the status bar expansion once, renders nothing.
2268
- * The peek is guarded by peekedRef so re-mounts are safe.
2166
+ * LearnCard — Generic render shell for an animated content deck.
2167
+ *
2168
+ * Program-owned. Callers pass the script via `blocks`. The script lives
2169
+ * under `src/lib/programs/<name>/content/`. The shell handles
2170
+ * dimension tracking, status-bar height math, and the `display="none"`
2171
+ * clamp on narrow terminals.
2269
2172
  */
2270
- const StatusPeekTrigger = ({ store, duration = 1e4, peekedRef }) => {
2271
- useEffect(() => {
2272
- if (peekedRef.current) return;
2273
- peekedRef.current = true;
2274
- store?.setStatusExpanded(true);
2275
- setTimeout(() => {
2276
- store?.setStatusExpanded(false);
2277
- }, duration);
2278
- }, [
2279
- store,
2280
- duration,
2281
- peekedRef
2282
- ]);
2283
- return /* @__PURE__ */ jsx(Text, { children: "You can view the Wizard's status below." });
2284
- };
2285
- const POSTHOG_DATA_FLOW = {
2286
- type: "lines",
2287
- interval: 500,
2288
- pause: 8e3,
2289
- lines: [
2290
- /* @__PURE__ */ jsx(Text, {
2291
- color: "gray",
2292
- children: " ┌──────────────────────────────┐"
2293
- }),
2294
- /* @__PURE__ */ jsxs(Text, { children: [
2295
- /* @__PURE__ */ jsx(Text, {
2296
- color: "gray",
2297
- children: " │ "
2298
- }),
2299
- /* @__PURE__ */ jsx(Text, {
2300
- bold: true,
2301
- color: "cyan",
2302
- children: "Your App"
2303
- }),
2304
- /* @__PURE__ */ jsx(Text, {
2305
- color: "gray",
2306
- children: " │"
2307
- })
2308
- ] }),
2309
- /* @__PURE__ */ jsxs(Text, { children: [
2310
- /* @__PURE__ */ jsx(Text, {
2311
- color: "gray",
2312
- children: " │ │ "
2313
- }),
2314
- /* @__PURE__ */ jsx(Text, { children: "posthog.capture()" }),
2315
- /* @__PURE__ */ jsx(Text, {
2316
- color: "gray",
2317
- children: " │"
2318
- })
2319
- ] }),
2320
- /* @__PURE__ */ jsxs(Text, { children: [
2321
- /* @__PURE__ */ jsx(Text, {
2322
- color: "gray",
2323
- children: " │ │ "
2324
- }),
2325
- /* @__PURE__ */ jsx(Text, {
2326
- dimColor: true,
2327
- children: "custom events"
2328
- }),
2329
- /* @__PURE__ */ jsx(Text, {
2330
- color: "gray",
2331
- children: " │"
2332
- })
2333
- ] }),
2334
- /* @__PURE__ */ jsxs(Text, { children: [
2335
- /* @__PURE__ */ jsx(Text, {
2336
- color: "gray",
2337
- children: " │ │ "
2338
- }),
2339
- /* @__PURE__ */ jsx(Text, {
2340
- dimColor: true,
2341
- children: "custom properties"
2342
- }),
2343
- /* @__PURE__ */ jsx(Text, {
2344
- color: "gray",
2345
- children: " │"
2346
- })
2347
- ] }),
2348
- /* @__PURE__ */ jsxs(Text, { children: [
2349
- /* @__PURE__ */ jsx(Text, {
2350
- color: "gray",
2351
- children: " │ │ "
2352
- }),
2353
- /* @__PURE__ */ jsx(Text, {
2354
- dimColor: true,
2355
- children: "person profiles"
2356
- }),
2357
- /* @__PURE__ */ jsx(Text, {
2358
- color: "gray",
2359
- children: " │"
2360
- })
2361
- ] }),
2362
- /* @__PURE__ */ jsxs(Text, { children: [
2363
- /* @__PURE__ */ jsx(Text, {
2364
- color: "gray",
2365
- children: " │ ↓ "
2366
- }),
2367
- /* @__PURE__ */ jsx(Text, {
2368
- dimColor: true,
2369
- children: "groups"
2370
- }),
2371
- /* @__PURE__ */ jsx(Text, {
2372
- color: "gray",
2373
- children: " │"
2374
- })
2375
- ] }),
2376
- /* @__PURE__ */ jsxs(Text, { children: [
2377
- /* @__PURE__ */ jsx(Text, {
2378
- color: "gray",
2379
- children: " │ "
2380
- }),
2173
+ /** Fixed chrome: ScreenContainer (3) + TabContainer tab bar (2) */
2174
+ const FIXED_CHROME = 5;
2175
+ const HEADER_ROWS = 2;
2176
+ const MIN_CONTENT_ROWS = 6;
2177
+ const LearnCard = ({ store, blocks, onComplete }) => {
2178
+ const [columns, rows] = useStdoutDimensions();
2179
+ const statusBarRows = (store ? store.statusMessages.length > 0 : false) ? (store?.statusExpanded ? 10 : 2) + 1 : 0;
2180
+ const contentHeight = rows - FIXED_CHROME - statusBarRows;
2181
+ const tooSmall = contentHeight < MIN_CONTENT_ROWS;
2182
+ const maxHeight = Math.max(1, contentHeight - HEADER_ROWS);
2183
+ const paneWidth = Math.floor((Math.min(120, columns) - 2) / 2) - 2;
2184
+ return /* @__PURE__ */ jsxs(Box, {
2185
+ flexDirection: "column",
2186
+ paddingX: 1,
2187
+ display: tooSmall ? "none" : "flex",
2188
+ children: [
2381
2189
  /* @__PURE__ */ jsx(Text, {
2382
2190
  bold: true,
2383
2191
  color: Colors.accent,
2384
- children: "PostHog SDK"
2385
- }),
2386
- /* @__PURE__ */ jsx(Text, {
2387
- color: "gray",
2388
- children: " │"
2389
- })
2390
- ] }),
2391
- /* @__PURE__ */ jsxs(Text, { children: [
2392
- /* @__PURE__ */ jsx(Text, {
2393
- color: "gray",
2394
- children: " │ ↓ "
2192
+ children: "Learn"
2395
2193
  }),
2396
- /* @__PURE__ */ jsx(Text, { children: "HTTP" }),
2397
- /* @__PURE__ */ jsx(Text, {
2398
- color: "gray",
2399
- children: " │"
2194
+ /* @__PURE__ */ jsx(Box, { height: 1 }),
2195
+ /* @__PURE__ */ jsx(ContentSequencer, {
2196
+ blocks,
2197
+ mode: 2,
2198
+ maxHeight,
2199
+ availableWidth: paneWidth,
2200
+ startDelay: 2e3,
2201
+ initialBlockIdx: store?.learnCardBlockIdx ?? 0,
2202
+ onBlockChange: (idx) => store?.setLearnCardBlockIdx(idx),
2203
+ onSequenceComplete: onComplete
2400
2204
  })
2401
- ] }),
2402
- /* @__PURE__ */ jsxs(Text, { children: [
2403
- /* @__PURE__ */ jsx(Text, {
2404
- color: "gray",
2405
- children: " │ "
2406
- }),
2205
+ ]
2206
+ });
2207
+ };
2208
+ //#endregion
2209
+ //#region src/ui/tui/components/TipsCard.tsx
2210
+ /**
2211
+ * TipsCard — Shows PostHog tips during the agent run.
2212
+ * Reactively shows/hides tips based on discovered features.
2213
+ * Supports toggling additional features via key bindings.
2214
+ */
2215
+ const TIPS = [
2216
+ {
2217
+ id: "persons",
2218
+ title: "You can also track people and groups with PostHog",
2219
+ description: "Events can be associated with the humans who generate them, letting you understand a specific user or customer's situation."
2220
+ },
2221
+ {
2222
+ id: "properties",
2223
+ title: "Get way more detail using properties",
2224
+ description: "Events and person records can have any properties you want. Track things like how they found your website, what subscription tier they choose, and much more."
2225
+ },
2226
+ {
2227
+ id: "stripe",
2228
+ title: "You can track Stripe revenue with PostHog",
2229
+ description: "Add Stripe as a data source while you wait:",
2230
+ url: "https://app.posthog.com/project/data-warehouse/new-source?kind=Stripe",
2231
+ visible: (store) => store.session.discoveredFeatures.includes("stripe")
2232
+ },
2233
+ {
2234
+ id: "llm",
2235
+ title: "PostHog can also help you track your LLM costs",
2236
+ description: "",
2237
+ visible: (store) => store.session.discoveredFeatures.includes("llm"),
2238
+ toggle: {
2239
+ key: "l",
2240
+ feature: "llm",
2241
+ enabledLabel: "LLM analytics setup queued next",
2242
+ prompt: "We detected LLM dependencies in your project.",
2243
+ isEnabled: (store) => store.session.llmOptIn
2244
+ }
2245
+ }
2246
+ ];
2247
+ const TipsCard = ({ store }) => {
2248
+ useInput((input) => {
2249
+ for (const tip of TIPS) if (tip.toggle && input.toLowerCase() === tip.toggle.key && (!tip.visible || tip.visible(store)) && !tip.toggle.isEnabled(store)) store.enableFeature(tip.toggle.feature);
2250
+ });
2251
+ return /* @__PURE__ */ jsxs(Box, {
2252
+ flexDirection: "column",
2253
+ paddingX: 1,
2254
+ children: [
2407
2255
  /* @__PURE__ */ jsx(Text, {
2408
2256
  bold: true,
2409
2257
  color: Colors.accent,
2410
- children: "PostHog Cloud"
2411
- }),
2412
- /* @__PURE__ */ jsx(Text, {
2413
- color: "gray",
2414
- children: " │"
2415
- })
2416
- ] }),
2417
- /* @__PURE__ */ jsxs(Text, { children: [
2418
- /* @__PURE__ */ jsx(Text, {
2419
- color: "gray",
2420
- children: " │ ↓ "
2421
- }),
2422
- /* @__PURE__ */ jsx(Text, { children: "query + visualize" }),
2423
- /* @__PURE__ */ jsx(Text, {
2424
- color: "gray",
2425
- children: " │"
2426
- })
2427
- ] }),
2428
- /* @__PURE__ */ jsxs(Text, { children: [
2429
- /* @__PURE__ */ jsx(Text, {
2430
- color: "gray",
2431
- children: " │ "
2432
- }),
2433
- /* @__PURE__ */ jsx(Text, {
2434
- bold: true,
2435
- color: "green",
2436
- children: "Dashboards & Insights"
2437
- }),
2438
- /* @__PURE__ */ jsx(Text, {
2439
- color: "gray",
2440
- children: " │"
2441
- })
2442
- ] }),
2443
- /* @__PURE__ */ jsx(Text, {
2444
- color: "gray",
2445
- children: " └──────────────────────────────┘"
2446
- })
2447
- ]
2448
- };
2449
- const PRODUCT_SUITE_BLOCK = {
2450
- type: "lines",
2451
- interval: 1e3,
2452
- pause: 15e3,
2453
- lines: [
2454
- /* @__PURE__ */ jsxs(Text, { children: [
2455
- /* @__PURE__ */ jsx(Text, {
2456
- color: "cyan",
2457
- children: " ◆ "
2458
- }),
2459
- "Product Analytics ",
2460
- /* @__PURE__ */ jsx(Text, {
2461
- color: "cyan",
2462
- children: "◆ "
2463
- }),
2464
- "Error Tracking"
2465
- ] }),
2466
- /* @__PURE__ */ jsxs(Text, { children: [
2467
- /* @__PURE__ */ jsx(Text, {
2468
- color: "cyan",
2469
- children: " ◆ "
2470
- }),
2471
- "Web Analytics ",
2472
- /* @__PURE__ */ jsx(Text, {
2473
- color: "cyan",
2474
- children: "◆ "
2475
- }),
2476
- "Session Replay"
2477
- ] }),
2478
- /* @__PURE__ */ jsxs(Text, { children: [
2479
- /* @__PURE__ */ jsx(Text, {
2480
- color: "cyan",
2481
- children: " ◆ "
2482
- }),
2483
- "Feature Flags ",
2484
- /* @__PURE__ */ jsx(Text, {
2485
- color: "cyan",
2486
- children: "◆ "
2487
- }),
2488
- "Data Pipelines"
2489
- ] }),
2490
- /* @__PURE__ */ jsxs(Text, { children: [
2491
- /* @__PURE__ */ jsx(Text, {
2492
- color: "cyan",
2493
- children: " ◆ "
2494
- }),
2495
- "Experiments ",
2496
- /* @__PURE__ */ jsx(Text, {
2497
- color: "cyan",
2498
- children: "◆ "
2499
- }),
2500
- "Data Warehouse"
2501
- ] }),
2502
- /* @__PURE__ */ jsxs(Text, { children: [
2503
- /* @__PURE__ */ jsx(Text, {
2504
- color: "cyan",
2505
- children: " ◆ "
2506
- }),
2507
- "LLM Analytics ",
2508
- /* @__PURE__ */ jsx(Text, {
2509
- color: "cyan",
2510
- children: "◆ "
2511
- }),
2512
- "Surveys"
2513
- ] }),
2514
- /* @__PURE__ */ jsxs(Text, { children: [
2515
- /* @__PURE__ */ jsx(Text, {
2516
- color: "cyan",
2517
- children: " ◆ "
2518
- }),
2519
- "Workflows ",
2520
- /* @__PURE__ */ jsx(Text, {
2521
- color: "cyan",
2522
- children: "◆ "
2523
- }),
2524
- "Logs"
2525
- ] }),
2526
- /* @__PURE__ */ jsxs(Text, { children: [
2527
- /* @__PURE__ */ jsx(Text, {
2528
- color: "cyan",
2529
- children: " ◆ "
2530
- }),
2531
- "Product Tours ",
2532
- /* @__PURE__ */ jsx(Text, {
2533
- color: "cyan",
2534
- children: "◆ "
2535
- }),
2536
- "Support"
2537
- ] }),
2538
- /* @__PURE__ */ jsxs(Text, { children: [
2539
- /* @__PURE__ */ jsx(Text, {
2540
- color: "cyan",
2541
- children: " ◆ "
2542
- }),
2543
- "Revenue Analytics ",
2544
- /* @__PURE__ */ jsx(Text, {
2545
- color: "cyan",
2546
- children: "◆ "
2547
- }),
2548
- "Endpoints"
2549
- ] }),
2550
- /* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
2551
- color: "cyan",
2552
- children: " ◆ "
2553
- }), "Customer Analytics"] })
2554
- ]
2555
- };
2556
- const LINE_CHART_BLOCK = {
2557
- type: "lines",
2558
- interval: 300,
2559
- pause: 6e3,
2560
- lines: [
2561
- /* @__PURE__ */ jsx(Text, {
2562
- bold: true,
2563
- children: " Trends · user signups (monthly)"
2564
- }),
2565
- /* @__PURE__ */ jsx(Text, { children: " " }),
2566
- /* @__PURE__ */ jsxs(Text, { children: [
2567
- /* @__PURE__ */ jsx(Text, {
2568
- color: "gray",
2569
- children: " 10k ┤"
2570
- }),
2571
- " ",
2572
- /* @__PURE__ */ jsx(Text, {
2573
- color: "cyan",
2574
- children: "╭──"
2575
- }),
2576
- /* @__PURE__ */ jsx(Text, {
2577
- dimColor: true,
2578
- children: " 9,575"
2579
- })
2580
- ] }),
2581
- /* @__PURE__ */ jsxs(Text, { children: [
2582
- /* @__PURE__ */ jsx(Text, {
2583
- color: "gray",
2584
- children: " │"
2585
- }),
2586
- " ",
2587
- /* @__PURE__ */ jsx(Text, {
2588
- color: "cyan",
2589
- children: "╭╯"
2590
- })
2591
- ] }),
2592
- /* @__PURE__ */ jsxs(Text, { children: [
2593
- /* @__PURE__ */ jsx(Text, {
2594
- color: "gray",
2595
- children: " 7.5k ┤"
2596
- }),
2597
- " ",
2598
- /* @__PURE__ */ jsx(Text, {
2599
- color: "cyan",
2600
- children: "╭╯"
2601
- })
2602
- ] }),
2603
- /* @__PURE__ */ jsxs(Text, { children: [
2604
- /* @__PURE__ */ jsx(Text, {
2605
- color: "gray",
2606
- children: " │"
2607
- }),
2608
- " ",
2609
- /* @__PURE__ */ jsx(Text, {
2610
- color: "cyan",
2611
- children: "╭─╯"
2612
- })
2613
- ] }),
2614
- /* @__PURE__ */ jsxs(Text, { children: [
2615
- /* @__PURE__ */ jsx(Text, {
2616
- color: "gray",
2617
- children: " 5k ┤"
2618
- }),
2619
- " ",
2620
- /* @__PURE__ */ jsx(Text, {
2621
- color: "cyan",
2622
- children: "╭─╯"
2623
- })
2624
- ] }),
2625
- /* @__PURE__ */ jsxs(Text, { children: [
2626
- /* @__PURE__ */ jsx(Text, {
2627
- color: "gray",
2628
- children: " │"
2629
- }),
2630
- " ",
2631
- /* @__PURE__ */ jsx(Text, {
2632
- color: "cyan",
2633
- children: "╭──╯"
2634
- })
2635
- ] }),
2636
- /* @__PURE__ */ jsxs(Text, { children: [
2637
- /* @__PURE__ */ jsx(Text, {
2638
- color: "gray",
2639
- children: " 2.5k ┤"
2640
- }),
2641
- " ",
2642
- /* @__PURE__ */ jsx(Text, {
2643
- color: "cyan",
2644
- children: "╭───╯"
2645
- })
2646
- ] }),
2647
- /* @__PURE__ */ jsxs(Text, { children: [
2648
- /* @__PURE__ */ jsx(Text, {
2649
- color: "gray",
2650
- children: " │"
2651
- }),
2652
- " ",
2653
- /* @__PURE__ */ jsx(Text, {
2654
- color: "cyan",
2655
- children: "╭──────╯"
2656
- })
2657
- ] }),
2658
- /* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
2659
- color: "gray",
2660
- children: " 0 ┤"
2661
- }), /* @__PURE__ */ jsx(Text, {
2662
- color: "cyan",
2663
- children: "──────╯"
2664
- })] }),
2665
- /* @__PURE__ */ jsx(Text, {
2666
- color: "gray",
2667
- children: " └┬─────┬─────┬─────┬─────┬──"
2668
- }),
2669
- /* @__PURE__ */ jsx(Text, {
2670
- dimColor: true,
2671
- children: " May Aug Nov Feb May"
2672
- })
2673
- ]
2674
- };
2675
- const FUNNEL_BLOCK = {
2676
- type: "lines",
2677
- interval: 200,
2678
- pause: 8e3,
2679
- lines: [
2680
- /* @__PURE__ */ jsx(Text, {
2681
- bold: true,
2682
- children: " Funnel · ride conversion"
2683
- }),
2684
- /* @__PURE__ */ jsx(Text, { children: " " }),
2685
- /* @__PURE__ */ jsxs(Text, { children: [
2686
- " ",
2687
- /* @__PURE__ */ jsx(Text, {
2688
- bold: true,
2689
- children: "1"
2690
- }),
2691
- " app_launched",
2692
- " ",
2693
- /* @__PURE__ */ jsx(Text, {
2694
- bold: true,
2695
- color: "green",
2696
- children: "100.00%"
2697
- })
2698
- ] }),
2699
- /* @__PURE__ */ jsx(Text, {
2700
- color: "cyan",
2701
- children: " ██████████████████████████████"
2702
- }),
2703
- /* @__PURE__ */ jsx(Text, {
2704
- dimColor: true,
2705
- children: " → 1,200 users"
2706
- }),
2707
- /* @__PURE__ */ jsx(Text, { children: " " }),
2708
- /* @__PURE__ */ jsxs(Text, { children: [
2709
- " ",
2710
- /* @__PURE__ */ jsx(Text, {
2711
- bold: true,
2712
- children: "2"
2713
- }),
2714
- " ride_requested",
2715
- " ",
2716
- /* @__PURE__ */ jsx(Text, {
2717
- dimColor: true,
2718
- children: "avg 2m 30s"
2719
- }),
2720
- " ",
2721
- /* @__PURE__ */ jsx(Text, {
2722
- bold: true,
2723
- color: "green",
2724
- children: "72.00%"
2725
- })
2726
- ] }),
2727
- /* @__PURE__ */ jsxs(Text, { children: [
2728
- " ",
2729
- /* @__PURE__ */ jsx(Text, {
2730
- color: "cyan",
2731
- children: "██████████████████████"
2732
- }),
2733
- /* @__PURE__ */ jsx(Text, {
2734
- dimColor: true,
2735
- children: "░░░░░░░░░"
2736
- })
2737
- ] }),
2738
- /* @__PURE__ */ jsxs(Text, { children: [
2739
- " ",
2740
- /* @__PURE__ */ jsx(Text, {
2741
- dimColor: true,
2742
- children: "→ 864 users"
2743
- }),
2744
- " ",
2745
- /* @__PURE__ */ jsx(Text, {
2746
- color: "red",
2747
- children: "↘"
2748
- }),
2749
- /* @__PURE__ */ jsx(Text, {
2750
- dimColor: true,
2751
- children: " 336 (28%)"
2752
- })
2753
- ] }),
2754
- /* @__PURE__ */ jsx(Text, { children: " " }),
2755
- /* @__PURE__ */ jsxs(Text, { children: [
2756
- " ",
2757
- /* @__PURE__ */ jsx(Text, {
2758
- bold: true,
2759
- children: "3"
2760
- }),
2761
- " ride_accepted",
2762
- " ",
2763
- /* @__PURE__ */ jsx(Text, {
2764
- dimColor: true,
2765
- children: "avg 5m 12s"
2766
- }),
2767
- " ",
2768
- /* @__PURE__ */ jsx(Text, {
2769
- bold: true,
2770
- color: "green",
2771
- children: "51.00%"
2772
- })
2773
- ] }),
2774
- /* @__PURE__ */ jsxs(Text, { children: [
2775
- " ",
2776
- /* @__PURE__ */ jsx(Text, {
2777
- color: "cyan",
2778
- children: "██████████████████"
2779
- }),
2780
- /* @__PURE__ */ jsx(Text, {
2781
- dimColor: true,
2782
- children: "░░░░░░░░░░░░░"
2783
- })
2784
- ] }),
2785
- /* @__PURE__ */ jsxs(Text, { children: [
2786
- " ",
2787
- /* @__PURE__ */ jsx(Text, {
2788
- dimColor: true,
2789
- children: "→ 612 users"
2790
- }),
2791
- " ",
2792
- /* @__PURE__ */ jsx(Text, {
2793
- color: "red",
2794
- children: "↘"
2795
- }),
2796
- /* @__PURE__ */ jsx(Text, {
2797
- dimColor: true,
2798
- children: " 252 (29%)"
2799
- })
2800
- ] }),
2801
- /* @__PURE__ */ jsx(Text, { children: " " }),
2802
- /* @__PURE__ */ jsxs(Text, { children: [
2803
- " ",
2804
- /* @__PURE__ */ jsx(Text, {
2805
- bold: true,
2806
- children: "4"
2807
- }),
2808
- " ride_started",
2809
- " ",
2810
- /* @__PURE__ */ jsx(Text, {
2811
- dimColor: true,
2812
- children: "avg 1m 45s"
2813
- }),
2814
- " ",
2815
- /* @__PURE__ */ jsx(Text, {
2816
- bold: true,
2817
- color: "green",
2818
- children: "38.00%"
2819
- })
2820
- ] }),
2821
- /* @__PURE__ */ jsxs(Text, { children: [
2822
- " ",
2823
- /* @__PURE__ */ jsx(Text, {
2824
- color: "cyan",
2825
- children: "█████████████"
2826
- }),
2827
- /* @__PURE__ */ jsx(Text, {
2828
- dimColor: true,
2829
- children: "░░░░░░░░░░░░░░░░░░"
2830
- })
2831
- ] }),
2832
- /* @__PURE__ */ jsxs(Text, { children: [
2833
- " ",
2834
- /* @__PURE__ */ jsx(Text, {
2835
- dimColor: true,
2836
- children: "→ 456 users"
2837
- }),
2838
- " ",
2839
- /* @__PURE__ */ jsx(Text, {
2840
- color: "red",
2841
- children: "↘"
2842
- }),
2843
- /* @__PURE__ */ jsx(Text, {
2844
- dimColor: true,
2845
- children: " 156 (25%)"
2846
- })
2847
- ] })
2848
- ]
2849
- };
2850
- /** Fixed chrome: ScreenContainer (3) + TabContainer tab bar (2) */
2851
- const FIXED_CHROME = 5;
2852
- const HEADER_ROWS = 2;
2853
- const MIN_CONTENT_ROWS = 6;
2854
- const LearnCard = ({ store, onComplete }) => {
2855
- const peekedRef = useRef(false);
2856
- const [columns, rows] = useStdoutDimensions();
2857
- const blocks = useMemo(() => [
2858
- {
2859
- content: "Welcome.",
2860
- pause: 3e3,
2861
- mode: 0,
2862
- animationInterval: 160
2863
- },
2864
- {
2865
- content: "The Wizard is an agent.",
2866
- pause: 4e3
2867
- },
2868
- {
2869
- content: "It handles the entire PostHog setup process on your behalf.",
2870
- pause: 5e3
2871
- },
2872
- {
2873
- content: "As we speak, it's building a plan to set up PostHog in your project.",
2874
- pause: 6e3
2875
- },
2876
- {
2877
- type: "clear",
2878
- pause: 2e3
2879
- },
2880
- {
2881
- pause: 5e3,
2882
- persist: true,
2883
- content: /* @__PURE__ */ jsx(StatusPeekTrigger, {
2884
- store,
2885
- peekedRef
2886
- })
2887
- },
2888
- {
2889
- pause: 6e3,
2890
- content: /* @__PURE__ */ jsxs(Text, { children: [
2891
- "Press",
2892
- " ",
2893
- /* @__PURE__ */ jsx(Text, {
2894
- color: Colors.accent,
2895
- bold: true,
2896
- children: "S"
2897
- }),
2898
- " ",
2899
- "to expand or collapse the status."
2900
- ] })
2901
- },
2902
- {
2903
- type: "clear",
2904
- pause: 2e3
2905
- },
2906
- {
2907
- content: "It takes about eight minutes.",
2908
- pause: 2e3
2909
- },
2910
- {
2911
- content: "So grab some coffee ☕️.",
2912
- pause: 2e3
2913
- },
2914
- {
2915
- content: "Or stick around and learn about PostHog.",
2916
- pause: 5e3
2917
- },
2918
- {
2919
- type: "clear",
2920
- pause: 3e3
2921
- },
2922
- {
2923
- content: "Events are the foundation of the PostHog platform.",
2924
- pause: 4e3
2925
- },
2926
- {
2927
- content: "Every time an action is performed in your codebase — like button clicks, function calls, or thrown errors — we can capture an event.",
2928
- pause: 6e3
2929
- },
2930
- {
2931
- content: "Events are sent to PostHog and joined with other product data.",
2932
- pause: 6e3
2933
- },
2934
- {
2935
- type: "clear",
2936
- pause: 1e3
2937
- },
2938
- {
2939
- content: "Here's the flow.",
2940
- pause: 1e3
2941
- },
2942
- POSTHOG_DATA_FLOW,
2943
- {
2944
- type: "clear",
2945
- pause: 2e3
2946
- },
2947
- {
2948
- content: "With enough event data, you can answer powerful questions about your product.",
2949
- pause: 4e3
2950
- },
2951
- {
2952
- content: "And create insights.",
2953
- pause: 4e3
2954
- },
2955
- {
2956
- type: "clear",
2957
- pause: 500
2958
- },
2959
- {
2960
- content: "Like trends to measure growth.",
2961
- pause: 2500
2962
- },
2963
- LINE_CHART_BLOCK,
2964
- {
2965
- type: "clear",
2966
- pause: 500
2967
- },
2968
- {
2969
- content: "Or funnels to reveal bottlenecks.",
2970
- pause: 2500
2971
- },
2972
- FUNNEL_BLOCK,
2973
- {
2974
- type: "clear",
2975
- pause: 1e3
2976
- },
2977
- {
2978
- content: "Use those signals to decide what to build next.",
2979
- pause: 4e3
2980
- },
2981
- {
2982
- content: "PostHog has all the dev tools you need.",
2983
- pause: 3e3
2984
- },
2985
- PRODUCT_SUITE_BLOCK
2986
- ], [store]);
2987
- const statusBarRows = (store ? store.statusMessages.length > 0 : false) ? (store?.statusExpanded ? 10 : 2) + 1 : 0;
2988
- const contentHeight = rows - FIXED_CHROME - statusBarRows;
2989
- const tooSmall = contentHeight < MIN_CONTENT_ROWS;
2990
- const maxHeight = Math.max(1, contentHeight - HEADER_ROWS);
2991
- const paneWidth = Math.floor((Math.min(120, columns) - 2) / 2) - 2;
2992
- return /* @__PURE__ */ jsxs(Box, {
2993
- flexDirection: "column",
2994
- paddingX: 1,
2995
- display: tooSmall ? "none" : "flex",
2996
- children: [
2997
- /* @__PURE__ */ jsx(Text, {
2998
- bold: true,
2999
- color: Colors.accent,
3000
- children: "Learn"
3001
- }),
3002
- /* @__PURE__ */ jsx(Box, { height: 1 }),
3003
- /* @__PURE__ */ jsx(ContentSequencer, {
3004
- blocks,
3005
- mode: 2,
3006
- maxHeight,
3007
- availableWidth: paneWidth,
3008
- startDelay: 2e3,
3009
- initialBlockIdx: store?.learnCardBlockIdx ?? 0,
3010
- onBlockChange: (idx) => store?.setLearnCardBlockIdx(idx),
3011
- onSequenceComplete: onComplete
3012
- })
3013
- ]
3014
- });
3015
- };
3016
- //#endregion
3017
- //#region src/ui/tui/components/TipsCard.tsx
3018
- /**
3019
- * TipsCard — Shows PostHog tips during the agent run.
3020
- * Reactively shows/hides tips based on discovered features.
3021
- * Supports toggling additional features via key bindings.
3022
- */
3023
- const TIPS = [
3024
- {
3025
- id: "persons",
3026
- title: "You can also track people and groups with PostHog",
3027
- description: "Events can be associated with the humans who generate them, letting you understand a specific user or customer's situation."
3028
- },
3029
- {
3030
- id: "properties",
3031
- title: "Get way more detail using properties",
3032
- description: "Events and person records can have any properties you want. Track things like how they found your website, what subscription tier they choose, and much more."
3033
- },
3034
- {
3035
- id: "stripe",
3036
- title: "You can track Stripe revenue with PostHog",
3037
- description: "Add Stripe as a data source while you wait:",
3038
- url: "https://app.posthog.com/project/data-warehouse/new-source?kind=Stripe",
3039
- visible: (store) => store.session.discoveredFeatures.includes("stripe")
3040
- },
3041
- {
3042
- id: "llm",
3043
- title: "PostHog can also help you track your LLM costs",
3044
- description: "",
3045
- visible: (store) => store.session.discoveredFeatures.includes("llm"),
3046
- toggle: {
3047
- key: "l",
3048
- feature: "llm",
3049
- enabledLabel: "LLM analytics setup queued next",
3050
- prompt: "We detected LLM dependencies in your project.",
3051
- isEnabled: (store) => store.session.llmOptIn
3052
- }
3053
- }
3054
- ];
3055
- const TipsCard = ({ store }) => {
3056
- useInput((input) => {
3057
- for (const tip of TIPS) if (tip.toggle && input.toLowerCase() === tip.toggle.key && (!tip.visible || tip.visible(store)) && !tip.toggle.isEnabled(store)) store.enableFeature(tip.toggle.feature);
3058
- });
3059
- return /* @__PURE__ */ jsxs(Box, {
3060
- flexDirection: "column",
3061
- paddingX: 1,
3062
- children: [
3063
- /* @__PURE__ */ jsx(Text, {
3064
- bold: true,
3065
- color: Colors.accent,
3066
- children: "Tips"
2258
+ children: "Tips"
3067
2259
  }),
3068
2260
  /* @__PURE__ */ jsx(Box, { height: 1 }),
3069
2261
  TIPS.filter((tip) => !tip.visible || tip.visible(store)).map((tip) => /* @__PURE__ */ jsxs(Box, {
@@ -3893,6 +3085,382 @@ const AuditChecksViewer = ({ checks }) => {
3893
3085
  });
3894
3086
  };
3895
3087
  //#endregion
3896
- export { CardLayout as C, WizardStore as E, SplitView as S, Icons as T, useStdoutDimensions as _, SEVERITY_ORDER as a, ProgressList as b, LearnCard as c, ScreenContainer as d, EventPlanViewer as f, GroupedPickerMenu as g, ConfirmationInput as h, SEVERITY_LABEL as i, HNViewer as l, ModalOverlay as m, McpScreen as n, ServiceHealthList as o, LogViewer as p, IssueTable as r, TipsCard as s, AuditChecksViewer as t, TabContainer as u, PickerMenu as v, Colors as w, LoadingBox as x, useKeyBindings as y };
3088
+ //#region src/ui/tui/screens/audit/slides/shared.tsx
3089
+ /** Narrow bordered box for the small ASCII illustrations in baseline slides. */
3090
+ const VisualBox = ({ children }) => /* @__PURE__ */ jsx(Box, {
3091
+ borderStyle: "single",
3092
+ borderColor: Colors.muted,
3093
+ paddingX: 1,
3094
+ flexDirection: "column",
3095
+ marginBottom: 1,
3096
+ children
3097
+ });
3098
+ //#endregion
3099
+ //#region src/ui/tui/screens/audit/slides/installation.tsx
3100
+ const InstallationVisual = () => /* @__PURE__ */ jsxs(VisualBox, { children: [
3101
+ /* @__PURE__ */ jsx(Text, {
3102
+ dimColor: true,
3103
+ children: "app boot"
3104
+ }),
3105
+ /* @__PURE__ */ jsxs(Text, { children: [
3106
+ /* @__PURE__ */ jsx(Text, {
3107
+ dimColor: true,
3108
+ children: " ▼ "
3109
+ }),
3110
+ /* @__PURE__ */ jsx(Text, {
3111
+ color: "green",
3112
+ children: "posthog.init(...)"
3113
+ }),
3114
+ /* @__PURE__ */ jsx(Text, {
3115
+ dimColor: true,
3116
+ children: " once"
3117
+ })
3118
+ ] }),
3119
+ /* @__PURE__ */ jsx(Text, {
3120
+ dimColor: true,
3121
+ children: " │"
3122
+ }),
3123
+ /* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
3124
+ dimColor: true,
3125
+ children: " ▼ "
3126
+ }), /* @__PURE__ */ jsx(Text, {
3127
+ color: "cyan",
3128
+ children: "posthog.capture('pageview')"
3129
+ })] }),
3130
+ /* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
3131
+ dimColor: true,
3132
+ children: " "
3133
+ }), /* @__PURE__ */ jsx(Text, {
3134
+ color: "cyan",
3135
+ children: "posthog.capture('signup')"
3136
+ })] }),
3137
+ /* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
3138
+ dimColor: true,
3139
+ children: " "
3140
+ }), /* @__PURE__ */ jsx(Text, {
3141
+ color: "cyan",
3142
+ children: "posthog.capture('purchase')"
3143
+ })] })
3144
+ ] });
3145
+ const InstallationSlide = {
3146
+ area: "Installation",
3147
+ intro: [
3148
+ "PostHog releases frequent SDK updates to fix bugs and add new features. We're checking your project's SDK version and making sure it's up to date.",
3149
+ "We're also checking that your SDK is initialized correctly and in the right part of your app's lifecycle.",
3150
+ "This ensures you won't miss any autocaptured events."
3151
+ ],
3152
+ visual: /* @__PURE__ */ jsx(InstallationVisual, {}),
3153
+ docsUrl: "https://posthog.com/docs/getting-started/install"
3154
+ };
3155
+ //#endregion
3156
+ //#region src/ui/tui/screens/audit/slides/identification.tsx
3157
+ const IdentificationVisual = () => /* @__PURE__ */ jsxs(VisualBox, { children: [
3158
+ /* @__PURE__ */ jsxs(Text, { children: [
3159
+ /* @__PURE__ */ jsx(Text, {
3160
+ bold: true,
3161
+ children: "browser "
3162
+ }),
3163
+ /* @__PURE__ */ jsx(Text, {
3164
+ dimColor: true,
3165
+ children: "capture"
3166
+ }),
3167
+ /* @__PURE__ */ jsx(Text, { children: " (" }),
3168
+ /* @__PURE__ */ jsx(Text, {
3169
+ color: "cyan",
3170
+ children: "u_42"
3171
+ }),
3172
+ /* @__PURE__ */ jsx(Text, { children: ", \"click\")" })
3173
+ ] }),
3174
+ /* @__PURE__ */ jsx(Text, {
3175
+ dimColor: true,
3176
+ children: " │"
3177
+ }),
3178
+ /* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
3179
+ dimColor: true,
3180
+ children: " ▼ "
3181
+ }), /* @__PURE__ */ jsx(Text, {
3182
+ color: "green",
3183
+ children: "same distinct_id"
3184
+ })] }),
3185
+ /* @__PURE__ */ jsx(Text, {
3186
+ dimColor: true,
3187
+ children: " │"
3188
+ }),
3189
+ /* @__PURE__ */ jsxs(Text, { children: [
3190
+ /* @__PURE__ */ jsx(Text, {
3191
+ bold: true,
3192
+ children: "server "
3193
+ }),
3194
+ /* @__PURE__ */ jsx(Text, {
3195
+ dimColor: true,
3196
+ children: "capture"
3197
+ }),
3198
+ /* @__PURE__ */ jsx(Text, { children: " (" }),
3199
+ /* @__PURE__ */ jsx(Text, {
3200
+ color: "cyan",
3201
+ children: "u_42"
3202
+ }),
3203
+ /* @__PURE__ */ jsx(Text, { children: ", \"charged\")" })
3204
+ ] })
3205
+ ] });
3206
+ const IdentificationSlide = {
3207
+ area: "Identification",
3208
+ intro: [
3209
+ "For events to be useful, they need to be reliably attributed to a user.",
3210
+ "We're checking your project's `identify()` calls to make sure they're correctly and consistently implemented.",
3211
+ "We're also checking that your `distinct_id`s are correctly passed between your client and server runtimes if applicable."
3212
+ ],
3213
+ visual: /* @__PURE__ */ jsx(IdentificationVisual, {}),
3214
+ docsUrl: "https://posthog.com/docs/product-analytics/identify"
3215
+ };
3216
+ //#endregion
3217
+ //#region src/ui/tui/screens/audit/slides/eventCapture.tsx
3218
+ const CaptureVisual = () => /* @__PURE__ */ jsxs(VisualBox, { children: [
3219
+ /* @__PURE__ */ jsxs(Text, { children: [
3220
+ /* @__PURE__ */ jsx(Text, {
3221
+ color: "cyan",
3222
+ children: "pageview "
3223
+ }),
3224
+ /* @__PURE__ */ jsx(Text, {
3225
+ color: "green",
3226
+ children: "████████████"
3227
+ }),
3228
+ /* @__PURE__ */ jsx(Text, {
3229
+ dimColor: true,
3230
+ children: " 1000"
3231
+ })
3232
+ ] }),
3233
+ /* @__PURE__ */ jsxs(Text, { children: [
3234
+ /* @__PURE__ */ jsx(Text, {
3235
+ color: "cyan",
3236
+ children: "signup "
3237
+ }),
3238
+ /* @__PURE__ */ jsx(Text, {
3239
+ color: "green",
3240
+ children: "████████"
3241
+ }),
3242
+ /* @__PURE__ */ jsx(Text, {
3243
+ dimColor: true,
3244
+ children: " 640"
3245
+ })
3246
+ ] }),
3247
+ /* @__PURE__ */ jsxs(Text, { children: [
3248
+ /* @__PURE__ */ jsx(Text, {
3249
+ color: "cyan",
3250
+ children: "activated "
3251
+ }),
3252
+ /* @__PURE__ */ jsx(Text, {
3253
+ color: "green",
3254
+ children: "█████"
3255
+ }),
3256
+ /* @__PURE__ */ jsx(Text, {
3257
+ dimColor: true,
3258
+ children: " 410"
3259
+ })
3260
+ ] }),
3261
+ /* @__PURE__ */ jsxs(Text, { children: [
3262
+ /* @__PURE__ */ jsx(Text, {
3263
+ color: "cyan",
3264
+ children: "purchased "
3265
+ }),
3266
+ /* @__PURE__ */ jsx(Text, {
3267
+ color: "green",
3268
+ children: "██"
3269
+ }),
3270
+ /* @__PURE__ */ jsx(Text, {
3271
+ dimColor: true,
3272
+ children: " 120"
3273
+ })
3274
+ ] })
3275
+ ] });
3276
+ const EventCaptureSlide = {
3277
+ area: "Event Capture",
3278
+ intro: [
3279
+ "Everything you do in PostHog starts with event captures. Every dashboard, insight, funnel, cohort, and replay is built on top of events.",
3280
+ "We're checking that your project's event capture calls cover key user actions and use sensible event names, so you can build high-quality insights and reports.",
3281
+ "We're also checking that you use a reverse proxy so your events are not blocked by ad blockers or tracking blockers."
3282
+ ],
3283
+ visual: /* @__PURE__ */ jsx(CaptureVisual, {}),
3284
+ docsUrl: "https://posthog.com/docs/product-analytics/capture-events"
3285
+ };
3286
+ //#endregion
3287
+ //#region src/ui/tui/screens/audit/slides/index.ts
3288
+ const AUDIT_AREA_SLIDES = [
3289
+ InstallationSlide,
3290
+ IdentificationSlide,
3291
+ EventCaptureSlide
3292
+ ];
3293
+ //#endregion
3294
+ //#region src/ui/tui/screens/audit-3000/slides/eventQuality.tsx
3295
+ const EventQualityVisual = () => /* @__PURE__ */ jsxs(VisualBox, { children: [
3296
+ /* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
3297
+ color: "green",
3298
+ children: "event_clicked "
3299
+ }), /* @__PURE__ */ jsx(Text, {
3300
+ color: "green",
3301
+ children: "✓"
3302
+ })] }),
3303
+ /* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
3304
+ color: "yellow",
3305
+ children: "eventClicked "
3306
+ }), /* @__PURE__ */ jsx(Text, {
3307
+ color: "yellow",
3308
+ children: "~ duplicate?"
3309
+ })] }),
3310
+ /* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
3311
+ color: "yellow",
3312
+ children: "click_event "
3313
+ }), /* @__PURE__ */ jsx(Text, {
3314
+ color: "yellow",
3315
+ children: "~ duplicate?"
3316
+ })] }),
3317
+ /* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
3318
+ color: "red",
3319
+ children: "big_kitchen_sink "
3320
+ }), /* @__PURE__ */ jsx(Text, {
3321
+ color: "red",
3322
+ children: "✗ 22 props"
3323
+ })] })
3324
+ ] });
3325
+ const EventQualitySlide = {
3326
+ area: "Event Quality",
3327
+ intro: [
3328
+ "LEVEL 5: EVENT QUALITY. The capture call-sites are clean. The events themselves are the real boss fight.",
3329
+ "Scanning for: naming inconsistencies, semantic duplicates, kitchen-sink event payloads, and (if your PostHog project is linked) which captured events actually drive insights and dashboards.",
3330
+ "4 subagents fan out in parallel. The ticker shows them clearing checks live."
3331
+ ],
3332
+ visual: /* @__PURE__ */ jsx(EventQualityVisual, {}),
3333
+ docsUrl: "https://posthog.com/docs/product-analytics/best-practices"
3334
+ };
3335
+ //#endregion
3336
+ //#region src/ui/tui/screens/audit-3000/slides/featureFlags.tsx
3337
+ const FeatureFlagsVisual = () => /* @__PURE__ */ jsxs(VisualBox, { children: [
3338
+ /* @__PURE__ */ jsxs(Text, { children: [
3339
+ /* @__PURE__ */ jsx(Text, {
3340
+ color: "red",
3341
+ children: "new-checkout-v2 "
3342
+ }),
3343
+ /* @__PURE__ */ jsx(Text, {
3344
+ dimColor: true,
3345
+ children: "no code refs "
3346
+ }),
3347
+ /* @__PURE__ */ jsx(Text, {
3348
+ color: "red",
3349
+ children: "DROP"
3350
+ })
3351
+ ] }),
3352
+ /* @__PURE__ */ jsxs(Text, { children: [
3353
+ /* @__PURE__ */ jsx(Text, {
3354
+ color: "yellow",
3355
+ children: "beta-dashboard "
3356
+ }),
3357
+ /* @__PURE__ */ jsx(Text, {
3358
+ dimColor: true,
3359
+ children: "1 ref, 100% on "
3360
+ }),
3361
+ /* @__PURE__ */ jsx(Text, {
3362
+ color: "yellow",
3363
+ children: "REVIEW"
3364
+ })
3365
+ ] }),
3366
+ /* @__PURE__ */ jsxs(Text, { children: [
3367
+ /* @__PURE__ */ jsx(Text, {
3368
+ color: "green",
3369
+ children: "killswitch-payments"
3370
+ }),
3371
+ /* @__PURE__ */ jsx(Text, {
3372
+ dimColor: true,
3373
+ children: "live experiment"
3374
+ }),
3375
+ /* @__PURE__ */ jsx(Text, {
3376
+ color: "green",
3377
+ children: "KEEP"
3378
+ })
3379
+ ] })
3380
+ ] });
3381
+ const FeatureFlagsSlide = {
3382
+ area: "Feature Flags",
3383
+ intro: [
3384
+ "LEVEL 6: STALE FLAGS. Old flags add evaluation overhead and confuse the next engineer who wonders if a flag is still live.",
3385
+ "Cross-referencing PostHog's stale-flag classification against your source tree. Each flag scored: safe-to-disable, needs-review, or unknown.",
3386
+ "The final report ships with a copy-paste cleanup prompt. We never touch a flag."
3387
+ ],
3388
+ visual: /* @__PURE__ */ jsx(FeatureFlagsVisual, {}),
3389
+ docsUrl: "https://posthog.com/docs/feature-flags"
3390
+ };
3391
+ //#endregion
3392
+ //#region src/ui/tui/screens/audit-3000/slides/expansion.tsx
3393
+ const ExpansionVisual = () => /* @__PURE__ */ jsxs(VisualBox, { children: [
3394
+ /* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
3395
+ color: "cyan",
3396
+ children: "product analytics "
3397
+ }), /* @__PURE__ */ jsx(Text, {
3398
+ color: "green",
3399
+ children: "■■■■■"
3400
+ })] }),
3401
+ /* @__PURE__ */ jsxs(Text, { children: [
3402
+ /* @__PURE__ */ jsx(Text, {
3403
+ color: "cyan",
3404
+ children: "error tracking "
3405
+ }),
3406
+ /* @__PURE__ */ jsx(Text, {
3407
+ color: "red",
3408
+ children: "□□□□□"
3409
+ }),
3410
+ /* @__PURE__ */ jsx(Text, {
3411
+ dimColor: true,
3412
+ children: " sentry detected"
3413
+ })
3414
+ ] }),
3415
+ /* @__PURE__ */ jsxs(Text, { children: [
3416
+ /* @__PURE__ */ jsx(Text, {
3417
+ color: "cyan",
3418
+ children: "session replay "
3419
+ }),
3420
+ /* @__PURE__ */ jsx(Text, {
3421
+ color: "yellow",
3422
+ children: "■■□□□"
3423
+ }),
3424
+ /* @__PURE__ */ jsx(Text, {
3425
+ dimColor: true,
3426
+ children: " partial"
3427
+ })
3428
+ ] }),
3429
+ /* @__PURE__ */ jsxs(Text, { children: [
3430
+ /* @__PURE__ */ jsx(Text, {
3431
+ color: "cyan",
3432
+ children: "llm observability "
3433
+ }),
3434
+ /* @__PURE__ */ jsx(Text, {
3435
+ color: "red",
3436
+ children: "□□□□□"
3437
+ }),
3438
+ /* @__PURE__ */ jsx(Text, {
3439
+ dimColor: true,
3440
+ children: " greenfield"
3441
+ })
3442
+ ] })
3443
+ ] });
3444
+ //#endregion
3445
+ //#region src/ui/tui/screens/audit-3000/slides/index.ts
3446
+ const AUDIT_3000_AREA_SLIDES = [
3447
+ InstallationSlide,
3448
+ IdentificationSlide,
3449
+ EventCaptureSlide,
3450
+ EventQualitySlide,
3451
+ FeatureFlagsSlide,
3452
+ {
3453
+ area: "Use Case: Expansion",
3454
+ intro: [
3455
+ "BONUS ROUND: EXPANSION. You might be paying for tools PostHog covers natively.",
3456
+ "Scanning for competitive SDKs (Sentry, LaunchDarkly, Mixpanel, Datadog, OpenTelemetry, GA4) and PostHog coverage gaps across 8 product surfaces.",
3457
+ "8 subagents in two waves of 4. Each one returns one of: cross-sell, greenfield, gap, or pass."
3458
+ ],
3459
+ visual: /* @__PURE__ */ jsx(ExpansionVisual, {}),
3460
+ docsUrl: "https://posthog.com/docs"
3461
+ }
3462
+ ];
3463
+ //#endregion
3464
+ export { ProgressList as C, WizardStore as D, CardLayout as E, useKeyBindings as S, SplitView as T, ModalOverlay as _, IssueTable as a, useStdoutDimensions as b, ServiceHealthList as c, ContentSequencer as d, HNViewer as f, LogViewer as g, EventPlanViewer as h, McpScreen as i, TipsCard as l, ScreenContainer as m, AUDIT_AREA_SLIDES as n, SEVERITY_LABEL as o, TabContainer as p, AuditChecksViewer as r, SEVERITY_ORDER as s, AUDIT_3000_AREA_SLIDES as t, LearnCard as u, ConfirmationInput as v, LoadingBox as w, PickerMenu as x, GroupedPickerMenu as y };
3897
3465
 
3898
- //# sourceMappingURL=AuditChecksViewer-CjBCZjxG.js.map
3466
+ //# sourceMappingURL=slides-yyC_W0RZ.js.map