@posthog/wizard 2.21.0 → 2.22.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/README.md +14 -1
  2. package/dist/{OutroScreen-CqF6SdBo.js → AiOptInRequiredScreen-B8mgZbe5.js} +482 -59
  3. package/dist/AiOptInRequiredScreen-B8mgZbe5.js.map +1 -0
  4. package/dist/{add-mcp-server-to-clients-DQHGhzt6.js → add-mcp-server-to-clients-lCxOS1A1.js} +12 -10
  5. package/dist/add-mcp-server-to-clients-lCxOS1A1.js.map +1 -0
  6. package/dist/{agent-interface-DE7txTqh.js → agent-interface-BPCzPvK-.js} +6 -5
  7. package/dist/{agent-interface-DE7txTqh.js.map → agent-interface-BPCzPvK-.js.map} +1 -1
  8. package/dist/{agent-runner-DUZ5OD6e.js → agent-runner-DgzF2mga.js} +13 -9
  9. package/dist/{agent-runner-DUZ5OD6e.js.map → agent-runner-DgzF2mga.js.map} +1 -1
  10. package/dist/{analytics-Bl5DPj_0.js → analytics-BZv-cKyn.js} +28 -4
  11. package/dist/analytics-BZv-cKyn.js.map +1 -0
  12. package/dist/{api-DuA0_88V.js → api-BkLZ8BWm.js} +3 -3
  13. package/dist/{api-DuA0_88V.js.map → api-BkLZ8BWm.js.map} +1 -1
  14. package/dist/bin.js +160 -49
  15. package/dist/bin.js.map +1 -1
  16. package/dist/{ci-install-BnOYI4mZ.js → ci-install-DBARq5LX.js} +4 -4
  17. package/dist/{ci-install-BnOYI4mZ.js.map → ci-install-DBARq5LX.js.map} +1 -1
  18. package/dist/{debug-h7Z9zEbD.js → debug-Ckumcrye.js} +189 -40
  19. package/dist/debug-Ckumcrye.js.map +1 -0
  20. package/dist/{debug-BVC48wlb.js → debug-DLsuyfln.js} +1 -1
  21. package/dist/{environment-uaLmtlH_.js → environment-DUh_8hqW.js} +3 -3
  22. package/dist/{environment-uaLmtlH_.js.map → environment-DUh_8hqW.js.map} +1 -1
  23. package/dist/{interactive-CW5gjyDd.js → interactive-DeiHgviS.js} +2 -2
  24. package/dist/{interactive-CW5gjyDd.js.map → interactive-DeiHgviS.js.map} +1 -1
  25. package/dist/{mcp-prompt-streaming-DMDwaark.js → mcp-prompt-streaming-kEJgmB30.js} +4 -4
  26. package/dist/{mcp-prompt-streaming-DMDwaark.js.map → mcp-prompt-streaming-kEJgmB30.js.map} +1 -1
  27. package/dist/{non-interactive-DJrVQ4nS.js → non-interactive-I4ifOSau.js} +2 -2
  28. package/dist/{non-interactive-DJrVQ4nS.js.map → non-interactive-I4ifOSau.js.map} +1 -1
  29. package/dist/{package-manager-DCUBRbr-.js → package-manager-fUeLORHg.js} +2 -2
  30. package/dist/{package-manager-DCUBRbr-.js.map → package-manager-fUeLORHg.js.map} +1 -1
  31. package/dist/{playground-DCVaVeVD.js → playground-DLLIz4Ql.js} +135 -19
  32. package/dist/playground-DLLIz4Ql.js.map +1 -0
  33. package/dist/{posthog-integration-ChdwFPMj.js → posthog-integration-COcPewVt.js} +48 -16
  34. package/dist/posthog-integration-COcPewVt.js.map +1 -0
  35. package/dist/{provisioning-GeMkBMSR.js → provisioning-7xU12_S9.js} +3 -3
  36. package/dist/{provisioning-GeMkBMSR.js.map → provisioning-7xU12_S9.js.map} +1 -1
  37. package/dist/{registry-VSSRH3sU.js → registry-YwaF-aD8.js} +7 -20
  38. package/dist/registry-YwaF-aD8.js.map +1 -0
  39. package/dist/{setup-utils-BfV4pydt.js → setup-utils-Cr4FxJDl.js} +114 -58
  40. package/dist/setup-utils-Cr4FxJDl.js.map +1 -0
  41. package/dist/{start-tui-BRvm5VP9.js → start-tui--E4PXdwG.js} +323 -134
  42. package/dist/start-tui--E4PXdwG.js.map +1 -0
  43. package/dist/{steps-DA4uvSbg.js → steps-CxUxdK4V.js} +6 -6
  44. package/dist/{steps-DA4uvSbg.js.map → steps-CxUxdK4V.js.map} +1 -1
  45. package/dist/telemetry-BS7yw3TP.js +68 -0
  46. package/dist/telemetry-BS7yw3TP.js.map +1 -0
  47. package/dist/{urls-B66Ib2jT.js → urls-BW23_XbC.js} +2 -2
  48. package/dist/{urls-B66Ib2jT.js.map → urls-BW23_XbC.js.map} +1 -1
  49. package/dist/{wizard-abort-gMB1eV6T.js → wizard-abort-BPsnXKY5.js} +1 -1
  50. package/dist/{wizard-abort-D1_DnFjm.js → wizard-abort-E66_R4S7.js} +3 -3
  51. package/dist/{wizard-abort-D1_DnFjm.js.map → wizard-abort-E66_R4S7.js.map} +1 -1
  52. package/dist/wizard-session-G3VWD6hv.js.map +1 -1
  53. package/dist/wizard-ui-YdGFRyu_.js.map +1 -1
  54. package/package.json +1 -1
  55. package/dist/OutroScreen-CqF6SdBo.js.map +0 -1
  56. package/dist/add-mcp-server-to-clients-DQHGhzt6.js.map +0 -1
  57. package/dist/analytics-Bl5DPj_0.js.map +0 -1
  58. package/dist/debug-h7Z9zEbD.js.map +0 -1
  59. package/dist/playground-DCVaVeVD.js.map +0 -1
  60. package/dist/posthog-integration-ChdwFPMj.js.map +0 -1
  61. package/dist/registry-VSSRH3sU.js.map +0 -1
  62. package/dist/setup-utils-BfV4pydt.js.map +0 -1
  63. package/dist/start-tui-BRvm5VP9.js.map +0 -1
  64. package/dist/telemetry-BRAonUea.js +0 -13
  65. package/dist/telemetry-BRAonUea.js.map +0 -1
