@posthog/wizard 2.16.1 → 2.18.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 (83) hide show
  1. package/dist/{add-mcp-server-to-clients-BS6Rjcwh.js → add-mcp-server-to-clients-DnPwZl1P.js} +38 -5
  2. package/dist/add-mcp-server-to-clients-DnPwZl1P.js.map +1 -0
  3. package/dist/{agent-interface-B4eUlMso.js → agent-interface-C2VEF-BD.js} +110 -54
  4. package/dist/agent-interface-C2VEF-BD.js.map +1 -0
  5. package/dist/{agent-runner-BxqiKVEf.js → agent-runner-Dw8cjZoN.js} +11 -8
  6. package/dist/{agent-runner-BxqiKVEf.js.map → agent-runner-Dw8cjZoN.js.map} +1 -1
  7. package/dist/{analytics-DUuUurR3.js → analytics-C-zcTO6g.js} +26 -4
  8. package/dist/analytics-C-zcTO6g.js.map +1 -0
  9. package/dist/{api-CGJ1iGps.js → api-B3MWP3vm.js} +14 -4
  10. package/dist/{api-CGJ1iGps.js.map → api-B3MWP3vm.js.map} +1 -1
  11. package/dist/bin.js +238 -82
  12. package/dist/bin.js.map +1 -1
  13. package/dist/{ci-install-DD7WMmIF.js → ci-install-DLuSmSq6.js} +4 -4
  14. package/dist/{ci-install-DD7WMmIF.js.map → ci-install-DLuSmSq6.js.map} +1 -1
  15. package/dist/{debug-Cd0hPlZy.js → debug--gQGudnY.js} +1 -1
  16. package/dist/{debug-ubpO6102.js → debug-BorYMfpE.js} +2 -2
  17. package/dist/{debug-ubpO6102.js.map → debug-BorYMfpE.js.map} +1 -1
  18. package/dist/{defaults-zrYmZ2ID.js → defaults-DA3-9dHT.js} +1 -1
  19. package/dist/{defaults-zrYmZ2ID.js.map → defaults-DA3-9dHT.js.map} +1 -1
  20. package/dist/{env-api-key-DEl3LJBv.js → env-api-key-MlzJYAvt.js} +1 -1
  21. package/dist/{env-api-key-DEl3LJBv.js.map → env-api-key-MlzJYAvt.js.map} +1 -1
  22. package/dist/{environment-BAaC5THg.js → environment-DIOtLqTQ.js} +3 -3
  23. package/dist/{environment-BAaC5THg.js.map → environment-DIOtLqTQ.js.map} +1 -1
  24. package/dist/{file-utils-DPmgn9Vm.js → file-utils-VAXoyXVA.js} +1 -1
  25. package/dist/{file-utils-DPmgn9Vm.js.map → file-utils-VAXoyXVA.js.map} +1 -1
  26. package/dist/{interactive-BaMAq88Q.js → interactive-DjGjlvY3.js} +2 -2
  27. package/dist/{interactive-BaMAq88Q.js.map → interactive-DjGjlvY3.js.map} +1 -1
  28. package/dist/{mcp-prompt-streaming-clGsVw8q.js → mcp-prompt-streaming-Dm47tmiy.js} +62 -12
  29. package/dist/mcp-prompt-streaming-Dm47tmiy.js.map +1 -0
  30. package/dist/{non-interactive-l2AKE3jD.js → non-interactive-C2f3Gwva.js} +2 -2
  31. package/dist/{non-interactive-l2AKE3jD.js.map → non-interactive-C2f3Gwva.js.map} +1 -1
  32. package/dist/{package-json-Cynjr9k4.js → package-json-DCuoye-H.js} +8 -2
  33. package/dist/{package-json-Cynjr9k4.js.map → package-json-DCuoye-H.js.map} +1 -1
  34. package/dist/{package-manager-BqsJK3ej.js → package-manager-Bl2KOUFK.js} +2 -2
  35. package/dist/{package-manager-BqsJK3ej.js.map → package-manager-Bl2KOUFK.js.map} +1 -1
  36. package/dist/{playground-DlE5RNfE.js → playground-ZLG68cvx.js} +21 -10
  37. package/dist/playground-ZLG68cvx.js.map +1 -0
  38. package/dist/{posthog-DWL8uOcl.js → posthog-Cr37rnla.js} +1 -1
  39. package/dist/{posthog-DWL8uOcl.js.map → posthog-Cr37rnla.js.map} +1 -1
  40. package/dist/{posthog-integration-Bf_vtWI9.js → posthog-integration-B_DLodqr.js} +282 -14
  41. package/dist/posthog-integration-B_DLodqr.js.map +1 -0
  42. package/dist/{provisioning-D_hAuxUN.js → provisioning-Bk4E6VYn.js} +9 -4
  43. package/dist/{provisioning-D_hAuxUN.js.map → provisioning-Bk4E6VYn.js.map} +1 -1
  44. package/dist/{registry-DKgYqROt.js → registry-DMM3UmZD.js} +5 -5
  45. package/dist/{registry-DKgYqROt.js.map → registry-DMM3UmZD.js.map} +1 -1
  46. package/dist/{setup-utils-D-uTycLX.js → setup-utils-Df9ezAjZ.js} +86 -38
  47. package/dist/setup-utils-Df9ezAjZ.js.map +1 -0
  48. package/dist/{slides-CL1mv_Kq.js → slides-DwvXZ8iS.js} +1583 -322
  49. package/dist/slides-DwvXZ8iS.js.map +1 -0
  50. package/dist/{start-tui-DXrv6cof.js → start-tui-P9aMwBzt.js} +28 -18
  51. package/dist/start-tui-P9aMwBzt.js.map +1 -0
  52. package/dist/{steps-CgScwqso.js → steps-RCRZbLjZ.js} +6 -6
  53. package/dist/{steps-CgScwqso.js.map → steps-RCRZbLjZ.js.map} +1 -1
  54. package/dist/{task-stream-CF6QMVMv.js → task-stream-CZRj6auI.js} +3 -3
  55. package/dist/{task-stream-CF6QMVMv.js.map → task-stream-CZRj6auI.js.map} +1 -1
  56. package/dist/{telemetry-v6O12Bep.js → telemetry-CMbVbpaY.js} +2 -2
  57. package/dist/{telemetry-v6O12Bep.js.map → telemetry-CMbVbpaY.js.map} +1 -1
  58. package/dist/urls-BzG_Jtw9.js +35 -0
  59. package/dist/urls-BzG_Jtw9.js.map +1 -0
  60. package/dist/{wizard-abort-BGoBKgvC.js → wizard-abort-Dl8WJQgJ.js} +1 -1
  61. package/dist/{wizard-abort-iTaJ8wC8.js → wizard-abort-QuKm_B5z.js} +3 -3
  62. package/dist/{wizard-abort-iTaJ8wC8.js.map → wizard-abort-QuKm_B5z.js.map} +1 -1
  63. package/dist/{wizard-session-gsn8Z3bZ.js → wizard-session-d27JGRGi.js} +1 -1
  64. package/dist/{wizard-session-gsn8Z3bZ.js.map → wizard-session-d27JGRGi.js.map} +1 -1
  65. package/dist/{wizard-session-7tMjgOvP.js → wizard-session-y304gEEI.js} +1 -1
  66. package/package.json +1 -1
  67. package/dist/TextBlock-CdeZog_6.js +0 -275
  68. package/dist/TextBlock-CdeZog_6.js.map +0 -1
  69. package/dist/add-mcp-server-to-clients-BS6Rjcwh.js.map +0 -1
  70. package/dist/agent-interface-B4eUlMso.js.map +0 -1
  71. package/dist/analytics-DUuUurR3.js.map +0 -1
  72. package/dist/api-B8OR0N1V.js +0 -2
  73. package/dist/mcp-prompt-streaming-clGsVw8q.js.map +0 -1
  74. package/dist/package-json-CumwmZpv.js +0 -2
  75. package/dist/playground-DlE5RNfE.js.map +0 -1
  76. package/dist/posthog-integration-Bf_vtWI9.js.map +0 -1
  77. package/dist/provisioning-BlBnlcFd.js +0 -2
  78. package/dist/setup-utils-BHZEdkNZ.js +0 -2
  79. package/dist/setup-utils-D-uTycLX.js.map +0 -1
  80. package/dist/skill-CnOQAZXp.js +0 -29
  81. package/dist/skill-CnOQAZXp.js.map +0 -1
  82. package/dist/slides-CL1mv_Kq.js.map +0 -1
  83. package/dist/start-tui-DXrv6cof.js.map +0 -1
@@ -1,11 +1,11 @@
1
- import { g as SERVICE_LABELS, s as logToFile } from "./debug-ubpO6102.js";
1
+ import { g as SERVICE_LABELS, s as logToFile } from "./debug-BorYMfpE.js";
2
2
  import { n as isTaskStatus } from "./wizard-ui-YdGFRyu_.js";
3
- import { n as sessionProperties, t as analytics } from "./analytics-DUuUurR3.js";
4
- import { i as buildSession } from "./wizard-session-gsn8Z3bZ.js";
5
- import { _ as AUDIT_SEVERITY_STYLE } from "./agent-interface-B4eUlMso.js";
6
- import { a as isObjectBlock, i as isLinesBlock, n as computeVisibleRange, o as Colors, r as isClearBlock, s as Icons, t as TextBlock } from "./TextBlock-CdeZog_6.js";
3
+ import { r as sessionProperties, t as analytics } from "./analytics-C-zcTO6g.js";
4
+ import { i as buildSession } from "./wizard-session-d27JGRGi.js";
5
+ import { v as AUDIT_SEVERITY_STYLE } from "./agent-interface-C2VEF-BD.js";
6
+ import { c as computeVisibleRange, d as isObjectBlock, f as Colors, l as isClearBlock, p as Icons, s as TextBlock, u as isLinesBlock } from "./posthog-integration-B_DLodqr.js";
7
7
  import { a as getProgramConfig, i as Program, l as getKindMeta, r as PROGRAM_REGISTRY } from "./bin.js";
8
- import { n as AVAILABLE_FEATURES, t as ALL_FEATURE_VALUES } from "./defaults-zrYmZ2ID.js";
8
+ import { n as AVAILABLE_FEATURES, t as ALL_FEATURE_VALUES } from "./defaults-DA3-9dHT.js";
9
9
  import * as fs$1 from "fs";
10
10
  import { Box, Text, measureElement, useInput, useStdout } from "ink";
11
11
  import { Component, Fragment, createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
@@ -120,6 +120,12 @@ var WizardRouter = class {
120
120
  * All session mutations that affect screen resolution go through
121
121
  * explicit setters so emitChange() is always called.
122
122
  */
123
+ /**
124
+ * FIFO cap on retained status lines. The status bar is the only consumer and
125
+ * renders at most EXPANDED_COUNT lines, so there is no reason to retain more —
126
+ * the cap is tied to the window it feeds.
127
+ */
128
+ const MAX_STATUS_MESSAGES = 10;
123
129
  var WizardStore = class {
124
130
  $session = map(buildSession({}));
125
131
  $statusMessages = atom([]);
@@ -571,7 +577,8 @@ var WizardStore = class {
571
577
  pushStatus(message) {
572
578
  const msgs = this.$statusMessages.get();
573
579
  if (msgs.length > 0 && msgs[msgs.length - 1] === message) return;
574
- this.$statusMessages.set([...msgs, message]);
580
+ const next = msgs.length >= MAX_STATUS_MESSAGES ? [...msgs.slice(msgs.length - MAX_STATUS_MESSAGES + 1), message] : [...msgs, message];
581
+ this.$statusMessages.set(next);
575
582
  this.emitChange();
576
583
  }
577
584
  setTasks(tasks) {
@@ -1840,6 +1847,15 @@ const ScreenContainer = ({ store, screens }) => {
1840
1847
  }) })
1841
1848
  });
1842
1849
  };
1850
+ //#endregion
1851
+ //#region src/ui/tui/primitives/TabContainer.tsx
1852
+ /**
1853
+ * TabContainer — Self-contained tabbed interface.
1854
+ * Absorbs BottomTabBar + StatusPanel functionality.
1855
+ *
1856
+ * Key bindings are declared via useKeyBindings, which auto-registers
1857
+ * hints in the KeyboardHintsBar (rendered by ScreenContainer).
1858
+ */
1843
1859
  const TabContainer = ({ tabs, statusMessage, expandableStatus = false, store }) => {
1844
1860
  const [activeTab, setActiveTab] = useState(0);
1845
1861
  const [localExpanded, setLocalExpanded] = useState(false);
@@ -2628,8 +2644,17 @@ const McpScreen = ({ store, installer, mode = "install" }) => {
2628
2644
  }, [installer]);
