@posthog/wizard 2.20.0 → 2.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/README.md +14 -1
  2. package/dist/{slides-BEshbXqG.js → AiOptInRequiredScreen-N6L80szR.js} +741 -33
  3. package/dist/AiOptInRequiredScreen-N6L80szR.js.map +1 -0
  4. package/dist/{add-mcp-server-to-clients-iV7BuQpD.js → add-mcp-server-to-clients-DqHCkHqM.js} +12 -10
  5. package/dist/add-mcp-server-to-clients-DqHCkHqM.js.map +1 -0
  6. package/dist/{agent-interface-B-LAvrNL.js → agent-interface-DZmVoik2.js} +5 -5
  7. package/dist/{agent-interface-B-LAvrNL.js.map → agent-interface-DZmVoik2.js.map} +1 -1
  8. package/dist/{agent-runner-w2Qu9M13.js → agent-runner-CGFUXR97.js} +13 -9
  9. package/dist/{agent-runner-w2Qu9M13.js.map → agent-runner-CGFUXR97.js.map} +1 -1
  10. package/dist/{analytics-C8lJzXjY.js → analytics-C_lVPZQT.js} +28 -4
  11. package/dist/analytics-C_lVPZQT.js.map +1 -0
  12. package/dist/{api-eUlUinVy.js → api-QI1lO_Bz.js} +3 -3
  13. package/dist/{api-eUlUinVy.js.map → api-QI1lO_Bz.js.map} +1 -1
  14. package/dist/bin.js +160 -49
  15. package/dist/bin.js.map +1 -1
  16. package/dist/{ci-install-CSo7Q1pK.js → ci-install-CXkKR4A-.js} +4 -4
  17. package/dist/{ci-install-CSo7Q1pK.js.map → ci-install-CXkKR4A-.js.map} +1 -1
  18. package/dist/{debug-BJu_sS4l.js → debug-D8QAez2V.js} +58 -13
  19. package/dist/debug-D8QAez2V.js.map +1 -0
  20. package/dist/{debug-CTViFiF-.js → debug-lPpecs0J.js} +1 -1
  21. package/dist/{environment-Dk_dWk3t.js → environment-CMmzgZkN.js} +3 -3
  22. package/dist/{environment-Dk_dWk3t.js.map → environment-CMmzgZkN.js.map} +1 -1
  23. package/dist/{interactive-BS2rIf1v.js → interactive-Bu8YchJG.js} +2 -2
  24. package/dist/{interactive-BS2rIf1v.js.map → interactive-Bu8YchJG.js.map} +1 -1
  25. package/dist/{mcp-prompt-streaming-BiMrlLl0.js → mcp-prompt-streaming-mYw2LPZZ.js} +4 -4
  26. package/dist/{mcp-prompt-streaming-BiMrlLl0.js.map → mcp-prompt-streaming-mYw2LPZZ.js.map} +1 -1
  27. package/dist/{non-interactive-C39d_KIp.js → non-interactive-De3tJM1y.js} +2 -2
  28. package/dist/{non-interactive-C39d_KIp.js.map → non-interactive-De3tJM1y.js.map} +1 -1
  29. package/dist/{package-manager-BfOTvFt-.js → package-manager-BVJnbp1u.js} +2 -2
  30. package/dist/{package-manager-BfOTvFt-.js.map → package-manager-BVJnbp1u.js.map} +1 -1
  31. package/dist/{playground-3OeRB7JU.js → playground-wyoq1yIH.js} +205 -4
  32. package/dist/playground-wyoq1yIH.js.map +1 -0
  33. package/dist/{posthog-integration-8iTgqy2J.js → posthog-integration-mrMF-2IP.js} +48 -16
  34. package/dist/posthog-integration-mrMF-2IP.js.map +1 -0
  35. package/dist/{provisioning-DxaT7bWw.js → provisioning-4zipVpbq.js} +3 -3
  36. package/dist/{provisioning-DxaT7bWw.js.map → provisioning-4zipVpbq.js.map} +1 -1
  37. package/dist/{registry-apQfB3rf.js → registry-BGUo4PlM.js} +7 -20
  38. package/dist/registry-BGUo4PlM.js.map +1 -0
  39. package/dist/{setup-utils-B9xqAXXl.js → setup-utils-DmhPyWkp.js} +114 -57
  40. package/dist/setup-utils-DmhPyWkp.js.map +1 -0
  41. package/dist/{start-tui-CCpKnZOY.js → start-tui-DaQiY_EB.js} +310 -452
  42. package/dist/start-tui-DaQiY_EB.js.map +1 -0
  43. package/dist/{steps-DKbDDnVH.js → steps-CrUceWR5.js} +6 -6
  44. package/dist/{steps-DKbDDnVH.js.map → steps-CrUceWR5.js.map} +1 -1
  45. package/dist/telemetry-CCVjGq7l.js +68 -0
  46. package/dist/telemetry-CCVjGq7l.js.map +1 -0
  47. package/dist/{urls-B6wBIwr1.js → urls-BNFpfcN8.js} +2 -2
  48. package/dist/{urls-B6wBIwr1.js.map → urls-BNFpfcN8.js.map} +1 -1
  49. package/dist/{wizard-abort-DhGgTlUA.js → wizard-abort-BmYb0bG2.js} +3 -3
  50. package/dist/{wizard-abort-DhGgTlUA.js.map → wizard-abort-BmYb0bG2.js.map} +1 -1
  51. package/dist/{wizard-abort-D8XZdVAR.js → wizard-abort-Bp2yxYAy.js} +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/add-mcp-server-to-clients-iV7BuQpD.js.map +0 -1
  56. package/dist/analytics-C8lJzXjY.js.map +0 -1
  57. package/dist/debug-BJu_sS4l.js.map +0 -1
  58. package/dist/playground-3OeRB7JU.js.map +0 -1
  59. package/dist/posthog-integration-8iTgqy2J.js.map +0 -1
  60. package/dist/registry-apQfB3rf.js.map +0 -1
  61. package/dist/setup-utils-B9xqAXXl.js.map +0 -1
  62. package/dist/slides-BEshbXqG.js.map +0 -1
  63. package/dist/start-tui-CCpKnZOY.js.map +0 -1
  64. package/dist/telemetry-DUeOcmpo.js +0 -13
  65. package/dist/telemetry-DUeOcmpo.js.map +0 -1
@@ -1,21 +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-BJu_sS4l.js";
2
- import { t as analytics } from "./analytics-C8lJzXjY.js";
3
- import { o as extractOAuthCode, t as getOrAskForProjectData } from "./setup-utils-B9xqAXXl.js";
4
- import { a as getUiHostFromHost } from "./urls-B6wBIwr1.js";
5
- import { i as fetchSlackConnected, t as ApiError } from "./api-eUlUinVy.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-D8QAez2V.js";
2
+ import { t as analytics } from "./analytics-C_lVPZQT.js";
3
+ import { o as extractOAuthCode, t as getOrAskForProjectData } from "./setup-utils-DmhPyWkp.js";
4
+ import { a as getUiHostFromHost } from "./urls-BNFpfcN8.js";
5
+ import { t as ApiError } from "./api-QI1lO_Bz.js";
6
6
  import { t as ADDITIONAL_FEATURE_LABELS } from "./wizard-session-G3VWD6hv.js";