@@ -1,20 +1,20 @@
1
- import { M as POSTHOG_DOCS_URL, O as Integration, R as REMOTE_SKILLS_BASE_URL, U as WIZARD_TOOLS_MENU_FLAG_KEY, _ as SIGNUP_WIZARD_READINESS_CONFIG, d as relativeToInstallDir, k as OAUTH_PORTS, l as WIZARD_LOG_FILE, m as setUI, q as getSkillsBaseUrl, s as logToFile, y as getBlockingServiceKeys } from "./debug-h7Z9zEbD.js";
2
- import { t as analytics } from "./analytics-Bl5DPj_0.js";
3
- import { o as extractOAuthCode, t as getOrAskForProjectData } from "./setup-utils-BfV4pydt.js";
4
- import { a as getUiHostFromHost } from "./urls-B66Ib2jT.js";
5
- import { t as ApiError } from "./api-DuA0_88V.js";
1
+ import { A as OAUTH_PORTS, J as WIZARD_TOOLS_MENU_FLAG_KEY, L as POSTHOG_ORG_AI_SETTINGS_URL, P as POSTHOG_DOCS_URL, R as POSTHOG_PRIVACY_URL, U as REMOTE_SKILLS_BASE_URL, V as POSTHOG_TERMS_URL, _ as SIGNUP_WIZARD_READINESS_CONFIG, d as relativeToInstallDir, j as OAUTH_TIMEOUT_MS, k as Integration, l as WIZARD_LOG_FILE, m as setUI, s as logToFile, y as getBlockingServiceKeys } from "./debug-Ckumcrye.js";
2
+ import { t as analytics } from "./analytics-BZv-cKyn.js";
3
+ import { o as extractOAuthCode, t as getOrAskForProjectData } from "./setup-utils-Cr4FxJDl.js";
4
+ import { a as getUiHostFromHost } from "./urls-BW23_XbC.js";
5
+ import { t as ApiError } from "./api-BkLZ8BWm.js";
6
6
  import { t as ADDITIONAL_FEATURE_LABELS } from "./wizard-session-G3VWD6hv.js";
7
- import { i as wizardAbort } from "./wizard-abort-D1_DnFjm.js";
8
- import { _ as AUDIT_CHECKS_KEY, b as coerceAuditChecks, g as AUDIT_CHECKS_FILE, m as fetchSkillMenu, p as downloadSkill, x as getAuditChecks, y as AUDIT_SEVERITY_STYLE } from "./agent-interface-DE7txTqh.js";
9
- import { f as Colors, p as Icons, t as EVENT_PLAN_FILE } from "./posthog-integration-ChdwFPMj.js";
7
+ import { i as wizardAbort } from "./wizard-abort-E66_R4S7.js";
8
+ import { _ as AUDIT_CHECKS_KEY, b as coerceAuditChecks, g as AUDIT_CHECKS_FILE, m as fetchSkillMenu, p as downloadSkill, x as getAuditChecks, y as AUDIT_SEVERITY_STYLE } from "./agent-interface-BPCzPvK-.js";
9
+ import { f as Colors, p as Icons, t as EVENT_PLAN_FILE } from "./posthog-integration-COcPewVt.js";
10
10
  import { a as getProgramConfig, d as getContentBlocks, f as POSTHOG_SDKS, i as Program, o as DISPLAY_NAME, p as STRIPE_SDKS, s as SOURCE_MAPS_CONTEXT_KEYS, u as fetchHealthIssues } from "./bin.js";
11
- import { A as SplitView, C as ConfirmationInput, D as useKeyBindings, E as PickerMenu, M as WizardStore, O as ProgressList, S as ModalOverlay, T as useStdoutDimensions, _ as HNViewer, a as VisualBox, b as EventPlanViewer, d as SEVERITY_LABEL, f as SEVERITY_ORDER, h as LearnCard, i as AUDIT_AREA_SLIDES, k as LoadingBox, l as McpScreen, m as TipsCard, n as SlackConnectScreen, o as AuditChecksViewer, p as ServiceHealthList, r as AUDIT_3000_AREA_SLIDES, s as McpSuggestedPromptsScreen, t as OutroScreen, u as IssueTable, v as TabContainer, x as LogViewer, y as ScreenContainer } from "./OutroScreen-CqF6SdBo.js";
11
+ import { A as useKeyBindings, C as EventPlanViewer, E as ConfirmationInput, F as WizardStore, M as LoadingBox, N as SplitView, O as useStdoutDimensions, S as ScreenContainer, T as ModalOverlay, _ as TipsCard, a as SlackConnectScreen, b as HNViewer, c as VisualBox, f as McpScreen, g as ServiceHealthList, h as SEVERITY_ORDER, i as OutroScreen, j as ProgressList, k as PickerMenu, l as AuditChecksViewer, m as SEVERITY_LABEL, n as SkillSourceInfo, o as AUDIT_3000_AREA_SLIDES, p as IssueTable, r as useSkillEntry, s as AUDIT_AREA_SLIDES, t as AiOptInRequiredScreen, u as McpSuggestedPromptsScreen, v as LearnCard, w as LogViewer, x as TabContainer } from "./AiOptInRequiredScreen-B8mgZbe5.js";
12
12
  import { t as ALL_FEATURE_VALUES } from "./defaults-BNWIWzjc.js";
13
- 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-DQHGhzt6.js";
14
- import { spawn, spawnSync } from "node:child_process";
15
- import { join } from "node:path";
13
+ 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-lCxOS1A1.js";
16
14
  import * as fs$1 from "fs";
17
15
  import path from "path";
16
+ import { join as join$1 } from "node:path";
17
+ import { spawn, spawnSync } from "node:child_process";
18
18
  import { Box, Text, render, useInput } from "ink";
19
19
  import { Fragment, createElement, useEffect, useMemo, useState, useSyncExternalStore } from "react";
