@posthog/wizard 2.13.1 → 2.14.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +0 -26
- package/README.md +1 -1
- package/dist/TextBlock-B3cm43YY.js +244 -0
- package/dist/TextBlock-B3cm43YY.js.map +1 -0
- package/dist/{add-mcp-server-to-clients-D1IyBa9u.js → add-mcp-server-to-clients-DVdyI6SQ.js} +7 -7
- package/dist/{add-mcp-server-to-clients-D1IyBa9u.js.map → add-mcp-server-to-clients-DVdyI6SQ.js.map} +1 -1
- package/dist/{agent-interface-D9DeIikl.js → agent-interface-BJoqBI04.js} +533 -255
- package/dist/agent-interface-BJoqBI04.js.map +1 -0
- package/dist/{agent-runner-B41-Iig3.js → agent-runner-oJ7Wyhl7.js} +102 -20
- package/dist/agent-runner-oJ7Wyhl7.js.map +1 -0
- package/dist/analytics-Cz_p0Xus.js +2 -0
- package/dist/{analytics-Cek5hIwm.js → analytics-kUCNQQJm.js} +2 -2
- package/dist/{analytics-Cek5hIwm.js.map → analytics-kUCNQQJm.js.map} +1 -1
- package/dist/bin.js +951 -141
- package/dist/bin.js.map +1 -1
- package/dist/{debug-B2BH87dh.js → debug-BH8HMBNX.js} +26 -21
- package/dist/debug-BH8HMBNX.js.map +1 -0
- package/dist/{debug-BNWsxaDm.js → debug-CgsJTJOO.js} +1 -1
- package/dist/{defaults-GbLPuHxj.js → defaults-DgKAzsD1.js} +1 -1
- package/dist/{defaults-GbLPuHxj.js.map → defaults-DgKAzsD1.js.map} +1 -1
- package/dist/{detection-BFl2AYV6.js → detection-DWNUEyek.js} +4 -4
- package/dist/detection-DWNUEyek.js.map +1 -0
- package/dist/{file-8iNrXHkG.js → file-BKbKreWF.js} +1 -1
- package/dist/{file-8iNrXHkG.js.map → file-BKbKreWF.js.map} +1 -1
- package/dist/{file-utils-DnTSiTJw.js → file-utils-DPmgn9Vm.js} +1 -1
- package/dist/{file-utils-DnTSiTJw.js.map → file-utils-DPmgn9Vm.js.map} +1 -1
- package/dist/{package-json-F_7oktsp.js → package-json-DZpnf6vU.js} +8 -10
- package/dist/package-json-DZpnf6vU.js.map +1 -0
- package/dist/package-json-_4PEss19.js +2 -0
- package/dist/{package-manager-BBTvHn9i.js → package-manager-DmDoOiaW.js} +2 -2
- package/dist/{package-manager-BBTvHn9i.js.map → package-manager-DmDoOiaW.js.map} +1 -1
- package/dist/{posthog-vm0k9PKS.js → posthog-BbQf_Hzq.js} +1 -1
- package/dist/{posthog-vm0k9PKS.js.map → posthog-BbQf_Hzq.js.map} +1 -1
- package/dist/posthog-integration-DZgP-ysj.js +1012 -0
- package/dist/posthog-integration-DZgP-ysj.js.map +1 -0
- package/dist/{provisioning-DRwH4skH.js → provisioning-Buqple4U.js} +3 -3
- package/dist/{provisioning-DRwH4skH.js.map → provisioning-Buqple4U.js.map} +1 -1
- package/dist/provisioning-CAf6fMWM.js +2 -0
- package/dist/{registry-CZjMhhsK.js → registry-PGYX7928.js} +5 -5
- package/dist/{registry-CZjMhhsK.js.map → registry-PGYX7928.js.map} +1 -1
- package/dist/setup-utils-LGtFkuI1.js +2 -0
- package/dist/{setup-utils-DGUR4Djo.js → setup-utils-xt6Z8gik.js} +77 -107
- package/dist/setup-utils-xt6Z8gik.js.map +1 -0
- package/dist/{AuditChecksViewer-CjBCZjxG.js → slides-0xga1duy.js} +626 -1058
- package/dist/slides-0xga1duy.js.map +1 -0
- package/dist/smoke-test-ci.sh +4 -4
- package/dist/{start-playground-DPYl5WR-.js → start-playground-DYElnFW1.js} +259 -10
- package/dist/start-playground-DYElnFW1.js.map +1 -0
- package/dist/{start-tui-Cj_4BhK8.js → start-tui-BBhG-LSW.js} +288 -446
- package/dist/start-tui-BBhG-LSW.js.map +1 -0
- package/dist/{steps-BFD76-MP.js → steps-B9mb9qRe.js} +7 -7
- package/dist/{steps-BFD76-MP.js.map → steps-B9mb9qRe.js.map} +1 -1
- package/dist/{task-stream-CX7Uf6EM.js → task-stream-DUpUZmFQ.js} +8 -8
- package/dist/task-stream-DUpUZmFQ.js.map +1 -0
- package/dist/telemetry-BFwKBgCJ.js +13 -0
- package/dist/telemetry-BFwKBgCJ.js.map +1 -0
- package/dist/{wizard-abort-54DpTnUi.js → wizard-abort-DWwOHzHR.js} +3 -3
- package/dist/{wizard-abort-54DpTnUi.js.map → wizard-abort-DWwOHzHR.js.map} +1 -1
- package/dist/{wizard-abort-CZH03nD0.js → wizard-abort-Djz2J6p9.js} +1 -1
- package/dist/wizard-session-CPhhll4P.js +2 -0
- package/dist/{wizard-session-BcNJTl2I.js → wizard-session-CsI33S4_.js} +6 -3
- package/dist/wizard-session-CsI33S4_.js.map +1 -0
- package/dist/wizard-ui-YdGFRyu_.js.map +1 -1
- package/package.json +3 -2
- package/dist/AuditChecksViewer-CjBCZjxG.js.map +0 -1
- package/dist/agent-interface-D9DeIikl.js.map +0 -1
- package/dist/agent-runner-B41-Iig3.js.map +0 -1
- package/dist/analytics-CpbY05Lf.js +0 -2
- package/dist/debug-B2BH87dh.js.map +0 -1
- package/dist/detection-BFl2AYV6.js.map +0 -1
- package/dist/package-json-BzVey4Bd.js +0 -2
- package/dist/package-json-F_7oktsp.js.map +0 -1
- package/dist/posthog-integration-vFBuSN5U.js +0 -259
- package/dist/posthog-integration-vFBuSN5U.js.map +0 -1
- package/dist/provisioning--RCv39tI.js +0 -2
- package/dist/router-COhhuIW3.js +0 -135
- package/dist/router-COhhuIW3.js.map +0 -1
- package/dist/setup-utils-DGUR4Djo.js.map +0 -1
- package/dist/setup-utils-eh1450iu.js +0 -2
- package/dist/start-playground-DPYl5WR-.js.map +0 -1
- package/dist/start-tui-Cj_4BhK8.js.map +0 -1
- package/dist/task-stream-CX7Uf6EM.js.map +0 -1
- package/dist/telemetry-DCyjsXhw.js +0 -13
- package/dist/telemetry-DCyjsXhw.js.map +0 -1
- package/dist/wizard-session-BQC9vy9Z.js +0 -2
- package/dist/wizard-session-BcNJTl2I.js.map +0 -1
- package/npm-shrinkwrap.json +0 -2931
|
@@ -1,17 +1,110 @@
|
|
|
1
|
-
import { d as SERVICE_LABELS } from "./debug-
|
|
1
|
+
import { d as SERVICE_LABELS } from "./debug-BH8HMBNX.js";
|
|
2
2
|
import { n as isTaskStatus } from "./wizard-ui-YdGFRyu_.js";
|
|
3
|
-
import { n as analytics, r as sessionProperties } from "./analytics-
|
|
4
|
-
import { r as buildSession } from "./wizard-session-
|
|
5
|
-
import {
|
|
6
|
-
import { r as
|
|
7
|
-
import { n as
|
|
8
|
-
import {
|
|
3
|
+
import { n as analytics, r as sessionProperties } from "./analytics-kUCNQQJm.js";
|
|
4
|
+
import { r as buildSession } from "./wizard-session-CsI33S4_.js";
|
|
5
|
+
import { _ as AUDIT_SEVERITY_STYLE } from "./agent-interface-BJoqBI04.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
|
|
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
|
-
|
|
55
|
-
|
|
56
|
-
|
|
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
|
|
154
|
+
* Scan program steps for gate predicates and onInit callbacks.
|
|
60
155
|
* Creates gate promises and fires init work.
|
|
61
156
|
*/
|
|
62
|
-
|
|
63
|
-
const steps =
|
|
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
|
|
186
|
+
* need to know which program has which pre-flow work.
|
|
93
187
|
*/
|
|
94
188
|
async runReadyHooks() {
|
|
95
|
-
const steps =
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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 —
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
*
|
|
2268
|
-
*
|
|
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
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
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: "
|
|
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(
|
|
2397
|
-
/* @__PURE__ */ jsx(
|
|
2398
|
-
|
|
2399
|
-
|
|
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
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
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: "
|
|
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
|
-
|
|
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=
|
|
3466
|
+
//# sourceMappingURL=slides-0xga1duy.js.map
|