@posthog/wizard 2.14.3 → 2.16.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 (94) hide show
  1. package/README.md +43 -1
  2. package/dist/{TextBlock-DEHERFec.js → TextBlock-DJVhBkr3.js} +4 -4
  3. package/dist/TextBlock-DJVhBkr3.js.map +1 -0
  4. package/dist/{add-mcp-server-to-clients-B48J7VVO.js → add-mcp-server-to-clients-9jQjc-CO.js} +5 -5
  5. package/dist/{add-mcp-server-to-clients-B48J7VVO.js.map → add-mcp-server-to-clients-9jQjc-CO.js.map} +1 -1
  6. package/dist/{agent-interface-cEdS_bNo.js → agent-interface-pBnqJL8P.js} +106 -21
  7. package/dist/agent-interface-pBnqJL8P.js.map +1 -0
  8. package/dist/{agent-runner-CK5r-zQF.js → agent-runner-H1FP6XTc.js} +12 -9
  9. package/dist/agent-runner-H1FP6XTc.js.map +1 -0
  10. package/dist/{analytics-DaDpDus8.js → analytics-DZaUgJte.js} +2 -2
  11. package/dist/{analytics-DaDpDus8.js.map → analytics-DZaUgJte.js.map} +1 -1
  12. package/dist/analytics-DqeW7XYt.js +2 -0
  13. package/dist/bin.js +965 -83
  14. package/dist/bin.js.map +1 -1
  15. package/dist/{debug-B_PK52GI.js → debug-B6rX6xye.js} +1 -1
  16. package/dist/{debug-BOogNcWX.js → debug-C4jRuzny.js} +57 -46
  17. package/dist/debug-C4jRuzny.js.map +1 -0
  18. package/dist/{defaults-DgKAzsD1.js → defaults-GbLPuHxj.js} +1 -1
  19. package/dist/{defaults-DgKAzsD1.js.map → defaults-GbLPuHxj.js.map} +1 -1
  20. package/dist/{detection-OCF8fpfp.js → detection-4eukp9HD.js} +3 -3
  21. package/dist/{detection-OCF8fpfp.js.map → detection-4eukp9HD.js.map} +1 -1
  22. package/dist/{env-api-key-D5G2PrXW.js → env-api-key-DU8uIEvo.js} +1 -1
  23. package/dist/{env-api-key-D5G2PrXW.js.map → env-api-key-DU8uIEvo.js.map} +1 -1
  24. package/dist/{file-utils-DPmgn9Vm.js → file-utils-DnTSiTJw.js} +1 -1
  25. package/dist/file-utils-DnTSiTJw.js.map +1 -0
  26. package/dist/mcp-prompt-streaming-DKiaymMt.js +200 -0
  27. package/dist/mcp-prompt-streaming-DKiaymMt.js.map +1 -0
  28. package/dist/package-json-Cttzi3C8.js +2 -0
  29. package/dist/package-json-v_g2YlN1.js +35 -0
  30. package/dist/package-json-v_g2YlN1.js.map +1 -0
  31. package/dist/{package-manager-CmMJAD-V.js → package-manager-DLt75bit.js} +2 -2
  32. package/dist/package-manager-DLt75bit.js.map +1 -0
  33. package/dist/posthog-7B92c2Ed.js +120 -0
  34. package/dist/posthog-7B92c2Ed.js.map +1 -0
  35. package/dist/{posthog-integration-By5930Gz.js → posthog-integration-CukaeYil.js} +13 -12
  36. package/dist/{posthog-integration-By5930Gz.js.map → posthog-integration-CukaeYil.js.map} +1 -1
  37. package/dist/{provisioning-BHa8VWaa.js → provisioning-C_ETLiZE.js} +3 -3
  38. package/dist/{provisioning-BHa8VWaa.js.map → provisioning-C_ETLiZE.js.map} +1 -1
  39. package/dist/provisioning-Ch6i8dRV.js +2 -0
  40. package/dist/{registry-DpROZPnl.js → registry-DqbwO5EL.js} +31 -31
  41. package/dist/registry-DqbwO5EL.js.map +1 -0
  42. package/dist/setup-utils-C5uZ9g60.js +2 -0
  43. package/dist/{setup-utils-Mzpk1vqG.js → setup-utils-DdAdxUTV.js} +170 -60
  44. package/dist/setup-utils-DdAdxUTV.js.map +1 -0
  45. package/dist/{slides-BtDXEXdn.js → slides-Dpj4j0w_.js} +580 -27
  46. package/dist/slides-Dpj4j0w_.js.map +1 -0
  47. package/dist/smoke-test-ci.sh +5 -2
  48. package/dist/smoke-test.sh +43 -0
  49. package/dist/{start-playground-zZL5y9id.js → start-playground-B40O4tye.js} +288 -6
  50. package/dist/start-playground-B40O4tye.js.map +1 -0
  51. package/dist/{start-tui-Cz7RZSn_.js → start-tui-CH_ZzQXx.js} +628 -26
  52. package/dist/start-tui-CH_ZzQXx.js.map +1 -0
  53. package/dist/{steps-C2XEzN79.js → steps-0d9XqvI6.js} +6 -6
  54. package/dist/{steps-C2XEzN79.js.map → steps-0d9XqvI6.js.map} +1 -1
  55. package/dist/task-stream-CoEsidgG.js +195 -0
  56. package/dist/task-stream-CoEsidgG.js.map +1 -0
  57. package/dist/{telemetry-BG2bOwCp.js → telemetry-jn2Daxl2.js} +2 -2
  58. package/dist/{telemetry-BG2bOwCp.js.map → telemetry-jn2Daxl2.js.map} +1 -1
  59. package/dist/{wizard-abort-BmT-F0Vr.js → wizard-abort-BjLIgu2s.js} +3 -3
  60. package/dist/{wizard-abort-BmT-F0Vr.js.map → wizard-abort-BjLIgu2s.js.map} +1 -1
  61. package/dist/{wizard-abort-CYW83OG5.js → wizard-abort-BlYGA1Jk.js} +1 -1
  62. package/dist/{wizard-session-CsI33S4_.js → wizard-session-Bi95IYca.js} +19 -2
  63. package/dist/wizard-session-Bi95IYca.js.map +1 -0
  64. package/dist/wizard-session-DPGTaJ4W.js +2 -0
  65. package/dist/wizard-ui-YdGFRyu_.js.map +1 -1
  66. package/package.json +3 -2
  67. package/dist/TextBlock-DEHERFec.js.map +0 -1
  68. package/dist/agent-interface-cEdS_bNo.js.map +0 -1
  69. package/dist/agent-runner-CK5r-zQF.js.map +0 -1
  70. package/dist/analytics-Bw8E-yhX.js +0 -2
  71. package/dist/craft-pre-release.sh +0 -10
  72. package/dist/debug-BOogNcWX.js.map +0 -1
  73. package/dist/file-BKbKreWF.js +0 -16
  74. package/dist/file-BKbKreWF.js.map +0 -1
  75. package/dist/file-utils-DPmgn9Vm.js.map +0 -1
  76. package/dist/package-json-DZpnf6vU.js +0 -23
  77. package/dist/package-json-DZpnf6vU.js.map +0 -1
  78. package/dist/package-json-_4PEss19.js +0 -2
  79. package/dist/package-manager-CmMJAD-V.js.map +0 -1
  80. package/dist/paths-DJS47p5x.js +0 -26
  81. package/dist/paths-DJS47p5x.js.map +0 -1
  82. package/dist/posthog-BbQf_Hzq.js +0 -11
  83. package/dist/posthog-BbQf_Hzq.js.map +0 -1
  84. package/dist/provisioning-gHqu_MXL.js +0 -2
  85. package/dist/registry-DpROZPnl.js.map +0 -1
  86. package/dist/setup-utils-Mzpk1vqG.js.map +0 -1
  87. package/dist/setup-utils-ptemIB6g.js +0 -2
  88. package/dist/slides-BtDXEXdn.js.map +0 -1
  89. package/dist/start-playground-zZL5y9id.js.map +0 -1
  90. package/dist/start-tui-Cz7RZSn_.js.map +0 -1
  91. package/dist/task-stream-DUpUZmFQ.js +0 -61
  92. package/dist/task-stream-DUpUZmFQ.js.map +0 -1
  93. package/dist/wizard-session-CPhhll4P.js +0 -2
  94. package/dist/wizard-session-CsI33S4_.js.map +0 -1