2629
2645
  const proceedToFeatureSelectOrInstall = (clientNames) => {
2630
2646
  setSelectedClientNames(clientNames);
2631
- if (store.session.mcpFeatures) doInstall(clientNames, store.session.mcpFeatures);
2632
- else setPhase("feature-select");
2647
+ if (store.session.mcpFeatures) {
2648
+ doInstall(clientNames, store.session.mcpFeatures);
2649
+ return;
2650
+ }
2651
+ if (!clientNames.some((name) => {
2652
+ return !clients.find((c) => c.name === name)?.finish;
2653
+ })) {
2654
+ doInstall(clientNames, []);
2655
+ return;
2656
+ }
2657
+ setPhase("feature-select");
2633
2658
  };
2634
2659
  const handleConfirm = () => {
2635
2660
  if (isRemove) doRemove();
@@ -2668,6 +2693,17 @@ const McpScreen = ({ store, installer, mode = "install" }) => {
2668
2693
  const outcome = result.length > 0 ? "installed" : "failed";
2669
2694
  setTimeout(() => markDone(store, outcome, result), 2e3);
2670
2695
  };
2696
+ const installValueBullets = [
2697
+ "Ask your agent: \"List my feature flags\" — and it does.",
2698
+ "Run SQL, build dashboards, ship flags, all from your IDE.",
2699
+ "No copy-pasting tokens or context. Your agent has the keys."
2700
+ ];
2701
+ const finishNotes = clients.flatMap((c) => c.finish && resultClients.includes(c.name) ? [{
2702
+ name: c.name,
2703
+ url: c.finish.url,
2704
+ instruction: c.finish.instruction
2705
+ }] : []);
2706
+ const installedNow = resultClients.filter((name) => !finishNotes.some((n) => n.name === name));
2671
2707
  return /* @__PURE__ */ jsxs(Box, {
2672
2708
  flexDirection: "column",
2673
2709
  flexGrow: 1,
@@ -2695,11 +2731,7 @@ const McpScreen = ({ store, installer, mode = "install" }) => {
2695
2731
  !isRemove && /* @__PURE__ */ jsx(Box, {
2696
2732
  flexDirection: "column",
2697
2733
  marginBottom: 1,
2698
- children: [
2699
- "Ask your agent: \"List my feature flags\" — and it does.",
2700
- "Run SQL, build dashboards, ship flags, all from your IDE.",
2701
- "No copy-pasting tokens or context. Your agent has the keys."
2702
- ].map((bullet) => /* @__PURE__ */ jsxs(Text, {
2734
+ children: installValueBullets.map((bullet) => /* @__PURE__ */ jsxs(Text, {
2703
2735
  dimColor: true,
2704
2736
  children: [
2705
2737
  "•",
@@ -2748,7 +2780,10 @@ const McpScreen = ({ store, installer, mode = "install" }) => {
2748
2780
  }),
2749
2781
  phase === "done" && /* @__PURE__ */ jsx(Box, {
2750
2782
  flexDirection: "column",
2751
- children: resultClients.length > 0 ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs(Text, {
2783
+ children: installedNow.length === 0 && finishNotes.length === 0 ? /* @__PURE__ */ jsxs(Text, {
2784
+ dimColor: true,
2785
+ children: [isRemove ? "Removal" : "Installation", " skipped."]
2786
+ }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [installedNow.length > 0 && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs(Text, {
2752
2787
  color: "green",
2753
2788
  bold: true,
2754
2789
  children: [
@@ -2759,258 +2794,1325 @@ const McpScreen = ({ store, installer, mode = "install" }) => {
2759
2794
  isRemove ? "removed from" : "installed for",
2760
2795
  ":"
2761
2796
  ]
2762
- }), resultClients.map((name, i) => /* @__PURE__ */ jsxs(Text, { children: [
2797
+ }), installedNow.map((name, i) => /* @__PURE__ */ jsxs(Text, { children: [
2763
2798
  " ",
2764
2799
  "•",
2765
2800
  " ",
2766
2801
  name
2767
- ] }, i))] }) : /* @__PURE__ */ jsxs(Text, {
2768
- dimColor: true,
2769
- children: [isRemove ? "Removal" : "Installation", " skipped."]
2770
- })
2802
+ ] }, i))] }), finishNotes.map((note) => /* @__PURE__ */ jsxs(Box, {
2803
+ flexDirection: "column",
2804
+ marginTop: 1,
2805
+ children: [
2806
+ /* @__PURE__ */ jsxs(Text, {
2807
+ color: "green",
2808
+ bold: true,
2809
+ children: [note.name, " \\u2014 finish in your browser:"]
2810
+ }),
2811
+ /* @__PURE__ */ jsxs(Text, { children: [
2812
+ " ",
2813
+ "Opened ",
2814
+ /* @__PURE__ */ jsx(Text, {
2815
+ color: "cyan",
2816
+ children: note.url
2817
+ })
2818
+ ] }),
2819
+ /* @__PURE__ */ jsxs(Text, {
2820
+ dimColor: true,
2821
+ children: [" ", note.instruction]
2822
+ }),
2823
+ /* @__PURE__ */ jsxs(Text, {
2824
+ dimColor: true,
2825
+ children: [" ", "(If it didn't open, paste the URL above.)"]
2826
+ })
2827
+ ]
2828
+ }, note.name))] })
2771
2829
  })
2772
2830
  ]
2773
2831
  })]
2774
2832
  });
2775
2833
  };
2776
2834
  //#endregion