7
- import { i as wizardAbort } from "./wizard-abort-DhGgTlUA.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-B-LAvrNL.js";
9
- import { f as Colors, p as Icons, t as EVENT_PLAN_FILE } from "./posthog-integration-8iTgqy2J.js";
7
+ import { i as wizardAbort } from "./wizard-abort-BmYb0bG2.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-DZmVoik2.js";
9
+ import { f as Colors, p as Icons, t as EVENT_PLAN_FILE } from "./posthog-integration-mrMF-2IP.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 { D as ProgressList, E as useKeyBindings, O as LoadingBox, S as ConfirmationInput, T as PickerMenu, _ as TabContainer, a as McpSuggestedPromptsScreen, b as LogViewer, c as McpScreen, d as SEVERITY_ORDER, f as ServiceHealthList, g as HNViewer, i as AuditChecksViewer, j as WizardStore, k as SplitView, l as IssueTable, m as LearnCard, n as AUDIT_AREA_SLIDES, p as TipsCard, r as VisualBox, s as getSlackAppCard, t as AUDIT_3000_AREA_SLIDES, u as SEVERITY_LABEL, v as ScreenContainer, w as useStdoutDimensions, x as ModalOverlay, y as EventPlanViewer } from "./slides-BEshbXqG.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-N6L80szR.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-iV7BuQpD.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-DqHCkHqM.js";
16
14
  import * as fs$1 from "fs";
17
15
  import path from "path";
18
- import opn from "opn";
16
+ import { join as join$1 } from "node:path";
17
+ import { spawn, spawnSync } from "node:child_process";
19
18
  import { Box, Text, render, useInput } from "ink";
20
19
  import { Fragment, createElement, useEffect, useMemo, useState, useSyncExternalStore } from "react";