20
20
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
@@ -67,6 +67,9 @@ var InkUI = class {
67
67
  setApiUser(user) {
68
68
  this.store.setApiUser(user);
69
69
  }
70
+ waitForAiOptIn() {
71
+ return this.store.getGate("ai-opt-in");
72
+ }
70
73
  setDetectedFramework(label) {
71
74
  this.store.setDetectedFramework(label);
72
75
  }
@@ -98,6 +101,9 @@ var InkUI = class {
98
101
  showAuthError(detail) {
99
102
  this.store.showAuthError(detail);
100
103
  }
104
+ showSessionTimeout() {
105
+ this.store.showSessionTimeout();
106
+ }
101
107
  requestQuestion(question) {
102
108
  return this.store.requestQuestion(question);
103
109
  }
@@ -235,9 +241,10 @@ const HealthCheckScreen = ({ store }) => {
235
241
  const isGithubReleasesDown = hasHardBlock && blockingKeys.includes("githubReleases");
236
242
  const canDownloadSkills = result.health.githubReleases.status === "healthy";
237
243
  const integration = store.session.integration;
238
- const title = hasHardBlock ? "Ongoing service disruptions" : "Service disruption detected";
244
+ const allBlockingHaveNoConnection = hasHardBlock && displayKeys.every((k) => result.health[k].status === "no-connection");
245
+ const title = isGithubReleasesDown ? "Ongoing service disruptions" : allBlockingHaveNoConnection ? "Couldn't reach PostHog" : hasHardBlock ? "Ongoing service disruptions" : "Service disruption detected";
239
246
  const docsUrl = store.session.frameworkConfig?.metadata.docsUrl;
240
- 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.";
247
+ const description = isGithubReleasesDown ? "The Wizard can't download necessary skills from GitHub Releases right now." : allBlockingHaveNoConnection ? "We couldn't reach these services from this machine. PostHog's status page shows no incidents, so this is most likely a network issue — VPN, firewall, captive portal, or flaky Wi-Fi." : 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.";
241
248
  const handleDownloadAndExit = async () => {
242
249
  if (downloading) return;
243
250
  setDownloading(true);
@@ -250,7 +257,7 @@ const HealthCheckScreen = ({ store }) => {
250
257
  setDownloaded(true);
251
258
  };
252
259
  return /* @__PURE__ */ jsxs(ModalOverlay, {
253
- borderColor: hasHardBlock ? "red" : "yellow",
260
+ borderColor: hasHardBlock && !allBlockingHaveNoConnection ? "red" : "yellow",
254
261
  title,
255
262
  width: 72,
256
263
  footer: isGithubReleasesDown ? /* @__PURE__ */ jsx(ConfirmationInput, {
@@ -287,7 +294,15 @@ const HealthCheckScreen = ({ store }) => {
287
294
  }),
288
295
  /* @__PURE__ */ jsx(Text, {
289
296
  dimColor: true,
290
- children: " Degraded"
297
+ children: " Degraded "
298
+ }),
299
+ /* @__PURE__ */ jsx(Text, {
300
+ color: "gray",
301
+ children: Icons.squareFilled
302
+ }),
303
+ /* @__PURE__ */ jsx(Text, {
304
+ dimColor: true,
305
+ children: " No connection"
291
306
  })
292
307
  ] })
293
308
  }), /* @__PURE__ */ jsx(ServiceHealthList, {
@@ -837,7 +852,7 @@ const WizardTitle = ({ title }) => /* @__PURE__ */ jsxs(Text, {
837
852
  title
838
853
  ]
839
854
  });
840
- const IntroScreenLayout = ({ installDir, title = "PostHog Wizard 🦔", showSubtitle = true, body, showDetection = true, detectionRows, children, menuOptions, onSelect, programLabel, skillId, errorView }) => {
855
+ const IntroScreenLayout = ({ installDir, title = "PostHog Wizard 🦔", showSubtitle = true, body, showDetection = true, detectionRows, children, menuOptions, menuAlign = "center", onSelect, programLabel, skillId, errorView }) => {
841
856
  const resolvedMenuOptions = menuOptions === void 0 ? [{
842
857
  label: "Continue",
843
858
  value: "continue"
@@ -933,9 +948,10 @@ const IntroScreenLayout = ({ installDir, title = "PostHog Wizard 🦔", showSubt
933
948
  ]
934
949
  }),
935
950
  /* @__PURE__ */ jsx(Box, {
936
- width: 24,
951
+ width: menuAlign === "left" ? 64 : 24,
952
+ marginTop: 1,
937
953
  children: resolvedMenuOptions && onSelect && /* @__PURE__ */ jsx(Box, {
938
- justifyContent: "center",
954
+ justifyContent: menuAlign === "left" ? "flex-start" : "center",
939
955
  children: /* @__PURE__ */ jsx(PickerMenu, {
940
956
  options: resolvedMenuOptions,
941
957
  onSelect: (value) => {
@@ -948,68 +964,51 @@ const IntroScreenLayout = ({ installDir, title = "PostHog Wizard 🦔", showSubt
948
964
  }) });
949
965
  };
950
966
  //#endregion
951
- //#region src/ui/tui/screens/SkillSourceInfo.tsx
967
+ //#region src/ui/tui/components/PrivacyPanel.tsx
952
968
  /**
953
- * Shared "Skill: <id> / URL: <downloadUrl>" block for intro screens.
969
+ * PrivacyPanel Shared disclosure component.
954
970
  *
955
- * `useSkillEntry` fetches the entry from the skill menu and re-runs when
956
- * `skillId` or `local` change. The previous fetch is cancelled (its result
957
- * is ignored) so a session that flips `local=false true` mid-mount picks
958
- * up the right base URL.
971
+ * Single source of truth for the wizard's privacy disclosure, rendered
972
+ * identically from the intro screen ("Privacy & data usage" menu option)
973
+ * and as an overlay from the auth screen ([I] keystroke).
959
974
  *
960
- * `<SkillSourceInfo>` renders the block, taking the entry as a prop so the
961
- * caller can reuse the same hook result for additional UI (e.g. showing
962
- * `skillEntry.name`) without invoking the hook twice.
975
+ * Must fit in a default-sized macOS Terminal (~24 rows). Two condensed
976
+ * paragraphs carry the top-level disclosure; the link footer follows.
977
+ * Users who want the full legal text follow the Terms / Privacy URLs to
978
+ * their browser.
963
979
  */
964
- function useSkillEntry(skillId, local) {
965
- const [skillEntry, setSkillEntry] = useState(null);
966
- const [fetchFailed, setFetchFailed] = useState(false);
967
- useEffect(() => {
968
- if (!skillId) {
969
- setFetchFailed(true);
970
- return;
971
- }
972
- let cancelled = false;
973
- setSkillEntry(null);
974
- setFetchFailed(false);
975
- fetchSkillMenu(getSkillsBaseUrl(local)).then((menu) => {
976
- if (cancelled) return;
977
- if (!menu) {
978
- setFetchFailed(true);
979
- return;
980
- }
981
- const match = Object.values(menu.categories).flat().find((s) => s.id === skillId);
982
- if (match) setSkillEntry(match);
983
- else setFetchFailed(true);
984
- });
985
- return () => {
986
- cancelled = true;
987
- };
988
- }, [skillId, local]);
989
- return {
990
- skillEntry,
991
- fetchFailed
992
- };
993
- }
994
- const SkillSourceInfo = ({ skillId, skillEntry, fetchFailed }) => /* @__PURE__ */ jsxs(Box, {
995
- flexDirection: "column",
996
- children: [/* @__PURE__ */ jsxs(Text, { children: [
997
- "Skill:",
998
- " ",
999
- /* @__PURE__ */ jsx(Text, {
1000
- italic: true,
1001
- color: "cyan",
1002
- children: skillId ?? "unknown"
1003
- })
1004
- ] }), /* @__PURE__ */ jsxs(Text, { children: [
1005
- "URL:",
1006
- " ",
1007
- /* @__PURE__ */ jsx(Text, {
1008
- color: "cyan",
1009
- children: skillEntry?.downloadUrl ?? (fetchFailed ? "unavailable" : "Loading...")
1010
- })
1011
- ] })]
1012
- });
980
+ const PrivacyPanel = () => {
981
+ return /* @__PURE__ */ jsxs(Box, {
982
+ flexDirection: "column",
983
+ width: 64,
984
+ flexShrink: 0,
985
+ children: [
986
+ /* @__PURE__ */ jsx(Text, { children: "We use Anthropic's Claude via the PostHog LLM gateway to read your source files as AI context. .env* files, secrets, and anything matched by the security scanner stay on your machine." }),
987
+ /* @__PURE__ */ jsx(Box, {
988
+ marginTop: 1,
989
+ children: /* @__PURE__ */ jsx(Text, { children: "To use the wizard, AI features must be enabled in your organization's settings." })
990
+ }),
991
+ /* @__PURE__ */ jsxs(Box, {
992
+ marginTop: 1,
993
+ flexDirection: "column",
994
+ children: [
995
+ /* @__PURE__ */ jsxs(Text, { children: ["Terms: ", /* @__PURE__ */ jsx(Text, {
996
+ color: "cyan",
997
+ children: POSTHOG_TERMS_URL
998
+ })] }),
999
+ /* @__PURE__ */ jsxs(Text, { children: ["Privacy: ", /* @__PURE__ */ jsx(Text, {
1000
+ color: "cyan",
1001
+ children: POSTHOG_PRIVACY_URL
1002
+ })] }),
1003
+ /* @__PURE__ */ jsxs(Text, { children: ["AI settings: ", /* @__PURE__ */ jsx(Text, {
1004
+ color: "cyan",
1005
+ children: POSTHOG_ORG_AI_SETTINGS_URL
1006
+ })] })
1007
+ ]
1008
+ })
1009
+ ]
1010
+ });
1011
+ };
1013
1012
  //#endregion
1014
1013
  //#region src/ui/tui/screens/PostHogIntegrationIntroScreen.tsx
1015
1014
  /**
@@ -1046,7 +1045,7 @@ const FrameworkPicker = ({ store, onComplete }) => {
1046
1045
  })),
1047
1046
  onSelect: (value) => {
1048
1047
  const integration = Array.isArray(value) ? value[0] : value;
1049
- import("./registry-VSSRH3sU.js").then((n) => n.n).then(({ FRAMEWORK_REGISTRY }) => {
1048
+ import("./registry-YwaF-aD8.js").then((n) => n.n).then(({ FRAMEWORK_REGISTRY }) => {
1050
1049
  const config = FRAMEWORK_REGISTRY[integration];
1051
1050
  store.setFrameworkConfig(integration, config);
1052
1051
  store.setDetectedFramework(config.metadata.name);
@@ -1079,7 +1078,7 @@ const PostHogIntegrationIntroScreen = ({ store }) => {
1079
1078
  const needsFrameworkPick = session.detectionComplete && !session.frameworkConfig;
1080
1079
  const unsupported = session.unsupportedVersion;
1081
1080
  const showContinue = session.frameworkConfig !== null && !detecting && !pickingFramework && view === "default" && !unsupported;
1082
- const title = detecting ? "PostHog Wizard starting up" : "PostHog Wizard 🦔";
1081
+ const title = view === "privacy" ? "Wizard privacy & usage" : detecting ? "PostHog Wizard starting up" : "PostHog Wizard 🦔";
1083
1082
  let body = null;
1084
1083
  if (detecting) body = /* @__PURE__ */ jsx(Box, {
1085
1084
  marginY: 1,
@@ -1101,7 +1100,7 @@ const PostHogIntegrationIntroScreen = ({ store }) => {
1101
1100
  });
1102
1101
  else if (view === "more-info") body = /* @__PURE__ */ jsxs(Box, {
1103
1102
  flexDirection: "column",
1104
- width: 56,
1103
+ width: 64,
1105
1104
  flexShrink: 0,
1106
1105
  children: [
1107
1106
  /* @__PURE__ */ jsxs(Text, { children: ["The wizard is an agent that executes PostHog tasks. Its code is open source: ", /* @__PURE__ */ jsx(Text, {
@@ -1128,10 +1127,10 @@ const PostHogIntegrationIntroScreen = ({ store }) => {
1128
1127
  marginTop: 1,
1129
1128
  paddingLeft: 4,
1130
1129
  children: [
1131
- /* @__PURE__ */ jsxs(Text, { children: [`\u2022`, " Product Analytics"] }),
1132
- /* @__PURE__ */ jsxs(Text, { children: [`\u2022`, " Web Analytics"] }),
1133
- /* @__PURE__ */ jsxs(Text, { children: [`\u2022`, " Session Replay"] }),
1134
- /* @__PURE__ */ jsxs(Text, { children: [`\u2022`, " Error Tracking"] })
1130
+ /* @__PURE__ */ jsxs(Text, { children: [`•`, " Product Analytics"] }),
1131
+ /* @__PURE__ */ jsxs(Text, { children: [`•`, " Web Analytics"] }),
1132
+ /* @__PURE__ */ jsxs(Text, { children: [`•`, " Session Replay"] }),
1133
+ /* @__PURE__ */ jsxs(Text, { children: [`•`, " Error Tracking"] })
1135
1134
  ]
1136
1135
  }),
1137
1136
  /* @__PURE__ */ jsxs(Box, {
@@ -1148,6 +1147,7 @@ const PostHogIntegrationIntroScreen = ({ store }) => {
1148
1147
  })
1149
1148
  ]
1150
1149
  });
1150
+ else if (view === "privacy") body = /* @__PURE__ */ jsx(PrivacyPanel, {});
1151
1151
  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." }) }) });
1152
1152
  const detectionRows = [];
1153
1153
  if (frameworkLabel) {
@@ -1218,6 +1218,13 @@ const PostHogIntegrationIntroScreen = ({ store }) => {
1218
1218
  else if (view === "more-info") menuOptions = [{
1219
1219
  label: "Back",
1220
1220
  value: "back"
1221
+ }, {
1222
+ label: "Privacy & data usage",
1223
+ value: "privacy"
1224
+ }];
1225
+ else if (view === "privacy") menuOptions = [{
1226
+ label: "Back",
1227
+ value: "back"
1221
1228
  }];
1222
1229
  else if (showContinue) menuOptions = [
1223
1230
  {
@@ -1252,8 +1259,9 @@ const PostHogIntegrationIntroScreen = ({ store }) => {
1252
1259
  setPickingFramework(true);
1253
1260
  setManuallySelected(true);
1254
1261
  } else if (value === "more-info") setView("more-info");
1262
+ else if (value === "privacy") setView("privacy");
1255
1263
  else if (value === "tools") setView("tools");
1256
- else if (value === "back") setView("default");
1264
+ else if (value === "back") setView(view === "privacy" ? "more-info" : "default");
1257
1265
  else store.completeSetup();
1258
1266
  };
1259
1267
  return /* @__PURE__ */ jsx(IntroScreenLayout, {
@@ -1264,6 +1272,7 @@ const PostHogIntegrationIntroScreen = ({ store }) => {
1264
1272
  showDetection: showContinue,
1265
1273
  detectionRows,
1266
1274
  menuOptions: unsupported ? null : menuOptions,
1275
+ menuAlign: "center",
1267
1276
  onSelect: handleSelect,
1268
1277
  programLabel: session.programLabel,
1269
1278
  skillId: session.skillId,
@@ -1582,6 +1591,7 @@ const MigrationIntroScreen = ({ store }) => {
1582
1591
  */
1583
1592
  const SourceMapsIntroScreen = ({ store }) => {
1584
1593
  useSyncExternalStore((cb) => store.subscribe(cb), () => store.getSnapshot());
1594
+ const [view, setView] = useState("default");
1585
1595
  const { session } = store;
1586
1596
  const detectError = session.frameworkContext[SOURCE_MAPS_CONTEXT_KEYS.detectError];
1587
1597
  const variant = session.frameworkContext[SOURCE_MAPS_CONTEXT_KEYS.skillVariant];
@@ -1596,7 +1606,54 @@ const SourceMapsIntroScreen = ({ store }) => {
1596
1606
  label: "Skill",
1597
1607
  value: `error-tracking-upload-source-maps-${variant}`
1598
1608
  });
1599
- const body = /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs(Box, {
1609
+ const body = view === "more-info" ? /* @__PURE__ */ jsxs(Box, {
1610
+ flexDirection: "column",
1611
+ width: 56,
1612
+ flexShrink: 0,
1613
+ children: [
1614
+ /* @__PURE__ */ jsxs(Text, { children: [
1615
+ "The wizard is an agent that executes PostHog tasks. Its code is open source: ",
1616
+ /* @__PURE__ */ jsx(Text, {
1617
+ color: "cyan",
1618
+ children: "https://github.com/PostHog/wizard"
1619
+ }),
1620
+ "."
1621
+ ] }),
1622
+ /* @__PURE__ */ jsx(Box, {
1623
+ flexDirection: "column",
1624
+ marginTop: 1,
1625
+ children: /* @__PURE__ */ jsxs(Text, { children: [
1626
+ "The",
1627
+ " ",
1628
+ /* @__PURE__ */ jsx(Text, {
1629
+ italic: true,
1630
+ color: "cyan",
1631
+ children: session.programLabel
1632
+ }),
1633
+ " ",
1634
+ "program sets up your project to upload source maps to PostHog, so Error Tracking shows production stack traces in your original source instead of minified bundles. It will:"
1635
+ ] })
1636
+ }),
1637
+ /* @__PURE__ */ jsxs(Box, {
1638
+ flexDirection: "column",
1639
+ marginTop: 1,
1640
+ paddingLeft: 4,
1641
+ children: [
1642
+ /* @__PURE__ */ jsxs(Text, { children: ["•", " Ask for a personal API key to authorize uploads"] }),
1643
+ /* @__PURE__ */ jsxs(Text, { children: ["•", " Wire map generation + upload into your build"] }),
1644
+ /* @__PURE__ */ jsxs(Text, { children: ["•", " Write the upload credentials to your .env"] }),
1645
+ /* @__PURE__ */ jsxs(Text, { children: ["•", " Wire CI for deploys and offer a local test run"] })
1646
+ ]
1647
+ }),
1648
+ /* @__PURE__ */ jsx(Box, {
1649
+ marginTop: 1,
1650
+ children: /* @__PURE__ */ jsx(Text, {
1651
+ dimColor: true,
1652
+ children: "Maps upload to PostHog during the production build and never need to be served publicly."
1653
+ })
1654
+ })
1655
+ ]
1656
+ }) : view === "privacy" ? /* @__PURE__ */ jsx(PrivacyPanel, {}) : /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs(Box, {
1600
1657
  flexDirection: "column",
1601
1658
  alignItems: "center",
1602
1659
  children: [/* @__PURE__ */ jsx(Text, { children: "Upload source maps for accurate error stack traces." }), /* @__PURE__ */ jsx(Box, {
@@ -1643,23 +1700,46 @@ const SourceMapsIntroScreen = ({ store }) => {
1643
1700
  }],
1644
1701
  onSelect: () => process.exit(1)
1645
1702
  })] }) : void 0;
1703
+ const menuOptions = view === "more-info" ? [{
1704
+ label: "Back",
1705
+ value: "back"
1706
+ }, {
1707
+ label: "Privacy & data usage",
1708
+ value: "privacy"
1709
+ }] : view === "privacy" ? [{
1710
+ label: "Back",
1711
+ value: "back"
1712
+ }] : [
1713
+ {
1714
+ label: "Continue",
1715
+ value: "continue"
1716
+ },
1717
+ {
1718
+ label: "More info",
1719
+ value: "more-info"
1720
+ },
1721
+ {
1722
+ label: "Cancel",
1723
+ value: "cancel"
1724
+ }
1725
+ ];
1726
+ const title = view === "privacy" ? "Wizard privacy & usage" : "PostHog Wizard 🦔";
1646
1727
  return /* @__PURE__ */ jsx(IntroScreenLayout, {
1647
1728
  installDir: session.installDir,
1729
+ title,
1730
+ showSubtitle: view === "default",
1648
1731
  body,
1649
- showDetection: true,
1732
+ showDetection: view === "default",
1650
1733
  detectionRows,
1651
1734
  errorView,
1652
1735
  programLabel: session.programLabel,
1653
1736
  skillId: session.skillId,
1654
- menuOptions: [{
1655
- label: "Continue",
1656
- value: "continue"
1657
- }, {
1658
- label: "Cancel",
1659
- value: "cancel"
1660
- }],
1737
+ menuOptions,
1661
1738
  onSelect: (value) => {
1662
1739
  if (value === "cancel") process.exit(0);
1740
+ else if (value === "more-info") setView("more-info");
1741
+ else if (value === "privacy") setView("privacy");
1742
+ else if (value === "back") setView(view === "privacy" ? "more-info" : "default");
1663
1743
  else store.completeSetup();
1664
1744
  }
1665
1745
  });
@@ -1832,7 +1912,7 @@ const DetectErrorBody = ({ error }) => {
1832
1912
  * Unlike the generic OutroScreen, this spells out the operational facts a user
1833
1913
  * needs to actually get de-minified stack traces: that packages were installed
1834
1914
  * and upload credentials written to .env, plus the three gotchas (builds
1835
- * upload, run the build, mirror the env vars in CI). All static guidance —
1915
+ * upload, run the build, give CI the same credentials). All static guidance —
1836
1916
  * driven only by the program's `buildOutroData` (kind / message / report /
1837
1917
  * docs), no per-run data.
1838
1918
  */
@@ -1899,12 +1979,7 @@ const SourceMapsOutroScreen = ({ store }) => {
1899
1979
  bold: true,
1900
1980
  children: "CI"
1901
1981
  }),
1902
- ", make sure the build job exposes the same env vars the wizard added to your ",
1903
- /* @__PURE__ */ jsx(Text, {
1904
- bold: true,
1905
- children: ".env"
1906
- }),
1907
- "."
1982
+ ", the build job needs the same upload credentials. If the wizard wired your pipeline, add the referenced secrets to your CI provider (e.g. GitHub repo secrets) before your next deploy."
1908
1983
  ] })
1909
1984
  ]
1910
1985
  }),
@@ -1915,7 +1990,7 @@ const SourceMapsOutroScreen = ({ store }) => {
1915
1990
  " ",
1916
1991
  /* @__PURE__ */ jsx(Text, {
1917
1992
  bold: true,
1918
- children: join(store.session.installDir, outroData.reportFile)
1993
+ children: join$1(store.session.installDir, outroData.reportFile)
1919
1994
  })
1920
1995
  ] })
1921
1996
  }),
@@ -2797,7 +2872,7 @@ const PendingChecksList = ({ checks }) => {
2797
2872
  //#region src/ui/tui/screens/audit/AuditRunScreen.tsx
2798
2873
  const AuditRunScreen = ({ store }) => {
2799
2874
  useSyncExternalStore((cb) => store.subscribe(cb), () => store.getSnapshot());
2800
- useFileWatcher(join(store.session.installDir, AUDIT_CHECKS_FILE), (parsed) => store.setFrameworkContext(AUDIT_CHECKS_KEY, coerceAuditChecks(parsed)));
2875
+ useFileWatcher(join$1(store.session.installDir, AUDIT_CHECKS_FILE), (parsed) => store.setFrameworkContext(AUDIT_CHECKS_KEY, coerceAuditChecks(parsed)));
2801
2876
  const statuses = store.statusMessages.length > 0 ? store.statusMessages : void 0;
2802
2877
  const [columns] = useStdoutDimensions();
2803
2878
  const checks = getAuditChecks(store.session);
@@ -2983,7 +3058,7 @@ const AuditOutroScreen = ({ store }) => {
2983
3058
  bold: true,
2984
3059
  children: "Report saved to:"
2985
3060
  }),
2986
- /* @__PURE__ */ jsx(Text, { children: join(store.session.installDir, outroData.reportFile) }),
3061
+ /* @__PURE__ */ jsx(Text, { children: join$1(store.session.installDir, outroData.reportFile) }),
2987
3062
  /* @__PURE__ */ jsx(Text, {
2988
3063
  dimColor: true,
2989
3064
  children: "A markdown file in your project folder. Open it in any editor to read the full audit."
@@ -3747,7 +3822,7 @@ const PlayfieldRow = ({ row, state }) => {
3747
3822
  const AUDIT_3000_REPORT_FILE_FALLBACK = "posthog-audit-3000-report.md";
3748
3823
  const Audit3000RunScreen = ({ store }) => {
3749
3824
  useSyncExternalStore((cb) => store.subscribe(cb), () => store.getSnapshot());
3750
- useFileWatcher(join(store.session.installDir, AUDIT_CHECKS_FILE), (parsed) => store.setFrameworkContext(AUDIT_CHECKS_KEY, coerceAuditChecks(parsed)));
3825
+ useFileWatcher(join$1(store.session.installDir, AUDIT_CHECKS_FILE), (parsed) => store.setFrameworkContext(AUDIT_CHECKS_KEY, coerceAuditChecks(parsed)));
3751
3826
  const statuses = store.statusMessages.length > 0 ? store.statusMessages : void 0;
3752
3827
  const [columns] = useStdoutDimensions();
3753
3828
  const [gameState, setGameState] = useState(() => initialState());
@@ -3967,7 +4042,7 @@ const Audit3000OutroScreen = ({ store }) => {
3967
4042
  color: "cyan",
3968
4043
  children: "High-score reel saved to:"
3969
4044
  }),
3970
- /* @__PURE__ */ jsx(Text, { children: join(store.session.installDir, outroData.reportFile) }),
4045
+ /* @__PURE__ */ jsx(Text, { children: join$1(store.session.installDir, outroData.reportFile) }),
3971
4046
  /* @__PURE__ */ jsx(Text, {
3972
4047
  dimColor: true,
3973
4048
  children: "A markdown file in your project folder — open it in any editor to read the full audit."
@@ -4100,19 +4175,47 @@ const SetupScreen = ({ store }) => {
4100
4175
  /**
4101
4176
  * AuthScreen — Shown while waiting for OAuth authentication.
4102
4177
  *
4103
- * Displays framework detection results, beta/disclosure notices,
4104
- * a waiting spinner, and the login URL when available.
4178
+ * Displays framework detection, a compressed privacy summary, a waiting
4179
+ * spinner, and the login URL when available. [I] opens the full
4180
+ * PrivacyPanel as an overlay. [P] (when loginUrl is set) lets the user
4181
+ * paste the callback URL by hand.
4182
+ *
4105
4183
  * The router resolves past this screen once session.credentials is set.
4106
4184
  */
4107
4185
  const AuthScreen = ({ store }) => {
4108
4186
  useSyncExternalStore((cb) => store.subscribe(cb), () => store.getSnapshot());
4187
+ const [showPrivacy, setShowPrivacy] = useState(false);
4109
4188
  const { session } = store;
4110
- useKeyBindings("auth", Boolean(session.loginUrl) ? [{
4111
- match: ["p", "P"],
4112
- label: "P",
4113
- action: "paste auth code",
4114
- handler: () => store.showManualAuthCode()
4115
- }] : []);
4189
+ const canPasteCode = Boolean(session.loginUrl);
4190
+ const bindings = [];
4191
+ if (!showPrivacy) {
4192
+ if (canPasteCode) bindings.push({
4193
+ match: ["p", "P"],
4194
+ label: "P",
4195
+ action: "paste auth code",
4196
+ handler: () => store.showManualAuthCode()
4197
+ });
4198
+ bindings.push({
4199
+ match: ["i", "I"],
4200
+ label: "I",
4201
+ action: "privacy info",
4202
+ handler: () => setShowPrivacy(true)
4203
+ });
4204
+ }
4205
+ useKeyBindings("auth", bindings);
4206
+ if (showPrivacy) return /* @__PURE__ */ jsx(IntroScreenLayout, {
4207
+ installDir: session.installDir,
4208
+ title: "Wizard privacy & usage",
4209
+ showSubtitle: false,
4210
+ showDetection: false,
4211
+ body: /* @__PURE__ */ jsx(PrivacyPanel, {}),
4212
+ menuOptions: [{
4213
+ label: "Back",
4214
+ value: "back"
4215
+ }],
4216
+ menuAlign: "left",
4217
+ onSelect: () => setShowPrivacy(false)
4218
+ });
4116
4219
  const config = session.frameworkConfig;
4117
4220
  const frameworkLabel = session.detectedFrameworkLabel ?? config?.metadata.name;
4118
4221
  return /* @__PURE__ */ jsxs(Box, {
@@ -4146,6 +4249,37 @@ const AuthScreen = ({ store }) => {
4146
4249
  })
4147
4250
  ]
4148
4251
  }),
4252
+ /* @__PURE__ */ jsxs(Box, {
4253
+ flexDirection: "column",
4254
+ marginBottom: 1,
4255
+ children: [
4256
+ /* @__PURE__ */ jsx(Text, {
4257
+ bold: true,
4258
+ dimColor: true,
4259
+ children: "How does the wizard use your data?"
4260
+ }),
4261
+ /* @__PURE__ */ jsxs(Text, {
4262
+ dimColor: true,
4263
+ children: ["•", " Source files are read by Claude for AI context"]
4264
+ }),
4265
+ /* @__PURE__ */ jsxs(Text, {
4266
+ dimColor: true,
4267
+ children: ["•", " .env* and secrets stay on your machine"]
4268
+ }),
4269
+ /* @__PURE__ */ jsxs(Text, {
4270
+ dimColor: true,
4271
+ children: [
4272
+ "•",
4273
+ " Press ",
4274
+ /* @__PURE__ */ jsx(Text, {
4275
+ color: Colors.accent,
4276
+ children: "[I]"
4277
+ }),
4278
+ " for full privacy & usage info"
4279
+ ]
4280
+ })
4281
+ ]
4282
+ }),
4149
4283
  /* @__PURE__ */ jsx(LoadingBox, { message: "Waiting for authentication..." }),
4150
4284
  session.loginUrl && /* @__PURE__ */ jsxs(Box, {
4151
4285
  marginTop: 1,
@@ -4191,7 +4325,7 @@ const AuthScreen = ({ store }) => {
4191
4325
  */
4192
4326
  const RunScreen = ({ store }) => {
4193
4327
  useSyncExternalStore((cb) => store.subscribe(cb), () => store.getSnapshot());
4194
- useFileWatcher(join(store.session.installDir, EVENT_PLAN_FILE), (parsed) => {
4328
+ useFileWatcher(join$1(store.session.installDir, EVENT_PLAN_FILE), (parsed) => {
4195
4329
  if (!Array.isArray(parsed)) return;
4196
4330
  store.setEventPlan(parsed.map((e) => ({
4197
4331
  name: e.name ?? e.event ?? "",
@@ -4277,7 +4411,7 @@ const KeepSkillsScreen = ({ store }) => {
4277
4411
  useSyncExternalStore((cb) => store.subscribe(cb), () => store.getSnapshot());
4278
4412
  const [phase, setPhase] = useState("loading");
4279
4413
  const [skills, setSkills] = useState([]);
4280
- const skillsDir = join(store.session.installDir, ".claude", "skills");
4414
+ const skillsDir = join$1(store.session.installDir, ".claude", "skills");
4281
4415
  useEffect(() => {
4282
4416
  (async () => {
4283
4417
  try {
@@ -4285,11 +4419,11 @@ const KeepSkillsScreen = ({ store }) => {
4285
4419
  const result = [];
4286
4420
  for (const dir of dirs) {
4287
4421
  try {
4288
- await access(join(skillsDir, dir.name, WIZARD_MARKER));
4422
+ await access(join$1(skillsDir, dir.name, WIZARD_MARKER));
4289
4423
  } catch {
4290
4424
  continue;
4291
4425
  }
4292
- const children = (await readdir(join(skillsDir, dir.name))).filter((c) => c !== WIZARD_MARKER);
4426
+ const children = (await readdir(join$1(skillsDir, dir.name))).filter((c) => c !== WIZARD_MARKER);
4293
4427
  result.push({
4294
4428
  name: dir.name,
4295
4429
  children
@@ -4314,7 +4448,7 @@ const KeepSkillsScreen = ({ store }) => {
4314
4448
  const handleRemove = async () => {
4315
4449
  setPhase("removing");
4316
4450
  for (const skill of skills) try {
4317
- await rm(join(skillsDir, skill.name), {
4451
+ await rm(join$1(skillsDir, skill.name), {
4318
4452
  recursive: true,
4319
4453
  force: true
4320
4454
  });
@@ -4559,6 +4693,53 @@ const AuthErrorScreen = ({ store }) => {
4559
4693
  });
4560
4694
  };
4561
4695
  //#endregion
4696
+ //#region src/ui/tui/screens/SessionTimeoutScreen.tsx
4697
+ /**
4698
+ * SessionTimeoutScreen — shown when the OAuth login window expires before the
4699
+ * user completes authorization.
4700
+ *
4701
+ * Pushed as an overlay so it takes priority over the gated AuthScreen (which
4702
+ * never completes without credentials). Terminal state: any key exits, since
4703
+ * the only way forward is to re-run the wizard for a fresh login window.
4704
+ */
4705
+ const TIMEOUT_MINUTES = Math.round(OAUTH_TIMEOUT_MS / 6e4);
4706
+ const SessionTimeoutScreen = ({ store }) => {
4707
+ useSyncExternalStore((cb) => store.subscribe(cb), () => store.getSnapshot());
4708
+ useInput(() => {
4709
+ process.exit(1);
4710
+ });
4711
+ return /* @__PURE__ */ jsxs(Box, {
4712
+ flexDirection: "column",
4713
+ flexGrow: 1,
4714
+ children: [
4715
+ /* @__PURE__ */ jsxs(Text, {
4716
+ color: "red",
4717
+ bold: true,
4718
+ children: ["✘", " Login timed out"]
4719
+ }),
4720
+ /* @__PURE__ */ jsx(Box, {
4721
+ marginTop: 1,
4722
+ children: /* @__PURE__ */ jsxs(Text, { children: [
4723
+ "The OAuth link timed out after ",
4724
+ TIMEOUT_MINUTES,
4725
+ " minutes."
4726
+ ] })
4727
+ }),
4728
+ /* @__PURE__ */ jsx(Box, {
4729
+ marginTop: 1,
4730
+ children: /* @__PURE__ */ jsx(Text, { children: "Re-run the wizard to get a fresh link and try again." })
4731
+ }),
4732
+ /* @__PURE__ */ jsx(Box, {
4733
+ marginTop: 1,
4734
+ children: /* @__PURE__ */ jsx(Text, {
4735
+ color: Colors.muted,
4736
+ children: "Press any key to exit"
4737
+ })
4738
+ })
4739
+ ]
4740
+ });
4741
+ };
4742
+ //#endregion
4562
4743
  //#region src/ui/tui/screens/WizardAskScreen.tsx
4563
4744
  /**
4564
4745
  * WizardAskScreen — Overlay for the `wizard_ask` MCP tool.
@@ -4763,14 +4944,14 @@ function createMcpSuggestedPromptsServices(_store) {
4763
4944
  };
4764
4945
  },
4765
4946
  checkSlackConnected: async (credentials, signal) => {
4766
- const { fetchSlackConnected } = await import("./api-DuA0_88V.js").then((n) => n.n);
4947
+ const { fetchSlackConnected } = await import("./api-BkLZ8BWm.js").then((n) => n.n);
4767
4948
  return fetchSlackConnected(credentials.accessToken, credentials.projectId, credentials.host, signal);
4768
4949
  },
4769
4950
  runPromptStreaming: (args) => runProductionPromptStreaming(args)
4770
4951
  };
4771
4952
  }
4772
4953
  async function* runProductionPromptStreaming(args) {
4773
- const { runMcpPromptViaSdk } = await import("./mcp-prompt-streaming-DMDwaark.js");
4954
+ const { runMcpPromptViaSdk } = await import("./mcp-prompt-streaming-kEJgmB30.js");
4774
4955
  yield* runMcpPromptViaSdk(args);
4775
4956
  }
4776
4957
  //#endregion
@@ -4788,6 +4969,7 @@ function createScreens(store, services) {
4788
4969
  ["port-conflict"]: /* @__PURE__ */ jsx(PortConflictScreen, { store }),
4789
4970
  ["manual-auth-code"]: /* @__PURE__ */ jsx(ManualAuthCodeScreen, { store }),
4790
4971
  ["auth-error"]: /* @__PURE__ */ jsx(AuthErrorScreen, { store }),
4972
+ ["session-timeout"]: /* @__PURE__ */ jsx(SessionTimeoutScreen, { store }),
4791
4973
  ["wizard-ask"]: /* @__PURE__ */ jsx(WizardAskScreen, { store }),
4792
4974
  ["intro"]: /* @__PURE__ */ jsx(PostHogIntegrationIntroScreen, { store }),
4793
4975
  ["revenue-intro"]: /* @__PURE__ */ jsx(RevenueIntroScreen, { store }),
@@ -4806,6 +4988,7 @@ function createScreens(store, services) {
4806
4988
  ["doctor-report"]: /* @__PURE__ */ jsx(DoctorReportScreen, { store }),
4807
4989
  ["setup"]: /* @__PURE__ */ jsx(SetupScreen, { store }),
4808
4990
  ["auth"]: /* @__PURE__ */ jsx(AuthScreen, { store }),
4991
+ ["ai-opt-in"]: /* @__PURE__ */ jsx(AiOptInRequiredScreen, { store }),
4809
4992
  ["run"]: /* @__PURE__ */ jsx(RunScreen, { store }),
4810
4993
  ["mcp"]: /* @__PURE__ */ jsx(McpScreen, {
4811
4994
  store,
@@ -4840,6 +5023,23 @@ const App = ({ store }) => {
4840
5023
  });
4841
5024
  };
4842
5025
  //#endregion
5026
+ //#region src/ui/tui/exit-line.ts
5027
+ const RESET_ATTRS$1 = "\x1B[0m";
5028
+ const GREEN = "\x1B[32m";
5029
+ const BOLD = "\x1B[1m";
5030
+ const DIM = "\x1B[2m";
5031
+ function getExitLine(store) {
5032
+ const outro = store.session.outroData;
5033
+ const label = store.session.programLabel ?? "Wizard";
5034
+ if (outro?.kind === "success") {
5035
+ const message = outro.message ?? `${label} completed successfully.`;
5036
+ const headline = `${GREEN}${BOLD}✔${RESET_ATTRS$1} ${message}${outro.reportFile && !message.includes(outro.reportFile) ? ` Check ./${outro.reportFile} for details.` : ""}`;
5037
+ if (outro.handoffPrompt) return `${headline}\n\n${DIM}Hand this to your coding agent to finish up (triple-click to select):${RESET_ATTRS$1}\n` + outro.handoffPrompt;
5038
+ return headline;
5039
+ }
5040
+ return `${DIM}${label} exited.${RESET_ATTRS$1}`;
5041
+ }
5042
+ //#endregion
4843
5043
  //#region src/ui/tui/start-tui.ts
4844
5044
  /**
4845
5045
  * start-tui.ts — Sets up the Ink TUI renderer and InkUI.
@@ -4854,27 +5054,16 @@ const CURSOR_HOME = "\x1B[H";
4854
5054
  const BG_BLACK = "\x1B[48;2;0;0;0m";
4855
5055
  const ENTER_ALT_SCREEN = "\x1B[?1049h";
4856
5056
  const LEAVE_ALT_SCREEN = "\x1B[?1049l";
4857
- const GREEN = "\x1B[32m";
4858
- const BOLD = "\x1B[1m";
4859
- const DIM = "\x1B[2m";
4860
5057
  function releaseTerminal() {
4861
5058
  process.stdout.write(RESET_ATTRS + LEAVE_ALT_SCREEN);
4862
5059
  }
4863
- function getExitLine(store) {
4864
- const outro = store.session.outroData;
4865
- const label = store.session.programLabel ?? "Wizard";
4866
- if (outro?.kind === "success") {
4867
- const message = outro.message ?? `${label} completed successfully.`;
4868
- return `${GREEN}${BOLD}\u2714${RESET_ATTRS} ${message}${outro.reportFile && !message.includes(outro.reportFile) ? ` Check ./${outro.reportFile} for details.` : ""}`;
4869
- }
4870
- return `${DIM}${label} exited.${RESET_ATTRS}`;
4871
- }
4872
5060
  function startTUI(version, program = Program.PostHogIntegration) {
4873
5061
  process.stdout.write(ENTER_ALT_SCREEN + BG_BLACK + CLEAR_SCREEN + CURSOR_HOME);
4874
5062
  const store = new WizardStore(program);
4875
5063
  store.version = version;
4876
5064
  setUI(new InkUI(store));
4877
5065
  const { unmount: inkUnmount, waitUntilExit } = render(createElement(App, { store }));
5066
+ analytics.wizardCapture("started", { program_id: program });
4878
5067
  store.runInitHooks();
4879
5068
  process.stdin.on("error", (err) => {
4880
5069
  if (err.code !== "EIO") throw err;
@@ -4902,4 +5091,4 @@ function startTUI(version, program = Program.PostHogIntegration) {
4902
5091
  //#endregion
4903
5092
  export { startTUI };
4904
5093
 
4905
- //# sourceMappingURL=start-tui-BRvm5VP9.js.map
5094
+ //# sourceMappingURL=start-tui--E4PXdwG.js.map