2777
- //#region src/lib/mcp-role-prompts.ts
2778
- /**
2779
- * Roles that ship from `role_at_organization` on the PostHog user object.
2780
- * `security` isn't in the enum upstream the engineering kit covers that audience.
2781
- */
2782
- const TAILORED_ROLES = [
2783
- "founder",
2784
- "product",
2785
- "leadership",
2786
- "marketing",
2787
- "engineering",
2788
- "data"
2789
- ];
2790
- const STOCK_MCP_SUGGESTED_PROMPTS = [
2835
+ //#region src/lib/mcp-role-prompts.copy.json
2836
+ var pinnedFirstPrompt = {
2837
+ "prompt": "Show me my top 5 events from the last 7 days",
2838
+ "description": "A safe first pick works on any project regardless of role or setup."
2839
+ };
2840
+ var defaultKit = [
2841
+ {
2842
+ "key": "verify",
2843
+ "prompt": "Annotate today with 'PostHog wizard install'",
2844
+ "description": "Creates a dated note on your project — visible on every chart. Delete anytime from PostHog."
2845
+ },
2846
+ {
2847
+ "key": "top-events",
2848
+ "prompt": "Show me my top 5 events from the last 7 days",
2849
+ "description": "Get a feel for what your project is tracking."
2850
+ },
2791
2851
  {
2792
- prompt: "What are my busiest 10 events and when did each last fire?",
2793
- description: "Inventories your project’s event stream so you can see what’s being captured at a glance."
2852
+ "key": "main-funnel",
2853
+ "prompt": "Build me a funnel for my main user journey and show where the drop-off is",
2854
+ "description": "Insight discovery — your agent picks the events."
2794
2855
  },
2795
2856
  {
2796
- prompt: "Show me daily event volume for the last 30 days.",
2797
- description: "Charts your event count day by day a quick read on volume and trend."
2857
+ "key": "flags-inventory",
2858
+ "prompt": "Show me my feature flags and what each is currently rolled out to",
2859
+ "description": "Inventory the rollout state of every flag in your project."
2798
2860
  },
2799
2861
  {
2800
- prompt: "Create a dashboard with my top 10 events broken down by day for the last 7 days.",
2801
- description: "Builds a saved dashboard you can pin and share written back to your project."
2862
+ "key": "error-trend",
2863
+ "prompt": "Show me daily error count for the last 30 days and flag anything that looks like a spike",
2864
+ "description": "Pulse-check on stability — no dashboard setup required."
2802
2865
  }
2803
2866
  ];
2804
- //#endregion
2805
- //#region src/ui/tui/screens/McpSuggestedPromptsScreen.tsx
2806
- /**
2807
- * McpSuggestedPromptsScreen — shown after MCP install succeeds in the
2808
- * standalone `wizard mcp add` program.
2809
- *
2810
- * Phases:
2811
- * 1. Choose — opens with a Log in / Exit picker, framed by a
2812
- * hardcoded teaser of three example prompts.
2813
- * 2. Authenticating runs `services.performLogin()` (OAuth in
2814
- * production, canned values in the playground).
2815
- * Renders a spinner + login URL inline while the
2816
- * promise is pending. Errors return to Choose
2817
- * with an inline error line.
2818
- * 3. PromptPicker — lists the role-tailored kit; user picks one to
2819
- * run. The picker has its own "Exit" entry so
2820
- * dismissal is discoverable without a hidden
2821
- * hotkey.
2822
- * 4. Running — streams the agent's response inline via
2823
- * `services.runPromptStreaming`. `[esc]` aborts
2824
- * and returns to the picker; `[enter]` after
2825
- * completion goes back to the picker so the user
2826
- * can run another or exit.
2827
- *
2828
- * Credentials are guaranteed non-null once PromptPicker / Running are
2829
- * reached (the Choose Authenticating gate forces a successful login
2830
- * before getting there). A defensive throw protects the Running
2831
- * useEffect against a state-machine bug.
2832
- */
2833
- const MAX_PROMPT_RUNS = 3;
2834
- const McpSuggestedPromptsScreen = ({ store, services }) => {
2835
- useSyncExternalStore((cb) => store.subscribe(cb), () => store.getSnapshot());
2836
- const session = store.session;
2837
- const kit = STOCK_MCP_SUGGESTED_PROMPTS;
2838
- const [phase, setPhase] = useState("choose");
2839
- const [loginError, setLoginError] = useState(null);
2840
- const [runningPrompt, setRunningPrompt] = useState(null);
2841
- const [runChunks, setRunChunks] = useState([]);
2842
- const [runStartedAt, setRunStartedAt] = useState(null);
2843
- const [runCount, setRunCount] = useState(0);
2844
- const canPickAnother = runCount < MAX_PROMPT_RUNS;
2845
- const runAbortRef = useRef(null);
2846
- useEffect(() => {
2847
- if (phase !== "authenticating") return;
2848
- let cancelled = false;
2849
- (async () => {
2850
- try {
2851
- const { credentials, roleAtOrganization, user } = await services.performLogin();
2852
- if (cancelled) return;
2853
- store.setCredentials(credentials);
2854
- store.setRoleAtOrganization(roleAtOrganization);
2855
- store.setApiUser(user);
2856
- store.setLoginUrl(null);
2857
- setPhase("prompt-picker");
2858
- } catch (err) {
2859
- if (cancelled) return;
2860
- const message = err instanceof Error ? err.message : String(err);
2861
- logToFile(`[McpSuggestedPromptsScreen] login failed: ${message}`);
2862
- store.setLoginUrl(null);
2863
- setLoginError(message);
2864
- setPhase("choose");
2865
- }
2866
- })();
2867
- return () => {
2868
- cancelled = true;
2869
- };
2870
- }, [
2871
- phase,
2872
- services,
2873
- store
2874
- ]);
2875
- useEffect(() => {
2876
- if (phase !== "running") return;
2877
- if (!runningPrompt) return;
2878
- if (!session.credentials) throw new Error("[McpSuggestedPromptsScreen] Running phase reached without credentials. The Choose gate should have prevented this.");
2879
- const controller = new AbortController();
2880
- runAbortRef.current = controller;
2881
- const startedAt = Date.now();
2882
- setRunStartedAt(startedAt);
2883
- setRunChunks([]);
2884
- (async () => {
2885
- const credentials = session.credentials;
2886
- if (!credentials) return;
2887
- try {
2888
- for await (const chunk of services.runPromptStreaming({
2889
- prompt: runningPrompt,
2890
- credentials,
2891
- signal: controller.signal
2892
- })) {
2893
- if (controller.signal.aborted) return;
2894
- setRunChunks((prev) => [...prev, chunk]);
2895
- if (chunk.kind === "done") {
2896
- analytics.wizardCapture("mcp suggested prompts run", {
2897
- prompt: runningPrompt,
2898
- durationMs: Date.now() - startedAt
2899
- });
2900
- return;
2901
- }
2902
- if (chunk.kind === "error") {
2903
- analytics.wizardCapture("mcp suggested prompts run failed", {
2904
- prompt: runningPrompt,
2905
- error: chunk.text
2906
- });
2907
- return;
2908
- }
2909
- }
2910
- } catch (err) {
2911
- if (controller.signal.aborted) return;
2912
- const text = err instanceof Error ? err.message : String(err);
2913
- setRunChunks((prev) => [...prev, {
2914
- kind: "error",
2915
- text
2916
- }]);
2917
- analytics.wizardCapture("mcp suggested prompts run failed", {
2918
- prompt: runningPrompt,
2919
- error: text
2920
- });
2921
- }
2922
- })();
2923
- return () => {
2924
- controller.abort();
2925
- if (runAbortRef.current === controller) runAbortRef.current = null;
2926
- };
2927
- }, [
2928
- phase,
2929
- runningPrompt,
2930
- services,
2931
- session.credentials
2932
- ]);
2933
- const dismiss = () => {
2934
- setPhase("done");
2935
- setTimeout(() => {
2936
- store.setMcpSuggestedPromptsDismissed();
2937
- }, 0);
2938
- };
2939
- const handleChoice = (value) => {
2940
- const choice = Array.isArray(value) ? value[0] : value;
2941
- setLoginError(null);
2942
- if (choice === "login") {
2943
- analytics.wizardCapture("mcp suggested prompts choose", { choice: "login" });
2944
- setPhase("authenticating");
2945
- } else {
2946
- analytics.wizardCapture("mcp suggested prompts choose", { choice: "exit" });
2947
- dismiss();
2867
+ var roleKits = {
2868
+ "founder": [
2869
+ {
2870
+ "key": "verify",
2871
+ "prompt": "Annotate today with 'PostHog wizard install'",
2872
+ "description": "Creates a dated note on your project — visible on every chart. Delete anytime from PostHog."
2873
+ },
2874
+ {
2875
+ "key": "exec-dashboard",
2876
+ "prompt": "Build me an exec dashboard with MRR, MAU, churn, and top events, then save it",
2877
+ "description": "A one-glance view of the business you can pin and share."
2878
+ },
2879
+ {
2880
+ "key": "wau",
2881
+ "prompt": "Show me weekly active users for the last 90 days",
2882
+ "description": "The trendline you actually care about."
2883
+ },
2884
+ {
2885
+ "key": "mau-trend",
2886
+ "prompt": "Show me weekly MAU for the last 12 weeks and where the inflection points are",
2887
+ "description": "See where growth bent up or down — without setting up alerts."
2888
+ },
2889
+ {
2890
+ "key": "nps-summary",
2891
+ "prompt": "Show me NPS responses from my paid users and summarize the themes",
2892
+ "description": "Pulse-check on the people paying you."
2948
2893
  }
2949
- };
2950
- const handlePromptPick = (value) => {
2951
- setRunningPrompt(Array.isArray(value) ? value[0] : value);
2952
- setRunCount((c) => c + 1);
2953
- setPhase("running");
2954
- };
2955
- useKeyBindings("mcp-suggested-prompts", [{
2956
- match: "escape",
2957
- label: "esc",
2958
- action: phase === "prompt-picker" ? "exit" : "exit",
2959
- handler: () => {
2960
- if (phase === "running") {
2961
- runAbortRef.current?.abort();
2962
- dismiss();
2963
- } else if (phase === "prompt-picker") dismiss();
2894
+ ],
2895
+ "product": [
2896
+ {
2897
+ "key": "verify",
2898
+ "prompt": "Annotate today with 'PostHog wizard install'",
2899
+ "description": "Creates a dated note on your project — visible on every chart. Delete anytime from PostHog."
2900
+ },
2901
+ {
2902
+ "key": "onboarding",
2903
+ "prompt": "Build a funnel for my onboarding flow and show me the biggest drop-off step",
2904
+ "description": "See where new users drop off in their first session."
2905
+ },
2906
+ {
2907
+ "key": "pricing-flag-state",
2908
+ "prompt": "Show me feature flags scoped to the pricing page and who's currently in each",
2909
+ "description": "Inspect rollout state of pricing experiments without changing anything."
2910
+ },
2911
+ {
2912
+ "key": "cta-compare",
2913
+ "prompt": "Show me how my upgrade CTA variants are converting across my recent experiments",
2914
+ "description": "Read the verdict on CTA tests without spinning up a new one."
2915
+ },
2916
+ {
2917
+ "key": "retention",
2918
+ "prompt": "Compute week-1 retention split by acquisition channel",
2919
+ "description": "Find the channel that actually retains users."
2964
2920
  }
2965
- }, {
2966
- match: "p",
2967
- label: "p",
2968
- action: canPickAnother ? "pick new prompt" : "cap reached",
2969
- handler: () => {
2970
- if (phase !== "running") return;
2971
- if (!canPickAnother) return;
2972
- runAbortRef.current?.abort();
2973
- setPhase("prompt-picker");
2921
+ ],
2922
+ "leadership": [
2923
+ {
2924
+ "key": "verify",
2925
+ "prompt": "Annotate today with 'PostHog wizard install'",
2926
+ "description": "Creates a dated note on your project — visible on every chart. Delete anytime from PostHog."
2927
+ },
2928
+ {
2929
+ "key": "board-dashboard",
2930
+ "prompt": "Build a board dashboard with revenue, MAU, churn, and support backlog, then save it",
2931
+ "description": "Pre-board prep in one prompt."
2932
+ },
2933
+ {
2934
+ "key": "mau-growth",
2935
+ "prompt": "Show MAU growth over the last 4 quarters",
2936
+ "description": "The chart for the next leadership slide."
2937
+ },
2938
+ {
2939
+ "key": "churn-trend",
2940
+ "prompt": "Show me churn over the last 8 weeks and where it moved most",
2941
+ "description": "See the trend without configuring a notification."
2942
+ },
2943
+ {
2944
+ "key": "upgrade-drivers",
2945
+ "prompt": "Which features drive the most upgrades?",
2946
+ "description": "Ranked breakdown of what actually moves the needle."
2974
2947
  }
2975
- }]);
2976
- return /* @__PURE__ */ jsx(Box, {
2977
- flexDirection: "column",
2978
- flexGrow: 1,
2979
- children: /* @__PURE__ */ jsxs(Box, {
2980
- marginTop: 1,
2981
- flexDirection: "column",
2982
- children: [
2983
- phase === "choose" && /* @__PURE__ */ jsx(ChoosePhase, {
2984
- error: loginError,
2985
- onSelect: handleChoice
2986
- }),
2987
- phase === "authenticating" && /* @__PURE__ */ jsx(AuthenticatingPhase, { loginUrl: session.loginUrl }),
2988
- phase === "prompt-picker" && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Box, {
2989
- marginBottom: 1,
2990
- children: /* @__PURE__ */ jsx(Text, {
2991
- bold: true,
2992
- color: Colors.accent,
2993
- children: "MCP tutorial"
2994
- })
2995
- }), /* @__PURE__ */ jsx(PromptPickerPhase, {
2996
- promptKit: kit,
2997
- userDisplayName: session.apiUser?.first_name || null,
2998
- onSelect: handlePromptPick
2999
- })] }),
3000
- phase === "running" && runningPrompt && /* @__PURE__ */ jsx(RunningPhase, {
3001
- prompt: runningPrompt,
3002
- chunks: runChunks,
3003
- startedAt: runStartedAt,
3004
- canPickAnother,
3005
- runCount,
3006
- maxRuns: MAX_PROMPT_RUNS
3007
- })
3008
- ]
3009
- })
3010
- });
2948
+ ],
2949
+ "marketing": [
2950
+ {
2951
+ "key": "verify",
2952
+ "prompt": "Annotate today with 'PostHog wizard install'",
2953
+ "description": "Creates a dated note on your project — visible on every chart. Delete anytime from PostHog."
2954
+ },
2955
+ {
2956
+ "key": "pricing-leavers",
2957
+ "prompt": "Show me users who saw pricing but didn't sign up — what did they do next?",
2958
+ "description": "Identify high-intent visitors and what they bounced to."
2959
+ },
2960
+ {
2961
+ "key": "hero-compare",
2962
+ "prompt": "Show me how my landing page hero variants performed — which group converted best?",
2963
+ "description": "Read the verdict on hero copy tests."
2964
+ },
2965
+ {
2966
+ "key": "newsletter-clicks",
2967
+ "prompt": "Find users who clicked our last newsletter and show me what they did next",
2968
+ "description": "See the downstream behavior of your last campaign."
2969
+ },
2970
+ {
2971
+ "key": "landing-annotation",
2972
+ "prompt": "Annotate today as the launch of the new landing page",
2973
+ "description": "Pin the deploy on every chart so future you can find it."
2974
+ }
2975
+ ],
2976
+ "engineering": [
2977
+ {
2978
+ "key": "verify",
2979
+ "prompt": "Annotate today with 'PostHog wizard install'",
2980
+ "description": "Creates a dated note on your project — visible on every chart. Delete anytime from PostHog."
2981
+ },
2982
+ {
2983
+ "key": "stale-flags",
2984
+ "prompt": "List flags rolled out to 100% — they're probably safe to delete",
2985
+ "description": "Dead-code hunt for your feature flag config."
2986
+ },
2987
+ {
2988
+ "key": "top-errors",
2989
+ "prompt": "Show me the top 5 unresolved errors this week",
2990
+ "description": "Triage queue without opening another tab."
2991
+ },
2992
+ {
2993
+ "key": "reliability-trend",
2994
+ "prompt": "Show me 5xx error rate over the last 24 hours by endpoint",
2995
+ "description": "See where reliability is drifting, no alert setup."
2996
+ },
2997
+ {
2998
+ "key": "zero-rollout-flags",
2999
+ "prompt": "Show me feature flags currently rolled out at 0% — anything ready to retire?",
3000
+ "description": "Find dead kill-switch flags you can clean up later."
3001
+ }
3002
+ ],
3003
+ "data": [
3004
+ {
3005
+ "key": "verify",
3006
+ "prompt": "Annotate today with 'PostHog wizard install'",
3007
+ "description": "Creates a dated note on your project — visible on every chart. Delete anytime from PostHog."
3008
+ },
3009
+ {
3010
+ "key": "top-events-24h",
3011
+ "prompt": "Top 5 events by volume in the last 24 hours",
3012
+ "description": "Smoke test for ingestion + a sanity check on volumes."
3013
+ },
3014
+ {
3015
+ "key": "paid-retention",
3016
+ "prompt": "Retention curve for paid users by signup month",
3017
+ "description": "The cohort chart you'd build first anyway."
3018
+ },
3019
+ {
3020
+ "key": "full-funnel",
3021
+ "prompt": "Funnel: signup → activated → first power feature → paid",
3022
+ "description": "Drop-off across the full journey, ready to slice."
3023
+ },
3024
+ {
3025
+ "key": "power-users-query",
3026
+ "prompt": "Show me users with 5+ sessions per week over the last month and what they have in common",
3027
+ "description": "Profile your power-user segment without materializing a cohort."
3028
+ }
3029
+ ]
3011
3030
  };
3012
- const ChoosePhase = ({ error, onSelect }) => /* @__PURE__ */ jsxs(Box, {
3013
- flexDirection: "column",
3031
+ var roleFamilyOverrides = {
3032
+ "product": {
3033
+ "frontend-web": { "cta-compare": {
3034
+ "prompt": "Compare conversion across the variants of my last upgrade CTA experiment (control, red, green)",
3035
+ "description": "Read the verdict on a three-arm frontend experiment."
3036
+ } },
3037
+ "mobile": {
3038
+ "onboarding": {
3039
+ "prompt": "Build a funnel app_open → onboarding_complete → first_session_complete and show me the drop-off",
3040
+ "description": "Mobile-flavored onboarding funnel with sensible defaults."
3041
+ },
3042
+ "cta-compare": {
3043
+ "prompt": "Show me feature flags gated on app version — who's in each release tier?",
3044
+ "description": "See which clients see what, without changing anything."
3045
+ }
3046
+ },
3047
+ "backend": { "onboarding": {
3048
+ "prompt": "Funnel of signup → first API call → paid for last 30 days",
3049
+ "description": "Backend funnel that reflects what your service actually sees."
3050
+ } }
3051
+ },
3052
+ "engineering": {
3053
+ "frontend-web": { "top-errors": {
3054
+ "prompt": "Top 5 JS errors by occurrence count this week, with affected URLs",
3055
+ "description": "Frontend-specific error triage — sorted by blast radius."
3056
+ } },
3057
+ "mobile": {
3058
+ "top-errors": {
3059
+ "prompt": "Top crashes this week by app version, sorted by affected users",
3060
+ "description": "Mobile crash triage straight from the same data PostHog has."
3061
+ },
3062
+ "reliability-trend": {
3063
+ "prompt": "Show me crash-free sessions over the last 7 days by app version",
3064
+ "description": "Crash-free trend per release — the one mobile metric that matters."
3065
+ }
3066
+ },
3067
+ "backend": {
3068
+ "top-errors": {
3069
+ "prompt": "Top 5 server-side errors this week, grouped by endpoint",
3070
+ "description": "Backend error triage by route, sorted by frequency."
3071
+ },
3072
+ "reliability-trend": {
3073
+ "prompt": "Show me p95 response time over the last 24 hours by endpoint",
3074
+ "description": "Latency trend from the data you already collect."
3075
+ }
3076
+ }
3077
+ },
3078
+ "data": { "backend": { "full-funnel": {
3079
+ "prompt": "Funnel: api_signup → first_api_call → first_paid_event over last 30 days",
3080
+ "description": "Backend conversion funnel — captures the value your service delivers."
3081
+ } } }
3082
+ };
3083
+ var roleGreetings = {
3084
+ "founder": {
3085
+ "headline": "Founders use MCP to keep a hand on growth.",
3086
+ "bullets": [
3087
+ "Weekly active users, retention, and revenue without leaving your IDE.",
3088
+ "Spot stalls in your trends without setting up dashboards by hand.",
3089
+ "Pin annotations on every chart so you remember what shipped."
3090
+ ],
3091
+ "outro": "Pick a prompt — your agent will run it on your project's real data."
3092
+ },
3093
+ "product": {
3094
+ "headline": "PMs use MCP to learn faster and decide quicker.",
3095
+ "bullets": [
3096
+ "Funnels for every onboarding flow you want to inspect.",
3097
+ "Inspect feature flags and experiment outcomes without leaving your IDE.",
3098
+ "Retention sliced by acquisition channel in seconds."
3099
+ ],
3100
+ "outro": "Pick a prompt — your agent will do the legwork."
3101
+ },
3102
+ "leadership": {
3103
+ "headline": "Read the business from your terminal.",
3104
+ "bullets": [
3105
+ "Board-ready dashboards in one prompt.",
3106
+ "Trend lines for MAU, churn, and revenue, one query away.",
3107
+ "The numbers for the next leadership slide, on tap."
3108
+ ],
3109
+ "outro": "Pick a prompt to see PostHog work for you."
3110
+ },
3111
+ "marketing": {
3112
+ "headline": "Inspect campaigns, end to end.",
3113
+ "bullets": [
3114
+ "Find high-intent visitors and what they did next.",
3115
+ "Compare landing-copy experiments and see which arm is winning.",
3116
+ "Tie every campaign to revenue with annotated launches."
3117
+ ],
3118
+ "outro": "Pick a prompt to try it on your data."
3119
+ },
3120
+ "engineering": {
3121
+ "headline": "MCP is your shortest path from bug to root cause.",
3122
+ "bullets": [
3123
+ "Top errors this week, sorted by blast radius.",
3124
+ "Latency and crash-free trends checked against real data.",
3125
+ "Audit which flags are stale or fully rolled out."
3126
+ ],
3127
+ "outro": "Pick a prompt — your agent has read access across your project."
3128
+ },
3129
+ "data": {
3130
+ "headline": "Data work without leaving the terminal.",
3131
+ "bullets": [
3132
+ "Profile any segment in seconds.",
3133
+ "Retention curves by signup month, sliced any way you want.",
3134
+ "Run SQL against your event stream — no copy-paste, no exports."
3135
+ ],
3136
+ "outro": "Pick a prompt — every result is real data from your project."
3137
+ }
3138
+ };
3139
+ var neutralGreeting = {
3140
+ "headline": "PostHog MCP turns your agent into a product analyst.",
3141
+ "bullets": [
3142
+ "Run queries, build insights, save dashboards — straight from your IDE.",
3143
+ "Every result is real data from your project.",
3144
+ "No copy-pasting tokens, no context switching."
3145
+ ],
3146
+ "outro": "Pick a prompt to see what MCP can do."
3147
+ };
3148
+ var toolFollowUps = {
3149
+ "query-error-tracking-issue": [
3150
+ {
3151
+ "label": "Stack trace for the top error",
3152
+ "prompt": "Show me the stack trace and recent occurrences for the top error."
3153
+ },
3154
+ {
3155
+ "label": "Who is most affected?",
3156
+ "prompt": "Which users have hit that error most often in the last 7 days?"
3157
+ },
3158
+ {
3159
+ "label": "When did it start?",
3160
+ "prompt": "Show me when that error first appeared and any deploy that landed nearby."
3161
+ },
3162
+ {
3163
+ "label": "Find related sessions",
3164
+ "prompt": "Find session recordings that hit that error so I can see what users were doing."
3165
+ },
3166
+ {
3167
+ "label": "Save the top-errors view",
3168
+ "prompt": "Save this top-errors view as an insight I can come back to."
3169
+ },
3170
+ {
3171
+ "label": "Pin to engineering dashboard",
3172
+ "prompt": "Pin this errors view to my engineering dashboard."
3173
+ }
3174
+ ],
3175
+ "query-trends": [
3176
+ {
3177
+ "label": "Break down by property",
3178
+ "prompt": "Break that trend down by the most common user property."
3179
+ },
3180
+ {
3181
+ "label": "Find the outlier day",
3182
+ "prompt": "Which day stood out the most and what else was going on?"
3183
+ },
3184
+ {
3185
+ "label": "Compare to last month",
3186
+ "prompt": "Compare that against the same period last month."
3187
+ },
3188
+ {
3189
+ "label": "Build a funnel from it",
3190
+ "prompt": "Build a funnel using the top events from that trend."
3191
+ },
3192
+ {
3193
+ "label": "Save as an insight",
3194
+ "prompt": "Save that trend as an insight named 'Trends'."
3195
+ },
3196
+ {
3197
+ "label": "Pin to main dashboard",
3198
+ "prompt": "Pin that trend to my main dashboard."
3199
+ }
3200
+ ],
3201
+ "query-funnel": [
3202
+ {
3203
+ "label": "Biggest drop-off",
3204
+ "prompt": "Which step has the biggest drop-off, and who falls out there?"
3205
+ },
3206
+ {
3207
+ "label": "Completion time",
3208
+ "prompt": "How long does it take users who complete that funnel?"
3209
+ },
3210
+ {
3211
+ "label": "Slice by platform",
3212
+ "prompt": "Show that funnel split by mobile vs desktop."
3213
+ },
3214
+ {
3215
+ "label": "Find drop-off sessions",
3216
+ "prompt": "Find session recordings of users who dropped out at the biggest step."
3217
+ },
3218
+ {
3219
+ "label": "Save the funnel",
3220
+ "prompt": "Save that funnel as an insight."
3221
+ },
3222
+ {
3223
+ "label": "Pin to dashboard",
3224
+ "prompt": "Pin that funnel to my main dashboard."
3225
+ }
3226
+ ],
3227
+ "query-retention": [
3228
+ {
3229
+ "label": "Best-retaining cohort",
3230
+ "prompt": "Which cohort retains the longest in that curve?"
3231
+ },
3232
+ {
3233
+ "label": "Worst-retaining cohort",
3234
+ "prompt": "Which cohort drops off fastest in that curve?"
3235
+ },
3236
+ {
3237
+ "label": "Slice by acquisition channel",
3238
+ "prompt": "Re-run that retention split by acquisition channel."
3239
+ },
3240
+ {
3241
+ "label": "Find churned users",
3242
+ "prompt": "Find session recordings of users who churned during week 1."
3243
+ },
3244
+ {
3245
+ "label": "Save the retention chart",
3246
+ "prompt": "Save that retention chart as an insight."
3247
+ },
3248
+ {
3249
+ "label": "Pin to growth dashboard",
3250
+ "prompt": "Pin that retention chart to my growth dashboard."
3251
+ }
3252
+ ],
3253
+ "query-feature-flag": [
3254
+ {
3255
+ "label": "Who's in this flag?",
3256
+ "prompt": "Show me which users are currently in the rollout for that flag."
3257
+ },
3258
+ {
3259
+ "label": "What changed recently?",
3260
+ "prompt": "Show me the rollout history for that flag — when did it last change?"
3261
+ },
3262
+ {
3263
+ "label": "Compare against another flag",
3264
+ "prompt": "Show me the audience overlap between that flag and one related flag."
3265
+ },
3266
+ {
3267
+ "label": "Find sessions for that flag",
3268
+ "prompt": "Find recent session recordings from users currently in that flag."
3269
+ },
3270
+ {
3271
+ "label": "Save flag inventory",
3272
+ "prompt": "Save this flag inventory as an insight."
3273
+ },
3274
+ {
3275
+ "label": "Pin to release dashboard",
3276
+ "prompt": "Pin this flag view to my release dashboard."
3277
+ }
3278
+ ],
3279
+ "query-survey-responses": [
3280
+ {
3281
+ "label": "Summarize the themes",
3282
+ "prompt": "Summarize the themes from those survey responses."
3283
+ },
3284
+ {
3285
+ "label": "Score distribution",
3286
+ "prompt": "Show me the score distribution across those responses."
3287
+ },
3288
+ {
3289
+ "label": "Who are the detractors?",
3290
+ "prompt": "Show me users who left a low score and what they did next."
3291
+ },
3292
+ {
3293
+ "label": "Find their sessions",
3294
+ "prompt": "Find session recordings from users who left a low score."
3295
+ },
3296
+ {
3297
+ "label": "Save the response summary",
3298
+ "prompt": "Save this response summary as an insight."
3299
+ },
3300
+ {
3301
+ "label": "Add to research notebook",
3302
+ "prompt": "Add this survey summary to my user research notebook."
3303
+ }
3304
+ ],
3305
+ "query-experiment": [
3306
+ {
3307
+ "label": "Which variant is winning?",
3308
+ "prompt": "Show me the conversion rate of each variant in that experiment."
3309
+ },
3310
+ {
3311
+ "label": "Slice by segment",
3312
+ "prompt": "Show me how each variant performed by user segment."
3313
+ },
3314
+ {
3315
+ "label": "Statistical significance",
3316
+ "prompt": "Has that experiment reached statistical significance yet?"
3317
+ },
3318
+ {
3319
+ "label": "Find variant sessions",
3320
+ "prompt": "Find session recordings from users in the winning variant."
3321
+ },
3322
+ {
3323
+ "label": "Save the readout",
3324
+ "prompt": "Save that experiment readout as an insight."
3325
+ },
3326
+ {
3327
+ "label": "Add to experiment notebook",
3328
+ "prompt": "Add this experiment readout to my experiments notebook."
3329
+ }
3330
+ ],
3331
+ "query-session-recordings-list": [
3332
+ {
3333
+ "label": "Summarize what users did",
3334
+ "prompt": "Summarize what users did in those sessions."
3335
+ },
3336
+ {
3337
+ "label": "Find common drop-offs",
3338
+ "prompt": "What's the most common step where users got stuck in those sessions?"
3339
+ },
3340
+ {
3341
+ "label": "Errors in those sessions",
3342
+ "prompt": "Which errors fired most often across those sessions?"
3343
+ },
3344
+ {
3345
+ "label": "Properties of those users",
3346
+ "prompt": "Show me the most common user properties across those sessions."
3347
+ },
3348
+ {
3349
+ "label": "Save the session summary",
3350
+ "prompt": "Save the summary of those sessions as an insight."
3351
+ },
3352
+ {
3353
+ "label": "Add to UX notebook",
3354
+ "prompt": "Add these session findings to my UX research notebook."
3355
+ }
3356
+ ],
3357
+ "execute-sql": [
3358
+ {
3359
+ "label": "Add p50/p90/p99",
3360
+ "prompt": "Re-run that query with p50/p90/p99 added."
3361
+ },
3362
+ {
3363
+ "label": "Slice differently",
3364
+ "prompt": "Re-run that query grouped by the most common user property."
3365
+ },
3366
+ {
3367
+ "label": "Find the outliers",
3368
+ "prompt": "Re-run that query and surface the top 5 outliers."
3369
+ },
3370
+ {
3371
+ "label": "Compare to last week",
3372
+ "prompt": "Compare that query result to the same window last week."
3373
+ },
3374
+ {
3375
+ "label": "Save as an insight",
3376
+ "prompt": "Turn that query result into a saved insight."
3377
+ },
3378
+ {
3379
+ "label": "Pin to data dashboard",
3380
+ "prompt": "Pin that query result to my data dashboard."
3381
+ }
3382
+ ],
3383
+ "create-dashboard": [
3384
+ {
3385
+ "label": "Add another tile",
3386
+ "prompt": "Add a tile showing daily active users to that dashboard."
3387
+ },
3388
+ {
3389
+ "label": "Add a leaderboard tile",
3390
+ "prompt": "Add a top-5 users tile to that dashboard."
3391
+ },
3392
+ {
3393
+ "label": "Annotate today",
3394
+ "prompt": "Annotate today on that dashboard as the launch baseline."
3395
+ },
3396
+ {
3397
+ "label": "Compare to last quarter",
3398
+ "prompt": "Add a tile comparing this quarter to the last on the same dashboard."
3399
+ },
3400
+ {
3401
+ "label": "Add an errors tile",
3402
+ "prompt": "Add a tile showing the top 3 errors this week to that dashboard."
3403
+ },
3404
+ {
3405
+ "label": "Add to dashboards notebook",
3406
+ "prompt": "Add a link to that dashboard in my dashboards notebook."
3407
+ }
3408
+ ],
3409
+ "create-insight": [
3410
+ {
3411
+ "label": "Pin to main dashboard",
3412
+ "prompt": "Pin that insight to my main dashboard."
3413
+ },
3414
+ {
3415
+ "label": "Split by user property",
3416
+ "prompt": "Re-run that insight split by the most common user property."
3417
+ },
3418
+ {
3419
+ "label": "Compare to a control",
3420
+ "prompt": "Re-run that insight comparing paid vs free users side-by-side."
3421
+ },
3422
+ {
3423
+ "label": "Save the underlying query",
3424
+ "prompt": "Save the underlying query for that insight so I can edit it later."
3425
+ },
3426
+ {
3427
+ "label": "Add to notebook",
3428
+ "prompt": "Add that insight to my analytics notebook."
3429
+ },
3430
+ {
3431
+ "label": "Annotate the moment",
3432
+ "prompt": "Annotate today on the chart for that insight."
3433
+ }
3434
+ ]
3435
+ };
3436
+ var roleFollowUps = {
3437
+ "founder": [
3438
+ {
3439
+ "label": "Pin to exec dashboard",
3440
+ "prompt": "Add that result to my exec dashboard."
3441
+ },
3442
+ {
3443
+ "label": "Tie it to revenue",
3444
+ "prompt": "How does that correlate with paid conversions?"
3445
+ },
3446
+ {
3447
+ "label": "Compare to last quarter",
3448
+ "prompt": "How does that compare against the same period last quarter?"
3449
+ },
3450
+ {
3451
+ "label": "Save for board update",
3452
+ "prompt": "Save that as an insight I can attach to the next board update."
3453
+ }
3454
+ ],
3455
+ "product": [
3456
+ {
3457
+ "label": "Build a funnel around it",
3458
+ "prompt": "Build a funnel that includes that step."
3459
+ },
3460
+ {
3461
+ "label": "Find high-intent users",
3462
+ "prompt": "Show me which users in that group also completed activation."
3463
+ },
3464
+ {
3465
+ "label": "Check related experiments",
3466
+ "prompt": "Show me how this metric trended across my recent experiments."
3467
+ },
3468
+ {
3469
+ "label": "Save to product notebook",
3470
+ "prompt": "Add this finding to my product analytics notebook."
3471
+ }
3472
+ ],
3473
+ "leadership": [
3474
+ {
3475
+ "label": "Compare to last quarter",
3476
+ "prompt": "How does that compare against the same period last quarter?"
3477
+ },
3478
+ {
3479
+ "label": "Pin to leadership dashboard",
3480
+ "prompt": "Pin this view to my leadership dashboard."
3481
+ },
3482
+ {
3483
+ "label": "Save for next meeting",
3484
+ "prompt": "Save this as an insight I can pull up in the next leadership meeting."
3485
+ }
3486
+ ],
3487
+ "marketing": [
3488
+ {
3489
+ "label": "Annotate the launch",
3490
+ "prompt": "Annotate today as the campaign launch on that chart."
3491
+ },
3492
+ {
3493
+ "label": "What did they do next?",
3494
+ "prompt": "Show me what users in that group did next."
3495
+ },
3496
+ {
3497
+ "label": "Tie back to channel",
3498
+ "prompt": "Split that result by acquisition channel."
3499
+ },
3500
+ {
3501
+ "label": "Compare to landing tests",
3502
+ "prompt": "Compare this result across my recent landing-page experiments."
3503
+ }
3504
+ ],
3505
+ "engineering": [
3506
+ {
3507
+ "label": "Did a deploy land?",
3508
+ "prompt": "Did that change land alongside a deploy in the last 24 hours?"
3509
+ },
3510
+ {
3511
+ "label": "Flag changes that fit",
3512
+ "prompt": "Show me which feature flag changes correlate with that change in metric."
3513
+ },
3514
+ {
3515
+ "label": "Group by release",
3516
+ "prompt": "Re-run that broken down by app version or release."
3517
+ },
3518
+ {
3519
+ "label": "Save to incident notebook",
3520
+ "prompt": "Save this analysis to my incident notebook."
3521
+ }
3522
+ ],
3523
+ "data": [
3524
+ {
3525
+ "label": "Add percentiles",
3526
+ "prompt": "Add p50/p90/p99 distributions to that result."
3527
+ },
3528
+ {
3529
+ "label": "Compare to last month",
3530
+ "prompt": "Show me how that result trended over the last month."
3531
+ },
3532
+ {
3533
+ "label": "Save as an insight",
3534
+ "prompt": "Save that query result as an insight."
3535
+ },
3536
+ {
3537
+ "label": "Pin to data dashboard",
3538
+ "prompt": "Pin this result to my data team dashboard."
3539
+ }
3540
+ ]
3541
+ };
3542
+ var genericFollowUps = [
3543
+ {
3544
+ "label": "Go one level deeper",
3545
+ "prompt": "Run that same question one level deeper."
3546
+ },
3547
+ {
3548
+ "label": "Take a different angle",
3549
+ "prompt": "Look at the same question from a completely different angle."
3550
+ },
3551
+ {
3552
+ "label": "Find the surprise",
3553
+ "prompt": "What's the most surprising thing in that result?"
3554
+ },
3555
+ {
3556
+ "label": "Slice by user",
3557
+ "prompt": "Re-run that split by the highest-value user segment."
3558
+ },
3559
+ {
3560
+ "label": "Compare with last month",
3561
+ "prompt": "How does that look compared to the same window a month ago?"
3562
+ },
3563
+ {
3564
+ "label": "Save as an insight",
3565
+ "prompt": "Save that result as an insight I can come back to."
3566
+ },
3567
+ {
3568
+ "label": "Pin to a dashboard",
3569
+ "prompt": "Pin this view to my main dashboard."
3570
+ },
3571
+ {
3572
+ "label": "Add to a notebook",
3573
+ "prompt": "Add this finding to my notebook."
3574
+ }
3575
+ ];
3576
+ var deepDiveFollowUps = [
3577
+ {
3578
+ "label": "Save this exploration",
3579
+ "prompt": "Save the most useful chart from this session as a dashboard I can come back to."
3580
+ },
3581
+ {
3582
+ "label": "Summarize what we found",
3583
+ "prompt": "Summarize the key findings from everything we just looked at in 3 bullets."
3584
+ },
3585
+ {
3586
+ "label": "Pin a session summary",
3587
+ "prompt": "Pin a summary of this session to my main dashboard."
3588
+ },
3589
+ {
3590
+ "label": "Write to a notebook",
3591
+ "prompt": "Write everything we just covered into a notebook entry I can revisit."
3592
+ }
3593
+ ];
3594
+ var crossSellByRole = {
3595
+ "founder": [{
3596
+ "product": "Session Replay",
3597
+ "prompt": "Find 3 recent sessions where a user looked at pricing but did not sign up.",
3598
+ "description": "Watch what users see — replay turns funnel drop-offs into video."
3599
+ }, {
3600
+ "product": "Surveys",
3601
+ "prompt": "Show me how my NPS results have trended over the last quarter.",
3602
+ "description": "Quantitative pulse check on the survey side of PostHog."
3603
+ }],
3604
+ "product": [{
3605
+ "product": "Experiments",
3606
+ "prompt": "Show me results from my latest onboarding experiment — which variant is winning?",
3607
+ "description": "Experiments piggyback on flags — same SDK, all readable here."
3608
+ }, {
3609
+ "product": "Session Replay",
3610
+ "prompt": "Find sessions where users got stuck on the empty state in onboarding.",
3611
+ "description": "See what funnels can't show you."
3612
+ }],
3613
+ "leadership": [{
3614
+ "product": "Surveys",
3615
+ "prompt": "Show me NPS scores from the last quarter — who are the detractors?",
3616
+ "description": "Read the survey data PostHog already collects for you."
3617
+ }, {
3618
+ "product": "Data Warehouse",
3619
+ "prompt": "Compare MRR by signup source using Stripe data joined with event data.",
3620
+ "description": "Query revenue alongside events when warehouse is connected."
3621
+ }],
3622
+ "marketing": [{
3623
+ "product": "Session Replay",
3624
+ "prompt": "Watch 5 sessions from users who came via our last campaign and converted.",
3625
+ "description": "See campaign visitors behave — beyond aggregate numbers."
3626
+ }, {
3627
+ "product": "Web Analytics",
3628
+ "prompt": "Show me top traffic sources to the pricing page this week.",
3629
+ "description": "GA-style first-party web analytics, no cookie banner."
3630
+ }],
3631
+ "engineering": [{
3632
+ "product": "Error Tracking",
3633
+ "prompt": "Show me the top 5 errors this week and who is affected.",
3634
+ "description": "Built-in error tracking — no Sentry subscription."
3635
+ }, {
3636
+ "product": "Session Replay",
3637
+ "prompt": "Replay the last 3 sessions that hit a 5xx error.",
3638
+ "description": "Stack trace meets replay — see what the user did."
3639
+ }],
3640
+ "data": [{
3641
+ "product": "Data Warehouse",
3642
+ "prompt": "Join my event stream with Stripe subscriptions to surface churn signals.",
3643
+ "description": "Connect Stripe / Salesforce / S3, query everything with SQL."
3644
+ }, {
3645
+ "product": "LLM Observability",
3646
+ "prompt": "Show me the top 5 LLM prompts by cost over the last 7 days.",
3647
+ "description": "Track LLM calls, latency, and cost next to product events."
3648
+ }]
3649
+ };
3650
+ var neutralCrossSell = [{
3651
+ "product": "Session Replay",
3652
+ "prompt": "Show me 5 recent sessions where users dropped off before completing signup.",
3653
+ "description": "Replay what users actually do — included on every plan."
3654
+ }, {
3655
+ "product": "Error Tracking",
3656
+ "prompt": "List the top errors my users hit this week.",
3657
+ "description": "Built-in error tracking — no separate tool."
3658
+ }];
3659
+ //#endregion
3660
+ //#region src/lib/mcp-role-prompts.ts
3661
+ /**
3662
+ * Roles that ship from `role_at_organization` on the PostHog user object.
3663
+ * `security` isn't in the enum upstream — the engineering kit covers
3664
+ * that audience.
3665
+ */
3666
+ const TAILORED_ROLES = [
3667
+ "founder",
3668
+ "product",
3669
+ "leadership",
3670
+ "marketing",
3671
+ "engineering",
3672
+ "data"
3673
+ ];
3674
+ const FOLLOW_UP_EXIT_SENTINEL = "__follow_up_exit__";
3675
+ /**
3676
+ * Always shown as the picker's first option regardless of role —
3677
+ * a safe generic read that works on any project setup. The screen
3678
+ * prepends it and dedupes against the role kit so it never appears
3679
+ * twice when DEFAULT_KIT happens to include it.
3680
+ */
3681
+ const PINNED_FIRST_PROMPT = pinnedFirstPrompt;
3682
+ const DEFAULT_KIT = defaultKit;
3683
+ const ROLE_KITS = roleKits;
3684
+ const ROLE_FAMILY_OVERRIDES = roleFamilyOverrides;
3685
+ const ROLE_GREETINGS = roleGreetings;
3686
+ const NEUTRAL_GREETING = neutralGreeting;
3687
+ const TOOL_FOLLOW_UPS = toolFollowUps;
3688
+ const ROLE_FOLLOW_UPS = roleFollowUps;
3689
+ const GENERIC_FOLLOW_UPS = genericFollowUps;
3690
+ const DEEP_DIVE_FOLLOW_UPS = deepDiveFollowUps;
3691
+ const CROSS_SELL_BY_ROLE = crossSellByRole;
3692
+ const NEUTRAL_CROSS_SELL = neutralCrossSell;
3693
+ const INTEGRATION_FAMILY = {
3694
+ nextjs: "fullstack",
3695
+ nuxt: "fullstack",
3696
+ "tanstack-start": "fullstack",
3697
+ astro: "fullstack",
3698
+ sveltekit: "fullstack",
3699
+ vue: "frontend-web",
3700
+ angular: "frontend-web",
3701
+ "react-router": "frontend-web",
3702
+ "tanstack-router": "frontend-web",
3703
+ javascript_web: "frontend-web",
3704
+ "react-native": "mobile",
3705
+ swift: "mobile",
3706
+ android: "mobile",
3707
+ django: "backend",
3708
+ flask: "backend",
3709
+ fastapi: "backend",
3710
+ python: "backend",
3711
+ laravel: "backend",
3712
+ rails: "backend",
3713
+ ruby: "backend",
3714
+ javascript_node: "backend"
3715
+ };
3716
+ const EXIT_FOLLOW_UP = {
3717
+ label: "I'm done — exit",
3718
+ prompt: FOLLOW_UP_EXIT_SENTINEL
3719
+ };
3720
+ function isTailoredRole(role) {
3721
+ return typeof role === "string" && TAILORED_ROLES.includes(role);
3722
+ }
3723
+ /**
3724
+ * Strip MCP tool-name prefixes so lookup keys can stay short. Real MCP
3725
+ * tool names arrive as `mcp__<server>__<tool>`; the agent SDK also
3726
+ * sometimes drops the prefix. We take the substring after the last
3727
+ * double-underscore (or the input untouched if there's none).
3728
+ */
3729
+ function normalizeToolName(toolName) {
3730
+ if (!toolName) return null;
3731
+ const idx = toolName.lastIndexOf("__");
3732
+ return idx >= 0 ? toolName.slice(idx + 2) : toolName;
3733
+ }
3734
+ /** Pick `n` items from a pool starting at a rotation offset. */
3735
+ function pickRotated(pool, n, rotation) {
3736
+ if (pool.length === 0) return [];
3737
+ if (pool.length <= n) return pool;
3738
+ const start = (Math.floor(rotation) % pool.length + pool.length) % pool.length;
3739
+ const result = [];
3740
+ for (let i = 0; i < n; i++) result.push(pool[(start + i) % pool.length]);
3741
+ return result;
3742
+ }
3743
+ /** Drop duplicates while preserving order (by prompt text). */
3744
+ function dedupeFollowUps(list) {
3745
+ const seen = /* @__PURE__ */ new Set();
3746
+ const out = [];
3747
+ for (const f of list) {
3748
+ if (seen.has(f.prompt)) continue;
3749
+ seen.add(f.prompt);
3750
+ out.push(f);
3751
+ }
3752
+ return out;
3753
+ }
3754
+ function getFrameworkFamily(integration) {
3755
+ if (!integration) return "unknown";
3756
+ return INTEGRATION_FAMILY[integration] ?? "unknown";
3757
+ }
3758
+ /**
3759
+ * Resolve the right kit given everything we know about the user + project.
3760
+ * Always returns at least DEFAULT_KIT; never throws.
3761
+ */
3762
+ function getRolePrompts(role, integration) {
3763
+ const family = getFrameworkFamily(integration);
3764
+ if (!isTailoredRole(role)) return DEFAULT_KIT;
3765
+ const baseKit = ROLE_KITS[role];
3766
+ const overridesForFamily = ROLE_FAMILY_OVERRIDES[role]?.[family];
3767
+ if (!overridesForFamily) return baseKit;
3768
+ return baseKit.map((entry) => {
3769
+ return (entry.key ? overridesForFamily[entry.key] : void 0) ?? entry;
3770
+ });
3771
+ }
3772
+ function getRoleGreeting(role) {
3773
+ if (!isTailoredRole(role)) return NEUTRAL_GREETING;
3774
+ return ROLE_GREETINGS[role];
3775
+ }
3776
+ /**
3777
+ * Resolve `FOLLOW_UP_COUNT` context-aware follow-ups + an always-present
3778
+ * exit entry. Pulls from up to four pools — tool-specific, role-specific,
3779
+ * deep-dive (only after the user has explored a few steps), and generic —
3780
+ * dedupes, filters out anything already in `branchHistory`, then picks
3781
+ * `FOLLOW_UP_COUNT` with a rotation offset driven by `branchHistory.length`
3782
+ * so successive visits surface different slices.
3783
+ */
3784
+ function getFollowUps(args) {
3785
+ const { lastToolName, role, branchHistory } = args;
3786
+ const normalized = normalizeToolName(lastToolName);
3787
+ const depth = branchHistory.length;
3788
+ const candidates = [];
3789
+ if (normalized && TOOL_FOLLOW_UPS[normalized]) candidates.push(...TOOL_FOLLOW_UPS[normalized]);
3790
+ if (isTailoredRole(role)) candidates.push(...ROLE_FOLLOW_UPS[role]);
3791
+ if (depth >= 3) candidates.push(...DEEP_DIVE_FOLLOW_UPS);
3792
+ candidates.push(...GENERIC_FOLLOW_UPS);
3793
+ const deduped = dedupeFollowUps(candidates);
3794
+ const seen = new Set(branchHistory);
3795
+ return [...pickRotated(deduped.filter((f) => !seen.has(f.prompt)), 3, depth), EXIT_FOLLOW_UP];
3796
+ }
3797
+ /**
3798
+ * Cross-sell prompts to surface above the role kit in PromptPicker.
3799
+ * Filtered by role so the recommendations stay coherent (founders see
3800
+ * the "exec-friendly" cross-sells, engineers see "debug-friendly", etc).
3801
+ */
3802
+ function getCrossSellPrompts(role) {
3803
+ if (!isTailoredRole(role)) return NEUTRAL_CROSS_SELL;
3804
+ return CROSS_SELL_BY_ROLE[role];
3805
+ }
3806
+ //#endregion
3807
+ //#region src/ui/tui/screens/McpSuggestedPromptsScreen.tsx
3808
+ /**
3809
+ * McpSuggestedPromptsScreen — shown after MCP install succeeds in the
3810
+ * standalone `wizard mcp add` program, and as the entry point for
3811
+ * `wizard mcp tutorial`.
3812
+ *
3813
+ * Phases:
3814
+ * 1. Choose — opens with a Log in / Exit picker, framed by a
3815
+ * teaser of what MCP can do.
3816
+ * 2. Authenticating — runs `services.performLogin()` (OAuth in
3817
+ * production, canned values in the playground).
3818
+ * Renders a spinner + login URL inline while the
3819
+ * promise is pending. Errors return to Choose
3820
+ * with an inline error line.
3821
+ * 3. Greeting — role-tuned welcome via `getRoleGreeting`. A
3822
+ * ContentSequencer animates the headline,
3823
+ * bullets, and outro, then hands off to
3824
+ * PromptPicker. Only fires once per session
3825
+ * (returning via `[p]` skips it).
3826
+ * 4. PromptPicker — lists the role-tailored kit from
3827
+ * `getRolePrompts`; user picks one to run.
3828
+ * 5. Running — streams the agent's response inline via
3829
+ * `services.runPromptStreaming`. Text chunks
3830
+ * typewrite in; tool calls and results render
3831
+ * as styled badges. `[esc]` aborts; `[p]`
3832
+ * returns to the picker. On `done`/`error`,
3833
+ * auto-advances to FollowUp.
3834
+ * 6. FollowUp — surfaces 3 context-aware next prompts inferred
3835
+ * from the last tool the agent used (via
3836
+ * `getFollowUps`), plus an explicit exit.
3837
+ * Picking a follow-up re-enters Running; the
3838
+ * conversation tree grows as deep as
3839
+ * MAX_PROMPT_RUNS allows.
3840
+ *
3841
+ * Credentials are guaranteed non-null once Greeting / PromptPicker /
3842
+ * Running / FollowUp are reached (the Choose → Authenticating gate
3843
+ * forces a successful login first). A defensive throw protects the
3844
+ * Running useEffect against a state-machine bug.
3845
+ */
3846
+ const MAX_PROMPT_RUNS = 5;
3847
+ const FOLLOW_UP_DELAY_MS = 3e3;
3848
+ const McpSuggestedPromptsScreen = ({ store, services }) => {
3849
+ useSyncExternalStore((cb) => store.subscribe(cb), () => store.getSnapshot());
3850
+ const session = store.session;
3851
+ const kit = getRolePrompts(session.roleAtOrganization, session.integration);
3852
+ const crossSell = useMemo(() => getCrossSellPrompts(session.roleAtOrganization), [session.roleAtOrganization]);
3853
+ const greeting = useMemo(() => getRoleGreeting(session.roleAtOrganization), [session.roleAtOrganization]);
3854
+ const [phase, setPhase] = useState("choose");
3855
+ const [loginError, setLoginError] = useState(null);
3856
+ const [runningPrompt, setRunningPrompt] = useState(null);
3857
+ const [runChunks, setRunChunks] = useState([]);
3858
+ const [runStartedAt, setRunStartedAt] = useState(null);
3859
+ const [runDurationSecs, setRunDurationSecs] = useState(null);
3860
+ const [runCount, setRunCount] = useState(0);
3861
+ const canPickAnother = runCount < MAX_PROMPT_RUNS;
3862
+ const [lastToolName, setLastToolName] = useState(null);
3863
+ const [branchHistory, setBranchHistory] = useState([]);
3864
+ const runAbortRef = useRef(null);
3865
+ const currentSessionIdRef = useRef(null);
3866
+ useEffect(() => {
3867
+ if (phase !== "authenticating") return;
3868
+ let cancelled = false;
3869
+ (async () => {
3870
+ try {
3871
+ const { credentials, roleAtOrganization, user } = await services.performLogin();
3872
+ if (cancelled) return;
3873
+ store.setCredentials(credentials);
3874
+ store.setRoleAtOrganization(roleAtOrganization);
3875
+ store.setApiUser(user);
3876
+ store.setLoginUrl(null);
3877
+ setPhase("greeting");
3878
+ } catch (err) {
3879
+ if (cancelled) return;
3880
+ const message = err instanceof Error ? err.message : String(err);
3881
+ logToFile(`[McpSuggestedPromptsScreen] login failed: ${message}`);
3882
+ store.setLoginUrl(null);
3883
+ setLoginError(message);
3884
+ setPhase("choose");
3885
+ }
3886
+ })();
3887
+ return () => {
3888
+ cancelled = true;
3889
+ };
3890
+ }, [
3891
+ phase,
3892
+ services,
3893
+ store
3894
+ ]);
3895
+ useEffect(() => {
3896
+ if (phase !== "running") return;
3897
+ if (!runningPrompt) return;
3898
+ if (!session.credentials) throw new Error("[McpSuggestedPromptsScreen] Running phase reached without credentials. The Choose gate should have prevented this.");
3899
+ const controller = new AbortController();
3900
+ runAbortRef.current = controller;
3901
+ const startedAt = Date.now();
3902
+ setRunStartedAt(startedAt);
3903
+ setRunChunks([]);
3904
+ setLastToolName(null);
3905
+ setRunDurationSecs(null);
3906
+ const finishStream = (kind, durationMs, errorText) => {
3907
+ if (controller.signal.aborted) return;
3908
+ setRunDurationSecs(Math.round(durationMs / 1e3));
3909
+ if (kind === "done") analytics.wizardCapture("mcp suggested prompts run", {
3910
+ prompt: runningPrompt,
3911
+ durationMs
3912
+ });
3913
+ else analytics.wizardCapture("mcp suggested prompts run failed", {
3914
+ prompt: runningPrompt,
3915
+ error: errorText
3916
+ });
3917
+ setTimeout(() => {
3918
+ if (controller.signal.aborted) return;
3919
+ setPhase("follow-up");
3920
+ }, FOLLOW_UP_DELAY_MS);
3921
+ };
3922
+ (async () => {
3923
+ const credentials = session.credentials;
3924
+ if (!credentials) return;
3925
+ try {
3926
+ for await (const chunk of services.runPromptStreaming({
3927
+ prompt: runningPrompt,
3928
+ credentials,
3929
+ signal: controller.signal,
3930
+ resumeSessionId: currentSessionIdRef.current ?? void 0
3931
+ })) {
3932
+ if (controller.signal.aborted) return;
3933
+ setRunChunks((prev) => [...prev, chunk]);
3934
+ if (chunk.kind === "tool-call") setLastToolName(chunk.toolName);
3935
+ if (chunk.kind === "done") {
3936
+ if (chunk.sessionId) currentSessionIdRef.current = chunk.sessionId;
3937
+ finishStream("done", Date.now() - startedAt);
3938
+ return;
3939
+ }
3940
+ if (chunk.kind === "error") {
3941
+ finishStream("error", Date.now() - startedAt, chunk.text);
3942
+ return;
3943
+ }
3944
+ }
3945
+ } catch (err) {
3946
+ if (controller.signal.aborted) return;
3947
+ const text = err instanceof Error ? err.message : String(err);
3948
+ setRunChunks((prev) => [...prev, {
3949
+ kind: "error",
3950
+ text
3951
+ }]);
3952
+ finishStream("error", Date.now() - startedAt, text);
3953
+ }
3954
+ })();
3955
+ return () => {
3956
+ controller.abort();
3957
+ if (runAbortRef.current === controller) runAbortRef.current = null;
3958
+ };
3959
+ }, [
3960
+ phase,
3961
+ runningPrompt,
3962
+ services,
3963
+ session.credentials
3964
+ ]);
3965
+ const enterGoodbye = () => {
3966
+ runAbortRef.current?.abort();
3967
+ setPhase("goodbye");
3968
+ };
3969
+ const closeWizard = () => {
3970
+ setPhase("done");
3971
+ setTimeout(() => {
3972
+ store.setMcpSuggestedPromptsDismissed();
3973
+ }, 0);
3974
+ };
3975
+ const handleChoice = (value) => {
3976
+ const choice = Array.isArray(value) ? value[0] : value;
3977
+ setLoginError(null);
3978
+ if (choice === "login") {
3979
+ analytics.wizardCapture("mcp suggested prompts choose", { choice: "login" });
3980
+ setPhase("authenticating");
3981
+ } else {
3982
+ analytics.wizardCapture("mcp suggested prompts choose", { choice: "exit" });
3983
+ enterGoodbye();
3984
+ }
3985
+ };
3986
+ const startRun = (prompt) => {
3987
+ setRunningPrompt(prompt);
3988
+ setRunCount((c) => c + 1);
3989
+ setBranchHistory((h) => [...h, prompt]);
3990
+ setPhase("running");
3991
+ };
3992
+ const handlePromptPick = (value) => {
3993
+ startRun(Array.isArray(value) ? value[0] : value);
3994
+ };
3995
+ const handleFollowUpPick = (value) => {
3996
+ const picked = Array.isArray(value) ? value[0] : value;
3997
+ if (picked === "__follow_up_exit__") {
3998
+ analytics.wizardCapture("mcp suggested prompts follow-up", {
3999
+ choice: "exit",
4000
+ depth: branchHistory.length
4001
+ });
4002
+ enterGoodbye();
4003
+ return;
4004
+ }
4005
+ analytics.wizardCapture("mcp suggested prompts follow-up", {
4006
+ choice: "continue",
4007
+ depth: branchHistory.length,
4008
+ lastToolName
4009
+ });
4010
+ startRun(picked);
4011
+ };
4012
+ useKeyBindings("mcp-suggested-prompts", [
4013
+ {
4014
+ match: "escape",
4015
+ label: "esc",
4016
+ action: phase === "goodbye" ? "close" : "exit",
4017
+ handler: () => {
4018
+ if (phase === "goodbye") closeWizard();
4019
+ else if (phase === "running" || phase === "prompt-picker" || phase === "follow-up" || phase === "greeting") enterGoodbye();
4020
+ }
4021
+ },
4022
+ {
4023
+ match: "p",
4024
+ label: "p",
4025
+ action: canPickAnother ? "pick new prompt" : "cap reached",
4026
+ handler: () => {
4027
+ if (phase !== "running" && phase !== "follow-up") return;
4028
+ if (!canPickAnother) return;
4029
+ runAbortRef.current?.abort();
4030
+ currentSessionIdRef.current = null;
4031
+ setPhase("prompt-picker");
4032
+ }
4033
+ },
4034
+ ...phase === "greeting" ? [{
4035
+ match: "return",
4036
+ label: "enter",
4037
+ action: "continue",
4038
+ handler: () => {
4039
+ setPhase("prompt-picker");
4040
+ }
4041
+ }] : []
4042
+ ]);
4043
+ return /* @__PURE__ */ jsx(Box, {
4044
+ flexDirection: "column",
4045
+ flexGrow: 1,
4046
+ children: /* @__PURE__ */ jsxs(Box, {
4047
+ marginTop: 1,
4048
+ flexDirection: "column",
4049
+ children: [
4050
+ phase === "choose" && /* @__PURE__ */ jsx(ChoosePhase, {
4051
+ error: loginError,
4052
+ onSelect: handleChoice
4053
+ }),
4054
+ phase === "authenticating" && /* @__PURE__ */ jsx(AuthenticatingPhase, { loginUrl: session.loginUrl }),
4055
+ phase === "greeting" && /* @__PURE__ */ jsx(GreetingPhase, {
4056
+ greeting,
4057
+ userDisplayName: session.apiUser?.first_name || null,
4058
+ onComplete: () => setPhase("prompt-picker")
4059
+ }),
4060
+ phase === "prompt-picker" && /* @__PURE__ */ jsx(PromptPickerPhase, {
4061
+ promptKit: kit,
4062
+ crossSell,
4063
+ onSelect: handlePromptPick
4064
+ }),
4065
+ phase === "running" && runningPrompt && /* @__PURE__ */ jsx(RunningPhase, {
4066
+ prompt: runningPrompt,
4067
+ chunks: runChunks,
4068
+ startedAt: runStartedAt,
4069
+ frozenDurationSecs: runDurationSecs,
4070
+ runCount,
4071
+ maxRuns: MAX_PROMPT_RUNS
4072
+ }),
4073
+ phase === "follow-up" && /* @__PURE__ */ jsxs(Box, {
4074
+ flexDirection: "column",
4075
+ flexGrow: 1,
4076
+ children: [runningPrompt && /* @__PURE__ */ jsx(Box, {
4077
+ flexDirection: "column",
4078
+ flexShrink: 1,
4079
+ children: /* @__PURE__ */ jsx(RunningPhase, {
4080
+ prompt: runningPrompt,
4081
+ chunks: runChunks,
4082
+ startedAt: runStartedAt,
4083
+ frozenDurationSecs: runDurationSecs,
4084
+ runCount,
4085
+ maxRuns: MAX_PROMPT_RUNS
4086
+ })
4087
+ }), /* @__PURE__ */ jsx(Box, {
4088
+ marginTop: 1,
4089
+ flexShrink: 0,
4090
+ flexDirection: "column",
4091
+ children: /* @__PURE__ */ jsx(FollowUpPhase, {
4092
+ lastToolName,
4093
+ lastPrompt: runningPrompt,
4094
+ chunks: runChunks,
4095
+ role: session.roleAtOrganization,
4096
+ branchHistory,
4097
+ canPickAnother,
4098
+ maxRuns: MAX_PROMPT_RUNS,
4099
+ onSelect: handleFollowUpPick
4100
+ })
4101
+ })]
4102
+ }),
4103
+ phase === "goodbye" && /* @__PURE__ */ jsx(GoodbyePhase, {
4104
+ installedClients: session.mcpInstalledClients,
4105
+ role: session.roleAtOrganization,
4106
+ integration: session.integration,
4107
+ engaged: branchHistory.length > 0,
4108
+ onClose: closeWizard
4109
+ })
4110
+ ]
4111
+ })
4112
+ });
4113
+ };
4114
+ const ChoosePhase = ({ error, onSelect }) => /* @__PURE__ */ jsxs(Box, {
4115
+ flexDirection: "column",
3014
4116
  children: [
3015
4117
  /* @__PURE__ */ jsx(Text, {
3016
4118
  bold: true,
@@ -3093,56 +4195,109 @@ const AuthenticatingPhase = ({ loginUrl }) => /* @__PURE__ */ jsxs(Box, {
3093
4195
  ] })
3094
4196
  })]
3095
4197
  });
3096
- const PromptPickerPhase = ({ promptKit, userDisplayName, onSelect }) => {
3097
- const options = promptKit.map((p) => ({
3098
- label: p.prompt,
3099
- value: p.prompt
3100
- }));
3101
- return /* @__PURE__ */ jsx(Box, {
4198
+ const GreetingPhase = ({ greeting, userDisplayName, onComplete }) => {
4199
+ const blocks = [];
4200
+ if (userDisplayName) blocks.push({
4201
+ content: `Hi ${userDisplayName}!`,
4202
+ mode: 0,
4203
+ animationInterval: 70,
4204
+ pause: 1200
4205
+ });
4206
+ blocks.push({
4207
+ content: greeting.headline,
4208
+ mode: 0,
4209
+ animationInterval: 45,
4210
+ pause: 2e3
4211
+ });
4212
+ blocks.push({
4213
+ type: "lines",
4214
+ lines: greeting.bullets.map((bullet, i) => /* @__PURE__ */ jsxs(Text, { children: [
4215
+ /* @__PURE__ */ jsx(Text, {
4216
+ color: Colors.primary,
4217
+ children: Icons.diamond
4218
+ }),
4219
+ " ",
4220
+ /* @__PURE__ */ jsx(Text, {
4221
+ dimColor: true,
4222
+ children: bullet
4223
+ })
4224
+ ] }, i)),
4225
+ interval: 700,
4226
+ pause: 2200
4227
+ });
4228
+ blocks.push({
4229
+ content: greeting.outro,
4230
+ mode: 0,
4231
+ animationInterval: 38,
4232
+ pause: 1800
4233
+ });
4234
+ return /* @__PURE__ */ jsxs(Box, {
3102
4235
  flexDirection: "column",
3103
- children: /* @__PURE__ */ jsx(ContentSequencer, {
3104
- blocks: [
3105
- {
3106
- content: `Hello there, ${userDisplayName || "there"}!`,
3107
- mode: 0,
3108
- animationInterval: 100,
3109
- pause: 1200,
3110
- dimWhenComplete: false
3111
- },
3112
- {
3113
- content: "Pick a prompt to see the PostHog MCP in action.",
3114
- mode: 0,
3115
- animationInterval: 50,
3116
- pause: 1e3,
3117
- dimWhenComplete: false
3118
- },
3119
- {
3120
- content: /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(PickerMenu, {
3121
- options,
3122
- optionMarginBottom: 1,
3123
- onSelect
3124
- }), /* @__PURE__ */ jsx(Box, {
3125
- marginTop: 2,
3126
- children: /* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
3127
- bold: true,
3128
- children: "[esc]"
3129
- }), /* @__PURE__ */ jsx(Text, { children: " to exit" })] })
3130
- })] }),
3131
- persist: true
3132
- }
3133
- ],
4236
+ children: [/* @__PURE__ */ jsx(Box, {
4237
+ marginBottom: 1,
4238
+ children: /* @__PURE__ */ jsx(Text, {
4239
+ bold: true,
4240
+ color: Colors.accent,
4241
+ children: "MCP tutorial"
4242
+ })
4243
+ }), /* @__PURE__ */ jsx(ContentSequencer, {
4244
+ blocks,
3134
4245
  mode: 0,
3135
- blockInterval: 350
3136
- })
4246
+ blockInterval: 500,
4247
+ onSequenceComplete: onComplete
4248
+ })]
4249
+ });
4250
+ };
4251
+ const PromptPickerPhase = ({ promptKit, crossSell, onSelect }) => {
4252
+ const seenPrompts = /* @__PURE__ */ new Set();
4253
+ const options = [
4254
+ PINNED_FIRST_PROMPT,
4255
+ ...crossSell,
4256
+ ...promptKit
4257
+ ].filter((o) => {
4258
+ if (seenPrompts.has(o.prompt)) return false;
4259
+ seenPrompts.add(o.prompt);
4260
+ return true;
4261
+ }).slice(0, 4).map((o) => ({
4262
+ label: o.product ? `Try ${o.product} — ${o.label ?? o.prompt}` : o.label ?? o.prompt,
4263
+ value: o.prompt
4264
+ }));
4265
+ return /* @__PURE__ */ jsxs(Box, {
4266
+ flexDirection: "column",
4267
+ children: [
4268
+ /* @__PURE__ */ jsx(Box, {
4269
+ marginBottom: 1,
4270
+ children: /* @__PURE__ */ jsx(Text, {
4271
+ bold: true,
4272
+ color: Colors.accent,
4273
+ children: "MCP tutorial"
4274
+ })
4275
+ }),
4276
+ /* @__PURE__ */ jsx(Box, {
4277
+ marginBottom: 1,
4278
+ children: /* @__PURE__ */ jsx(Text, { children: "Pick a prompt to see the PostHog MCP in action." })
4279
+ }),
4280
+ /* @__PURE__ */ jsx(PickerMenu, {
4281
+ options,
4282
+ optionMarginBottom: 1,
4283
+ onSelect
4284
+ }),
4285
+ /* @__PURE__ */ jsx(Box, {
4286
+ marginTop: 2,
4287
+ children: /* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
4288
+ bold: true,
4289
+ children: "[esc]"
4290
+ }), /* @__PURE__ */ jsx(Text, { children: " to exit" })] })
4291
+ })
4292
+ ]
3137
4293
  });