21
20
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
@@ -68,6 +67,9 @@ var InkUI = class {
68
67
  setApiUser(user) {
69
68
  this.store.setApiUser(user);
70
69
  }
70
+ waitForAiOptIn() {
71
+ return this.store.getGate("ai-opt-in");
72
+ }
71
73
  setDetectedFramework(label) {
72
74
  this.store.setDetectedFramework(label);
73
75
  }
@@ -99,6 +101,9 @@ var InkUI = class {
99
101
  showAuthError(detail) {
100
102
  this.store.showAuthError(detail);
101
103
  }
104
+ showSessionTimeout() {
105
+ this.store.showSessionTimeout();
106
+ }
102
107
  requestQuestion(question) {
103
108
  return this.store.requestQuestion(question);
104
109
  }
@@ -838,7 +843,7 @@ const WizardTitle = ({ title }) => /* @__PURE__ */ jsxs(Text, {
838
843
  title
839
844
  ]
840
845
  });
841
- const IntroScreenLayout = ({ installDir, title = "PostHog Wizard 🦔", showSubtitle = true, body, showDetection = true, detectionRows, children, menuOptions, onSelect, programLabel, skillId, errorView }) => {
846
+ const IntroScreenLayout = ({ installDir, title = "PostHog Wizard 🦔", showSubtitle = true, body, showDetection = true, detectionRows, children, menuOptions, menuAlign = "center", onSelect, programLabel, skillId, errorView }) => {
842
847
  const resolvedMenuOptions = menuOptions === void 0 ? [{
843
848
  label: "Continue",
844
849
  value: "continue"
@@ -934,9 +939,10 @@ const IntroScreenLayout = ({ installDir, title = "PostHog Wizard 🦔", showSubt
934
939
  ]
935
940
  }),
936
941
  /* @__PURE__ */ jsx(Box, {
937
- width: 24,
942
+ width: menuAlign === "left" ? 64 : 24,
943
+ marginTop: 1,
938
944
  children: resolvedMenuOptions && onSelect && /* @__PURE__ */ jsx(Box, {
939
- justifyContent: "center",
945
+ justifyContent: menuAlign === "left" ? "flex-start" : "center",
940
946
  children: /* @__PURE__ */ jsx(PickerMenu, {
941
947
  options: resolvedMenuOptions,
942
948
  onSelect: (value) => {
@@ -949,68 +955,51 @@ const IntroScreenLayout = ({ installDir, title = "PostHog Wizard 🦔", showSubt
949
955
  }) });
950
956
  };
951
957
  //#endregion
952
- //#region src/ui/tui/screens/SkillSourceInfo.tsx
958
+ //#region src/ui/tui/components/PrivacyPanel.tsx
953
959
  /**
954
- * Shared "Skill: <id> / URL: <downloadUrl>" block for intro screens.
960
+ * PrivacyPanel Shared disclosure component.
955
961
  *
956
- * `useSkillEntry` fetches the entry from the skill menu and re-runs when
957
- * `skillId` or `local` change. The previous fetch is cancelled (its result
958
- * is ignored) so a session that flips `local=false true` mid-mount picks
959
- * up the right base URL.
962
+ * Single source of truth for the wizard's privacy disclosure, rendered
963
+ * identically from the intro screen ("Privacy & data usage" menu option)
964
+ * and as an overlay from the auth screen ([I] keystroke).
960
965
  *
961
- * `<SkillSourceInfo>` renders the block, taking the entry as a prop so the
962
- * caller can reuse the same hook result for additional UI (e.g. showing
963
- * `skillEntry.name`) without invoking the hook twice.
966
+ * Must fit in a default-sized macOS Terminal (~24 rows). Two condensed
967
+ * paragraphs carry the top-level disclosure; the link footer follows.
968
+ * Users who want the full legal text follow the Terms / Privacy URLs to
969
+ * their browser.
964
970
  */
965
- function useSkillEntry(skillId, local) {
966
- const [skillEntry, setSkillEntry] = useState(null);
967
- const [fetchFailed, setFetchFailed] = useState(false);
968
- useEffect(() => {
969
- if (!skillId) {
970
- setFetchFailed(true);
971
- return;
972
- }
973
- let cancelled = false;
974
- setSkillEntry(null);
975
- setFetchFailed(false);
976
- fetchSkillMenu(getSkillsBaseUrl(local)).then((menu) => {
977
- if (cancelled) return;
978
- if (!menu) {
979
- setFetchFailed(true);
980
- return;
981
- }
982
- const match = Object.values(menu.categories).flat().find((s) => s.id === skillId);
983
- if (match) setSkillEntry(match);
984
- else setFetchFailed(true);
985
- });
986
- return () => {
987
- cancelled = true;
988
- };
989
- }, [skillId, local]);
990
- return {
991
- skillEntry,
992
- fetchFailed
993
- };
994
- }
995
- const SkillSourceInfo = ({ skillId, skillEntry, fetchFailed }) => /* @__PURE__ */ jsxs(Box, {
996
- flexDirection: "column",
997
- children: [/* @__PURE__ */ jsxs(Text, { children: [
998
- "Skill:",
999
- " ",
1000
- /* @__PURE__ */ jsx(Text, {
1001
- italic: true,
1002
- color: "cyan",
1003
- children: skillId ?? "unknown"
1004
- })
1005
- ] }), /* @__PURE__ */ jsxs(Text, { children: [
1006
- "URL:",
1007
- " ",
1008
- /* @__PURE__ */ jsx(Text, {
1009
- color: "cyan",
1010
- children: skillEntry?.downloadUrl ?? (fetchFailed ? "unavailable" : "Loading...")
1011
- })
1012
- ] })]
1013
- });
971
+ const PrivacyPanel = () => {
972
+ return /* @__PURE__ */ jsxs(Box, {
973
+ flexDirection: "column",
974
+ width: 64,
975
+ flexShrink: 0,
976
+ children: [
977
+ /* @__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." }),
978
+ /* @__PURE__ */ jsx(Box, {
979
+ marginTop: 1,
980
+ children: /* @__PURE__ */ jsx(Text, { children: "To use the wizard, AI features must be enabled in your organization's settings." })
981
+ }),
982
+ /* @__PURE__ */ jsxs(Box, {
983
+ marginTop: 1,
984
+ flexDirection: "column",
985
+ children: [
986
+ /* @__PURE__ */ jsxs(Text, { children: ["Terms: ", /* @__PURE__ */ jsx(Text, {
987
+ color: "cyan",
988
+ children: POSTHOG_TERMS_URL
989
+ })] }),
990
+ /* @__PURE__ */ jsxs(Text, { children: ["Privacy: ", /* @__PURE__ */ jsx(Text, {
991
+ color: "cyan",
992
+ children: POSTHOG_PRIVACY_URL
993
+ })] }),
994
+ /* @__PURE__ */ jsxs(Text, { children: ["AI settings: ", /* @__PURE__ */ jsx(Text, {
995
+ color: "cyan",
996
+ children: POSTHOG_ORG_AI_SETTINGS_URL
997
+ })] })
998
+ ]
999
+ })
1000
+ ]
1001
+ });
1002
+ };
1014
1003
  //#endregion
1015
1004
  //#region src/ui/tui/screens/PostHogIntegrationIntroScreen.tsx
1016
1005
  /**
@@ -1047,7 +1036,7 @@ const FrameworkPicker = ({ store, onComplete }) => {
1047
1036
  })),
1048
1037
  onSelect: (value) => {
1049
1038
  const integration = Array.isArray(value) ? value[0] : value;
1050
- import("./registry-apQfB3rf.js").then((n) => n.n).then(({ FRAMEWORK_REGISTRY }) => {
1039
+ import("./registry-BGUo4PlM.js").then((n) => n.n).then(({ FRAMEWORK_REGISTRY }) => {
1051
1040
  const config = FRAMEWORK_REGISTRY[integration];
1052
1041
  store.setFrameworkConfig(integration, config);
1053
1042
  store.setDetectedFramework(config.metadata.name);
@@ -1080,7 +1069,7 @@ const PostHogIntegrationIntroScreen = ({ store }) => {
1080
1069
  const needsFrameworkPick = session.detectionComplete && !session.frameworkConfig;
1081
1070
  const unsupported = session.unsupportedVersion;
1082
1071
  const showContinue = session.frameworkConfig !== null && !detecting && !pickingFramework && view === "default" && !unsupported;
1083
- const title = detecting ? "PostHog Wizard starting up" : "PostHog Wizard 🦔";
1072
+ const title = view === "privacy" ? "Wizard privacy & usage" : detecting ? "PostHog Wizard starting up" : "PostHog Wizard 🦔";
1084
1073
  let body = null;
1085
1074
  if (detecting) body = /* @__PURE__ */ jsx(Box, {
1086
1075
  marginY: 1,
@@ -1102,7 +1091,7 @@ const PostHogIntegrationIntroScreen = ({ store }) => {
1102
1091
  });
1103
1092
  else if (view === "more-info") body = /* @__PURE__ */ jsxs(Box, {
1104
1093
  flexDirection: "column",
1105
- width: 56,
1094
+ width: 64,
1106
1095
  flexShrink: 0,
1107
1096
  children: [
1108
1097
  /* @__PURE__ */ jsxs(Text, { children: ["The wizard is an agent that executes PostHog tasks. Its code is open source: ", /* @__PURE__ */ jsx(Text, {
@@ -1129,10 +1118,10 @@ const PostHogIntegrationIntroScreen = ({ store }) => {
1129
1118
  marginTop: 1,
1130
1119
  paddingLeft: 4,
1131
1120
  children: [
1132
- /* @__PURE__ */ jsxs(Text, { children: [`\u2022`, " Product Analytics"] }),
1133
- /* @__PURE__ */ jsxs(Text, { children: [`\u2022`, " Web Analytics"] }),
1134
- /* @__PURE__ */ jsxs(Text, { children: [`\u2022`, " Session Replay"] }),
1135
- /* @__PURE__ */ jsxs(Text, { children: [`\u2022`, " Error Tracking"] })
1121
+ /* @__PURE__ */ jsxs(Text, { children: [`•`, " Product Analytics"] }),
1122
+ /* @__PURE__ */ jsxs(Text, { children: [`•`, " Web Analytics"] }),
1123
+ /* @__PURE__ */ jsxs(Text, { children: [`•`, " Session Replay"] }),
1124
+ /* @__PURE__ */ jsxs(Text, { children: [`•`, " Error Tracking"] })
1136
1125
  ]
1137
1126
  }),
1138
1127
  /* @__PURE__ */ jsxs(Box, {
@@ -1149,6 +1138,7 @@ const PostHogIntegrationIntroScreen = ({ store }) => {
1149
1138
  })
1150
1139
  ]
1151
1140
  });
1141
+ else if (view === "privacy") body = /* @__PURE__ */ jsx(PrivacyPanel, {});
1152
1142
  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." }) }) });
1153
1143
  const detectionRows = [];
1154
1144
  if (frameworkLabel) {
@@ -1219,6 +1209,13 @@ const PostHogIntegrationIntroScreen = ({ store }) => {
1219
1209
  else if (view === "more-info") menuOptions = [{
1220
1210
  label: "Back",
1221
1211
  value: "back"
1212
+ }, {
1213
+ label: "Privacy & data usage",
1214
+ value: "privacy"
1215
+ }];
1216
+ else if (view === "privacy") menuOptions = [{
1217
+ label: "Back",
1218
+ value: "back"
1222
1219
  }];
1223
1220
  else if (showContinue) menuOptions = [
1224
1221
  {
@@ -1253,8 +1250,9 @@ const PostHogIntegrationIntroScreen = ({ store }) => {
1253
1250
  setPickingFramework(true);
1254
1251
  setManuallySelected(true);
1255
1252
  } else if (value === "more-info") setView("more-info");
1253
+ else if (value === "privacy") setView("privacy");
1256
1254
  else if (value === "tools") setView("tools");
1257
- else if (value === "back") setView("default");
1255
+ else if (value === "back") setView(view === "privacy" ? "more-info" : "default");
1258
1256
  else store.completeSetup();
1259
1257
  };
1260
1258
  return /* @__PURE__ */ jsx(IntroScreenLayout, {
@@ -1265,6 +1263,7 @@ const PostHogIntegrationIntroScreen = ({ store }) => {
1265
1263
  showDetection: showContinue,
1266
1264
  detectionRows,
1267
1265
  menuOptions: unsupported ? null : menuOptions,
1266
+ menuAlign: "center",
1268
1267
  onSelect: handleSelect,
1269
1268
  programLabel: session.programLabel,
1270
1269
  skillId: session.skillId,
@@ -1583,6 +1582,7 @@ const MigrationIntroScreen = ({ store }) => {
1583
1582
  */
1584
1583
  const SourceMapsIntroScreen = ({ store }) => {
1585
1584
  useSyncExternalStore((cb) => store.subscribe(cb), () => store.getSnapshot());
1585
+ const [view, setView] = useState("default");
1586
1586
  const { session } = store;
1587
1587
  const detectError = session.frameworkContext[SOURCE_MAPS_CONTEXT_KEYS.detectError];
1588
1588
  const variant = session.frameworkContext[SOURCE_MAPS_CONTEXT_KEYS.skillVariant];
@@ -1597,7 +1597,54 @@ const SourceMapsIntroScreen = ({ store }) => {
1597
1597
  label: "Skill",
1598
1598
  value: `error-tracking-upload-source-maps-${variant}`
1599
1599
  });
1600
- const body = /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs(Box, {
1600
+ const body = view === "more-info" ? /* @__PURE__ */ jsxs(Box, {
1601
+ flexDirection: "column",
1602
+ width: 56,
1603
+ flexShrink: 0,
1604
+ children: [
1605
+ /* @__PURE__ */ jsxs(Text, { children: [
1606
+ "The wizard is an agent that executes PostHog tasks. Its code is open source: ",
1607
+ /* @__PURE__ */ jsx(Text, {
1608
+ color: "cyan",
1609
+ children: "https://github.com/PostHog/wizard"
1610
+ }),
1611
+ "."
1612
+ ] }),
1613
+ /* @__PURE__ */ jsx(Box, {
1614
+ flexDirection: "column",
1615
+ marginTop: 1,
1616
+ children: /* @__PURE__ */ jsxs(Text, { children: [
1617
+ "The",
1618
+ " ",
1619
+ /* @__PURE__ */ jsx(Text, {
1620
+ italic: true,
1621
+ color: "cyan",
1622
+ children: session.programLabel
1623
+ }),
1624
+ " ",
1625
+ "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:"
1626
+ ] })
1627
+ }),
1628
+ /* @__PURE__ */ jsxs(Box, {
1629
+ flexDirection: "column",
1630
+ marginTop: 1,
1631
+ paddingLeft: 4,
1632
+ children: [
1633
+ /* @__PURE__ */ jsxs(Text, { children: ["•", " Ask for a personal API key to authorize uploads"] }),
1634
+ /* @__PURE__ */ jsxs(Text, { children: ["•", " Wire map generation + upload into your build"] }),
1635
+ /* @__PURE__ */ jsxs(Text, { children: ["•", " Write the upload credentials to your .env"] }),
1636
+ /* @__PURE__ */ jsxs(Text, { children: ["•", " Wire CI for deploys and offer a local test run"] })
1637
+ ]
1638
+ }),
1639
+ /* @__PURE__ */ jsx(Box, {
1640
+ marginTop: 1,
1641
+ children: /* @__PURE__ */ jsx(Text, {
1642
+ dimColor: true,
1643
+ children: "Maps upload to PostHog during the production build and never need to be served publicly."
1644
+ })
1645
+ })
1646
+ ]
1647
+ }) : view === "privacy" ? /* @__PURE__ */ jsx(PrivacyPanel, {}) : /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs(Box, {
1601
1648
  flexDirection: "column",
1602
1649
  alignItems: "center",
1603
1650
  children: [/* @__PURE__ */ jsx(Text, { children: "Upload source maps for accurate error stack traces." }), /* @__PURE__ */ jsx(Box, {
@@ -1644,23 +1691,46 @@ const SourceMapsIntroScreen = ({ store }) => {
1644
1691
  }],
1645
1692
  onSelect: () => process.exit(1)
1646
1693
  })] }) : void 0;
1694
+ const menuOptions = view === "more-info" ? [{
1695
+ label: "Back",
1696
+ value: "back"
1697
+ }, {
1698
+ label: "Privacy & data usage",
1699
+ value: "privacy"
1700
+ }] : view === "privacy" ? [{
1701
+ label: "Back",
1702
+ value: "back"
1703
+ }] : [
1704
+ {
1705
+ label: "Continue",
1706
+ value: "continue"
1707
+ },
1708
+ {
1709
+ label: "More info",
1710
+ value: "more-info"
1711
+ },
1712
+ {
1713
+ label: "Cancel",
1714
+ value: "cancel"
1715
+ }
1716
+ ];
1717
+ const title = view === "privacy" ? "Wizard privacy & usage" : "PostHog Wizard 🦔";
1647
1718
  return /* @__PURE__ */ jsx(IntroScreenLayout, {
1648
1719
  installDir: session.installDir,
1720
+ title,
1721
+ showSubtitle: view === "default",
1649
1722
  body,
1650
- showDetection: true,
1723
+ showDetection: view === "default",
1651
1724
  detectionRows,
1652
1725
  errorView,
1653
1726
  programLabel: session.programLabel,
1654
1727
  skillId: session.skillId,
1655
- menuOptions: [{
1656
- label: "Continue",
1657
- value: "continue"
1658
- }, {
1659
- label: "Cancel",
1660
- value: "cancel"
1661
- }],
1728
+ menuOptions,
1662
1729
  onSelect: (value) => {
1663
1730
  if (value === "cancel") process.exit(0);
1731
+ else if (value === "more-info") setView("more-info");
1732
+ else if (value === "privacy") setView("privacy");
1733
+ else if (value === "back") setView(view === "privacy" ? "more-info" : "default");
1664
1734
  else store.completeSetup();
1665
1735
  }
1666
1736
  });
@@ -1833,7 +1903,7 @@ const DetectErrorBody = ({ error }) => {
1833
1903
  * Unlike the generic OutroScreen, this spells out the operational facts a user
1834
1904
  * needs to actually get de-minified stack traces: that packages were installed
1835
1905
  * and upload credentials written to .env, plus the three gotchas (builds
1836
- * upload, run the build, mirror the env vars in CI). All static guidance —
1906
+ * upload, run the build, give CI the same credentials). All static guidance —
1837
1907
  * driven only by the program's `buildOutroData` (kind / message / report /
1838
1908
  * docs), no per-run data.
1839
1909
  */
@@ -1900,12 +1970,7 @@ const SourceMapsOutroScreen = ({ store }) => {
1900
1970
  bold: true,
1901
1971
  children: "CI"
1902
1972
  }),
1903
- ", make sure the build job exposes the same env vars the wizard added to your ",
1904
- /* @__PURE__ */ jsx(Text, {
1905
- bold: true,
1906
- children: ".env"
1907
- }),
1908
- "."
1973
+ ", 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."
1909
1974
  ] })
1910
1975
  ]
1911
1976
  }),
@@ -1916,7 +1981,7 @@ const SourceMapsOutroScreen = ({ store }) => {
1916
1981
  " ",
1917
1982
  /* @__PURE__ */ jsx(Text, {
1918
1983
  bold: true,
1919
- children: join(store.session.installDir, outroData.reportFile)
1984
+ children: join$1(store.session.installDir, outroData.reportFile)
1920
1985
  })
1921
1986
  ] })
1922
1987
  }),
@@ -2798,7 +2863,7 @@ const PendingChecksList = ({ checks }) => {
2798
2863
  //#region src/ui/tui/screens/audit/AuditRunScreen.tsx
2799
2864
  const AuditRunScreen = ({ store }) => {
2800
2865
  useSyncExternalStore((cb) => store.subscribe(cb), () => store.getSnapshot());
2801
- useFileWatcher(join(store.session.installDir, AUDIT_CHECKS_FILE), (parsed) => store.setFrameworkContext(AUDIT_CHECKS_KEY, coerceAuditChecks(parsed)));
2866
+ useFileWatcher(join$1(store.session.installDir, AUDIT_CHECKS_FILE), (parsed) => store.setFrameworkContext(AUDIT_CHECKS_KEY, coerceAuditChecks(parsed)));
2802
2867
  const statuses = store.statusMessages.length > 0 ? store.statusMessages : void 0;
2803
2868
  const [columns] = useStdoutDimensions();
2804
2869
  const checks = getAuditChecks(store.session);
@@ -2984,7 +3049,7 @@ const AuditOutroScreen = ({ store }) => {
2984
3049
  bold: true,
2985
3050
  children: "Report saved to:"
2986
3051
  }),
2987
- /* @__PURE__ */ jsx(Text, { children: join(store.session.installDir, outroData.reportFile) }),
3052
+ /* @__PURE__ */ jsx(Text, { children: join$1(store.session.installDir, outroData.reportFile) }),
2988
3053
  /* @__PURE__ */ jsx(Text, {
2989
3054
  dimColor: true,
2990
3055
  children: "A markdown file in your project folder. Open it in any editor to read the full audit."
@@ -3748,7 +3813,7 @@ const PlayfieldRow = ({ row, state }) => {
3748
3813
  const AUDIT_3000_REPORT_FILE_FALLBACK = "posthog-audit-3000-report.md";
3749
3814
  const Audit3000RunScreen = ({ store }) => {
3750
3815
  useSyncExternalStore((cb) => store.subscribe(cb), () => store.getSnapshot());
3751
- useFileWatcher(join(store.session.installDir, AUDIT_CHECKS_FILE), (parsed) => store.setFrameworkContext(AUDIT_CHECKS_KEY, coerceAuditChecks(parsed)));
3816
+ useFileWatcher(join$1(store.session.installDir, AUDIT_CHECKS_FILE), (parsed) => store.setFrameworkContext(AUDIT_CHECKS_KEY, coerceAuditChecks(parsed)));
3752
3817
  const statuses = store.statusMessages.length > 0 ? store.statusMessages : void 0;
3753
3818
  const [columns] = useStdoutDimensions();
3754
3819
  const [gameState, setGameState] = useState(() => initialState());
@@ -3968,7 +4033,7 @@ const Audit3000OutroScreen = ({ store }) => {
3968
4033
  color: "cyan",
3969
4034
  children: "High-score reel saved to:"
3970
4035
  }),
3971
- /* @__PURE__ */ jsx(Text, { children: join(store.session.installDir, outroData.reportFile) }),
4036
+ /* @__PURE__ */ jsx(Text, { children: join$1(store.session.installDir, outroData.reportFile) }),
3972
4037
  /* @__PURE__ */ jsx(Text, {
3973
4038
  dimColor: true,
3974
4039
  children: "A markdown file in your project folder — open it in any editor to read the full audit."
@@ -4101,19 +4166,47 @@ const SetupScreen = ({ store }) => {
4101
4166
  /**
4102
4167
  * AuthScreen — Shown while waiting for OAuth authentication.
4103
4168
  *
4104
- * Displays framework detection results, beta/disclosure notices,
4105
- * a waiting spinner, and the login URL when available.
4169
+ * Displays framework detection, a compressed privacy summary, a waiting
4170
+ * spinner, and the login URL when available. [I] opens the full
4171
+ * PrivacyPanel as an overlay. [P] (when loginUrl is set) lets the user
4172
+ * paste the callback URL by hand.
4173
+ *
4106
4174
  * The router resolves past this screen once session.credentials is set.
4107
4175
  */
4108
4176
  const AuthScreen = ({ store }) => {
4109
4177
  useSyncExternalStore((cb) => store.subscribe(cb), () => store.getSnapshot());
4178
+ const [showPrivacy, setShowPrivacy] = useState(false);
4110
4179
  const { session } = store;
4111
- useKeyBindings("auth", Boolean(session.loginUrl) ? [{
4112
- match: ["p", "P"],
4113
- label: "P",
4114
- action: "paste auth code",
4115
- handler: () => store.showManualAuthCode()
4116
- }] : []);
4180
+ const canPasteCode = Boolean(session.loginUrl);
4181
+ const bindings = [];
4182
+ if (!showPrivacy) {
4183
+ if (canPasteCode) bindings.push({
4184
+ match: ["p", "P"],
4185
+ label: "P",
4186
+ action: "paste auth code",
4187
+ handler: () => store.showManualAuthCode()
4188
+ });
4189
+ bindings.push({
4190
+ match: ["i", "I"],
4191
+ label: "I",
4192
+ action: "privacy info",
4193
+ handler: () => setShowPrivacy(true)
4194
+ });
4195
+ }
4196
+ useKeyBindings("auth", bindings);
4197
+ if (showPrivacy) return /* @__PURE__ */ jsx(IntroScreenLayout, {
4198
+ installDir: session.installDir,
4199
+ title: "Wizard privacy & usage",
4200
+ showSubtitle: false,
4201
+ showDetection: false,
4202
+ body: /* @__PURE__ */ jsx(PrivacyPanel, {}),
4203
+ menuOptions: [{
4204
+ label: "Back",
4205
+ value: "back"
4206
+ }],
4207
+ menuAlign: "left",
4208
+ onSelect: () => setShowPrivacy(false)
4209
+ });
4117
4210
  const config = session.frameworkConfig;
4118
4211
  const frameworkLabel = session.detectedFrameworkLabel ?? config?.metadata.name;
4119
4212
  return /* @__PURE__ */ jsxs(Box, {
@@ -4147,6 +4240,37 @@ const AuthScreen = ({ store }) => {
4147
4240
  })
4148
4241
  ]
4149
4242
  }),
4243
+ /* @__PURE__ */ jsxs(Box, {
4244
+ flexDirection: "column",
4245
+ marginBottom: 1,
4246
+ children: [
4247
+ /* @__PURE__ */ jsx(Text, {
4248
+ bold: true,
4249
+ dimColor: true,
4250
+ children: "How does the wizard use your data?"
4251
+ }),
4252
+ /* @__PURE__ */ jsxs(Text, {
4253
+ dimColor: true,
4254
+ children: ["•", " Source files are read by Claude for AI context"]
4255
+ }),
4256
+ /* @__PURE__ */ jsxs(Text, {
4257
+ dimColor: true,
4258
+ children: ["•", " .env* and secrets stay on your machine"]
4259
+ }),
4260
+ /* @__PURE__ */ jsxs(Text, {
4261
+ dimColor: true,
4262
+ children: [
4263
+ "•",
4264
+ " Press ",
4265
+ /* @__PURE__ */ jsx(Text, {
4266
+ color: Colors.accent,
4267
+ children: "[I]"
4268
+ }),
4269
+ " for full privacy & usage info"
4270
+ ]
4271
+ })
4272
+ ]
4273
+ }),
4150
4274
  /* @__PURE__ */ jsx(LoadingBox, { message: "Waiting for authentication..." }),
4151
4275
  session.loginUrl && /* @__PURE__ */ jsxs(Box, {
4152
4276
  marginTop: 1,
@@ -4192,7 +4316,7 @@ const AuthScreen = ({ store }) => {
4192
4316
  */
4193
4317
  const RunScreen = ({ store }) => {
4194
4318
  useSyncExternalStore((cb) => store.subscribe(cb), () => store.getSnapshot());
4195
- useFileWatcher(join(store.session.installDir, EVENT_PLAN_FILE), (parsed) => {
4319
+ useFileWatcher(join$1(store.session.installDir, EVENT_PLAN_FILE), (parsed) => {
4196
4320
  if (!Array.isArray(parsed)) return;
4197
4321
  store.setEventPlan(parsed.map((e) => ({
4198
4322
  name: e.name ?? e.event ?? "",
@@ -4264,155 +4388,6 @@ const RunScreen = ({ store }) => {
4264
4388
  });
4265
4389
  };
4266
4390
  //#endregion
4267
- //#region src/ui/tui/screens/SlackConnectScreen.tsx
4268
- /**
4269
- * SlackConnectScreen — the dedicated "Connect Slack" step shown after the
4270
- * MCP tutorial (`wizard mcp tutorial`) and after a successful install
4271
- * (`wizard mcp add`).
4272
- *
4273
- * Presents the PostHog Slack app plus role-tailored use-cases. The copy
4274
- * adapts to whether Slack is already connected (polled while the screen
4275
- * is up, held as local state):
4276
- * • not connected (or unknown) — nudge + "Open Slack setup", which
4277
- * launches the browser at the integration settings page and keeps
4278
- * the screen alive; the poll flips it to connected once the user
4279
- * finishes the manual OAuth step in the browser.
4280
- * • already connected — confirm it and skip the connect CTA, so users
4281
- * who already have it aren't nagged.
4282
- * "Skip" / "Done" / esc dismiss the step (`slackStepDismissed`) and let
4283
- * the router advance to exit.
4284
- */
4285
- var ChoiceValue = /* @__PURE__ */ function(ChoiceValue) {
4286
- ChoiceValue["Open"] = "open";
4287
- ChoiceValue["Skip"] = "skip";
4288
- return ChoiceValue;
4289
- }(ChoiceValue || {});
4290
- const POLL_INTERVAL_MS = 3e3;
4291
- const SlackConnectScreen = ({ store }) => {
4292
- useSyncExternalStore((cb) => store.subscribe(cb), () => store.getSnapshot());
4293
- const role = store.session.roleAtOrganization;
4294
- const slack = getSlackAppCard();
4295
- useEffect(() => {
4296
- analytics.wizardCapture("slack connect shown", { role });
4297
- }, []);
4298
- const connected = store.session.slackConnected === true;
4299
- const credentials = store.session.credentials;
4300
- useEffect(() => {
4301
- if (!credentials || connected) return;
4302
- let cancelled = false;
4303
- let timer;
4304
- const controller = new AbortController();
4305
- const check = () => {
4306
- fetchSlackConnected(credentials.accessToken, credentials.projectId, credentials.host, controller.signal).then((isConnected) => {
4307
- if (cancelled) return;
4308
- if (isConnected) store.setSlackConnected(true);
4309
- else timer = setTimeout(check, POLL_INTERVAL_MS);
4310
- }).catch((err) => {
4311
- if (cancelled) return;
4312
- analytics.captureException(err instanceof Error ? err : new Error(String(err)), { step: "slack_connected_check" });
4313
- });
4314
- };
4315
- check();
4316
- return () => {
4317
- cancelled = true;
4318
- if (timer) clearTimeout(timer);
4319
- controller.abort();
4320
- };
4321
- }, [
4322
- credentials,
4323
- connected,
4324
- store
4325
- ]);
4326
- const dismiss = () => {
4327
- analytics.wizardCapture("slack connect skipped", {
4328
- role,
4329
- connected
4330
- });
4331
- store.setSlackStepDismissed();
4332
- };
4333
- const handleSelect = (value) => {
4334
- if ((Array.isArray(value) ? value[0] : value) === "open") {
4335
- analytics.wizardCapture("slack connect opened", { role });
4336
- opn(slack.setupUrl, { wait: false }).catch(() => {});
4337
- return;
4338
- }
4339
- dismiss();
4340
- };
4341
- useKeyBindings("slack-connect", [{
4342
- match: "escape",
4343
- label: "esc",
4344
- action: connected ? "done" : "skip",
4345
- handler: () => dismiss()
4346
- }]);
4347
- return /* @__PURE__ */ jsx(Box, {
4348
- flexDirection: "column",
4349
- flexGrow: 1,
4350
- children: /* @__PURE__ */ jsxs(Box, {
4351
- marginTop: 1,
4352
- flexDirection: "column",
4353
- children: [
4354
- connected ? /* @__PURE__ */ jsxs(Text, {
4355
- bold: true,
4356
- color: Colors.success,
4357
- children: [Icons.check, " Slack connected"]
4358
- }) : /* @__PURE__ */ jsx(Text, {
4359
- bold: true,
4360
- color: Colors.accent,
4361
- children: slack.headline
4362
- }),
4363
- /* @__PURE__ */ jsx(Box, {
4364
- marginTop: 1,
4365
- children: /* @__PURE__ */ jsx(Text, { children: connected ? "Slack is connected — here's what you can do:" : slack.pitch })
4366
- }),
4367
- /* @__PURE__ */ jsx(Box, {
4368
- marginTop: 1,
4369
- flexDirection: "column",
4370
- children: slack.capabilities.map((capability, i) => /* @__PURE__ */ jsx(Box, {
4371
- marginTop: i === 0 ? 0 : 1,
4372
- children: /* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsxs(Text, {
4373
- color: "cyan",
4374
- children: [Icons.diamond, " "]
4375
- }), capability] })
4376
- }, i))
4377
- }),
4378
- /* @__PURE__ */ jsxs(Box, {
4379
- marginTop: 1,
4380
- flexDirection: "column",
4381
- children: [!connected && /* @__PURE__ */ jsxs(Text, {
4382
- dimColor: true,
4383
- children: ["Connect it: ", /* @__PURE__ */ jsx(Text, {
4384
- color: "cyan",
4385
- children: slack.setupUrl
4386
- })]
4387
- }), /* @__PURE__ */ jsxs(Text, {
4388
- dimColor: true,
4389
- children: ["Learn more: ", /* @__PURE__ */ jsx(Text, {
4390
- color: "cyan",
4391
- children: slack.learnMoreUrl
4392
- })]
4393
- })]
4394
- }),
4395
- /* @__PURE__ */ jsx(Box, {
4396
- marginTop: 1,
4397
- children: /* @__PURE__ */ jsx(PickerMenu, {
4398
- options: connected ? [{
4399
- label: "Done",
4400
- value: "skip"
4401
- }] : [{
4402
- label: "Open Slack setup",
4403
- value: "open"
4404
- }, {
4405
- label: "Skip",
4406
- value: "skip"
4407
- }],
4408
- onSelect: handleSelect
4409
- })
4410
- })
4411
- ]
4412
- })
4413
- });
4414
- };
4415
- //#endregion
4416
4391
  //#region src/ui/tui/screens/KeepSkillsScreen.tsx
4417
4392
  /**
4418
4393
  * KeepSkillsScreen — Ask whether to keep installed skills in .claude/skills/.
@@ -4427,7 +4402,7 @@ const KeepSkillsScreen = ({ store }) => {
4427
4402
  useSyncExternalStore((cb) => store.subscribe(cb), () => store.getSnapshot());
4428
4403
  const [phase, setPhase] = useState("loading");
4429
4404
  const [skills, setSkills] = useState([]);
4430
- const skillsDir = join(store.session.installDir, ".claude", "skills");
4405
+ const skillsDir = join$1(store.session.installDir, ".claude", "skills");
4431
4406
  useEffect(() => {
4432
4407
  (async () => {
4433
4408
  try {
@@ -4435,11 +4410,11 @@ const KeepSkillsScreen = ({ store }) => {
4435
4410
  const result = [];
4436
4411
  for (const dir of dirs) {
4437
4412
  try {
4438
- await access(join(skillsDir, dir.name, WIZARD_MARKER));
4413
+ await access(join$1(skillsDir, dir.name, WIZARD_MARKER));
4439
4414
  } catch {
4440
4415
  continue;
4441
4416
  }
4442
- const children = (await readdir(join(skillsDir, dir.name))).filter((c) => c !== WIZARD_MARKER);
4417
+ const children = (await readdir(join$1(skillsDir, dir.name))).filter((c) => c !== WIZARD_MARKER);
4443
4418
  result.push({
4444
4419
  name: dir.name,
4445
4420
  children
@@ -4464,7 +4439,7 @@ const KeepSkillsScreen = ({ store }) => {
4464
4439
  const handleRemove = async () => {
4465
4440
  setPhase("removing");
4466
4441
  for (const skill of skills) try {
4467
- await rm(join(skillsDir, skill.name), {
4442
+ await rm(join$1(skillsDir, skill.name), {
4468
4443
  recursive: true,
4469
4444
  force: true
4470
4445
  });
@@ -4564,178 +4539,6 @@ const KeepSkillsScreen = ({ store }) => {
4564
4539
  });
4565
4540
  };
4566
4541
  //#endregion
4567
- //#region src/ui/tui/screens/OutroScreen.tsx
4568
- /**
4569
- * OutroScreen — Default post-run summary.
4570
- *
4571
- * Renders the success / error / cancel views from `outroData`. Programs
4572
- * that need a different success view (e.g. with extra summary content)
4573
- * ship their own screen component (see audit/AuditOutroScreen.tsx).
4574
- */
4575
- const OutroScreen = ({ store }) => {
4576
- useSyncExternalStore((cb) => store.subscribe(cb), () => store.getSnapshot());
4577
- useInput(() => {
4578
- store.setOutroDismissed();
4579
- });
4580
- const outroData = store.session.outroData;
4581
- if (!outroData) return /* @__PURE__ */ jsx(Box, {
4582
- flexDirection: "column",
4583
- flexGrow: 1,
4584
- children: /* @__PURE__ */ jsx(Text, {
4585
- dimColor: true,
4586
- children: "Finishing up..."
4587
- })
4588
- });
4589
- return /* @__PURE__ */ jsxs(Box, {
4590
- flexDirection: "column",
4591
- flexGrow: 1,
4592
- children: [
4593
- outroData.kind === "success" && /* @__PURE__ */ jsxs(Box, {
4594
- flexDirection: "column",
4595
- children: [
4596
- /* @__PURE__ */ jsxs(Text, {
4597
- color: "green",
4598
- bold: true,
4599
- children: ["✔ ", outroData.message || "Done!"]
4600
- }),
4601
- outroData.body && /* @__PURE__ */ jsx(Box, {
4602
- marginTop: 1,
4603
- children: /* @__PURE__ */ jsx(Text, {
4604
- dimColor: true,
4605
- children: outroData.body
4606
- })
4607
- }),
4608
- outroData.reportFile && /* @__PURE__ */ jsx(Box, {
4609
- marginTop: 1,
4610
- children: /* @__PURE__ */ jsxs(Text, { children: [
4611
- "Check ",
4612
- /* @__PURE__ */ jsxs(Text, {
4613
- bold: true,
4614
- children: ["./", outroData.reportFile]
4615
- }),
4616
- " for details"
4617
- ] })
4618
- }),
4619
- outroData.changes && outroData.changes.length > 0 && /* @__PURE__ */ jsxs(Box, {
4620
- flexDirection: "column",
4621
- marginTop: 1,
4622
- children: [/* @__PURE__ */ jsx(Text, {
4623
- color: "cyan",
4624
- bold: true,
4625
- children: "What the agent did:"
4626
- }), outroData.changes.map((change, i) => /* @__PURE__ */ jsxs(Text, { children: ["• ", change] }, i))]
4627
- }),
4628
- store.eventPlan.length > 0 && /* @__PURE__ */ jsxs(Box, {
4629
- flexDirection: "column",
4630
- marginTop: 1,
4631
- children: [/* @__PURE__ */ jsx(Text, {
4632
- color: "cyan",
4633
- bold: true,
4634
- children: "Events added:"
4635
- }), store.eventPlan.map((event) => /* @__PURE__ */ jsxs(Text, { children: [
4636
- "• ",
4637
- /* @__PURE__ */ jsx(Text, {
4638
- bold: true,
4639
- children: event.name
4640
- }),
4641
- /* @__PURE__ */ jsxs(Text, {
4642
- dimColor: true,
4643
- children: [" ", event.description]
4644
- })
4645
- ] }, event.name))]
4646
- }),
4647
- outroData.dashboardUrl && /* @__PURE__ */ jsx(Box, {
4648
- marginTop: 1,
4649
- children: /* @__PURE__ */ jsxs(Text, { children: [
4650
- "We've also made you a dashboard:",
4651
- " ",
4652
- /* @__PURE__ */ jsx(Text, {
4653
- color: "cyan",
4654
- children: outroData.dashboardUrl
4655
- })
4656
- ] })
4657
- }),
4658
- outroData.notebookUrl && /* @__PURE__ */ jsx(Box, {
4659
- marginTop: 1,
4660
- children: /* @__PURE__ */ jsxs(Text, { children: [
4661
- "And uploaded the report to a PostHog notebook:",
4662
- " ",
4663
- /* @__PURE__ */ jsx(Text, {
4664
- color: "cyan",
4665
- children: outroData.notebookUrl
4666
- })
4667
- ] })
4668
- }),
4669
- outroData.docsUrl && /* @__PURE__ */ jsx(Box, {
4670
- marginTop: 1,
4671
- children: /* @__PURE__ */ jsxs(Text, { children: ["Learn more: ", /* @__PURE__ */ jsx(Text, {
4672
- color: "cyan",
4673
- children: outroData.docsUrl
4674
- })] })
4675
- }),
4676
- outroData.continueUrl && /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { children: [
4677
- "Continue onboarding:",
4678
- " ",
4679
- /* @__PURE__ */ jsx(Text, {
4680
- color: "cyan",
4681
- children: outroData.continueUrl
4682
- })
4683
- ] }) }),
4684
- /* @__PURE__ */ jsx(Box, {
4685
- marginTop: 1,
4686
- children: /* @__PURE__ */ jsx(Text, {
4687
- dimColor: true,
4688
- children: "Note: This wizard uses an LLM agent to analyze and modify your project. Please review the changes made."
4689
- })
4690
- }),
4691
- /* @__PURE__ */ jsx(Text, {
4692
- dimColor: true,
4693
- children: "How did this work for you? Drop us a line: wizard@posthog.com"
4694
- })
4695
- ]
4696
- }),
4697
- outroData.kind === "error" && /* @__PURE__ */ jsxs(Box, {
4698
- flexDirection: "column",
4699
- children: [
4700
- /* @__PURE__ */ jsxs(Text, {
4701
- color: "red",
4702
- bold: true,
4703
- children: ["✘ ", outroData.message || "An error occurred"]
4704
- }),
4705
- outroData.body && /* @__PURE__ */ jsx(Box, {
4706
- marginTop: 1,
4707
- children: /* @__PURE__ */ jsx(Text, {
4708
- dimColor: true,
4709
- children: outroData.body
4710
- })
4711
- }),
4712
- outroData.docsUrl && /* @__PURE__ */ jsx(Box, {
4713
- marginTop: 1,
4714
- children: /* @__PURE__ */ jsxs(Text, { children: ["Docs: ", /* @__PURE__ */ jsx(Text, {
4715
- color: "cyan",
4716
- children: outroData.docsUrl
4717
- })] })
4718
- })
4719
- ]
4720
- }),
4721
- outroData.kind === "cancel" && /* @__PURE__ */ jsx(Box, {
4722
- flexDirection: "column",
4723
- children: /* @__PURE__ */ jsxs(Text, {
4724
- color: "yellow",
4725
- children: ["■ ", outroData.message || "Cancelled"]
4726
- })
4727
- }),
4728
- /* @__PURE__ */ jsx(Box, {
4729
- marginTop: 1,
4730
- children: /* @__PURE__ */ jsx(Text, {
4731
- color: Colors.muted,
4732
- children: "Press any key to continue"
4733
- })
4734
- })
4735
- ]
4736
- });
4737
- };
4738
- //#endregion
4739
4542
  //#region src/ui/tui/screens/ExitScreen.tsx
4740
4543
  /**
4741
4544
  * ExitScreen — Final step in every program.
@@ -4881,6 +4684,53 @@ const AuthErrorScreen = ({ store }) => {
4881
4684
  });
4882
4685
  };
4883
4686
  //#endregion
4687
+ //#region src/ui/tui/screens/SessionTimeoutScreen.tsx
4688
+ /**
4689
+ * SessionTimeoutScreen — shown when the OAuth login window expires before the
4690
+ * user completes authorization.
4691
+ *
4692
+ * Pushed as an overlay so it takes priority over the gated AuthScreen (which
4693
+ * never completes without credentials). Terminal state: any key exits, since
4694
+ * the only way forward is to re-run the wizard for a fresh login window.
4695
+ */
4696
+ const TIMEOUT_MINUTES = Math.round(OAUTH_TIMEOUT_MS / 6e4);
4697
+ const SessionTimeoutScreen = ({ store }) => {
4698
+ useSyncExternalStore((cb) => store.subscribe(cb), () => store.getSnapshot());
4699
+ useInput(() => {
4700
+ process.exit(1);
4701
+ });
4702
+ return /* @__PURE__ */ jsxs(Box, {
4703
+ flexDirection: "column",
4704
+ flexGrow: 1,
4705
+ children: [
4706
+ /* @__PURE__ */ jsxs(Text, {
4707
+ color: "red",
4708
+ bold: true,
4709
+ children: ["✘", " Login timed out"]
4710
+ }),
4711
+ /* @__PURE__ */ jsx(Box, {
4712
+ marginTop: 1,
4713
+ children: /* @__PURE__ */ jsxs(Text, { children: [
4714
+ "The OAuth link timed out after ",
4715
+ TIMEOUT_MINUTES,
4716
+ " minutes."
4717
+ ] })
4718
+ }),
4719
+ /* @__PURE__ */ jsx(Box, {
4720
+ marginTop: 1,
4721
+ children: /* @__PURE__ */ jsx(Text, { children: "Re-run the wizard to get a fresh link and try again." })
4722
+ }),
4723
+ /* @__PURE__ */ jsx(Box, {
4724
+ marginTop: 1,
4725
+ children: /* @__PURE__ */ jsx(Text, {
4726
+ color: Colors.muted,
4727
+ children: "Press any key to exit"
4728
+ })
4729
+ })
4730
+ ]
4731
+ });
4732
+ };
4733
+ //#endregion
4884
4734
  //#region src/ui/tui/screens/WizardAskScreen.tsx
4885
4735
  /**
4886
4736
  * WizardAskScreen — Overlay for the `wizard_ask` MCP tool.
@@ -5085,14 +4935,14 @@ function createMcpSuggestedPromptsServices(_store) {
5085
4935
  };
5086
4936
  },
5087
4937
  checkSlackConnected: async (credentials, signal) => {
5088
- const { fetchSlackConnected } = await import("./api-eUlUinVy.js").then((n) => n.n);
4938
+ const { fetchSlackConnected } = await import("./api-QI1lO_Bz.js").then((n) => n.n);
5089
4939
  return fetchSlackConnected(credentials.accessToken, credentials.projectId, credentials.host, signal);
5090
4940
  },
5091
4941
  runPromptStreaming: (args) => runProductionPromptStreaming(args)
5092
4942
  };
5093
4943
  }
5094
4944
  async function* runProductionPromptStreaming(args) {
5095
- const { runMcpPromptViaSdk } = await import("./mcp-prompt-streaming-BiMrlLl0.js");
4945
+ const { runMcpPromptViaSdk } = await import("./mcp-prompt-streaming-mYw2LPZZ.js");
5096
4946
  yield* runMcpPromptViaSdk(args);
5097
4947
  }
5098
4948
  //#endregion
@@ -5110,6 +4960,7 @@ function createScreens(store, services) {
5110
4960
  ["port-conflict"]: /* @__PURE__ */ jsx(PortConflictScreen, { store }),
5111
4961
  ["manual-auth-code"]: /* @__PURE__ */ jsx(ManualAuthCodeScreen, { store }),
5112
4962
  ["auth-error"]: /* @__PURE__ */ jsx(AuthErrorScreen, { store }),
4963
+ ["session-timeout"]: /* @__PURE__ */ jsx(SessionTimeoutScreen, { store }),
5113
4964
  ["wizard-ask"]: /* @__PURE__ */ jsx(WizardAskScreen, { store }),
5114
4965
  ["intro"]: /* @__PURE__ */ jsx(PostHogIntegrationIntroScreen, { store }),
5115
4966
  ["revenue-intro"]: /* @__PURE__ */ jsx(RevenueIntroScreen, { store }),
@@ -5128,6 +4979,7 @@ function createScreens(store, services) {
5128
4979
  ["doctor-report"]: /* @__PURE__ */ jsx(DoctorReportScreen, { store }),
5129
4980
  ["setup"]: /* @__PURE__ */ jsx(SetupScreen, { store }),
5130
4981
  ["auth"]: /* @__PURE__ */ jsx(AuthScreen, { store }),
4982
+ ["ai-opt-in"]: /* @__PURE__ */ jsx(AiOptInRequiredScreen, { store }),
5131
4983
  ["run"]: /* @__PURE__ */ jsx(RunScreen, { store }),
5132
4984
  ["mcp"]: /* @__PURE__ */ jsx(McpScreen, {
5133
4985
  store,
@@ -5162,6 +5014,23 @@ const App = ({ store }) => {
5162
5014
  });
5163
5015
  };
5164
5016
  //#endregion
5017
+ //#region src/ui/tui/exit-line.ts
5018
+ const RESET_ATTRS$1 = "\x1B[0m";
5019
+ const GREEN = "\x1B[32m";
5020
+ const BOLD = "\x1B[1m";
5021
+ const DIM = "\x1B[2m";
5022
+ function getExitLine(store) {
5023
+ const outro = store.session.outroData;
5024
+ const label = store.session.programLabel ?? "Wizard";
5025
+ if (outro?.kind === "success") {
5026
+ const message = outro.message ?? `${label} completed successfully.`;
5027
+ const headline = `${GREEN}${BOLD}✔${RESET_ATTRS$1} ${message}${outro.reportFile && !message.includes(outro.reportFile) ? ` Check ./${outro.reportFile} for details.` : ""}`;
5028
+ 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;
5029
+ return headline;
5030
+ }
5031
+ return `${DIM}${label} exited.${RESET_ATTRS$1}`;
5032
+ }
5033
+ //#endregion
5165
5034
  //#region src/ui/tui/start-tui.ts
5166
5035
  /**
5167
5036
  * start-tui.ts — Sets up the Ink TUI renderer and InkUI.
@@ -5176,27 +5045,16 @@ const CURSOR_HOME = "\x1B[H";
5176
5045
  const BG_BLACK = "\x1B[48;2;0;0;0m";
5177
5046
  const ENTER_ALT_SCREEN = "\x1B[?1049h";
5178
5047
  const LEAVE_ALT_SCREEN = "\x1B[?1049l";
5179
- const GREEN = "\x1B[32m";
5180
- const BOLD = "\x1B[1m";
5181
- const DIM = "\x1B[2m";
5182
5048
  function releaseTerminal() {
5183
5049
  process.stdout.write(RESET_ATTRS + LEAVE_ALT_SCREEN);
5184
5050
  }
5185
- function getExitLine(store) {
5186
- const outro = store.session.outroData;
5187
- const label = store.session.programLabel ?? "Wizard";
5188
- if (outro?.kind === "success") {
5189
- const message = outro.message ?? `${label} completed successfully.`;
5190
- return `${GREEN}${BOLD}\u2714${RESET_ATTRS} ${message}${outro.reportFile && !message.includes(outro.reportFile) ? ` Check ./${outro.reportFile} for details.` : ""}`;
5191
- }
5192
- return `${DIM}${label} exited.${RESET_ATTRS}`;
5193
- }
5194
5051
  function startTUI(version, program = Program.PostHogIntegration) {
5195
5052
  process.stdout.write(ENTER_ALT_SCREEN + BG_BLACK + CLEAR_SCREEN + CURSOR_HOME);
5196
5053
  const store = new WizardStore(program);
5197
5054
  store.version = version;
5198
5055
  setUI(new InkUI(store));
5199
5056
  const { unmount: inkUnmount, waitUntilExit } = render(createElement(App, { store }));
5057
+ analytics.wizardCapture("started", { program_id: program });
5200
5058
  store.runInitHooks();
5201
5059
  process.stdin.on("error", (err) => {
5202
5060
  if (err.code !== "EIO") throw err;
@@ -5224,4 +5082,4 @@ function startTUI(version, program = Program.PostHogIntegration) {
5224
5082
  //#endregion
5225
5083
  export { startTUI };
5226
5084
 
5227
- //# sourceMappingURL=start-tui-CCpKnZOY.js.map
5085
+ //# sourceMappingURL=start-tui-DaQiY_EB.js.map