@@ -1,11 +1,11 @@
1
- import { d as SERVICE_LABELS } from "./debug-BOogNcWX.js";
1
+ import { g as SERVICE_LABELS, s as logToFile } from "./debug-C4jRuzny.js";
2
2
  import { n as isTaskStatus } from "./wizard-ui-YdGFRyu_.js";
3
- import { n as analytics, r as sessionProperties } from "./analytics-DaDpDus8.js";
4
- import { r as buildSession } from "./wizard-session-CsI33S4_.js";
5
- import { _ as AUDIT_SEVERITY_STYLE } from "./agent-interface-cEdS_bNo.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-DEHERFec.js";
7
- import { a as getKindMeta, n as Program, r as getProgramConfig, t as PROGRAM_REGISTRY } from "./bin.js";
8
- import { n as AVAILABLE_FEATURES, t as ALL_FEATURE_VALUES } from "./defaults-DgKAzsD1.js";
3
+ import { n as analytics, r as sessionProperties } from "./analytics-DZaUgJte.js";
4
+ import { i as buildSession } from "./wizard-session-Bi95IYca.js";
5
+ import { _ as AUDIT_SEVERITY_STYLE } from "./agent-interface-pBnqJL8P.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-DJVhBkr3.js";
7
+ import { n as Program, r as getProgramConfig, s as getKindMeta, t as PROGRAM_REGISTRY } from "./bin.js";
8
+ import { n as AVAILABLE_FEATURES, t as ALL_FEATURE_VALUES } from "./defaults-GbLPuHxj.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";
@@ -144,6 +144,8 @@ var WizardStore = class {
144
144
  _backupAndFixSettings = null;
145
145
  /** Blocks OAuth flow until the port-conflict overlay is dismissed. */
146
146
  _resolvePortConflict = null;
147
+ /** Resolves the OAuth flow with a manually-entered authorization code. */
148
+ _resolveManualAuthCode = null;
147
149
  /** Resolves the in-flight wizard_ask request. */
148
150
  _resolvePendingQuestion = null;
149
151
  constructor(program = Program.PostHogIntegration) {
@@ -272,6 +274,14 @@ var WizardStore = class {
272
274
  analytics.wizardCapture("auth complete", { project_id: credentials?.projectId });
273
275
  this.emitChange();
274
276
  }
277
+ setRoleAtOrganization(role) {
278
+ this.$session.setKey("roleAtOrganization", role);
279
+ this.emitChange();
280
+ }
281
+ setApiUser(user) {
282
+ this.$session.setKey("apiUser", user);
283
+ this.emitChange();
284
+ }
275
285
  setFrameworkConfig(integration, config) {
276
286
  this.$session.setKey("integration", integration);
277
287
  this.$session.setKey("frameworkConfig", config);
@@ -294,6 +304,10 @@ var WizardStore = class {
294
304
  this.$session.setKey("loginUrl", url);
295
305
  this.emitChange();
296
306
  }
307
+ setAuthorizeUrl(url) {
308
+ this.$session.setKey("authorizeUrl", url);
309
+ this.emitChange();
310
+ }
297
311
  setReadinessResult(result) {
298
312
  this.$session.setKey("readinessResult", result);
299
313
  this.emitChange();
@@ -337,6 +351,33 @@ var WizardStore = class {
337
351
  this._resolvePortConflict = null;
338
352
  }
339
353
  /**
354
+ * Return a promise that resolves when the user submits a manually-entered
355
+ * OAuth code via the paste modal. The OAuth flow races this against the
356
+ * local callback server — see `performOAuthFlow`.
357
+ */
358
+ waitForManualAuthCode() {
359
+ return new Promise((resolve) => {
360
+ this._resolveManualAuthCode = resolve;
361
+ });
362
+ }
363
+ /** Open the manual OAuth code-entry overlay over the auth screen. */
364
+ showManualAuthCode() {
365
+ this.pushOverlay("manual-auth-code");
366
+ }
367
+ /** Dismiss the manual OAuth code overlay without submitting. */
368
+ dismissManualAuthCode() {
369
+ this.popOverlay();
370
+ }
371
+ /**
372
+ * Submit a manually-entered authorization code: dismiss the overlay and
373
+ * resolve the in-flight OAuth flow so it can exchange the code for a token.
374
+ */
375
+ submitManualAuthCode(code) {
376
+ this.popOverlay();
377
+ this._resolveManualAuthCode?.(code);
378
+ this._resolveManualAuthCode = null;
379
+ }
380
+ /**
340
381
  * Open the WizardAsk overlay with a set of questions and return a promise
341
382
  * that resolves once the user submits answers (or the request is cancelled).
342
383
  *
@@ -433,6 +474,10 @@ var WizardStore = class {
433
474
  });
434
475
  this.emitChange();
435
476
  }
477
+ setMcpSuggestedPromptsDismissed() {
478
+ this.$session.setKey("mcpSuggestedPromptsDismissed", true);
479
+ this.emitChange();
480
+ }
436
481
  setOutroDismissed() {
437
482
  this.$session.setKey("outroDismissed", true);
438
483
  this.emitChange();
@@ -855,12 +900,13 @@ function useKeyBindings(id, bindings) {
855
900
  * Key bindings are declared via useKeyBindings, which auto-registers
856
901
  * hints in the KeyboardHintsBar.
857
902
  */
858
- const PickerMenu = ({ message, options, mode = "single", centered = false, columns = 1, onSelect }) => {
903
+ const PickerMenu = ({ message, options, mode = "single", centered = false, columns = 1, optionMarginBottom = 0, onSelect }) => {
859
904
  if (mode === "multi") return /* @__PURE__ */ jsx(MultiPickerMenu, {
860
905
  message,
861
906
  options,
862
907
  centered,
863
908
  columns,
909
+ optionMarginBottom,
864
910
  onSelect
865
911
  });
866
912
  return /* @__PURE__ */ jsx(SinglePickerMenu, {
@@ -868,11 +914,12 @@ const PickerMenu = ({ message, options, mode = "single", centered = false, colum
868
914
  options,
869
915
  centered,
870
916
  columns,
917
+ optionMarginBottom,
871
918
  onSelect
872
919
  });
873
920
  };
874
921
  /** Custom single-select with triangle indicator and accent highlight. */
875
- const SinglePickerMenu = ({ message, options, centered = false, columns = 1, onSelect }) => {
922
+ const SinglePickerMenu = ({ message, options, centered = false, columns = 1, optionMarginBottom = 0, onSelect }) => {
876
923
  const [focused, setFocused] = useState(0);
877
924
  const rows = Math.ceil(options.length / columns);
878
925
  const bindings = [{
@@ -933,6 +980,7 @@ const SinglePickerMenu = ({ message, options, centered = false, columns = 1, onS
933
980
  const label = opt.hint ? `${opt.label} (${opt.hint})` : opt.label;
934
981
  return /* @__PURE__ */ jsxs(Box, {
935
982
  gap: 1,
983
+ marginBottom: optionMarginBottom,
936
984
  children: [/* @__PURE__ */ jsx(Text, {
937
985
  color: isFocused ? Colors.accent : void 0,
938
986
  dimColor: !isFocused,
@@ -950,7 +998,7 @@ const SinglePickerMenu = ({ message, options, centered = false, columns = 1, onS
950
998
  });
951
999
  };
952
1000
  /** Custom multi-select with checkbox glyphs and accent highlight. */
953
- const MultiPickerMenu = ({ message, options, centered = false, columns = 1, onSelect }) => {
1001
+ const MultiPickerMenu = ({ message, options, centered = false, columns = 1, optionMarginBottom = 0, onSelect }) => {
954
1002
  const [focused, setFocused] = useState(0);
955
1003
  const [selected, setSelected] = useState(/* @__PURE__ */ new Set());
956
1004
  const rows = Math.ceil(options.length / columns);
@@ -1034,6 +1082,7 @@ const MultiPickerMenu = ({ message, options, centered = false, columns = 1, onSe
1034
1082
  const checkbox = isSelected ? Icons.squareFilled : Icons.squareOpen;
1035
1083
  return /* @__PURE__ */ jsxs(Box, {
1036
1084
  gap: 1,
1085
+ marginBottom: optionMarginBottom,
1037
1086
  children: [/* @__PURE__ */ jsx(Text, {
1038
1087
  color: isSelected ? "white" : Colors.muted,
1039
1088
  dimColor: !isFocused && !isSelected,
@@ -2151,7 +2200,8 @@ const BlockRenderer = ({ block, active, completed, onComplete, mode, bullet, ani
2151
2200
  animationInterval: block.animationInterval ?? animationInterval,
2152
2201
  sentenceInterval: block.sentenceInterval ?? sentenceInterval,
2153
2202
  maxHeight,
2154
- availableWidth
2203
+ availableWidth,
2204
+ dimWhenComplete: block.dimWhenComplete ?? true
2155
2205
  });
2156
2206
  return /* @__PURE__ */ jsx(NodeBlock, {
2157
2207
  content: block.content,
@@ -2589,10 +2639,10 @@ const McpScreen = ({ store, installer, mode = "install" }) => {
2589
2639
  return /* @__PURE__ */ jsxs(Box, {
2590
2640
  flexDirection: "column",
2591
2641
  flexGrow: 1,
2592
- children: [/* @__PURE__ */ jsxs(Text, {
2642
+ children: [/* @__PURE__ */ jsx(Text, {
2593
2643
  bold: true,
2594
2644
  color: Colors.accent,
2595
- children: ["MCP Server ", isRemove ? "Removal" : "Setup"]
2645
+ children: isRemove ? "Remove the PostHog MCP" : "Install the MCP so you can chat to your data"
2596
2646
  }), /* @__PURE__ */ jsxs(Box, {
2597
2647
  marginTop: 1,
2598
2648
  flexDirection: "column",
@@ -2609,19 +2659,38 @@ const McpScreen = ({ store, installer, mode = "install" }) => {
2609
2659
  " MCP clients detected. Skipping..."
2610
2660
  ]
2611
2661
  }),
2612
- phase === "ask" && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs(Text, {
2613
- dimColor: true,
2614
- children: ["Detected: ", clients.map((c) => c.name).join(", ")]
2615
- }), /* @__PURE__ */ jsx(Box, {
2616
- marginTop: 1,
2617
- children: /* @__PURE__ */ jsx(ConfirmationInput, {
2618
- message: `${isRemove ? "Remove" : "Install"} the PostHog MCP server${clients.some((c) => c.supportsPlugin) ? " and plugin" : ""}?`,
2619
- confirmLabel: isRemove ? "Remove" : "Install",
2620
- cancelLabel: "No thanks",
2621
- onConfirm: handleConfirm,
2622
- onCancel: handleSkip
2662
+ phase === "ask" && /* @__PURE__ */ jsxs(Fragment$1, { children: [
2663
+ !isRemove && /* @__PURE__ */ jsx(Box, {
2664
+ flexDirection: "column",
2665
+ marginBottom: 1,
2666
+ children: [
2667
+ "Ask your agent: \"List my feature flags\" — and it does.",
2668
+ "Run SQL, build dashboards, ship flags, all from your IDE.",
2669
+ "No copy-pasting tokens or context. Your agent has the keys."
2670
+ ].map((bullet) => /* @__PURE__ */ jsxs(Text, {
2671
+ dimColor: true,
2672
+ children: [
2673
+ "•",
2674
+ " ",
2675
+ bullet
2676
+ ]
2677
+ }, bullet))
2678
+ }),
2679
+ /* @__PURE__ */ jsxs(Text, {
2680
+ dimColor: true,
2681
+ children: ["Detected: ", clients.map((c) => c.name).join(", ")]
2682
+ }),
2683
+ /* @__PURE__ */ jsx(Box, {
2684
+ marginTop: 1,
2685
+ children: /* @__PURE__ */ jsx(ConfirmationInput, {
2686
+ message: `${isRemove ? "Remove" : "Install"} the PostHog MCP server${clients.some((c) => c.supportsPlugin) ? " and plugin" : ""}?`,
2687
+ confirmLabel: isRemove ? "Remove" : "Install",
2688
+ cancelLabel: "No thanks",
2689
+ onConfirm: handleConfirm,
2690
+ onCancel: handleSkip
2691
+ })
2623
2692
  })
2624
- })] }),
2693
+ ] }),
2625
2694
  phase === "pick" && /* @__PURE__ */ jsx(PickerMenu, {
2626
2695
  message: "Select editor to install MCP server",
2627
2696
  options: clients.map((c) => ({
@@ -2673,6 +2742,490 @@ const McpScreen = ({ store, installer, mode = "install" }) => {
2673
2742
  });
2674
2743
  };
2675
2744
  //#endregion
2745
+ //#region src/lib/mcp-role-prompts.ts
2746
+ /**
2747
+ * Roles that ship from `role_at_organization` on the PostHog user object.
2748
+ * `security` isn't in the enum upstream — the engineering kit covers that audience.
2749
+ */
2750
+ const TAILORED_ROLES = [
2751
+ "founder",
2752
+ "product",
2753
+ "leadership",
2754
+ "marketing",
2755
+ "engineering",
2756
+ "data"
2757
+ ];
2758
+ const STOCK_MCP_SUGGESTED_PROMPTS = [
2759
+ {
2760
+ prompt: "What are my busiest 10 events and when did each last fire?",
2761
+ description: "Inventories your project’s event stream so you can see what’s being captured at a glance."
2762
+ },
2763
+ {
2764
+ prompt: "Show me daily event volume for the last 30 days.",
2765
+ description: "Charts your event count day by day — a quick read on volume and trend."
2766
+ },
2767
+ {
2768
+ prompt: "Create a dashboard with my top 10 events broken down by day for the last 7 days.",
2769
+ description: "Builds a saved dashboard you can pin and share — written back to your project."
2770
+ }
2771
+ ];
2772
+ //#endregion
2773
+ //#region src/ui/tui/screens/McpSuggestedPromptsScreen.tsx
2774
+ /**
2775
+ * McpSuggestedPromptsScreen — shown after MCP install succeeds in the
2776
+ * standalone `wizard mcp add` program.
2777
+ *
2778
+ * Phases:
2779
+ * 1. Choose — opens with a Log in / Exit picker, framed by a
2780
+ * hardcoded teaser of three example prompts.
2781
+ * 2. Authenticating — runs `services.performLogin()` (OAuth in
2782
+ * production, canned values in the playground).
2783
+ * Renders a spinner + login URL inline while the
2784
+ * promise is pending. Errors return to Choose
2785
+ * with an inline error line.
2786
+ * 3. PromptPicker — lists the role-tailored kit; user picks one to
2787
+ * run. The picker has its own "Exit" entry so
2788
+ * dismissal is discoverable without a hidden
2789
+ * hotkey.
2790
+ * 4. Running — streams the agent's response inline via
2791
+ * `services.runPromptStreaming`. `[esc]` aborts
2792
+ * and returns to the picker; `[enter]` after
2793
+ * completion goes back to the picker so the user
2794
+ * can run another or exit.
2795
+ *
2796
+ * Credentials are guaranteed non-null once PromptPicker / Running are
2797
+ * reached (the Choose → Authenticating gate forces a successful login
2798
+ * before getting there). A defensive throw protects the Running
2799
+ * useEffect against a state-machine bug.
2800
+ */
2801
+ const MAX_PROMPT_RUNS = 3;
2802
+ const McpSuggestedPromptsScreen = ({ store, services }) => {
2803
+ useSyncExternalStore((cb) => store.subscribe(cb), () => store.getSnapshot());
2804
+ const session = store.session;
2805
+ const kit = STOCK_MCP_SUGGESTED_PROMPTS;
2806
+ const [phase, setPhase] = useState("choose");
2807
+ const [loginError, setLoginError] = useState(null);
2808
+ const [runningPrompt, setRunningPrompt] = useState(null);
2809
+ const [runChunks, setRunChunks] = useState([]);
2810
+ const [runStartedAt, setRunStartedAt] = useState(null);
2811
+ const [runCount, setRunCount] = useState(0);
2812
+ const canPickAnother = runCount < MAX_PROMPT_RUNS;
2813
+ const runAbortRef = useRef(null);
2814
+ useEffect(() => {
2815
+ if (phase !== "authenticating") return;
2816
+ let cancelled = false;
2817
+ (async () => {
2818
+ try {
2819
+ const { credentials, roleAtOrganization, user } = await services.performLogin();
2820
+ if (cancelled) return;
2821
+ store.setCredentials(credentials);
2822
+ store.setRoleAtOrganization(roleAtOrganization);
2823
+ store.setApiUser(user);
2824
+ store.setLoginUrl(null);
2825
+ setPhase("prompt-picker");
2826
+ } catch (err) {
2827
+ if (cancelled) return;
2828
+ const message = err instanceof Error ? err.message : String(err);
2829
+ logToFile(`[McpSuggestedPromptsScreen] login failed: ${message}`);
2830
+ store.setLoginUrl(null);
2831
+ setLoginError(message);
2832
+ setPhase("choose");
2833
+ }
2834
+ })();
2835
+ return () => {
2836
+ cancelled = true;
2837
+ };
2838
+ }, [
2839
+ phase,
2840
+ services,
2841
+ store
2842
+ ]);
2843
+ useEffect(() => {
2844
+ if (phase !== "running") return;
2845
+ if (!runningPrompt) return;
2846
+ if (!session.credentials) throw new Error("[McpSuggestedPromptsScreen] Running phase reached without credentials. The Choose gate should have prevented this.");
2847
+ const controller = new AbortController();
2848
+ runAbortRef.current = controller;
2849
+ const startedAt = Date.now();
2850
+ setRunStartedAt(startedAt);
2851
+ setRunChunks([]);
2852
+ (async () => {
2853
+ const credentials = session.credentials;
2854
+ if (!credentials) return;
2855
+ try {
2856
+ for await (const chunk of services.runPromptStreaming({
2857
+ prompt: runningPrompt,
2858
+ credentials,
2859
+ signal: controller.signal
2860
+ })) {
2861
+ if (controller.signal.aborted) return;
2862
+ setRunChunks((prev) => [...prev, chunk]);
2863
+ if (chunk.kind === "done") {
2864
+ analytics.wizardCapture("mcp suggested prompts run", {
2865
+ prompt: runningPrompt,
2866
+ durationMs: Date.now() - startedAt
2867
+ });
2868
+ return;
2869
+ }
2870
+ if (chunk.kind === "error") {
2871
+ analytics.wizardCapture("mcp suggested prompts run failed", {
2872
+ prompt: runningPrompt,
2873
+ error: chunk.text
2874
+ });
2875
+ return;
2876
+ }
2877
+ }
2878
+ } catch (err) {
2879
+ if (controller.signal.aborted) return;
2880
+ const text = err instanceof Error ? err.message : String(err);
2881
+ setRunChunks((prev) => [...prev, {
2882
+ kind: "error",
2883
+ text
2884
+ }]);
2885
+ analytics.wizardCapture("mcp suggested prompts run failed", {
2886
+ prompt: runningPrompt,
2887
+ error: text
2888
+ });
2889
+ }
2890
+ })();
2891
+ return () => {
2892
+ controller.abort();
2893
+ if (runAbortRef.current === controller) runAbortRef.current = null;
2894
+ };
2895
+ }, [
2896
+ phase,
2897
+ runningPrompt,
2898
+ services,
2899
+ session.credentials
2900
+ ]);
2901
+ const dismiss = () => {
2902
+ setPhase("done");
2903
+ setTimeout(() => {
2904
+ store.setMcpSuggestedPromptsDismissed();
2905
+ }, 0);
2906
+ };
2907
+ const handleChoice = (value) => {
2908
+ const choice = Array.isArray(value) ? value[0] : value;
2909
+ setLoginError(null);
2910
+ if (choice === "login") {
2911
+ analytics.wizardCapture("mcp suggested prompts choose", { choice: "login" });
2912
+ setPhase("authenticating");
2913
+ } else {
2914
+ analytics.wizardCapture("mcp suggested prompts choose", { choice: "exit" });
2915
+ dismiss();
2916
+ }
2917
+ };
2918
+ const handlePromptPick = (value) => {
2919
+ setRunningPrompt(Array.isArray(value) ? value[0] : value);
2920
+ setRunCount((c) => c + 1);
2921
+ setPhase("running");
2922
+ };
2923
+ useKeyBindings("mcp-suggested-prompts", [{
2924
+ match: "escape",
2925
+ label: "esc",
2926
+ action: phase === "prompt-picker" ? "exit" : "exit",
2927
+ handler: () => {
2928
+ if (phase === "running") {
2929
+ runAbortRef.current?.abort();
2930
+ dismiss();
2931
+ } else if (phase === "prompt-picker") dismiss();
2932
+ }
2933
+ }, {
2934
+ match: "p",
2935
+ label: "p",
2936
+ action: canPickAnother ? "pick new prompt" : "cap reached",
2937
+ handler: () => {
2938
+ if (phase !== "running") return;
2939
+ if (!canPickAnother) return;
2940
+ runAbortRef.current?.abort();
2941
+ setPhase("prompt-picker");
2942
+ }
2943
+ }]);
2944
+ return /* @__PURE__ */ jsx(Box, {
2945
+ flexDirection: "column",
2946
+ flexGrow: 1,
2947
+ children: /* @__PURE__ */ jsxs(Box, {
2948
+ marginTop: 1,
2949
+ flexDirection: "column",
2950
+ children: [
2951
+ phase === "choose" && /* @__PURE__ */ jsx(ChoosePhase, {
2952
+ error: loginError,
2953
+ onSelect: handleChoice
2954
+ }),
2955
+ phase === "authenticating" && /* @__PURE__ */ jsx(AuthenticatingPhase, { loginUrl: session.loginUrl }),
2956
+ phase === "prompt-picker" && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Box, {
2957
+ marginBottom: 1,
2958
+ children: /* @__PURE__ */ jsx(Text, {
2959
+ bold: true,
2960
+ color: Colors.accent,
2961
+ children: "MCP tutorial"
2962
+ })
2963
+ }), /* @__PURE__ */ jsx(PromptPickerPhase, {
2964
+ promptKit: kit,
2965
+ userDisplayName: session.apiUser?.first_name || null,
2966
+ onSelect: handlePromptPick
2967
+ })] }),
2968
+ phase === "running" && runningPrompt && /* @__PURE__ */ jsx(RunningPhase, {
2969
+ prompt: runningPrompt,
2970
+ chunks: runChunks,
2971
+ startedAt: runStartedAt,
2972
+ canPickAnother,
2973
+ runCount,
2974
+ maxRuns: MAX_PROMPT_RUNS
2975
+ })
2976
+ ]
2977
+ })
2978
+ });
2979
+ };
2980
+ const ChoosePhase = ({ error, onSelect }) => /* @__PURE__ */ jsxs(Box, {
2981
+ flexDirection: "column",
2982
+ children: [
2983
+ /* @__PURE__ */ jsx(Text, {
2984
+ bold: true,
2985
+ color: Colors.accent,
2986
+ children: "PostHog MCP"
2987
+ }),
2988
+ /* @__PURE__ */ jsx(Box, {
2989
+ marginTop: 1,
2990
+ children: /* @__PURE__ */ jsx(Text, { children: "With MCP your agent works directly with the PostHog platform. You can prompt it to:" })
2991
+ }),
2992
+ /* @__PURE__ */ jsxs(Box, {
2993
+ marginTop: 1,
2994
+ flexDirection: "column",
2995
+ children: [
2996
+ /* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
2997
+ color: "cyan",
2998
+ children: Icons.diamond
2999
+ }), " Build dashboards"] }),
3000
+ /* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
3001
+ color: "cyan",
3002
+ children: Icons.diamond
3003
+ }), " Run SQL queries"] }),
3004
+ /* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
3005
+ color: "cyan",
3006
+ children: Icons.diamond
3007
+ }), " Deploy feature flags"] }),
3008
+ /* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
3009
+ color: "cyan",
3010
+ children: Icons.diamond
3011
+ }), " Debug exceptions and errors"] }),
3012
+ /* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
3013
+ color: "cyan",
3014
+ children: Icons.diamond
3015
+ }), " And lots more..."] })
3016
+ ]
3017
+ }),
3018
+ /* @__PURE__ */ jsx(Box, {
3019
+ marginTop: 1,
3020
+ children: /* @__PURE__ */ jsx(Text, { children: "Want a live demo using real data from your project?" })
3021
+ }),
3022
+ /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(PickerMenu, {
3023
+ options: [{
3024
+ label: "Start MCP tutorial",
3025
+ value: "login"
3026
+ }, {
3027
+ label: "Exit",
3028
+ value: "exit"
3029
+ }],
3030
+ onSelect
3031
+ }) }),
3032
+ error && /* @__PURE__ */ jsx(Box, {
3033
+ marginTop: 1,
3034
+ children: /* @__PURE__ */ jsxs(Text, {
3035
+ color: "red",
3036
+ children: [
3037
+ "Login failed: ",
3038
+ error,
3039
+ ". Try again or exit."
3040
+ ]
3041
+ })
3042
+ })
3043
+ ]
3044
+ });
3045
+ const AuthenticatingPhase = ({ loginUrl }) => /* @__PURE__ */ jsxs(Box, {
3046
+ flexDirection: "column",
3047
+ children: [/* @__PURE__ */ jsx(LoadingBox, { message: "Waiting for authentication..." }), loginUrl && /* @__PURE__ */ jsx(Box, {
3048
+ marginTop: 1,
3049
+ marginBottom: 1,
3050
+ flexDirection: "column",
3051
+ children: /* @__PURE__ */ jsxs(Text, { children: [
3052
+ /* @__PURE__ */ jsx(Text, {
3053
+ dimColor: true,
3054
+ children: "If the browser didn't open, copy and paste:"
3055
+ }),
3056
+ "\n\n",
3057
+ /* @__PURE__ */ jsx(Text, {
3058
+ color: "cyan",
3059
+ children: loginUrl
3060
+ })
3061
+ ] })
3062
+ })]
3063
+ });
3064
+ const PromptPickerPhase = ({ promptKit, userDisplayName, onSelect }) => {
3065
+ const options = promptKit.map((p) => ({
3066
+ label: p.prompt,
3067
+ value: p.prompt
3068
+ }));
3069
+ return /* @__PURE__ */ jsx(Box, {
3070
+ flexDirection: "column",
3071
+ children: /* @__PURE__ */ jsx(ContentSequencer, {
3072
+ blocks: [
3073
+ {
3074
+ content: `Hello there, ${userDisplayName || "there"}!`,
3075
+ mode: 0,
3076
+ animationInterval: 100,
3077
+ pause: 1200,
3078
+ dimWhenComplete: false
3079
+ },
3080
+ {
3081
+ content: "Pick a prompt to see the PostHog MCP in action.",
3082
+ mode: 0,
3083
+ animationInterval: 50,
3084
+ pause: 1e3,
3085
+ dimWhenComplete: false
3086
+ },
3087
+ {
3088
+ content: /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(PickerMenu, {
3089
+ options,
3090
+ optionMarginBottom: 1,
3091
+ onSelect
3092
+ }), /* @__PURE__ */ jsx(Box, {
3093
+ marginTop: 2,
3094
+ children: /* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
3095
+ bold: true,
3096
+ children: "[esc]"
3097
+ }), /* @__PURE__ */ jsx(Text, { children: " to exit" })] })
3098
+ })] }),
3099
+ persist: true
3100
+ }
3101
+ ],
3102
+ mode: 0,
3103
+ blockInterval: 350
3104
+ })
3105
+ });
3106
+ };
3107
+ const RunningPhase = ({ prompt, chunks, startedAt, canPickAnother, runCount, maxRuns }) => {
3108
+ const isDone = chunks.some((c) => c.kind === "done");
3109
+ const errorChunk = chunks.find((c) => c.kind === "error");
3110
+ const finished = isDone || !!errorChunk;
3111
+ const elapsed = startedAt ? Math.round((Date.now() - startedAt) / 1e3) : 0;
3112
+ const visibleChunks = finished ? chunks.filter((c) => c.kind === "text" || c.kind === "error") : chunks;
3113
+ const cappedChunks = finished ? capTextChunks(visibleChunks) : visibleChunks;
3114
+ return /* @__PURE__ */ jsxs(Box, {
3115
+ flexDirection: "column",
3116
+ children: [
3117
+ /* @__PURE__ */ jsxs(Text, { children: [
3118
+ /* @__PURE__ */ jsx(Text, {
3119
+ bold: true,
3120
+ children: "Prompt:"
3121
+ }),
3122
+ " ",
3123
+ /* @__PURE__ */ jsx(Text, {
3124
+ color: Colors.accent,
3125
+ children: prompt
3126
+ })
3127
+ ] }),
3128
+ /* @__PURE__ */ jsxs(Box, {
3129
+ marginTop: 1,
3130
+ gap: 1,
3131
+ children: [
3132
+ !finished && /* @__PURE__ */ jsx(Spinner, {}),
3133
+ /* @__PURE__ */ jsx(Text, {
3134
+ bold: finished,
3135
+ children: finished ? errorChunk ? `Failed after ${elapsed}s.` : `Done in ${elapsed}s.` : "Streaming from PostHog MCP"
3136
+ }),
3137
+ /* @__PURE__ */ jsxs(Text, {
3138
+ dimColor: true,
3139
+ children: [
3140
+ "(",
3141
+ runCount,
3142
+ "/",
3143
+ maxRuns,
3144
+ " prompts)"
3145
+ ]
3146
+ })
3147
+ ]
3148
+ }),
3149
+ /* @__PURE__ */ jsx(Box, {
3150
+ marginTop: 1,
3151
+ flexDirection: "column",
3152
+ children: cappedChunks.map((chunk, idx) => /* @__PURE__ */ jsx(ChunkLine, { chunk }, idx))
3153
+ }),
3154
+ finished && !canPickAnother && /* @__PURE__ */ jsx(Box, {
3155
+ marginTop: 1,
3156
+ children: /* @__PURE__ */ jsxs(Text, { children: [
3157
+ /* @__PURE__ */ jsxs(Text, {
3158
+ dimColor: true,
3159
+ children: [
3160
+ "You've hit the ",
3161
+ maxRuns,
3162
+ "-prompt tutorial cap. Press",
3163
+ " "
3164
+ ]
3165
+ }),
3166
+ /* @__PURE__ */ jsx(Text, {
3167
+ bold: true,
3168
+ dimColor: true,
3169
+ children: "[esc]"
3170
+ }),
3171
+ /* @__PURE__ */ jsx(Text, {
3172
+ dimColor: true,
3173
+ children: " to exit."
3174
+ })
3175
+ ] })
3176
+ })
3177
+ ]
3178
+ });
3179
+ };
3180
+ /**
3181
+ * Belt-and-suspenders fallback for runs where Claude ignored the
3182
+ * terminal-fit system prompt and produced an overlong response. Joins
3183
+ * all text chunks, slices to the last N lines that fit in the current
3184
+ * terminal, and prepends an indicator showing how many lines got cut.
3185
+ * Errors are preserved separately so failures don't disappear into the
3186
+ * truncation.
3187
+ */
3188
+ function capTextChunks(chunks) {
3189
+ const rows = process.stdout.rows ?? 24;
3190
+ const maxMessageRows = Math.max(6, rows - 8);
3191
+ const textChunks = chunks.filter((c) => c.kind === "text");
3192
+ const errors = chunks.filter((c) => c.kind === "error");
3193
+ if (textChunks.length === 0) return chunks;
3194
+ const lines = textChunks.map((c) => c.text).join("").split("\n");
3195
+ if (lines.length <= maxMessageRows) return chunks;
3196
+ const hidden = lines.length - maxMessageRows;
3197
+ const tail = lines.slice(-maxMessageRows).join("\n");
3198
+ return [{
3199
+ kind: "text",
3200
+ text: `[${hidden} line${hidden === 1 ? "" : "s"} above — expand terminal to see more]\n\n${tail}`
3201
+ }, ...errors];
3202
+ }
3203
+ const ChunkLine = ({ chunk }) => {
3204
+ if (chunk.kind === "text") return /* @__PURE__ */ jsx(Text, { children: chunk.text });
3205
+ if (chunk.kind === "tool-call") return /* @__PURE__ */ jsxs(Text, { children: [
3206
+ " ",
3207
+ /* @__PURE__ */ jsxs(Text, {
3208
+ color: "cyan",
3209
+ children: ["↳ ", chunk.toolName]
3210
+ }),
3211
+ chunk.detail ? ` ${chunk.detail}` : ""
3212
+ ] });
3213
+ if (chunk.kind === "tool-result") return /* @__PURE__ */ jsxs(Text, { children: [
3214
+ " ",
3215
+ /* @__PURE__ */ jsx(Text, {
3216
+ color: "green",
3217
+ children: "✓"
3218
+ }),
3219
+ " ",
3220
+ chunk.detail
3221
+ ] });
3222
+ if (chunk.kind === "error") return /* @__PURE__ */ jsxs(Text, {
3223
+ color: "red",
3224
+ children: ["Error: ", chunk.text]
3225
+ });
3226
+ return null;
3227
+ };
3228
+ //#endregion
2676
3229
  //#region src/ui/tui/screens/audit/AuditChecksViewer/AreaHeaderRow.tsx
2677
3230
  /** Sub-header row inside the scrollable body — one per area group. */
2678
3231
  const AreaHeaderRow = ({ area, resolved, total }) => /* @__PURE__ */ jsxs(Box, {
@@ -3461,6 +4014,6 @@ const AUDIT_3000_AREA_SLIDES = [
3461
4014
  }
3462
4015
  ];
3463
4016
  //#endregion
3464
- export { ProgressList as C, WizardStore as D, CardLayout as E, useKeyBindings as S, SplitView as T, ModalOverlay as _, IssueTable as a, useStdoutDimensions as b, ServiceHealthList as c, ContentSequencer as d, HNViewer as f, LogViewer as g, EventPlanViewer as h, McpScreen as i, TipsCard as l, ScreenContainer as m, AUDIT_AREA_SLIDES as n, SEVERITY_LABEL as o, TabContainer as p, AuditChecksViewer as r, SEVERITY_ORDER as s, AUDIT_3000_AREA_SLIDES as t, LearnCard as u, ConfirmationInput as v, LoadingBox as w, PickerMenu as x, GroupedPickerMenu as y };
4017
+ export { PickerMenu as C, SplitView as D, LoadingBox as E, CardLayout as O, useStdoutDimensions as S, ProgressList as T, EventPlanViewer as _, TAILORED_ROLES as a, ConfirmationInput as b, SEVERITY_LABEL as c, TipsCard as d, LearnCard as f, ScreenContainer as g, TabContainer as h, McpSuggestedPromptsScreen as i, WizardStore as k, SEVERITY_ORDER as l, HNViewer as m, AUDIT_AREA_SLIDES as n, McpScreen as o, ContentSequencer as p, AuditChecksViewer as r, IssueTable as s, AUDIT_3000_AREA_SLIDES as t, ServiceHealthList as u, LogViewer as v, useKeyBindings as w, GroupedPickerMenu as x, ModalOverlay as y };
3465
4018
 
3466
- //# sourceMappingURL=slides-BtDXEXdn.js.map
4019
+ //# sourceMappingURL=slides-Dpj4j0w_.js.map