3138
4294
  };
3139
- const RunningPhase = ({ prompt, chunks, startedAt, canPickAnother, runCount, maxRuns }) => {
4295
+ const RunningPhase = ({ prompt, chunks, startedAt, frozenDurationSecs, runCount, maxRuns }) => {
3140
4296
  const isDone = chunks.some((c) => c.kind === "done");
3141
4297
  const errorChunk = chunks.find((c) => c.kind === "error");
3142
4298
  const finished = isDone || !!errorChunk;
3143
- const elapsed = startedAt ? Math.round((Date.now() - startedAt) / 1e3) : 0;
3144
- const visibleChunks = finished ? chunks.filter((c) => c.kind === "text" || c.kind === "error") : chunks;
3145
- const cappedChunks = finished ? capTextChunks(visibleChunks) : visibleChunks;
4299
+ const elapsed = frozenDurationSecs ?? (startedAt ? Math.round((Date.now() - startedAt) / 1e3) : 0);
4300
+ const visibleChunks = finished ? capTextChunks(collapseToFinalAnswer(chunks)) : chunks;
3146
4301
  return /* @__PURE__ */ jsxs(Box, {
3147
4302
  flexDirection: "column",
3148
4303
  children: [
@@ -3181,52 +4336,63 @@ const RunningPhase = ({ prompt, chunks, startedAt, canPickAnother, runCount, max
3181
4336
  /* @__PURE__ */ jsx(Box, {
3182
4337
  marginTop: 1,
3183
4338
  flexDirection: "column",
3184
- children: cappedChunks.map((chunk, idx) => /* @__PURE__ */ jsx(ChunkLine, { chunk }, idx))
3185
- }),
3186
- finished && !canPickAnother && /* @__PURE__ */ jsx(Box, {
3187
- marginTop: 1,
3188
- children: /* @__PURE__ */ jsxs(Text, { children: [
3189
- /* @__PURE__ */ jsxs(Text, {
3190
- dimColor: true,
3191
- children: [
3192
- "You've hit the ",
3193
- maxRuns,
3194
- "-prompt tutorial cap. Press",
3195
- " "
3196
- ]
3197
- }),
3198
- /* @__PURE__ */ jsx(Text, {
3199
- bold: true,
3200
- dimColor: true,
3201
- children: "[esc]"
3202
- }),
3203
- /* @__PURE__ */ jsx(Text, {
3204
- dimColor: true,
3205
- children: " to exit."
3206
- })
3207
- ] })
4339
+ children: visibleChunks.map((chunk, idx) => /* @__PURE__ */ jsx(ChunkLine, { chunk }, idx))
3208
4340
  })
3209
4341
  ]
3210
4342
  });
3211
4343
  };
3212
4344
  /**
4345
+ * Strip everything except the agent's final answer + any error chunks.
4346
+ * Drops tool-call / tool-result chatter (their work is done once the
4347
+ * stream completes) and any text blocks emitted BEFORE the last text
4348
+ * block — those are typically Sonnet's "I'll query X…" preamble that
4349
+ * arrives alongside the first tool_use and adds noise above the picker.
4350
+ *
4351
+ * If the run produced no text at all (pure tool calls, or only errors),
4352
+ * fall through to whatever chunks survived so the user isn't left with
4353
+ * a blank result.
4354
+ */
4355
+ function collapseToFinalAnswer(chunks) {
4356
+ const textChunks = chunks.filter((c) => c.kind === "text");
4357
+ const errors = chunks.filter((c) => c.kind === "error");
4358
+ if (textChunks.length === 0) return errors;
4359
+ return [textChunks[textChunks.length - 1], ...errors];
4360
+ }
4361
+ /**
3213
4362
  * Belt-and-suspenders fallback for runs where Claude ignored the
3214
4363
  * terminal-fit system prompt and produced an overlong response. Joins
3215
- * all text chunks, slices to the last N lines that fit in the current
3216
- * terminal, and prepends an indicator showing how many lines got cut.
3217
- * Errors are preserved separately so failures don't disappear into the
3218
- * truncation.
4364
+ * all text chunks, then walks them from the bottom keeping only as many
4365
+ * lines as fit in the visual row budget — wide lines that wrap to
4366
+ * multiple rows on a narrow terminal cost their wrapped row count, not
4367
+ * 1. Prepends an indicator showing how many source lines got cut. Tool
4368
+ * calls, results, and errors are preserved separately so they don't
4369
+ * disappear into the truncation.
4370
+ *
4371
+ * Visual-row-aware truncation is what makes the FollowUp picker feel
4372
+ * pinned: a 5-row table that wraps to 12 visual rows on a 60-col
4373
+ * terminal correctly counts as 12, so the cap leaves exactly the room
4374
+ * the picker needs.
3219
4375
  */
3220
4376
  function capTextChunks(chunks) {
3221
4377
  const rows = process.stdout.rows ?? 24;
3222
- const maxMessageRows = Math.max(6, rows - 8);
4378
+ const cols = process.stdout.columns ?? 120;
4379
+ const maxVisualRows = Math.max(3, rows - 19);
3223
4380
  const textChunks = chunks.filter((c) => c.kind === "text");
3224
4381
  const errors = chunks.filter((c) => c.kind === "error");
3225
4382
  if (textChunks.length === 0) return chunks;
3226
4383
  const lines = textChunks.map((c) => c.text).join("").split("\n");
3227
- if (lines.length <= maxMessageRows) return chunks;
3228
- const hidden = lines.length - maxMessageRows;
3229
- const tail = lines.slice(-maxMessageRows).join("\n");
4384
+ const visualRows = (line) => Math.max(1, Math.ceil(line.length / cols));
4385
+ let used = 0;
4386
+ let keepFrom = lines.length;
4387
+ for (let i = lines.length - 1; i >= 0; i--) {
4388
+ const cost = visualRows(lines[i]);
4389
+ if (used + cost > maxVisualRows) break;
4390
+ used += cost;
4391
+ keepFrom = i;
4392
+ }
4393
+ if (keepFrom === 0) return chunks;
4394
+ const hidden = keepFrom;
4395
+ const tail = lines.slice(keepFrom).join("\n");
3230
4396
  return [{
3231
4397
  kind: "text",
3232
4398
  text: `[${hidden} line${hidden === 1 ? "" : "s"} above — expand terminal to see more]\n\n${tail}`
@@ -3257,6 +4423,101 @@ const ChunkLine = ({ chunk }) => {
3257
4423
  });
3258
4424
  return null;
3259
4425
  };
4426
+ const FollowUpPhase = ({ lastToolName, lastPrompt, chunks, role, branchHistory, canPickAnother, maxRuns, onSelect }) => {
4427
+ const followUps = useMemo(() => getFollowUps({
4428
+ lastToolName,
4429
+ lastPrompt: lastPrompt || "",
4430
+ role,
4431
+ branchHistory
4432
+ }), [
4433
+ lastToolName,
4434
+ lastPrompt,
4435
+ role,
4436
+ branchHistory
4437
+ ]);
4438
+ const options = canPickAnother ? followUps.map((f) => ({
4439
+ label: f.label ?? f.prompt,
4440
+ value: f.prompt
4441
+ })) : [{
4442
+ label: "Exit",
4443
+ value: FOLLOW_UP_EXIT_SENTINEL
4444
+ }];
4445
+ return /* @__PURE__ */ jsxs(Box, {
4446
+ flexDirection: "column",
4447
+ children: [/* @__PURE__ */ jsx(Text, { children: chunks.find((c) => c.kind === "error") ? "That one errored out — try a different angle?" : !canPickAnother ? `You've hit the ${maxRuns}-prompt tutorial cap.` : `Want to keep exploring? Select a follow-up prompt.` }), /* @__PURE__ */ jsx(PickerMenu, {
4448
+ options,
4449
+ onSelect
4450
+ })]
4451
+ });
4452
+ };
4453
+ const GoodbyePhase = ({ installedClients, role, integration, engaged, onClose }) => {
4454
+ const samples = getRolePrompts(role, integration).slice(0, 3);
4455
+ const headline = engaged ? "Nice work. You can keep talking to PostHog anytime." : "You're all set — PostHog MCP is here when you're ready.";
4456
+ const introLine = installedClients.length > 0 ? /* @__PURE__ */ jsxs(Text, { children: [
4457
+ "MCP is set up in",
4458
+ " ",
4459
+ /* @__PURE__ */ jsx(Text, {
4460
+ bold: true,
4461
+ color: Colors.primary,
4462
+ children: installedClients.join(", ")
4463
+ }),
4464
+ ". Open one and try a prompt like:"
4465
+ ] }) : /* @__PURE__ */ jsx(Text, { children: "Wherever you have MCP set up (Claude Code, Cursor, VS Code, Windsurf, Zed, etc.), open the agent and try a prompt like:" });
4466
+ return /* @__PURE__ */ jsxs(Box, {
4467
+ flexDirection: "column",
4468
+ children: [
4469
+ /* @__PURE__ */ jsx(Box, {
4470
+ marginBottom: 1,
4471
+ children: /* @__PURE__ */ jsx(Text, {
4472
+ bold: true,
4473
+ color: Colors.accent,
4474
+ children: headline
4475
+ })
4476
+ }),
4477
+ /* @__PURE__ */ jsx(Box, {
4478
+ marginBottom: 1,
4479
+ children: introLine
4480
+ }),
4481
+ /* @__PURE__ */ jsx(Box, {
4482
+ marginBottom: 1,
4483
+ flexDirection: "column",
4484
+ children: samples.map((p, i) => /* @__PURE__ */ jsxs(Box, { children: [
4485
+ /* @__PURE__ */ jsx(Text, {
4486
+ color: Colors.primary,
4487
+ children: Icons.triangleSmallRight
4488
+ }),
4489
+ /* @__PURE__ */ jsx(Text, { children: " " }),
4490
+ /* @__PURE__ */ jsx(Text, {
4491
+ dimColor: true,
4492
+ children: p.prompt
4493
+ })
4494
+ ] }, i))
4495
+ }),
4496
+ /* @__PURE__ */ jsx(Box, {
4497
+ marginBottom: 1,
4498
+ children: /* @__PURE__ */ jsxs(Text, {
4499
+ dimColor: true,
4500
+ children: [
4501
+ "Re-run this tutorial anytime with",
4502
+ " ",
4503
+ /* @__PURE__ */ jsx(Text, {
4504
+ bold: true,
4505
+ children: "npx @posthog/wizard mcp tutorial"
4506
+ }),
4507
+ "."
4508
+ ]
4509
+ })
4510
+ }),
4511
+ /* @__PURE__ */ jsx(PickerMenu, {
4512
+ options: [{
4513
+ label: "Close",
4514
+ value: "close"
4515
+ }],
4516
+ onSelect: onClose
4517
+ })
4518
+ ]
4519
+ });
4520
+ };
3260
4521
  //#endregion
3261
4522
  //#region src/ui/tui/screens/audit/AuditChecksViewer/AreaHeaderRow.tsx
3262
4523
  /** Sub-header row inside the scrollable body — one per area group. */
@@ -4120,4 +5381,4 @@ const AUDIT_3000_AREA_SLIDES = [
4120
5381
  //#endregion
4121
5382
  export { WizardStore as A, useStdoutDimensions as C, LoadingBox as D, ProgressList as E, SplitView as O, GroupedPickerMenu as S, useKeyBindings as T, ScreenContainer as _, McpSuggestedPromptsScreen as a, ModalOverlay as b, IssueTable as c, ServiceHealthList as d, TipsCard as f, TabContainer as g, HNViewer as h, AuditChecksViewer as i, CardLayout as k, SEVERITY_LABEL as l, ContentSequencer as m, AUDIT_AREA_SLIDES as n, TAILORED_ROLES as o, LearnCard as p, VisualBox as r, McpScreen as s, AUDIT_3000_AREA_SLIDES as t, SEVERITY_ORDER as u, EventPlanViewer as v, PickerMenu as w, ConfirmationInput as x, LogViewer as y };
4122
5383
 
4123
- //# sourceMappingURL=slides-CL1mv_Kq.js.map
5384
+ //# sourceMappingURL=slides-DwvXZ8iS.js.map