@posthog/wizard 2.11.0 → 2.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +48 -7
- package/dist/{McpScreen-DvUncZBi.js → AuditChecksViewer-DsfXIO9e.js} +330 -21
- package/dist/AuditChecksViewer-DsfXIO9e.js.map +1 -0
- package/dist/{add-mcp-server-to-clients-Br1hDRiB.js → add-mcp-server-to-clients-BKoew3aT.js} +5 -5
- package/dist/{add-mcp-server-to-clients-Br1hDRiB.js.map → add-mcp-server-to-clients-BKoew3aT.js.map} +1 -1
- package/dist/{readiness-gQvQNCeL.js → agent-interface-D5W9BAB2.js} +326 -461
- package/dist/agent-interface-D5W9BAB2.js.map +1 -0
- package/dist/{agent-runner-fWYFO4H0.js → agent-runner-B8Cx6X6x.js} +19 -30
- package/dist/{agent-runner-fWYFO4H0.js.map → agent-runner-B8Cx6X6x.js.map} +1 -1
- package/dist/analytics-DmD31Ssc.js +123 -0
- package/dist/analytics-DmD31Ssc.js.map +1 -0
- package/dist/analytics-JDitS2JI.js +2 -0
- package/dist/bin.js +324 -42
- package/dist/bin.js.map +1 -1
- package/dist/debug-Bkaqv1ab.js +686 -0
- package/dist/debug-Bkaqv1ab.js.map +1 -0
- package/dist/{debug-D-0xueVl.js → debug-I5sRZubJ.js} +1 -1
- package/dist/{defaults-CPH6eWhN.js → defaults-GbLPuHxj.js} +1 -1
- package/dist/{defaults-CPH6eWhN.js.map → defaults-GbLPuHxj.js.map} +1 -1
- package/dist/{detection-B7GNzve-.js → detection-C_RfYYDe.js} +3 -3
- package/dist/{detection-B7GNzve-.js.map → detection-C_RfYYDe.js.map} +1 -1
- package/dist/{env-api-key-DU8uIEvo.js → env-api-key-D5G2PrXW.js} +1 -1
- package/dist/{env-api-key-DU8uIEvo.js.map → env-api-key-D5G2PrXW.js.map} +1 -1
- package/dist/{file-DhSBlq-x.js → file-8iNrXHkG.js} +2 -2
- package/dist/{file-DhSBlq-x.js.map → file-8iNrXHkG.js.map} +1 -1
- package/dist/{file-utils-Dy9JncCo.js → file-utils-DnTSiTJw.js} +1 -1
- package/dist/{file-utils-Dy9JncCo.js.map → file-utils-DnTSiTJw.js.map} +1 -1
- package/dist/{package-manager-D3Lo6nXf.js → package-manager-qxP2PpM_.js} +2 -2
- package/dist/{package-manager-D3Lo6nXf.js.map → package-manager-qxP2PpM_.js.map} +1 -1
- package/dist/paths-DJS47p5x.js +26 -0
- package/dist/paths-DJS47p5x.js.map +1 -0
- package/dist/{posthog-integration-D4SRhJIQ.js → posthog-integration-DX77Msto.js} +41 -13
- package/dist/posthog-integration-DX77Msto.js.map +1 -0
- package/dist/{posthog-ByrpqEjN.js → posthog-vm0k9PKS.js} +1 -1
- package/dist/{posthog-ByrpqEjN.js.map → posthog-vm0k9PKS.js.map} +1 -1
- package/dist/provisioning-CHfTOEvg.js +2 -0
- package/dist/provisioning-DUj285NO.js +166 -0
- package/dist/provisioning-DUj285NO.js.map +1 -0
- package/dist/{registry-DaPKstG3.js → registry-CCtIsqb8.js} +4 -5
- package/dist/{registry-DaPKstG3.js.map → registry-CCtIsqb8.js.map} +1 -1
- package/dist/{router-SgzmfLGi.js → router-BTfmEDDJ.js} +3 -3
- package/dist/router-BTfmEDDJ.js.map +1 -0
- package/dist/{setup-utils-y4s-3uKT.js → setup-utils-Bv8z6HMb.js} +11 -150
- package/dist/setup-utils-Bv8z6HMb.js.map +1 -0
- package/dist/setup-utils-CoX-vLgw.js +2 -0
- package/dist/{start-playground-g1TxpCZ5.js → start-playground-DYNQ8rOz.js} +102 -7
- package/dist/start-playground-DYNQ8rOz.js.map +1 -0
- package/dist/{start-tui-CQef69NR.js → start-tui-DleQG3La.js} +969 -124
- package/dist/start-tui-DleQG3La.js.map +1 -0
- package/dist/{steps-D1zKDqAo.js → steps-C-syS8if.js} +8 -8
- package/dist/steps-C-syS8if.js.map +1 -0
- package/dist/{task-stream-DX_jKDQu.js → task-stream-CX7Uf6EM.js} +4 -4
- package/dist/{task-stream-DX_jKDQu.js.map → task-stream-CX7Uf6EM.js.map} +1 -1
- package/dist/{telemetry-CyUUSAYy.js → telemetry-DHZfjgqx.js} +2 -2
- package/dist/{telemetry-CyUUSAYy.js.map → telemetry-DHZfjgqx.js.map} +1 -1
- package/dist/{wizard-abort-DZmO_sIZ.js → wizard-abort-DIhFXJ5N.js} +1 -1
- package/dist/{wizard-abort-Buodno3f.js → wizard-abort-DfhWuzaw.js} +6 -4
- package/dist/{wizard-abort-Buodno3f.js.map → wizard-abort-DfhWuzaw.js.map} +1 -1
- package/dist/wizard-session-BQC9vy9Z.js +2 -0
- package/dist/{wizard-session-D5bggSsu.js → wizard-session-BcNJTl2I.js} +1 -1
- package/dist/{wizard-session-D5bggSsu.js.map → wizard-session-BcNJTl2I.js.map} +1 -1
- package/dist/{wizard-ui-BExOjdjA.js → wizard-ui-YdGFRyu_.js} +1 -1
- package/dist/wizard-ui-YdGFRyu_.js.map +1 -0
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/dist/McpScreen-DvUncZBi.js.map +0 -1
- package/dist/agent-skill-DJOzDaQV.js +0 -59
- package/dist/agent-skill-DJOzDaQV.js.map +0 -1
- package/dist/analytics-CfAUlt6-.js +0 -2
- package/dist/analytics-D3rY3TaN.js +0 -210
- package/dist/analytics-D3rY3TaN.js.map +0 -1
- package/dist/debug-gWEjmYVV.js +0 -203
- package/dist/debug-gWEjmYVV.js.map +0 -1
- package/dist/paths-BL-x2rFy.js +0 -16
- package/dist/paths-BL-x2rFy.js.map +0 -1
- package/dist/posthog-integration-D4SRhJIQ.js.map +0 -1
- package/dist/readiness-gQvQNCeL.js.map +0 -1
- package/dist/router-SgzmfLGi.js.map +0 -1
- package/dist/setup-utils-_ONxN-TT.js +0 -2
- package/dist/setup-utils-y4s-3uKT.js.map +0 -1
- package/dist/start-playground-g1TxpCZ5.js.map +0 -1
- package/dist/start-tui-CQef69NR.js.map +0 -1
- package/dist/steps-D1zKDqAo.js.map +0 -1
- package/dist/wizard-session-COhklXAF.js +0 -2
- package/dist/wizard-ui-BExOjdjA.js.map +0 -1
|
@@ -1,22 +1,25 @@
|
|
|
1
|
-
import { l as setUI, s as logToFile } from "./debug-
|
|
2
|
-
import {
|
|
3
|
-
import { n as
|
|
4
|
-
import { l as ApiError, p as getUiHostFromHost } from "./setup-utils-
|
|
5
|
-
import { t as ADDITIONAL_FEATURE_LABELS } from "./wizard-session-
|
|
6
|
-
import { r as wizardAbort } from "./wizard-abort-
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import "./
|
|
12
|
-
import
|
|
13
|
-
import {
|
|
1
|
+
import { C as Integration, D as POSTHOG_DOCS_URL, H as getSkillsBaseUrl, N as REMOTE_SKILLS_BASE_URL, R as WIZARD_TOOLS_MENU_FLAG_KEY, f as SIGNUP_WIZARD_READINESS_CONFIG, l as setUI, m as getBlockingServiceKeys, s as logToFile, w as OAUTH_PORTS } from "./debug-Bkaqv1ab.js";
|
|
2
|
+
import { a as relativeToInstallDir, n as WIZARD_LOG_FILE } from "./paths-DJS47p5x.js";
|
|
3
|
+
import { n as analytics } from "./analytics-DmD31Ssc.js";
|
|
4
|
+
import { l as ApiError, p as getUiHostFromHost } from "./setup-utils-Bv8z6HMb.js";
|
|
5
|
+
import { t as ADDITIONAL_FEATURE_LABELS } from "./wizard-session-BcNJTl2I.js";
|
|
6
|
+
import { r as wizardAbort } from "./wizard-abort-DfhWuzaw.js";
|
|
7
|
+
import { _ as coerceAuditChecks, d as fetchSkillMenu, g as AUDIT_SEVERITY_STYLE, h as AUDIT_REPORT_FILE, m as AUDIT_CHECKS_KEY, p as AUDIT_CHECKS_FILE, u as downloadSkill, v as getAuditChecks } from "./agent-interface-D5W9BAB2.js";
|
|
8
|
+
import { t as EVENT_PLAN_FILE } from "./posthog-integration-DX77Msto.js";
|
|
9
|
+
import { a as POSTHOG_SDKS, o as STRIPE_SDKS, r as fetchHealthIssues } from "./bin.js";
|
|
10
|
+
import { t as ALL_FEATURE_VALUES } from "./defaults-GbLPuHxj.js";
|
|
11
|
+
import { a as getSupportedClients, c as removeMCPServer, i as getInstalledClients, o as getSupportedPluginClients, s as installPlugins, u as isPluginCapable } from "./add-mcp-server-to-clients-BKoew3aT.js";
|
|
12
|
+
import "./router-BTfmEDDJ.js";
|
|
13
|
+
import { C as Colors, T as WizardStore, _ as useStdoutDimensions, a as SEVERITY_ORDER, b as LoadingBox, c as LearnCard, d as ScreenContainer, f as EventPlanViewer, h as ConfirmationInput, i as SEVERITY_LABEL, l as HNViewer, m as ModalOverlay, n as McpScreen, o as ServiceHealthList, p as LogViewer, r as IssueTable, s as TipsCard, t as AuditChecksViewer, u as TabContainer, v as PickerMenu, w as Icons, x as SplitView, y as ProgressList } from "./AuditChecksViewer-DsfXIO9e.js";
|
|
14
|
+
import { spawn, spawnSync } from "node:child_process";
|
|
14
15
|
import { join } from "node:path";
|
|
16
|
+
import * as fs$1 from "fs";
|
|
15
17
|
import path from "path";
|
|
16
18
|
import { Box, Text, render, useInput } from "ink";
|
|
17
|
-
import { createElement, useEffect, useMemo, useState, useSyncExternalStore } from "react";
|
|
18
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
19
|
-
import {
|
|
19
|
+
import { Fragment, createElement, useEffect, useMemo, useState, useSyncExternalStore } from "react";
|
|
20
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
21
|
+
import { Spinner } from "@inkjs/ui";
|
|
22
|
+
import { access, readdir, rm } from "node:fs/promises";
|
|
20
23
|
//#region src/ui/tui/ink-ui.ts
|
|
21
24
|
const ANSI_RE = /\x1b\[[0-9;]*m/g;
|
|
22
25
|
function stripAnsi(s) {
|
|
@@ -31,7 +34,8 @@ var InkUI = class {
|
|
|
31
34
|
}
|
|
32
35
|
outro(message) {
|
|
33
36
|
this.store.pushStatus(stripAnsi(message));
|
|
34
|
-
|
|
37
|
+
const existing = this.store.session.outroData;
|
|
38
|
+
this.store.setOutroData(existing ?? {
|
|
35
39
|
kind: "success",
|
|
36
40
|
message: stripAnsi(message)
|
|
37
41
|
});
|
|
@@ -41,6 +45,20 @@ var InkUI = class {
|
|
|
41
45
|
this.store.setOutroData(data);
|
|
42
46
|
if (this.store.session.runPhase !== "error") this.store.setRunPhase("error");
|
|
43
47
|
}
|
|
48
|
+
waitForOutroDismissed() {
|
|
49
|
+
return new Promise((resolve) => {
|
|
50
|
+
if (this.store.session.outroDismissed) {
|
|
51
|
+
resolve();
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const unsub = this.store.subscribe(() => {
|
|
55
|
+
if (this.store.session.outroDismissed) {
|
|
56
|
+
unsub();
|
|
57
|
+
resolve();
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
}
|
|
44
62
|
setCredentials(credentials) {
|
|
45
63
|
this.store.setCredentials(credentials);
|
|
46
64
|
}
|
|
@@ -117,6 +135,9 @@ var InkUI = class {
|
|
|
117
135
|
setEventPlan(events) {
|
|
118
136
|
this.store.setEventPlan(events);
|
|
119
137
|
}
|
|
138
|
+
setFrameworkContext(key, value) {
|
|
139
|
+
this.store.setFrameworkContext(key, value);
|
|
140
|
+
}
|
|
120
141
|
};
|
|
121
142
|
//#endregion
|
|
122
143
|
//#region src/ui/tui/screens/health/HealthCheckScreen.tsx
|
|
@@ -177,14 +198,18 @@ const HealthCheckScreen = ({ store }) => {
|
|
|
177
198
|
justifyContent: "center",
|
|
178
199
|
children: /* @__PURE__ */ jsx(LoadingBox, { message: "Checking service status..." })
|
|
179
200
|
});
|
|
180
|
-
const
|
|
181
|
-
|
|
182
|
-
const
|
|
201
|
+
const isSignup = store.session.signup;
|
|
202
|
+
const blockingKeys = getBlockingServiceKeys(result.health, isSignup ? SIGNUP_WIZARD_READINESS_CONFIG : void 0);
|
|
203
|
+
const warningKeys = isSignup ? getBlockingServiceKeys(result.health).filter((k) => !blockingKeys.includes(k)) : [];
|
|
204
|
+
const hasHardBlock = blockingKeys.length > 0;
|
|
205
|
+
const displayKeys = hasHardBlock ? blockingKeys : warningKeys;
|
|
206
|
+
if (displayKeys.length === 0) return null;
|
|
207
|
+
const isGithubReleasesDown = hasHardBlock && blockingKeys.includes("githubReleases");
|
|
183
208
|
const canDownloadSkills = result.health.githubReleases.status === "healthy";
|
|
184
209
|
const integration = store.session.integration;
|
|
185
|
-
const title =
|
|
210
|
+
const title = hasHardBlock ? "Ongoing service disruptions" : "Service disruption detected";
|
|
186
211
|
const docsUrl = store.session.frameworkConfig?.metadata.docsUrl;
|
|
187
|
-
const description = isGithubReleasesDown ? "The Wizard can't download necessary skills from GitHub Releases right now." : "The Wizard
|
|
212
|
+
const description = isGithubReleasesDown ? "The Wizard can't download necessary skills from GitHub Releases right now." : hasHardBlock ? "The Wizard cannot start while these services are down." : "Some services are degraded. You can continue, but parts of the wizard may not work reliably.";
|
|
188
213
|
const handleDownloadAndExit = async () => {
|
|
189
214
|
if (downloading) return;
|
|
190
215
|
setDownloading(true);
|
|
@@ -197,7 +222,7 @@ const HealthCheckScreen = ({ store }) => {
|
|
|
197
222
|
setDownloaded(true);
|
|
198
223
|
};
|
|
199
224
|
return /* @__PURE__ */ jsxs(ModalOverlay, {
|
|
200
|
-
borderColor: "red",
|
|
225
|
+
borderColor: hasHardBlock ? "red" : "yellow",
|
|
201
226
|
title,
|
|
202
227
|
width: 72,
|
|
203
228
|
footer: isGithubReleasesDown ? /* @__PURE__ */ jsx(ConfirmationInput, {
|
|
@@ -239,7 +264,7 @@ const HealthCheckScreen = ({ store }) => {
|
|
|
239
264
|
] })
|
|
240
265
|
}), /* @__PURE__ */ jsx(ServiceHealthList, {
|
|
241
266
|
health: result.health,
|
|
242
|
-
filterKeys:
|
|
267
|
+
filterKeys: displayKeys,
|
|
243
268
|
showHealthy: false
|
|
244
269
|
})]
|
|
245
270
|
}),
|
|
@@ -699,7 +724,7 @@ const IntroScreenLayout = ({ installDir, title = "PostHog Wizard 🦔", showSubt
|
|
|
699
724
|
children: /* @__PURE__ */ jsx(WizardTitle, { title })
|
|
700
725
|
}), errorView]
|
|
701
726
|
});
|
|
702
|
-
return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs(Box, {
|
|
727
|
+
return /* @__PURE__ */ jsx(Fragment$1, { children: /* @__PURE__ */ jsxs(Box, {
|
|
703
728
|
flexDirection: "column",
|
|
704
729
|
flexGrow: 1,
|
|
705
730
|
alignItems: "center",
|
|
@@ -790,6 +815,69 @@ const IntroScreenLayout = ({ installDir, title = "PostHog Wizard 🦔", showSubt
|
|
|
790
815
|
}) });
|
|
791
816
|
};
|
|
792
817
|
//#endregion
|
|
818
|
+
//#region src/ui/tui/screens/SkillSourceInfo.tsx
|
|
819
|
+
/**
|
|
820
|
+
* Shared "Skill: <id> / URL: <downloadUrl>" block for intro screens.
|
|
821
|
+
*
|
|
822
|
+
* `useSkillEntry` fetches the entry from the skill menu and re-runs when
|
|
823
|
+
* `skillId` or `local` change. The previous fetch is cancelled (its result
|
|
824
|
+
* is ignored) so a session that flips `local=false → true` mid-mount picks
|
|
825
|
+
* up the right base URL.
|
|
826
|
+
*
|
|
827
|
+
* `<SkillSourceInfo>` renders the block, taking the entry as a prop so the
|
|
828
|
+
* caller can reuse the same hook result for additional UI (e.g. showing
|
|
829
|
+
* `skillEntry.name`) without invoking the hook twice.
|
|
830
|
+
*/
|
|
831
|
+
function useSkillEntry(skillId, local) {
|
|
832
|
+
const [skillEntry, setSkillEntry] = useState(null);
|
|
833
|
+
const [fetchFailed, setFetchFailed] = useState(false);
|
|
834
|
+
useEffect(() => {
|
|
835
|
+
if (!skillId) {
|
|
836
|
+
setFetchFailed(true);
|
|
837
|
+
return;
|
|
838
|
+
}
|
|
839
|
+
let cancelled = false;
|
|
840
|
+
setSkillEntry(null);
|
|
841
|
+
setFetchFailed(false);
|
|
842
|
+
fetchSkillMenu(getSkillsBaseUrl(local)).then((menu) => {
|
|
843
|
+
if (cancelled) return;
|
|
844
|
+
if (!menu) {
|
|
845
|
+
setFetchFailed(true);
|
|
846
|
+
return;
|
|
847
|
+
}
|
|
848
|
+
const match = Object.values(menu.categories).flat().find((s) => s.id === skillId);
|
|
849
|
+
if (match) setSkillEntry(match);
|
|
850
|
+
else setFetchFailed(true);
|
|
851
|
+
});
|
|
852
|
+
return () => {
|
|
853
|
+
cancelled = true;
|
|
854
|
+
};
|
|
855
|
+
}, [skillId, local]);
|
|
856
|
+
return {
|
|
857
|
+
skillEntry,
|
|
858
|
+
fetchFailed
|
|
859
|
+
};
|
|
860
|
+
}
|
|
861
|
+
const SkillSourceInfo = ({ skillId, skillEntry, fetchFailed }) => /* @__PURE__ */ jsxs(Box, {
|
|
862
|
+
flexDirection: "column",
|
|
863
|
+
children: [/* @__PURE__ */ jsxs(Text, { children: [
|
|
864
|
+
"Skill:",
|
|
865
|
+
" ",
|
|
866
|
+
/* @__PURE__ */ jsx(Text, {
|
|
867
|
+
italic: true,
|
|
868
|
+
color: "cyan",
|
|
869
|
+
children: skillId ?? "unknown"
|
|
870
|
+
})
|
|
871
|
+
] }), /* @__PURE__ */ jsxs(Text, { children: [
|
|
872
|
+
"URL:",
|
|
873
|
+
" ",
|
|
874
|
+
/* @__PURE__ */ jsx(Text, {
|
|
875
|
+
color: "cyan",
|
|
876
|
+
children: skillEntry?.downloadUrl ?? (fetchFailed ? "unavailable" : "Loading...")
|
|
877
|
+
})
|
|
878
|
+
] })]
|
|
879
|
+
});
|
|
880
|
+
//#endregion
|
|
793
881
|
//#region src/ui/tui/screens/PostHogIntegrationIntroScreen.tsx
|
|
794
882
|
/**
|
|
795
883
|
* PostHogIntegrationIntroScreen — Intro screen for the core PostHog integration.
|
|
@@ -825,7 +913,7 @@ const FrameworkPicker = ({ store, onComplete }) => {
|
|
|
825
913
|
})),
|
|
826
914
|
onSelect: (value) => {
|
|
827
915
|
const integration = Array.isArray(value) ? value[0] : value;
|
|
828
|
-
import("./registry-
|
|
916
|
+
import("./registry-CCtIsqb8.js").then((n) => n.n).then(({ FRAMEWORK_REGISTRY }) => {
|
|
829
917
|
const config = FRAMEWORK_REGISTRY[integration];
|
|
830
918
|
store.setFrameworkConfig(integration, config);
|
|
831
919
|
store.setDetectedFramework(config.metadata.name);
|
|
@@ -853,6 +941,7 @@ const PostHogIntegrationIntroScreen = ({ store }) => {
|
|
|
853
941
|
const { session } = store;
|
|
854
942
|
const config = session.frameworkConfig;
|
|
855
943
|
const frameworkLabel = session.detectedFrameworkLabel ?? config?.metadata.name;
|
|
944
|
+
const { skillEntry, fetchFailed } = useSkillEntry(session.skillId, session.localMcp);
|
|
856
945
|
const detecting = !session.detectionComplete;
|
|
857
946
|
const needsFrameworkPick = session.detectionComplete && !session.frameworkConfig;
|
|
858
947
|
const unsupported = session.unsupportedVersion;
|
|
@@ -863,7 +952,7 @@ const PostHogIntegrationIntroScreen = ({ store }) => {
|
|
|
863
952
|
marginY: 1,
|
|
864
953
|
children: /* @__PURE__ */ jsx(LoadingBox, { message: "Detecting project framework..." })
|
|
865
954
|
});
|
|
866
|
-
else if (needsFrameworkPick && !pickingFramework) body = /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Box, {
|
|
955
|
+
else if (needsFrameworkPick && !pickingFramework) body = /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Box, {
|
|
867
956
|
marginY: 1,
|
|
868
957
|
children: /* @__PURE__ */ jsx(Text, {
|
|
869
958
|
dimColor: true,
|
|
@@ -912,21 +1001,21 @@ const PostHogIntegrationIntroScreen = ({ store }) => {
|
|
|
912
1001
|
/* @__PURE__ */ jsxs(Text, { children: [`\u2022`, " Error Tracking"] })
|
|
913
1002
|
]
|
|
914
1003
|
}),
|
|
915
|
-
/* @__PURE__ */
|
|
1004
|
+
/* @__PURE__ */ jsxs(Box, {
|
|
916
1005
|
flexDirection: "column",
|
|
917
1006
|
marginTop: 1,
|
|
918
|
-
children: /* @__PURE__ */
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
1007
|
+
children: [/* @__PURE__ */ jsx(Text, { children: "If you prefer your own AI setup, download the skill:" }), /* @__PURE__ */ jsx(Box, {
|
|
1008
|
+
marginTop: 1,
|
|
1009
|
+
children: /* @__PURE__ */ jsx(SkillSourceInfo, {
|
|
1010
|
+
skillId: session.skillId,
|
|
1011
|
+
skillEntry,
|
|
1012
|
+
fetchFailed
|
|
924
1013
|
})
|
|
925
|
-
|
|
1014
|
+
})]
|
|
926
1015
|
})
|
|
927
1016
|
]
|
|
928
1017
|
});
|
|
929
|
-
else if (showContinue) body = /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Text, { children: "Let's do two hours of work in eight minutes." }) }) });
|
|
1018
|
+
else if (showContinue) body = /* @__PURE__ */ jsx(Fragment$1, { children: /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Text, { children: "Let's do two hours of work in eight minutes." }) }) });
|
|
930
1019
|
const detectionRows = [];
|
|
931
1020
|
if (frameworkLabel) {
|
|
932
1021
|
const suffixParts = [];
|
|
@@ -1116,7 +1205,7 @@ const RevenueIntroScreen = ({ store }) => {
|
|
|
1116
1205
|
]
|
|
1117
1206
|
})
|
|
1118
1207
|
]
|
|
1119
|
-
}) : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs(Box, {
|
|
1208
|
+
}) : /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs(Box, {
|
|
1120
1209
|
flexDirection: "column",
|
|
1121
1210
|
alignItems: "center",
|
|
1122
1211
|
children: [/* @__PURE__ */ jsx(Text, { children: "Let's create revenue analytics with Stripe and PostHog." }), /* @__PURE__ */ jsx(Box, {
|
|
@@ -1144,7 +1233,7 @@ const RevenueIntroScreen = ({ store }) => {
|
|
|
1144
1233
|
]
|
|
1145
1234
|
}, p))]
|
|
1146
1235
|
})] });
|
|
1147
|
-
const errorView = detectError ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs(Box, {
|
|
1236
|
+
const errorView = detectError ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs(Box, {
|
|
1148
1237
|
flexDirection: "column",
|
|
1149
1238
|
marginBottom: 1,
|
|
1150
1239
|
children: [/* @__PURE__ */ jsxs(Text, {
|
|
@@ -1206,7 +1295,7 @@ const DetectErrorBody = ({ error }) => {
|
|
|
1206
1295
|
"not-dir": "is not a directory",
|
|
1207
1296
|
unreadable: "could not be accessed"
|
|
1208
1297
|
}[error.reason];
|
|
1209
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs(Text, { children: [
|
|
1298
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs(Text, { children: [
|
|
1210
1299
|
"This path ",
|
|
1211
1300
|
reasonText,
|
|
1212
1301
|
":"
|
|
@@ -1215,7 +1304,7 @@ const DetectErrorBody = ({ error }) => {
|
|
|
1215
1304
|
children: [" ", error.path]
|
|
1216
1305
|
})] });
|
|
1217
1306
|
}
|
|
1218
|
-
case "no-package-json": return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1307
|
+
case "no-package-json": return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
1219
1308
|
/* @__PURE__ */ jsx(Text, { children: "No package.json found in this directory." }),
|
|
1220
1309
|
/* @__PURE__ */ jsx(Text, {
|
|
1221
1310
|
dimColor: true,
|
|
@@ -1226,7 +1315,7 @@ const DetectErrorBody = ({ error }) => {
|
|
|
1226
1315
|
children: "Run this command from your project root."
|
|
1227
1316
|
})
|
|
1228
1317
|
] });
|
|
1229
|
-
case "no-sdks": return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1318
|
+
case "no-sdks": return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
1230
1319
|
/* @__PURE__ */ jsxs(Text, { children: [
|
|
1231
1320
|
"Neither PostHog nor Stripe SDKs detected (scanned",
|
|
1232
1321
|
" ",
|
|
@@ -1275,7 +1364,7 @@ const DetectErrorBody = ({ error }) => {
|
|
|
1275
1364
|
})
|
|
1276
1365
|
})
|
|
1277
1366
|
] });
|
|
1278
|
-
case "missing-posthog": return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs(Text, { children: [
|
|
1367
|
+
case "missing-posthog": return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs(Text, { children: [
|
|
1279
1368
|
"Found Stripe (",
|
|
1280
1369
|
error.foundStripe.join(", "),
|
|
1281
1370
|
") but no PostHog SDK."
|
|
@@ -1293,7 +1382,7 @@ const DetectErrorBody = ({ error }) => {
|
|
|
1293
1382
|
]
|
|
1294
1383
|
})
|
|
1295
1384
|
})] });
|
|
1296
|
-
case "missing-stripe": return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1385
|
+
case "missing-stripe": return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
1297
1386
|
/* @__PURE__ */ jsxs(Text, { children: [
|
|
1298
1387
|
"Found PostHog (",
|
|
1299
1388
|
error.foundPosthog.join(", "),
|
|
@@ -1324,37 +1413,17 @@ const DetectErrorBody = ({ error }) => {
|
|
|
1324
1413
|
//#endregion
|
|
1325
1414
|
//#region src/ui/tui/screens/AgentSkillIntroScreen.tsx
|
|
1326
1415
|
/**
|
|
1327
|
-
* AgentSkillIntroScreen —
|
|
1416
|
+
* AgentSkillIntroScreen — Default intro for generic agent-skill workflows.
|
|
1328
1417
|
*
|
|
1329
|
-
*
|
|
1330
|
-
*
|
|
1418
|
+
* Workflows that need a different intro ship their own screen component
|
|
1419
|
+
* (see audit/AuditIntroScreen.tsx).
|
|
1331
1420
|
*/
|
|
1332
1421
|
const AgentSkillIntroScreen = ({ store }) => {
|
|
1333
1422
|
useSyncExternalStore((cb) => store.subscribe(cb), () => store.getSnapshot());
|
|
1334
1423
|
const [showingMoreInfo, setShowingMoreInfo] = useState(false);
|
|
1335
|
-
const [skillEntry, setSkillEntry] = useState(null);
|
|
1336
|
-
const [fetchFailed, setFetchFailed] = useState(false);
|
|
1337
1424
|
const { session } = store;
|
|
1338
1425
|
const skillId = session.skillId ?? "unknown";
|
|
1339
|
-
const
|
|
1340
|
-
useEffect(() => {
|
|
1341
|
-
if (!showingMoreInfo || skillEntry || fetchFailed) return;
|
|
1342
|
-
fetchSkillMenu(getSkillsBaseUrl(session.localMcp)).then((menu) => {
|
|
1343
|
-
if (!menu) {
|
|
1344
|
-
setFetchFailed(true);
|
|
1345
|
-
return;
|
|
1346
|
-
}
|
|
1347
|
-
const match = Object.values(menu.categories).flat().find((s) => s.id === skillId);
|
|
1348
|
-
if (match) setSkillEntry(match);
|
|
1349
|
-
else setFetchFailed(true);
|
|
1350
|
-
});
|
|
1351
|
-
}, [
|
|
1352
|
-
showingMoreInfo,
|
|
1353
|
-
skillEntry,
|
|
1354
|
-
fetchFailed,
|
|
1355
|
-
skillId,
|
|
1356
|
-
session.localMcp
|
|
1357
|
-
]);
|
|
1426
|
+
const { skillEntry, fetchFailed } = useSkillEntry(skillId, session.localMcp);
|
|
1358
1427
|
let body;
|
|
1359
1428
|
if (showingMoreInfo) body = /* @__PURE__ */ jsxs(Box, {
|
|
1360
1429
|
flexDirection: "column",
|
|
@@ -1369,23 +1438,11 @@ const AgentSkillIntroScreen = ({ store }) => {
|
|
|
1369
1438
|
children: "https://github.com/PostHog/wizard"
|
|
1370
1439
|
})] })
|
|
1371
1440
|
}),
|
|
1372
|
-
/* @__PURE__ */
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
color: "cyan",
|
|
1378
|
-
children: skillEntry?.id ?? skillId
|
|
1379
|
-
})
|
|
1380
|
-
] }),
|
|
1381
|
-
/* @__PURE__ */ jsxs(Text, { children: [
|
|
1382
|
-
"URL:",
|
|
1383
|
-
" ",
|
|
1384
|
-
/* @__PURE__ */ jsx(Text, {
|
|
1385
|
-
color: "cyan",
|
|
1386
|
-
children: skillEntry?.downloadUrl ?? (fetchFailed ? "unavailable" : "Loading...")
|
|
1387
|
-
})
|
|
1388
|
-
] }),
|
|
1441
|
+
/* @__PURE__ */ jsx(SkillSourceInfo, {
|
|
1442
|
+
skillId,
|
|
1443
|
+
skillEntry,
|
|
1444
|
+
fetchFailed
|
|
1445
|
+
}),
|
|
1389
1446
|
/* @__PURE__ */ jsx(Box, {
|
|
1390
1447
|
marginTop: 1,
|
|
1391
1448
|
children: /* @__PURE__ */ jsx(Text, {
|
|
@@ -1433,7 +1490,7 @@ const AgentSkillIntroScreen = ({ store }) => {
|
|
|
1433
1490
|
installDir: session.installDir,
|
|
1434
1491
|
showSubtitle: !showingMoreInfo,
|
|
1435
1492
|
body,
|
|
1436
|
-
showDetection:
|
|
1493
|
+
showDetection: !showingMoreInfo,
|
|
1437
1494
|
workflowLabel: session.workflowLabel,
|
|
1438
1495
|
skillId: session.skillId,
|
|
1439
1496
|
menuOptions,
|
|
@@ -1441,6 +1498,780 @@ const AgentSkillIntroScreen = ({ store }) => {
|
|
|
1441
1498
|
});
|
|
1442
1499
|
};
|
|
1443
1500
|
//#endregion
|
|
1501
|
+
//#region src/ui/tui/screens/audit/AuditIntroScreen.tsx
|
|
1502
|
+
const AUDIT_SKILL_ID = "audit";
|
|
1503
|
+
const AuditIntroScreen = ({ store }) => {
|
|
1504
|
+
useSyncExternalStore((cb) => store.subscribe(cb), () => store.getSnapshot());
|
|
1505
|
+
const [showingMoreInfo, setShowingMoreInfo] = useState(false);
|
|
1506
|
+
const { session } = store;
|
|
1507
|
+
const { skillEntry, fetchFailed } = useSkillEntry(AUDIT_SKILL_ID, session.localMcp);
|
|
1508
|
+
const body = showingMoreInfo ? /* @__PURE__ */ jsxs(Box, {
|
|
1509
|
+
flexDirection: "column",
|
|
1510
|
+
width: 56,
|
|
1511
|
+
children: [
|
|
1512
|
+
/* @__PURE__ */ jsx(Box, {
|
|
1513
|
+
marginBottom: 1,
|
|
1514
|
+
children: /* @__PURE__ */ jsxs(Text, { children: ["The wizard is an agent that executes PostHog tasks. Its code is open source: ", /* @__PURE__ */ jsx(Text, {
|
|
1515
|
+
color: "cyan",
|
|
1516
|
+
children: "https://github.com/PostHog/wizard"
|
|
1517
|
+
})] })
|
|
1518
|
+
}),
|
|
1519
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
1520
|
+
"The",
|
|
1521
|
+
" ",
|
|
1522
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1523
|
+
color: "cyan",
|
|
1524
|
+
italic: true,
|
|
1525
|
+
children: AUDIT_SKILL_ID
|
|
1526
|
+
}),
|
|
1527
|
+
" ",
|
|
1528
|
+
"workflow reviews your project's PostHog integration against best practices to help you capture high-quality events and writes a report for suggested actions. Nothing in your project will be modified."
|
|
1529
|
+
] }),
|
|
1530
|
+
/* @__PURE__ */ jsx(Box, {
|
|
1531
|
+
marginTop: 1,
|
|
1532
|
+
children: /* @__PURE__ */ jsx(SkillSourceInfo, {
|
|
1533
|
+
skillId: AUDIT_SKILL_ID,
|
|
1534
|
+
skillEntry,
|
|
1535
|
+
fetchFailed
|
|
1536
|
+
})
|
|
1537
|
+
})
|
|
1538
|
+
]
|
|
1539
|
+
}) : /* @__PURE__ */ jsx(Box, {
|
|
1540
|
+
flexDirection: "column",
|
|
1541
|
+
alignItems: "center",
|
|
1542
|
+
children: /* @__PURE__ */ jsx(Text, { children: "Let's review your existing PostHog setup for best practices." })
|
|
1543
|
+
});
|
|
1544
|
+
const menuOptions = showingMoreInfo ? [{
|
|
1545
|
+
label: "Back",
|
|
1546
|
+
value: "back"
|
|
1547
|
+
}] : [
|
|
1548
|
+
{
|
|
1549
|
+
label: "Continue",
|
|
1550
|
+
value: "continue"
|
|
1551
|
+
},
|
|
1552
|
+
{
|
|
1553
|
+
label: "More info",
|
|
1554
|
+
value: "more-info"
|
|
1555
|
+
},
|
|
1556
|
+
{
|
|
1557
|
+
label: "Cancel",
|
|
1558
|
+
value: "cancel"
|
|
1559
|
+
}
|
|
1560
|
+
];
|
|
1561
|
+
const handleSelect = (value) => {
|
|
1562
|
+
if (value === "cancel") process.exit(0);
|
|
1563
|
+
else if (value === "more-info") setShowingMoreInfo(true);
|
|
1564
|
+
else if (value === "back") setShowingMoreInfo(false);
|
|
1565
|
+
else store.completeSetup();
|
|
1566
|
+
};
|
|
1567
|
+
return /* @__PURE__ */ jsx(IntroScreenLayout, {
|
|
1568
|
+
installDir: session.installDir,
|
|
1569
|
+
body,
|
|
1570
|
+
showDetection: !showingMoreInfo,
|
|
1571
|
+
workflowLabel: session.workflowLabel,
|
|
1572
|
+
skillId: session.skillId,
|
|
1573
|
+
menuOptions,
|
|
1574
|
+
onSelect: handleSelect
|
|
1575
|
+
});
|
|
1576
|
+
};
|
|
1577
|
+
//#endregion
|
|
1578
|
+
//#region src/ui/tui/hooks/file-watcher.ts
|
|
1579
|
+
/**
|
|
1580
|
+
* File watcher (UI concern).
|
|
1581
|
+
*
|
|
1582
|
+
* `fs.watch` alone is unreliable for atomic-rename writes (which is how Claude
|
|
1583
|
+
* rewrites JSON files), so the watcher pairs `fs.watch` with a continuous
|
|
1584
|
+
* mtime-polled re-read. The poll catches missed events; the watch keeps
|
|
1585
|
+
* latency low when it does fire. We dedupe with `mtimeMs` so steady-state
|
|
1586
|
+
* polls cost a single `stat`.
|
|
1587
|
+
*
|
|
1588
|
+
* Screens that need to mirror an agent-emitted JSON file into the store call
|
|
1589
|
+
* `useFileWatcher(absolutePath, onUpdate)`; the watcher starts on mount and
|
|
1590
|
+
* tears down on unmount.
|
|
1591
|
+
*/
|
|
1592
|
+
const DEFAULT_POLL_INTERVAL_MS = 5e3;
|
|
1593
|
+
const DEFAULT_ATTACH_RETRY_INTERVAL_MS = 1e3;
|
|
1594
|
+
/** Watch `path` for JSON updates and call `onUpdate(parsed)` whenever the
|
|
1595
|
+
* file's mtime changes and the contents are valid JSON. Caller must invoke
|
|
1596
|
+
* `handle.stop()` to release the watcher. */
|
|
1597
|
+
function startFileWatcher(path, onUpdate, options = {}) {
|
|
1598
|
+
const pollIntervalMs = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
|
|
1599
|
+
const attachRetryIntervalMs = options.attachRetryIntervalMs ?? DEFAULT_ATTACH_RETRY_INTERVAL_MS;
|
|
1600
|
+
const watchers = [];
|
|
1601
|
+
const intervals = [];
|
|
1602
|
+
let lastMtimeMs = 0;
|
|
1603
|
+
const read = (force = false) => {
|
|
1604
|
+
try {
|
|
1605
|
+
const stat = fs$1.statSync(path);
|
|
1606
|
+
if (!force && stat.mtimeMs === lastMtimeMs) return;
|
|
1607
|
+
lastMtimeMs = stat.mtimeMs;
|
|
1608
|
+
onUpdate(JSON.parse(fs$1.readFileSync(path, "utf-8")));
|
|
1609
|
+
} catch {}
|
|
1610
|
+
};
|
|
1611
|
+
intervals.push(setInterval(() => read(), pollIntervalMs));
|
|
1612
|
+
try {
|
|
1613
|
+
watchers.push(fs$1.watch(path, () => read(true)));
|
|
1614
|
+
read(true);
|
|
1615
|
+
} catch {
|
|
1616
|
+
const attachInterval = setInterval(() => {
|
|
1617
|
+
try {
|
|
1618
|
+
fs$1.accessSync(path);
|
|
1619
|
+
clearInterval(attachInterval);
|
|
1620
|
+
const idx = intervals.indexOf(attachInterval);
|
|
1621
|
+
if (idx >= 0) intervals.splice(idx, 1);
|
|
1622
|
+
watchers.push(fs$1.watch(path, () => read(true)));
|
|
1623
|
+
} catch {}
|
|
1624
|
+
}, attachRetryIntervalMs);
|
|
1625
|
+
intervals.push(attachInterval);
|
|
1626
|
+
}
|
|
1627
|
+
return { stop() {
|
|
1628
|
+
for (const w of watchers) w.close();
|
|
1629
|
+
for (const i of intervals) clearInterval(i);
|
|
1630
|
+
} };
|
|
1631
|
+
}
|
|
1632
|
+
/** React hook wrapping `startFileWatcher`. Starts on mount, stops on unmount
|
|
1633
|
+
* or when `path` changes. `onUpdate` and `options` are captured at mount
|
|
1634
|
+
* time — change `path` to restart with a new callback. */
|
|
1635
|
+
function useFileWatcher(path, onUpdate, options = {}) {
|
|
1636
|
+
useEffect(() => {
|
|
1637
|
+
const handle = startFileWatcher(path, onUpdate, options);
|
|
1638
|
+
return () => handle.stop();
|
|
1639
|
+
}, [path]);
|
|
1640
|
+
}
|
|
1641
|
+
//#endregion
|
|
1642
|
+
//#region src/ui/tui/screens/audit/slides/shared.tsx
|
|
1643
|
+
/** Narrow bordered box for the small ASCII illustrations in baseline slides. */
|
|
1644
|
+
const VisualBox = ({ children }) => /* @__PURE__ */ jsx(Box, {
|
|
1645
|
+
borderStyle: "single",
|
|
1646
|
+
borderColor: Colors.muted,
|
|
1647
|
+
paddingX: 1,
|
|
1648
|
+
flexDirection: "column",
|
|
1649
|
+
marginBottom: 1,
|
|
1650
|
+
children
|
|
1651
|
+
});
|
|
1652
|
+
//#endregion
|
|
1653
|
+
//#region src/ui/tui/screens/audit/slides/installation.tsx
|
|
1654
|
+
const InstallationVisual = () => /* @__PURE__ */ jsxs(VisualBox, { children: [
|
|
1655
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1656
|
+
dimColor: true,
|
|
1657
|
+
children: "app boot"
|
|
1658
|
+
}),
|
|
1659
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
1660
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1661
|
+
dimColor: true,
|
|
1662
|
+
children: " ▼ "
|
|
1663
|
+
}),
|
|
1664
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1665
|
+
color: "green",
|
|
1666
|
+
children: "posthog.init(...)"
|
|
1667
|
+
}),
|
|
1668
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1669
|
+
dimColor: true,
|
|
1670
|
+
children: " once"
|
|
1671
|
+
})
|
|
1672
|
+
] }),
|
|
1673
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1674
|
+
dimColor: true,
|
|
1675
|
+
children: " │"
|
|
1676
|
+
}),
|
|
1677
|
+
/* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
|
|
1678
|
+
dimColor: true,
|
|
1679
|
+
children: " ▼ "
|
|
1680
|
+
}), /* @__PURE__ */ jsx(Text, {
|
|
1681
|
+
color: "cyan",
|
|
1682
|
+
children: "posthog.capture('pageview')"
|
|
1683
|
+
})] }),
|
|
1684
|
+
/* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
|
|
1685
|
+
dimColor: true,
|
|
1686
|
+
children: " "
|
|
1687
|
+
}), /* @__PURE__ */ jsx(Text, {
|
|
1688
|
+
color: "cyan",
|
|
1689
|
+
children: "posthog.capture('signup')"
|
|
1690
|
+
})] }),
|
|
1691
|
+
/* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
|
|
1692
|
+
dimColor: true,
|
|
1693
|
+
children: " "
|
|
1694
|
+
}), /* @__PURE__ */ jsx(Text, {
|
|
1695
|
+
color: "cyan",
|
|
1696
|
+
children: "posthog.capture('purchase')"
|
|
1697
|
+
})] })
|
|
1698
|
+
] });
|
|
1699
|
+
const InstallationSlide = {
|
|
1700
|
+
area: "Installation",
|
|
1701
|
+
intro: [
|
|
1702
|
+
"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.",
|
|
1703
|
+
"We're also checking that your SDK is initialized correctly and in the right part of your app's lifecycle.",
|
|
1704
|
+
"This ensures you won't miss any autocaptured events."
|
|
1705
|
+
],
|
|
1706
|
+
visual: /* @__PURE__ */ jsx(InstallationVisual, {}),
|
|
1707
|
+
docsUrl: "https://posthog.com/docs/getting-started/install"
|
|
1708
|
+
};
|
|
1709
|
+
//#endregion
|
|
1710
|
+
//#region src/ui/tui/screens/audit/slides/identification.tsx
|
|
1711
|
+
const IdentificationVisual = () => /* @__PURE__ */ jsxs(VisualBox, { children: [
|
|
1712
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
1713
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1714
|
+
bold: true,
|
|
1715
|
+
children: "browser "
|
|
1716
|
+
}),
|
|
1717
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1718
|
+
dimColor: true,
|
|
1719
|
+
children: "capture"
|
|
1720
|
+
}),
|
|
1721
|
+
/* @__PURE__ */ jsx(Text, { children: " (" }),
|
|
1722
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1723
|
+
color: "cyan",
|
|
1724
|
+
children: "u_42"
|
|
1725
|
+
}),
|
|
1726
|
+
/* @__PURE__ */ jsx(Text, { children: ", \"click\")" })
|
|
1727
|
+
] }),
|
|
1728
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1729
|
+
dimColor: true,
|
|
1730
|
+
children: " │"
|
|
1731
|
+
}),
|
|
1732
|
+
/* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
|
|
1733
|
+
dimColor: true,
|
|
1734
|
+
children: " ▼ "
|
|
1735
|
+
}), /* @__PURE__ */ jsx(Text, {
|
|
1736
|
+
color: "green",
|
|
1737
|
+
children: "same distinct_id"
|
|
1738
|
+
})] }),
|
|
1739
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1740
|
+
dimColor: true,
|
|
1741
|
+
children: " │"
|
|
1742
|
+
}),
|
|
1743
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
1744
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1745
|
+
bold: true,
|
|
1746
|
+
children: "server "
|
|
1747
|
+
}),
|
|
1748
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1749
|
+
dimColor: true,
|
|
1750
|
+
children: "capture"
|
|
1751
|
+
}),
|
|
1752
|
+
/* @__PURE__ */ jsx(Text, { children: " (" }),
|
|
1753
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1754
|
+
color: "cyan",
|
|
1755
|
+
children: "u_42"
|
|
1756
|
+
}),
|
|
1757
|
+
/* @__PURE__ */ jsx(Text, { children: ", \"charged\")" })
|
|
1758
|
+
] })
|
|
1759
|
+
] });
|
|
1760
|
+
const IdentificationSlide = {
|
|
1761
|
+
area: "Identification",
|
|
1762
|
+
intro: [
|
|
1763
|
+
"For events to be useful, they need to be reliably attributed to a user.",
|
|
1764
|
+
"We're checking your project's `identify()` calls to make sure they're correctly and consistently implemented.",
|
|
1765
|
+
"We're also checking that your `distinct_id`s are correctly passed between your client and server runtimes if applicable."
|
|
1766
|
+
],
|
|
1767
|
+
visual: /* @__PURE__ */ jsx(IdentificationVisual, {}),
|
|
1768
|
+
docsUrl: "https://posthog.com/docs/product-analytics/identify"
|
|
1769
|
+
};
|
|
1770
|
+
//#endregion
|
|
1771
|
+
//#region src/ui/tui/screens/audit/slides/eventCapture.tsx
|
|
1772
|
+
const CaptureVisual = () => /* @__PURE__ */ jsxs(VisualBox, { children: [
|
|
1773
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
1774
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1775
|
+
color: "cyan",
|
|
1776
|
+
children: "pageview "
|
|
1777
|
+
}),
|
|
1778
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1779
|
+
color: "green",
|
|
1780
|
+
children: "████████████"
|
|
1781
|
+
}),
|
|
1782
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1783
|
+
dimColor: true,
|
|
1784
|
+
children: " 1000"
|
|
1785
|
+
})
|
|
1786
|
+
] }),
|
|
1787
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
1788
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1789
|
+
color: "cyan",
|
|
1790
|
+
children: "signup "
|
|
1791
|
+
}),
|
|
1792
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1793
|
+
color: "green",
|
|
1794
|
+
children: "████████"
|
|
1795
|
+
}),
|
|
1796
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1797
|
+
dimColor: true,
|
|
1798
|
+
children: " 640"
|
|
1799
|
+
})
|
|
1800
|
+
] }),
|
|
1801
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
1802
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1803
|
+
color: "cyan",
|
|
1804
|
+
children: "activated "
|
|
1805
|
+
}),
|
|
1806
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1807
|
+
color: "green",
|
|
1808
|
+
children: "█████"
|
|
1809
|
+
}),
|
|
1810
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1811
|
+
dimColor: true,
|
|
1812
|
+
children: " 410"
|
|
1813
|
+
})
|
|
1814
|
+
] }),
|
|
1815
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
1816
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1817
|
+
color: "cyan",
|
|
1818
|
+
children: "purchased "
|
|
1819
|
+
}),
|
|
1820
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1821
|
+
color: "green",
|
|
1822
|
+
children: "██"
|
|
1823
|
+
}),
|
|
1824
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1825
|
+
dimColor: true,
|
|
1826
|
+
children: " 120"
|
|
1827
|
+
})
|
|
1828
|
+
] })
|
|
1829
|
+
] });
|
|
1830
|
+
//#endregion
|
|
1831
|
+
//#region src/ui/tui/screens/audit/slides/index.ts
|
|
1832
|
+
const AUDIT_AREA_SLIDES = [
|
|
1833
|
+
InstallationSlide,
|
|
1834
|
+
IdentificationSlide,
|
|
1835
|
+
{
|
|
1836
|
+
area: "Event Capture",
|
|
1837
|
+
intro: [
|
|
1838
|
+
"Everything you do in PostHog starts with event captures. Every dashboard, insight, funnel, cohort, and replay is built on top of events.",
|
|
1839
|
+
"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.",
|
|
1840
|
+
"We're also checking that you use a reverse proxy so your events are not blocked by ad blockers or tracking blockers."
|
|
1841
|
+
],
|
|
1842
|
+
visual: /* @__PURE__ */ jsx(CaptureVisual, {}),
|
|
1843
|
+
docsUrl: "https://posthog.com/docs/product-analytics/capture-events"
|
|
1844
|
+
}
|
|
1845
|
+
];
|
|
1846
|
+
//#endregion
|
|
1847
|
+
//#region src/ui/tui/screens/audit/AuditAreaPane.tsx
|
|
1848
|
+
/**
|
|
1849
|
+
* AuditAreaPane — left-pane slide that follows whatever area the agent is
|
|
1850
|
+
* currently checking, plus a wrap-up state once every check is resolved
|
|
1851
|
+
* and the agent has moved on to writing the report.
|
|
1852
|
+
*
|
|
1853
|
+
* Three states, gated top-down on the ledger:
|
|
1854
|
+
* 1. firstPending defined → render the slide for that area
|
|
1855
|
+
* 2. checks empty → blank (the seed hook fires before
|
|
1856
|
+
* this screen mounts in practice;
|
|
1857
|
+
* this is just defensive)
|
|
1858
|
+
* 3. all checks non-pending → "writing report" wrap-up
|
|
1859
|
+
*
|
|
1860
|
+
* Pressing `O` opens the active slide's docs URL.
|
|
1861
|
+
*/
|
|
1862
|
+
const FINDING_STATUSES = [
|
|
1863
|
+
"error",
|
|
1864
|
+
"warning",
|
|
1865
|
+
"suggestion"
|
|
1866
|
+
];
|
|
1867
|
+
const isFinding = (c) => FINDING_STATUSES.includes(c.status);
|
|
1868
|
+
const fallbackSlide = (area) => ({
|
|
1869
|
+
area,
|
|
1870
|
+
intro: [`Verifying ${area.toLowerCase()}…`],
|
|
1871
|
+
docsUrl: ""
|
|
1872
|
+
});
|
|
1873
|
+
const openLink = (url) => {
|
|
1874
|
+
spawn(process.platform === "darwin" ? "open" : process.platform === "win32" ? "cmd" : "xdg-open", process.platform === "win32" ? [
|
|
1875
|
+
"/c",
|
|
1876
|
+
"start",
|
|
1877
|
+
"",
|
|
1878
|
+
url
|
|
1879
|
+
] : [url], {
|
|
1880
|
+
detached: true,
|
|
1881
|
+
stdio: "ignore"
|
|
1882
|
+
}).unref();
|
|
1883
|
+
};
|
|
1884
|
+
const AuditAreaPane = ({ checks, reportPath }) => {
|
|
1885
|
+
const activeArea = checks.filter((c) => c.status === "pending")[0]?.area;
|
|
1886
|
+
const slide = activeArea ? AUDIT_AREA_SLIDES.find((s) => s.area === activeArea) ?? fallbackSlide(activeArea) : null;
|
|
1887
|
+
useInput((input) => {
|
|
1888
|
+
if (input.toLowerCase() === "o" && slide?.docsUrl) openLink(slide.docsUrl);
|
|
1889
|
+
});
|
|
1890
|
+
if (slide) return /* @__PURE__ */ jsx(ActiveSlide, {
|
|
1891
|
+
slide,
|
|
1892
|
+
hasFindings: checks.some(isFinding)
|
|
1893
|
+
});
|
|
1894
|
+
if (checks.length === 0) return null;
|
|
1895
|
+
return /* @__PURE__ */ jsx(WritingReport, { reportPath });
|
|
1896
|
+
};
|
|
1897
|
+
const ActiveSlide = ({ slide, hasFindings }) => /* @__PURE__ */ jsxs(Box, {
|
|
1898
|
+
flexDirection: "column",
|
|
1899
|
+
paddingX: 1,
|
|
1900
|
+
children: [
|
|
1901
|
+
/* @__PURE__ */ jsxs(Text, {
|
|
1902
|
+
bold: true,
|
|
1903
|
+
color: Colors.accent,
|
|
1904
|
+
children: ["Verifying ", slide.area.toLowerCase()]
|
|
1905
|
+
}),
|
|
1906
|
+
/* @__PURE__ */ jsx(Box, { height: 1 }),
|
|
1907
|
+
slide.visual,
|
|
1908
|
+
slide.intro.map((paragraph, i) => /* @__PURE__ */ jsxs(Fragment, { children: [i > 0 && /* @__PURE__ */ jsx(Box, { height: 1 }), /* @__PURE__ */ jsx(Text, { children: paragraph })] }, i)),
|
|
1909
|
+
/* @__PURE__ */ jsx(Box, {
|
|
1910
|
+
marginTop: 1,
|
|
1911
|
+
children: /* @__PURE__ */ jsxs(Text, {
|
|
1912
|
+
dimColor: true,
|
|
1913
|
+
children: [slide.docsUrl && /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
1914
|
+
"[",
|
|
1915
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1916
|
+
color: Colors.accent,
|
|
1917
|
+
children: "O"
|
|
1918
|
+
}),
|
|
1919
|
+
"] Learn more"
|
|
1920
|
+
] }), hasFindings && /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
1921
|
+
slide.docsUrl && " ",
|
|
1922
|
+
"[",
|
|
1923
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1924
|
+
color: Colors.accent,
|
|
1925
|
+
children: "→"
|
|
1926
|
+
}),
|
|
1927
|
+
"] View issues"
|
|
1928
|
+
] })]
|
|
1929
|
+
})
|
|
1930
|
+
})
|
|
1931
|
+
]
|
|
1932
|
+
});
|
|
1933
|
+
const WritingReport = ({ reportPath }) => /* @__PURE__ */ jsxs(Box, {
|
|
1934
|
+
flexDirection: "column",
|
|
1935
|
+
paddingX: 1,
|
|
1936
|
+
children: [
|
|
1937
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1938
|
+
bold: true,
|
|
1939
|
+
color: Colors.accent,
|
|
1940
|
+
children: "We've wrapped up the review."
|
|
1941
|
+
}),
|
|
1942
|
+
/* @__PURE__ */ jsx(Box, { height: 1 }),
|
|
1943
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
1944
|
+
"To help you get the most out of your PostHog integration, we're preparing a report for you at ",
|
|
1945
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1946
|
+
color: "cyan",
|
|
1947
|
+
children: reportPath
|
|
1948
|
+
}),
|
|
1949
|
+
"."
|
|
1950
|
+
] }),
|
|
1951
|
+
/* @__PURE__ */ jsx(Box, { height: 1 }),
|
|
1952
|
+
/* @__PURE__ */ jsx(Text, { children: "We'll cover what we checked and suggest where we can improve the existing integration." }),
|
|
1953
|
+
/* @__PURE__ */ jsx(Box, { height: 1 }),
|
|
1954
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1955
|
+
dimColor: true,
|
|
1956
|
+
children: "Hang tight!"
|
|
1957
|
+
})
|
|
1958
|
+
]
|
|
1959
|
+
});
|
|
1960
|
+
//#endregion
|
|
1961
|
+
//#region src/ui/tui/screens/audit/PendingChecksList.tsx
|
|
1962
|
+
function groupByArea(checks) {
|
|
1963
|
+
const order = [];
|
|
1964
|
+
const map = /* @__PURE__ */ new Map();
|
|
1965
|
+
for (const c of checks) {
|
|
1966
|
+
if (!map.has(c.area)) {
|
|
1967
|
+
map.set(c.area, []);
|
|
1968
|
+
order.push(c.area);
|
|
1969
|
+
}
|
|
1970
|
+
map.get(c.area).push(c);
|
|
1971
|
+
}
|
|
1972
|
+
return order.map((area) => ({
|
|
1973
|
+
area,
|
|
1974
|
+
checks: map.get(area)
|
|
1975
|
+
}));
|
|
1976
|
+
}
|
|
1977
|
+
function groupIcon(group) {
|
|
1978
|
+
const total = group.checks.length;
|
|
1979
|
+
const complete = group.checks.filter((c) => c.status !== "pending").length;
|
|
1980
|
+
if (complete === 0) return {
|
|
1981
|
+
icon: Icons.squareOpen,
|
|
1982
|
+
color: Colors.muted
|
|
1983
|
+
};
|
|
1984
|
+
if (complete === total) return {
|
|
1985
|
+
icon: Icons.squareFilled,
|
|
1986
|
+
color: Colors.success
|
|
1987
|
+
};
|
|
1988
|
+
return {
|
|
1989
|
+
icon: Icons.triangleRight,
|
|
1990
|
+
color: Colors.primary
|
|
1991
|
+
};
|
|
1992
|
+
}
|
|
1993
|
+
const GroupHeader = ({ group, showIcon, isActive }) => {
|
|
1994
|
+
const complete = group.checks.filter((c) => c.status !== "pending").length;
|
|
1995
|
+
const total = group.checks.length;
|
|
1996
|
+
const { icon, color } = groupIcon(group);
|
|
1997
|
+
return /* @__PURE__ */ jsxs(Box, { children: [isActive ? /* @__PURE__ */ jsx(Box, {
|
|
1998
|
+
marginRight: 1,
|
|
1999
|
+
children: /* @__PURE__ */ jsx(Spinner, {})
|
|
2000
|
+
}) : showIcon ? /* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
|
|
2001
|
+
color,
|
|
2002
|
+
children: icon
|
|
2003
|
+
}), " "] }) : null, /* @__PURE__ */ jsxs(Text, { children: [
|
|
2004
|
+
/* @__PURE__ */ jsx(Text, {
|
|
2005
|
+
bold: true,
|
|
2006
|
+
children: group.area
|
|
2007
|
+
}),
|
|
2008
|
+
" ",
|
|
2009
|
+
/* @__PURE__ */ jsxs(Text, {
|
|
2010
|
+
dimColor: true,
|
|
2011
|
+
children: [
|
|
2012
|
+
"(",
|
|
2013
|
+
complete,
|
|
2014
|
+
"/",
|
|
2015
|
+
total,
|
|
2016
|
+
")"
|
|
2017
|
+
]
|
|
2018
|
+
})
|
|
2019
|
+
] })] });
|
|
2020
|
+
};
|
|
2021
|
+
const CheckRow = ({ check }) => {
|
|
2022
|
+
const { glyph, color } = AUDIT_SEVERITY_STYLE[check.status];
|
|
2023
|
+
return /* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
|
|
2024
|
+
color,
|
|
2025
|
+
children: glyph
|
|
2026
|
+
}), /* @__PURE__ */ jsxs(Text, {
|
|
2027
|
+
dimColor: check.status === "pending",
|
|
2028
|
+
children: [" ", check.label]
|
|
2029
|
+
})] });
|
|
2030
|
+
};
|
|
2031
|
+
const COLLAPSE_BELOW_ROWS = 24;
|
|
2032
|
+
const PendingChecksList = ({ checks }) => {
|
|
2033
|
+
const [, termRows] = useStdoutDimensions();
|
|
2034
|
+
if (checks.length === 0) return /* @__PURE__ */ jsxs(Box, {
|
|
2035
|
+
flexDirection: "column",
|
|
2036
|
+
children: [
|
|
2037
|
+
/* @__PURE__ */ jsx(Text, {
|
|
2038
|
+
bold: true,
|
|
2039
|
+
children: "Checks"
|
|
2040
|
+
}),
|
|
2041
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
2042
|
+
/* @__PURE__ */ jsx(LoadingBox, { message: "Seeding audit checklist..." })
|
|
2043
|
+
]
|
|
2044
|
+
});
|
|
2045
|
+
const groups = groupByArea(checks);
|
|
2046
|
+
const activeIndex = groups.findIndex((g) => g.checks.some((c) => c.status === "pending"));
|
|
2047
|
+
return /* @__PURE__ */ jsxs(Box, {
|
|
2048
|
+
flexDirection: "column",
|
|
2049
|
+
children: [
|
|
2050
|
+
/* @__PURE__ */ jsx(Text, {
|
|
2051
|
+
bold: true,
|
|
2052
|
+
children: "Checks"
|
|
2053
|
+
}),
|
|
2054
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
2055
|
+
termRows < COLLAPSE_BELOW_ROWS ? groups.map((group, i) => /* @__PURE__ */ jsx(GroupHeader, {
|
|
2056
|
+
group,
|
|
2057
|
+
showIcon: true,
|
|
2058
|
+
isActive: i === activeIndex
|
|
2059
|
+
}, group.area)) : groups.map((group, i) => /* @__PURE__ */ jsxs(Box, {
|
|
2060
|
+
flexDirection: "column",
|
|
2061
|
+
marginTop: i === 0 ? 0 : 1,
|
|
2062
|
+
children: [/* @__PURE__ */ jsx(GroupHeader, {
|
|
2063
|
+
group,
|
|
2064
|
+
showIcon: false,
|
|
2065
|
+
isActive: i === activeIndex
|
|
2066
|
+
}), group.checks.map((c) => /* @__PURE__ */ jsx(CheckRow, { check: c }, c.id))]
|
|
2067
|
+
}, group.area))
|
|
2068
|
+
]
|
|
2069
|
+
});
|
|
2070
|
+
};
|
|
2071
|
+
//#endregion
|
|
2072
|
+
//#region src/ui/tui/screens/audit/AuditRunScreen.tsx
|
|
2073
|
+
const AuditRunScreen = ({ store }) => {
|
|
2074
|
+
useSyncExternalStore((cb) => store.subscribe(cb), () => store.getSnapshot());
|
|
2075
|
+
useFileWatcher(join(store.session.installDir, AUDIT_CHECKS_FILE), (parsed) => store.setFrameworkContext(AUDIT_CHECKS_KEY, coerceAuditChecks(parsed)));
|
|
2076
|
+
const statuses = store.statusMessages.length > 0 ? store.statusMessages : void 0;
|
|
2077
|
+
const [columns] = useStdoutDimensions();
|
|
2078
|
+
const checks = getAuditChecks(store.session);
|
|
2079
|
+
const reportPath = `./${AUDIT_REPORT_FILE}`;
|
|
2080
|
+
const pendingChecksList = /* @__PURE__ */ jsx(PendingChecksList, { checks });
|
|
2081
|
+
return /* @__PURE__ */ jsx(TabContainer, {
|
|
2082
|
+
tabs: [
|
|
2083
|
+
{
|
|
2084
|
+
id: "status",
|
|
2085
|
+
label: "Status",
|
|
2086
|
+
component: columns < 80 ? /* @__PURE__ */ jsx(Box, {
|
|
2087
|
+
flexDirection: "column",
|
|
2088
|
+
flexGrow: 1,
|
|
2089
|
+
children: pendingChecksList
|
|
2090
|
+
}) : /* @__PURE__ */ jsx(SplitView, {
|
|
2091
|
+
left: /* @__PURE__ */ jsx(AuditAreaPane, {
|
|
2092
|
+
checks,
|
|
2093
|
+
reportPath
|
|
2094
|
+
}),
|
|
2095
|
+
right: pendingChecksList
|
|
2096
|
+
})
|
|
2097
|
+
},
|
|
2098
|
+
{
|
|
2099
|
+
id: "audit-checks",
|
|
2100
|
+
label: "Audit plan",
|
|
2101
|
+
component: /* @__PURE__ */ jsx(AuditChecksViewer, { checks })
|
|
2102
|
+
},
|
|
2103
|
+
{
|
|
2104
|
+
id: "logs",
|
|
2105
|
+
label: "Tail logs",
|
|
2106
|
+
component: /* @__PURE__ */ jsx(LogViewer, { filePath: WIZARD_LOG_FILE })
|
|
2107
|
+
},
|
|
2108
|
+
{
|
|
2109
|
+
id: "hn",
|
|
2110
|
+
label: "HN",
|
|
2111
|
+
component: /* @__PURE__ */ jsx(HNViewer, {})
|
|
2112
|
+
}
|
|
2113
|
+
],
|
|
2114
|
+
statusMessage: statuses,
|
|
2115
|
+
expandableStatus: true,
|
|
2116
|
+
store
|
|
2117
|
+
});
|
|
2118
|
+
};
|
|
2119
|
+
//#endregion
|
|
2120
|
+
//#region src/ui/tui/screens/audit/AuditChecksOutroSection.tsx
|
|
2121
|
+
const MAX_VISIBLE = 6;
|
|
2122
|
+
const AuditChecksOutroSection = ({ checks, installDir }) => {
|
|
2123
|
+
if (checks.length === 0) return null;
|
|
2124
|
+
const errors = checks.filter((c) => c.status === "error");
|
|
2125
|
+
const warnings = checks.filter((c) => c.status === "warning");
|
|
2126
|
+
const suggestions = checks.filter((c) => c.status === "suggestion");
|
|
2127
|
+
const problematic = [
|
|
2128
|
+
...errors,
|
|
2129
|
+
...warnings,
|
|
2130
|
+
...suggestions
|
|
2131
|
+
];
|
|
2132
|
+
const visible = problematic.slice(0, MAX_VISIBLE);
|
|
2133
|
+
const hidden = problematic.length - visible.length;
|
|
2134
|
+
return /* @__PURE__ */ jsxs(Box, {
|
|
2135
|
+
flexDirection: "column",
|
|
2136
|
+
marginTop: 1,
|
|
2137
|
+
children: [
|
|
2138
|
+
/* @__PURE__ */ jsx(Text, {
|
|
2139
|
+
color: "cyan",
|
|
2140
|
+
bold: true,
|
|
2141
|
+
children: "Items audited:"
|
|
2142
|
+
}),
|
|
2143
|
+
/* @__PURE__ */ jsxs(Text, {
|
|
2144
|
+
dimColor: true,
|
|
2145
|
+
children: [
|
|
2146
|
+
checks.length,
|
|
2147
|
+
" checks · ",
|
|
2148
|
+
errors.length,
|
|
2149
|
+
" errors · ",
|
|
2150
|
+
warnings.length,
|
|
2151
|
+
" ",
|
|
2152
|
+
"warnings · ",
|
|
2153
|
+
suggestions.length,
|
|
2154
|
+
" suggestions"
|
|
2155
|
+
]
|
|
2156
|
+
}),
|
|
2157
|
+
problematic.length === 0 ? /* @__PURE__ */ jsxs(Text, {
|
|
2158
|
+
color: "green",
|
|
2159
|
+
children: ["•", " No issues found."]
|
|
2160
|
+
}) : /* @__PURE__ */ jsxs(Fragment$1, { children: [visible.map((item) => {
|
|
2161
|
+
const style = AUDIT_SEVERITY_STYLE[item.status];
|
|
2162
|
+
return /* @__PURE__ */ jsxs(Box, {
|
|
2163
|
+
flexDirection: "column",
|
|
2164
|
+
marginTop: 1,
|
|
2165
|
+
children: [/* @__PURE__ */ jsxs(Text, { children: [
|
|
2166
|
+
/* @__PURE__ */ jsx(Text, {
|
|
2167
|
+
color: style.color,
|
|
2168
|
+
children: style.glyph
|
|
2169
|
+
}),
|
|
2170
|
+
" ",
|
|
2171
|
+
/* @__PURE__ */ jsx(Text, {
|
|
2172
|
+
bold: true,
|
|
2173
|
+
children: item.label
|
|
2174
|
+
}),
|
|
2175
|
+
" ",
|
|
2176
|
+
/* @__PURE__ */ jsxs(Text, {
|
|
2177
|
+
dimColor: true,
|
|
2178
|
+
children: [
|
|
2179
|
+
"(",
|
|
2180
|
+
item.area,
|
|
2181
|
+
")"
|
|
2182
|
+
]
|
|
2183
|
+
})
|
|
2184
|
+
] }), item.file && /* @__PURE__ */ jsxs(Text, {
|
|
2185
|
+
dimColor: true,
|
|
2186
|
+
children: [" ", relativeToInstallDir(item.file, installDir)]
|
|
2187
|
+
})]
|
|
2188
|
+
}, item.id);
|
|
2189
|
+
}), hidden > 0 && /* @__PURE__ */ jsxs(Text, {
|
|
2190
|
+
dimColor: true,
|
|
2191
|
+
children: [
|
|
2192
|
+
"… and ",
|
|
2193
|
+
hidden,
|
|
2194
|
+
" more — see the report."
|
|
2195
|
+
]
|
|
2196
|
+
})] })
|
|
2197
|
+
]
|
|
2198
|
+
});
|
|
2199
|
+
};
|
|
2200
|
+
//#endregion
|
|
2201
|
+
//#region src/ui/tui/screens/audit/AuditOutroScreen.tsx
|
|
2202
|
+
/**
|
|
2203
|
+
* AuditOutroScreen — Audit-specific post-run summary. Renders the standard
|
|
2204
|
+
* success / error / cancel views with the audit checks summary inlined into
|
|
2205
|
+
* the success body. The report path is hardcoded to AUDIT_REPORT_FILE.
|
|
2206
|
+
*/
|
|
2207
|
+
const AuditOutroScreen = ({ store }) => {
|
|
2208
|
+
useSyncExternalStore((cb) => store.subscribe(cb), () => store.getSnapshot());
|
|
2209
|
+
useInput(() => {
|
|
2210
|
+
store.setOutroDismissed();
|
|
2211
|
+
});
|
|
2212
|
+
const outroData = store.session.outroData;
|
|
2213
|
+
if (!outroData) return /* @__PURE__ */ jsx(Box, {
|
|
2214
|
+
flexDirection: "column",
|
|
2215
|
+
flexGrow: 1,
|
|
2216
|
+
children: /* @__PURE__ */ jsx(Text, {
|
|
2217
|
+
dimColor: true,
|
|
2218
|
+
children: "Finishing up..."
|
|
2219
|
+
})
|
|
2220
|
+
});
|
|
2221
|
+
return /* @__PURE__ */ jsxs(Box, {
|
|
2222
|
+
flexDirection: "column",
|
|
2223
|
+
flexGrow: 1,
|
|
2224
|
+
children: [
|
|
2225
|
+
outroData.kind === "success" && /* @__PURE__ */ jsxs(Box, {
|
|
2226
|
+
flexDirection: "column",
|
|
2227
|
+
children: [
|
|
2228
|
+
/* @__PURE__ */ jsxs(Text, {
|
|
2229
|
+
color: "green",
|
|
2230
|
+
bold: true,
|
|
2231
|
+
children: ["✔ ", outroData.message || "Audit complete!"]
|
|
2232
|
+
}),
|
|
2233
|
+
/* @__PURE__ */ jsx(AuditChecksOutroSection, {
|
|
2234
|
+
checks: getAuditChecks(store.session),
|
|
2235
|
+
installDir: store.session.installDir
|
|
2236
|
+
}),
|
|
2237
|
+
outroData.docsUrl && /* @__PURE__ */ jsx(Box, {
|
|
2238
|
+
marginTop: 1,
|
|
2239
|
+
children: /* @__PURE__ */ jsxs(Text, { children: ["Learn more: ", /* @__PURE__ */ jsx(Text, {
|
|
2240
|
+
color: "cyan",
|
|
2241
|
+
children: outroData.docsUrl
|
|
2242
|
+
})] })
|
|
2243
|
+
})
|
|
2244
|
+
]
|
|
2245
|
+
}),
|
|
2246
|
+
outroData.kind === "error" && /* @__PURE__ */ jsxs(Box, {
|
|
2247
|
+
flexDirection: "column",
|
|
2248
|
+
children: [/* @__PURE__ */ jsxs(Text, {
|
|
2249
|
+
color: "red",
|
|
2250
|
+
bold: true,
|
|
2251
|
+
children: ["✘ ", outroData.message || "An error occurred"]
|
|
2252
|
+
}), outroData.body && /* @__PURE__ */ jsx(Box, {
|
|
2253
|
+
marginTop: 1,
|
|
2254
|
+
children: /* @__PURE__ */ jsx(Text, {
|
|
2255
|
+
dimColor: true,
|
|
2256
|
+
children: outroData.body
|
|
2257
|
+
})
|
|
2258
|
+
})]
|
|
2259
|
+
}),
|
|
2260
|
+
outroData.kind === "cancel" && /* @__PURE__ */ jsxs(Text, {
|
|
2261
|
+
color: "yellow",
|
|
2262
|
+
children: ["■ ", outroData.message || "Cancelled"]
|
|
2263
|
+
}),
|
|
2264
|
+
/* @__PURE__ */ jsx(Box, {
|
|
2265
|
+
marginTop: 1,
|
|
2266
|
+
children: /* @__PURE__ */ jsx(Text, {
|
|
2267
|
+
color: Colors.muted,
|
|
2268
|
+
children: "Press any key to continue"
|
|
2269
|
+
})
|
|
2270
|
+
})
|
|
2271
|
+
]
|
|
2272
|
+
});
|
|
2273
|
+
};
|
|
2274
|
+
//#endregion
|
|
1444
2275
|
//#region src/ui/tui/screens/SetupScreen.tsx
|
|
1445
2276
|
/**
|
|
1446
2277
|
* SetupScreen — Generic framework disambiguation.
|
|
@@ -1575,17 +2406,21 @@ const AuthScreen = ({ store }) => {
|
|
|
1575
2406
|
//#endregion
|
|
1576
2407
|
//#region src/ui/tui/screens/RunScreen.tsx
|
|
1577
2408
|
/**
|
|
1578
|
-
* RunScreen —
|
|
1579
|
-
*
|
|
1580
|
-
* Two tabs:
|
|
1581
|
-
* - Status: SplitView with LearnCard (left) + ProgressList (right)
|
|
1582
|
-
* - Logs: LogViewer tailing the wizard log file
|
|
2409
|
+
* RunScreen — Default observational view of the agent run.
|
|
1583
2410
|
*
|
|
1584
|
-
*
|
|
1585
|
-
*
|
|
2411
|
+
* Tabs: Status (LearnCard + ProgressList), Event plan (when present),
|
|
2412
|
+
* Tail logs, HN. Workflows that need a different tab list ship their own
|
|
2413
|
+
* screen component (see audit/AuditRunScreen.tsx).
|
|
1586
2414
|
*/
|
|
1587
2415
|
const RunScreen = ({ store }) => {
|
|
1588
2416
|
useSyncExternalStore((cb) => store.subscribe(cb), () => store.getSnapshot());
|
|
2417
|
+
useFileWatcher(join(store.session.installDir, EVENT_PLAN_FILE), (parsed) => {
|
|
2418
|
+
if (!Array.isArray(parsed)) return;
|
|
2419
|
+
store.setEventPlan(parsed.map((e) => ({
|
|
2420
|
+
name: e.name ?? e.event ?? "",
|
|
2421
|
+
description: e.description ?? ""
|
|
2422
|
+
})));
|
|
2423
|
+
});
|
|
1589
2424
|
const [columns] = useStdoutDimensions();
|
|
1590
2425
|
const progressItems = store.tasks.map((t) => ({
|
|
1591
2426
|
label: t.label,
|
|
@@ -1655,6 +2490,7 @@ const RunScreen = ({ store }) => {
|
|
|
1655
2490
|
*
|
|
1656
2491
|
* When done, calls store.setSkillsComplete() and exits the process.
|
|
1657
2492
|
*/
|
|
2493
|
+
const WIZARD_MARKER = ".posthog-wizard";
|
|
1658
2494
|
const KeepSkillsScreen = ({ store }) => {
|
|
1659
2495
|
useSyncExternalStore((cb) => store.subscribe(cb), () => store.getSnapshot());
|
|
1660
2496
|
const [phase, setPhase] = useState("loading");
|
|
@@ -1666,7 +2502,12 @@ const KeepSkillsScreen = ({ store }) => {
|
|
|
1666
2502
|
const dirs = (await readdir(skillsDir, { withFileTypes: true })).filter((e) => e.isDirectory());
|
|
1667
2503
|
const result = [];
|
|
1668
2504
|
for (const dir of dirs) {
|
|
1669
|
-
|
|
2505
|
+
try {
|
|
2506
|
+
await access(join(skillsDir, dir.name, WIZARD_MARKER));
|
|
2507
|
+
} catch {
|
|
2508
|
+
continue;
|
|
2509
|
+
}
|
|
2510
|
+
const children = (await readdir(join(skillsDir, dir.name))).filter((c) => c !== WIZARD_MARKER);
|
|
1670
2511
|
result.push({
|
|
1671
2512
|
name: dir.name,
|
|
1672
2513
|
children
|
|
@@ -1690,8 +2531,14 @@ const KeepSkillsScreen = ({ store }) => {
|
|
|
1690
2531
|
};
|
|
1691
2532
|
const handleRemove = async () => {
|
|
1692
2533
|
setPhase("removing");
|
|
2534
|
+
for (const skill of skills) try {
|
|
2535
|
+
await rm(join(skillsDir, skill.name), {
|
|
2536
|
+
recursive: true,
|
|
2537
|
+
force: true
|
|
2538
|
+
});
|
|
2539
|
+
} catch {}
|
|
1693
2540
|
try {
|
|
1694
|
-
await rm(skillsDir, {
|
|
2541
|
+
if ((await readdir(skillsDir)).length === 0) await rm(skillsDir, {
|
|
1695
2542
|
recursive: true,
|
|
1696
2543
|
force: true
|
|
1697
2544
|
});
|
|
@@ -1717,7 +2564,7 @@ const KeepSkillsScreen = ({ store }) => {
|
|
|
1717
2564
|
dimColor: true,
|
|
1718
2565
|
children: "Checking installed skills..."
|
|
1719
2566
|
}),
|
|
1720
|
-
phase === "ask" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2567
|
+
phase === "ask" && /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
1721
2568
|
/* @__PURE__ */ jsx(Text, {
|
|
1722
2569
|
dimColor: true,
|
|
1723
2570
|
children: "The wizard installed open-source skills that help AI coding agents integrate PostHog into your project:"
|
|
@@ -1787,9 +2634,11 @@ const KeepSkillsScreen = ({ store }) => {
|
|
|
1787
2634
|
//#endregion
|
|
1788
2635
|
//#region src/ui/tui/screens/OutroScreen.tsx
|
|
1789
2636
|
/**
|
|
1790
|
-
* OutroScreen —
|
|
1791
|
-
*
|
|
1792
|
-
*
|
|
2637
|
+
* OutroScreen — Default post-run summary.
|
|
2638
|
+
*
|
|
2639
|
+
* Renders the success / error / cancel views from `outroData`. Workflows
|
|
2640
|
+
* that need a different success view (e.g. with extra summary content)
|
|
2641
|
+
* ship their own screen component (see audit/AuditOutroScreen.tsx).
|
|
1793
2642
|
*/
|
|
1794
2643
|
const OutroScreen = ({ store }) => {
|
|
1795
2644
|
useSyncExternalStore((cb) => store.subscribe(cb), () => store.getSnapshot());
|
|
@@ -1815,11 +2664,14 @@ const OutroScreen = ({ store }) => {
|
|
|
1815
2664
|
/* @__PURE__ */ jsxs(Text, {
|
|
1816
2665
|
color: "green",
|
|
1817
2666
|
bold: true,
|
|
1818
|
-
children: [
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
2667
|
+
children: ["✔ ", outroData.message || "Done!"]
|
|
2668
|
+
}),
|
|
2669
|
+
outroData.body && /* @__PURE__ */ jsx(Box, {
|
|
2670
|
+
marginTop: 1,
|
|
2671
|
+
children: /* @__PURE__ */ jsx(Text, {
|
|
2672
|
+
dimColor: true,
|
|
2673
|
+
children: outroData.body
|
|
2674
|
+
})
|
|
1823
2675
|
}),
|
|
1824
2676
|
outroData.reportFile && /* @__PURE__ */ jsx(Box, {
|
|
1825
2677
|
marginTop: 1,
|
|
@@ -1839,11 +2691,7 @@ const OutroScreen = ({ store }) => {
|
|
|
1839
2691
|
color: "cyan",
|
|
1840
2692
|
bold: true,
|
|
1841
2693
|
children: "What the agent did:"
|
|
1842
|
-
}), outroData.changes.map((change, i) => /* @__PURE__ */ jsxs(Text, { children: [
|
|
1843
|
-
"•",
|
|
1844
|
-
" ",
|
|
1845
|
-
change
|
|
1846
|
-
] }, i))]
|
|
2694
|
+
}), outroData.changes.map((change, i) => /* @__PURE__ */ jsxs(Text, { children: ["• ", change] }, i))]
|
|
1847
2695
|
}),
|
|
1848
2696
|
store.eventPlan.length > 0 && /* @__PURE__ */ jsxs(Box, {
|
|
1849
2697
|
flexDirection: "column",
|
|
@@ -1853,8 +2701,7 @@ const OutroScreen = ({ store }) => {
|
|
|
1853
2701
|
bold: true,
|
|
1854
2702
|
children: "Events added:"
|
|
1855
2703
|
}), store.eventPlan.map((event) => /* @__PURE__ */ jsxs(Text, { children: [
|
|
1856
|
-
"•",
|
|
1857
|
-
" ",
|
|
2704
|
+
"• ",
|
|
1858
2705
|
/* @__PURE__ */ jsx(Text, {
|
|
1859
2706
|
bold: true,
|
|
1860
2707
|
children: event.name
|
|
@@ -1887,10 +2734,10 @@ const OutroScreen = ({ store }) => {
|
|
|
1887
2734
|
children: "Note: This wizard uses an LLM agent to analyze and modify your project. Please review the changes made."
|
|
1888
2735
|
})
|
|
1889
2736
|
}),
|
|
1890
|
-
/* @__PURE__ */ jsx(
|
|
2737
|
+
/* @__PURE__ */ jsx(Text, {
|
|
1891
2738
|
dimColor: true,
|
|
1892
2739
|
children: "How did this work for you? Drop us a line: wizard@posthog.com"
|
|
1893
|
-
})
|
|
2740
|
+
})
|
|
1894
2741
|
]
|
|
1895
2742
|
}),
|
|
1896
2743
|
outroData.kind === "error" && /* @__PURE__ */ jsxs(Box, {
|
|
@@ -1899,11 +2746,7 @@ const OutroScreen = ({ store }) => {
|
|
|
1899
2746
|
/* @__PURE__ */ jsxs(Text, {
|
|
1900
2747
|
color: "red",
|
|
1901
2748
|
bold: true,
|
|
1902
|
-
children: [
|
|
1903
|
-
"✘",
|
|
1904
|
-
" ",
|
|
1905
|
-
outroData.message || "An error occurred"
|
|
1906
|
-
]
|
|
2749
|
+
children: ["✘ ", outroData.message || "An error occurred"]
|
|
1907
2750
|
}),
|
|
1908
2751
|
outroData.body && /* @__PURE__ */ jsx(Box, {
|
|
1909
2752
|
marginTop: 1,
|
|
@@ -1925,11 +2768,7 @@ const OutroScreen = ({ store }) => {
|
|
|
1925
2768
|
flexDirection: "column",
|
|
1926
2769
|
children: /* @__PURE__ */ jsxs(Text, {
|
|
1927
2770
|
color: "yellow",
|
|
1928
|
-
children: [
|
|
1929
|
-
"■",
|
|
1930
|
-
" ",
|
|
1931
|
-
outroData.message || "Cancelled"
|
|
1932
|
-
]
|
|
2771
|
+
children: ["■ ", outroData.message || "Cancelled"]
|
|
1933
2772
|
})
|
|
1934
2773
|
}),
|
|
1935
2774
|
/* @__PURE__ */ jsx(Box, {
|
|
@@ -2080,6 +2919,9 @@ function createScreens(store, services) {
|
|
|
2080
2919
|
["intro"]: /* @__PURE__ */ jsx(PostHogIntegrationIntroScreen, { store }),
|
|
2081
2920
|
["revenue-intro"]: /* @__PURE__ */ jsx(RevenueIntroScreen, { store }),
|
|
2082
2921
|
["agent-skill-intro"]: /* @__PURE__ */ jsx(AgentSkillIntroScreen, { store }),
|
|
2922
|
+
["audit-intro"]: /* @__PURE__ */ jsx(AuditIntroScreen, { store }),
|
|
2923
|
+
["audit-run"]: /* @__PURE__ */ jsx(AuditRunScreen, { store }),
|
|
2924
|
+
["audit-outro"]: /* @__PURE__ */ jsx(AuditOutroScreen, { store }),
|
|
2083
2925
|
["health-check"]: /* @__PURE__ */ jsx(HealthCheckScreen, { store }),
|
|
2084
2926
|
["doctor-intro"]: /* @__PURE__ */ jsx(DoctorIntroScreen, { store }),
|
|
2085
2927
|
["doctor-report"]: /* @__PURE__ */ jsx(DoctorReportScreen, { store }),
|
|
@@ -2137,7 +2979,10 @@ function releaseTerminal() {
|
|
|
2137
2979
|
function getExitLine(store) {
|
|
2138
2980
|
const outro = store.session.outroData;
|
|
2139
2981
|
const label = store.session.workflowLabel ?? "Wizard";
|
|
2140
|
-
if (outro?.kind === "success")
|
|
2982
|
+
if (outro?.kind === "success") {
|
|
2983
|
+
const message = outro.message ?? `${label} completed successfully.`;
|
|
2984
|
+
return `${GREEN}${BOLD}\u2714${RESET_ATTRS} ${message}${outro.reportFile && !message.includes(outro.reportFile) ? ` Check ./${outro.reportFile} for details.` : ""}`;
|
|
2985
|
+
}
|
|
2141
2986
|
return `${DIM}${label} exited.${RESET_ATTRS}`;
|
|
2142
2987
|
}
|
|
2143
2988
|
function startTUI(version, flow = "posthog-integration") {
|
|
@@ -2164,4 +3009,4 @@ function startTUI(version, flow = "posthog-integration") {
|
|
|
2164
3009
|
//#endregion
|
|
2165
3010
|
export { startTUI };
|
|
2166
3011
|
|
|
2167
|
-
//# sourceMappingURL=start-tui-
|
|
3012
|
+
//# sourceMappingURL=start-tui-DleQG3La.js.map
|