@posthog/wizard 2.19.0 → 2.21.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 (67) hide show
  1. package/README.md +11 -0
  2. package/dist/{slides-mT2s9wM_.js → OutroScreen-CqF6SdBo.js} +614 -122
  3. package/dist/OutroScreen-CqF6SdBo.js.map +1 -0
  4. package/dist/{add-mcp-server-to-clients-CjnvTVj0.js → add-mcp-server-to-clients-DQHGhzt6.js} +4 -4
  5. package/dist/{add-mcp-server-to-clients-CjnvTVj0.js.map → add-mcp-server-to-clients-DQHGhzt6.js.map} +1 -1
  6. package/dist/{agent-interface-CQU6x4Hj.js → agent-interface-DE7txTqh.js} +163 -52
  7. package/dist/agent-interface-DE7txTqh.js.map +1 -0
  8. package/dist/{agent-runner-Cj7saDkL.js → agent-runner-DUZ5OD6e.js} +10 -9
  9. package/dist/{agent-runner-Cj7saDkL.js.map → agent-runner-DUZ5OD6e.js.map} +1 -1
  10. package/dist/{analytics-Df-Xb81i.js → analytics-Bl5DPj_0.js} +2 -2
  11. package/dist/{analytics-Df-Xb81i.js.map → analytics-Bl5DPj_0.js.map} +1 -1
  12. package/dist/{api-Dw6_orDE.js → api-DuA0_88V.js} +25 -4
  13. package/dist/{api-Dw6_orDE.js.map → api-DuA0_88V.js.map} +1 -1
  14. package/dist/bin.js +74 -47
  15. package/dist/bin.js.map +1 -1
  16. package/dist/check-screens.tsx +124 -0
  17. package/dist/{ci-install-BKAvFfK6.js → ci-install-BnOYI4mZ.js} +4 -4
  18. package/dist/{ci-install-BKAvFfK6.js.map → ci-install-BnOYI4mZ.js.map} +1 -1
  19. package/dist/{debug-Cp_wNn8i.js → debug-BVC48wlb.js} +1 -1
  20. package/dist/{debug-DnMO6O8O.js → debug-h7Z9zEbD.js} +2 -2
  21. package/dist/{debug-DnMO6O8O.js.map → debug-h7Z9zEbD.js.map} +1 -1
  22. package/dist/{environment-Ls0H9ljT.js → environment-uaLmtlH_.js} +3 -3
  23. package/dist/{environment-Ls0H9ljT.js.map → environment-uaLmtlH_.js.map} +1 -1
  24. package/dist/{interactive-D15byhpc.js → interactive-CW5gjyDd.js} +2 -2
  25. package/dist/{interactive-D15byhpc.js.map → interactive-CW5gjyDd.js.map} +1 -1
  26. package/dist/{mcp-prompt-streaming-DQOTQfW1.js → mcp-prompt-streaming-DMDwaark.js} +4 -4
  27. package/dist/{mcp-prompt-streaming-DQOTQfW1.js.map → mcp-prompt-streaming-DMDwaark.js.map} +1 -1
  28. package/dist/{non-interactive-DcFLJtl_.js → non-interactive-DJrVQ4nS.js} +2 -2
  29. package/dist/{non-interactive-DcFLJtl_.js.map → non-interactive-DJrVQ4nS.js.map} +1 -1
  30. package/dist/{package-manager-DUPgLGpQ.js → package-manager-DCUBRbr-.js} +2 -2
  31. package/dist/{package-manager-DUPgLGpQ.js.map → package-manager-DCUBRbr-.js.map} +1 -1
  32. package/dist/{playground-BZ0hGjbL.js → playground-DCVaVeVD.js} +138 -9
  33. package/dist/playground-DCVaVeVD.js.map +1 -0
  34. package/dist/{posthog-integration-C8qhJnI3.js → posthog-integration-ChdwFPMj.js} +17 -11
  35. package/dist/posthog-integration-ChdwFPMj.js.map +1 -0
  36. package/dist/{provisioning-C-2ExcqY.js → provisioning-GeMkBMSR.js} +3 -3
  37. package/dist/{provisioning-C-2ExcqY.js.map → provisioning-GeMkBMSR.js.map} +1 -1
  38. package/dist/{registry-hBUgaWFx.js → registry-VSSRH3sU.js} +4 -4
  39. package/dist/{registry-hBUgaWFx.js.map → registry-VSSRH3sU.js.map} +1 -1
  40. package/dist/{setup-utils-DetnhXo0.js → setup-utils-BfV4pydt.js} +12 -10
  41. package/dist/setup-utils-BfV4pydt.js.map +1 -0
  42. package/dist/{start-tui-BfXoErKg.js → start-tui-BRvm5VP9.js} +93 -228
  43. package/dist/start-tui-BRvm5VP9.js.map +1 -0
  44. package/dist/{steps-SoDXSUxe.js → steps-DA4uvSbg.js} +6 -6
  45. package/dist/{steps-SoDXSUxe.js.map → steps-DA4uvSbg.js.map} +1 -1
  46. package/dist/{task-stream-CZRj6auI.js → task-stream-CZawuzlz.js} +2 -2
  47. package/dist/{task-stream-CZRj6auI.js.map → task-stream-CZawuzlz.js.map} +1 -1
  48. package/dist/{telemetry-CPcMFxcO.js → telemetry-BRAonUea.js} +2 -2
  49. package/dist/{telemetry-CPcMFxcO.js.map → telemetry-BRAonUea.js.map} +1 -1
  50. package/dist/{urls-BO7doNJG.js → urls-B66Ib2jT.js} +2 -2
  51. package/dist/{urls-BO7doNJG.js.map → urls-B66Ib2jT.js.map} +1 -1
  52. package/dist/{wizard-abort-CDXufkqJ.js → wizard-abort-D1_DnFjm.js} +12 -7
  53. package/dist/wizard-abort-D1_DnFjm.js.map +1 -0
  54. package/dist/wizard-abort-gMB1eV6T.js +2 -0
  55. package/dist/{wizard-session-d27JGRGi.js → wizard-session-G3VWD6hv.js} +3 -1
  56. package/dist/{wizard-session-d27JGRGi.js.map → wizard-session-G3VWD6hv.js.map} +1 -1
  57. package/dist/{wizard-session-y304gEEI.js → wizard-session-wPJtNl4c.js} +1 -1
  58. package/dist/wizard-ui-YdGFRyu_.js.map +1 -1
  59. package/package.json +4 -2
  60. package/dist/agent-interface-CQU6x4Hj.js.map +0 -1
  61. package/dist/playground-BZ0hGjbL.js.map +0 -1
  62. package/dist/posthog-integration-C8qhJnI3.js.map +0 -1
  63. package/dist/setup-utils-DetnhXo0.js.map +0 -1
  64. package/dist/slides-mT2s9wM_.js.map +0 -1
  65. package/dist/start-tui-BfXoErKg.js.map +0 -1
  66. package/dist/wizard-abort-CDXufkqJ.js.map +0 -1
  67. package/dist/wizard-abort-CtMY57ZE.js +0 -2
@@ -1,12 +1,14 @@
1
- import { g as SERVICE_LABELS, s as logToFile } from "./debug-DnMO6O8O.js";
1
+ import { g as SERVICE_LABELS, s as logToFile } from "./debug-h7Z9zEbD.js";
2
2
  import { n as isTaskStatus } from "./wizard-ui-YdGFRyu_.js";
3
- import { r as sessionProperties, t as analytics } from "./analytics-Df-Xb81i.js";
4
- import { i as buildSession } from "./wizard-session-d27JGRGi.js";
5
- import { v as AUDIT_SEVERITY_STYLE } from "./agent-interface-CQU6x4Hj.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-C8qhJnI3.js";
3
+ import { r as sessionProperties, t as analytics } from "./analytics-Bl5DPj_0.js";
4
+ import { i as fetchSlackConnected } from "./api-DuA0_88V.js";
5
+ import { i as buildSession } from "./wizard-session-G3VWD6hv.js";
6
+ import { y as AUDIT_SEVERITY_STYLE } from "./agent-interface-DE7txTqh.js";
7
+ 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-ChdwFPMj.js";
7
8
  import { a as getProgramConfig, i as Program, l as getKindMeta, r as PROGRAM_REGISTRY } from "./bin.js";
8
9
  import { n as AVAILABLE_FEATURES, o as isAllFeaturesSelected, t as ALL_FEATURE_VALUES } from "./defaults-BNWIWzjc.js";
9
10
  import * as fs$1 from "fs";
11
+ import opn from "opn";
10
12
  import { Box, Text, measureElement, useInput, useStdout } from "ink";
11
13
  import { Component, Fragment, createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
12
14
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
@@ -159,8 +161,7 @@ var WizardStore = class {
159
161
  this._initFromProgram(program);
160
162
  }
161
163
  /**
162
- * Scan program steps for gate predicates and onInit callbacks.
163
- * Creates gate promises and fires init work.
164
+ * Scan program steps for gate predicates and create gate promises.
164
165
  */
165
166
  _initFromProgram(program) {
166
167
  const steps = getProgramConfig(program).steps;
@@ -176,6 +177,15 @@ var WizardStore = class {
176
177
  resolved: false
177
178
  });
178
179
  }
180
+ }
181
+ /**
182
+ * Run the program steps' onInit callbacks. startTUI calls this once
183
+ * the screens are actually rendering — constructing a store alone
184
+ * (tests, playground) must not fire init work like the health-check
185
+ * pre-flight, whose probes belong only to flows that show its screen.
186
+ */
187
+ runInitHooks() {
188
+ const steps = getProgramConfig(this.router.activeProgram).steps;
179
189
  const getSession = () => this.session;
180
190
  const ctx = {
181
191
  get session() {
@@ -487,6 +497,14 @@ var WizardStore = class {
487
497
  this.$session.setKey("mcpSuggestedPromptsDismissed", true);
488
498
  this.emitChange();
489
499
  }
500
+ setSlackStepDismissed() {
501
+ this.$session.setKey("slackStepDismissed", true);
502
+ this.emitChange();
503
+ }
504
+ setSlackConnected(connected) {
505
+ this.$session.setKey("slackConnected", connected);
506
+ this.emitChange();
507
+ }
490
508
  setOutroDismissed() {
491
509
  this.$session.setKey("outroDismissed", true);
492
510
  this.emitChange();
@@ -891,6 +909,27 @@ function useKeyBindings(id, bindings) {
891
909
  * Key bindings are declared via useKeyBindings, which auto-registers
892
910
  * hints in the KeyboardHintsBar.
893
911
  */
912
+ /**
913
+ * Step through a column's options in `dir`, wrapping, until an enabled
914
+ * option is found. Returns `from` unchanged if the column is entirely
915
+ * disabled.
916
+ */
917
+ function stepEnabled(options, rows, from, dir) {
918
+ const colStart = Math.floor(from / rows) * rows;
919
+ const colLen = Math.min(rows, options.length - colStart);
920
+ let row = from % rows;
921
+ for (let i = 0; i < colLen; i++) {
922
+ row = (row + dir + colLen) % colLen;
923
+ const idx = colStart + row;
924
+ if (!options[idx]?.disabled) return idx;
925
+ }
926
+ return from;
927
+ }
928
+ /** Index of the first enabled option, for the initial focus. */
929
+ function firstEnabled(options) {
930
+ const idx = options.findIndex((o) => !o.disabled);
931
+ return idx === -1 ? 0 : idx;
932
+ }
894
933
  const PickerMenu = ({ message, options, mode = "single", centered = false, columns = 1, optionMarginBottom = 0, onSelect }) => {
895
934
  if (mode === "multi") return /* @__PURE__ */ jsx(MultiPickerMenu, {
896
935
  message,
@@ -911,22 +950,18 @@ const PickerMenu = ({ message, options, mode = "single", centered = false, colum
911
950
  };
912
951
  /** Custom single-select with triangle indicator and accent highlight. */
913
952
  const SinglePickerMenu = ({ message, options, centered = false, columns = 1, optionMarginBottom = 0, onSelect }) => {
914
- const [focused, setFocused] = useState(0);
953
+ const [focused, setFocused] = useState(() => firstEnabled(options));
915
954
  const rows = Math.ceil(options.length / columns);
955
+ useEffect(() => {
956
+ if (focused >= options.length || options[focused]?.disabled) setFocused(firstEnabled(options));
957
+ }, [options, focused]);
916
958
  const bindings = [{
917
959
  match: ["upArrow", "downArrow"],
918
960
  label: "↑↓",
919
961
  action: "navigate",
920
962
  handler: (_input, key) => {
921
- const col = Math.floor(focused / rows);
922
- const row = focused % rows;
923
- if (key.upArrow) if (row > 0) setFocused(col * rows + row - 1);
924
- else setFocused(Math.min(col * rows + rows - 1, options.length - 1));
925
- if (key.downArrow) {
926
- const next = col * rows + row + 1;
927
- if (next < options.length && row + 1 < rows) setFocused(next);
928
- else setFocused(col * rows);
929
- }
963
+ if (key.upArrow) setFocused(stepEnabled(options, rows, focused, -1));
964
+ if (key.downArrow) setFocused(stepEnabled(options, rows, focused, 1));
930
965
  }
931
966
  }, {
932
967
  match: "return",
@@ -934,7 +969,7 @@ const SinglePickerMenu = ({ message, options, centered = false, columns = 1, opt
934
969
  action: "select",
935
970
  handler: () => {
936
971
  const selected = options[focused];
937
- if (selected) onSelect(selected.value);
972
+ if (selected && !selected.disabled) onSelect(selected.value);
938
973
  }
939
974
  }];
940
975
  if (columns > 1) bindings.splice(1, 0, {
@@ -944,14 +979,17 @@ const SinglePickerMenu = ({ message, options, centered = false, columns = 1, opt
944
979
  handler: (_input, key) => {
945
980
  const col = Math.floor(focused / rows);
946
981
  const row = focused % rows;
982
+ let next = focused;
947
983
  if (key.leftArrow) {
948
984
  const prevCol = col > 0 ? col - 1 : columns - 1;
949
- setFocused(Math.min(prevCol * rows + row, options.length - 1));
985
+ next = Math.min(prevCol * rows + row, options.length - 1);
950
986
  }
951
987
  if (key.rightArrow) {
952
988
  const nextCol = col < columns - 1 ? col + 1 : 0;
953
- setFocused(Math.min(nextCol * rows + row, options.length - 1));
989
+ next = Math.min(nextCol * rows + row, options.length - 1);
954
990
  }
991
+ if (options[next]?.disabled) next = stepEnabled(options, rows, next, 1);
992
+ setFocused(next);
955
993
  }
956
994
  });
957
995
  useKeyBindings("single-picker", bindings);
@@ -972,16 +1010,23 @@ const SinglePickerMenu = ({ message, options, centered = false, columns = 1, opt
972
1010
  return /* @__PURE__ */ jsxs(Box, {
973
1011
  gap: 1,
974
1012
  marginBottom: optionMarginBottom,
975
- children: [/* @__PURE__ */ jsx(Text, {
976
- color: isFocused ? Colors.accent : void 0,
977
- dimColor: !isFocused,
978
- children: isFocused ? Icons.triangleSmallRight : " "
979
- }), /* @__PURE__ */ jsx(Text, {
980
- color: isFocused ? Colors.accent : void 0,
981
- bold: isFocused,
982
- dimColor: !isFocused,
983
- children: label
984
- })]
1013
+ children: [
1014
+ /* @__PURE__ */ jsx(Text, {
1015
+ color: isFocused ? Colors.accent : void 0,
1016
+ dimColor: !isFocused,
1017
+ children: isFocused ? Icons.triangleSmallRight : " "
1018
+ }),
1019
+ opt.icon && /* @__PURE__ */ jsx(Text, {
1020
+ color: opt.icon.color,
1021
+ children: opt.icon.glyph
1022
+ }),
1023
+ /* @__PURE__ */ jsx(Text, {
1024
+ color: opt.disabled ? Colors.muted : isFocused ? Colors.accent : void 0,
1025
+ bold: isFocused && !opt.disabled,
1026
+ dimColor: !isFocused || opt.disabled,
1027
+ children: label
1028
+ })
1029
+ ]
985
1030
  }, flatIdx);
986
1031
  })
987
1032
  }, colIdx))
@@ -990,24 +1035,20 @@ const SinglePickerMenu = ({ message, options, centered = false, columns = 1, opt
990
1035
  };
991
1036
  /** Custom multi-select with checkbox glyphs and accent highlight. */
992
1037
  const MultiPickerMenu = ({ message, options, centered = false, columns = 1, optionMarginBottom = 0, onSelect }) => {
993
- const [focused, setFocused] = useState(0);
1038
+ const [focused, setFocused] = useState(() => firstEnabled(options));
994
1039
  const [selected, setSelected] = useState(/* @__PURE__ */ new Set());
995
1040
  const rows = Math.ceil(options.length / columns);
1041
+ useEffect(() => {
1042
+ if (focused >= options.length || options[focused]?.disabled) setFocused(firstEnabled(options));
1043
+ }, [options, focused]);
996
1044
  const bindings = [
997
1045
  {
998
1046
  match: ["upArrow", "downArrow"],
999
1047
  label: "↑↓",
1000
1048
  action: "navigate",
1001
1049
  handler: (_input, key) => {
1002
- const col = Math.floor(focused / rows);
1003
- const row = focused % rows;
1004
- if (key.upArrow) if (row > 0) setFocused(col * rows + row - 1);
1005
- else setFocused(Math.min(col * rows + rows - 1, options.length - 1));
1006
- if (key.downArrow) {
1007
- const next = col * rows + row + 1;
1008
- if (next < options.length && row + 1 < rows) setFocused(next);
1009
- else setFocused(col * rows);
1010
- }
1050
+ if (key.upArrow) setFocused(stepEnabled(options, rows, focused, -1));
1051
+ if (key.downArrow) setFocused(stepEnabled(options, rows, focused, 1));
1011
1052
  }
1012
1053
  },
1013
1054
  {
@@ -1015,6 +1056,7 @@ const MultiPickerMenu = ({ message, options, centered = false, columns = 1, opti
1015
1056
  label: "space",
1016
1057
  action: "toggle",
1017
1058
  handler: () => {
1059
+ if (options[focused]?.disabled) return;
1018
1060
  setSelected((prev) => {
1019
1061
  const next = new Set(prev);
1020
1062
  if (next.has(focused)) {
@@ -1035,7 +1077,7 @@ const MultiPickerMenu = ({ message, options, centered = false, columns = 1, opti
1035
1077
  handler: () => {
1036
1078
  if (selected.size === 0) {
1037
1079
  const hovered = options[focused];
1038
- if (hovered) onSelect(hovered.value);
1080
+ if (hovered && !hovered.disabled) onSelect(hovered.value);
1039
1081
  } else onSelect([...selected].sort().map((i) => options[i].value));
1040
1082
  }
1041
1083
  }
@@ -1047,14 +1089,17 @@ const MultiPickerMenu = ({ message, options, centered = false, columns = 1, opti
1047
1089
  handler: (_input, key) => {
1048
1090
  const col = Math.floor(focused / rows);
1049
1091
  const row = focused % rows;
1092
+ let next = focused;
1050
1093
  if (key.leftArrow) {
1051
1094
  const prevCol = col > 0 ? col - 1 : columns - 1;
1052
- setFocused(Math.min(prevCol * rows + row, options.length - 1));
1095
+ next = Math.min(prevCol * rows + row, options.length - 1);
1053
1096
  }
1054
1097
  if (key.rightArrow) {
1055
1098
  const nextCol = col < columns - 1 ? col + 1 : 0;
1056
- setFocused(Math.min(nextCol * rows + row, options.length - 1));
1099
+ next = Math.min(nextCol * rows + row, options.length - 1);
1057
1100
  }
1101
+ if (options[next]?.disabled) next = stepEnabled(options, rows, next, 1);
1102
+ setFocused(next);
1058
1103
  }
1059
1104
  });
1060
1105
  useKeyBindings("multi-picker", bindings);
@@ -1079,16 +1124,23 @@ const MultiPickerMenu = ({ message, options, centered = false, columns = 1, opti
1079
1124
  return /* @__PURE__ */ jsxs(Box, {
1080
1125
  gap: 1,
1081
1126
  marginBottom: optionMarginBottom,
1082
- children: [/* @__PURE__ */ jsx(Text, {
1083
- color: isSelected ? "white" : Colors.muted,
1084
- dimColor: !isFocused && !isSelected,
1085
- children: checkbox
1086
- }), /* @__PURE__ */ jsx(Text, {
1087
- color: isFocused ? Colors.accent : void 0,
1088
- bold: isFocused,
1089
- dimColor: !isFocused,
1090
- children: label
1091
- })]
1127
+ children: [
1128
+ /* @__PURE__ */ jsx(Text, {
1129
+ color: isSelected ? "white" : Colors.muted,
1130
+ dimColor: !isFocused && !isSelected,
1131
+ children: checkbox
1132
+ }),
1133
+ opt.icon && /* @__PURE__ */ jsx(Text, {
1134
+ color: opt.icon.color,
1135
+ children: opt.icon.glyph
1136
+ }),
1137
+ /* @__PURE__ */ jsx(Text, {
1138
+ color: opt.disabled ? Colors.muted : isFocused ? Colors.accent : void 0,
1139
+ bold: isFocused && !opt.disabled,
1140
+ dimColor: !isFocused || opt.disabled,
1141
+ children: label
1142
+ })
1143
+ ]
1092
1144
  }, flatIdx);
1093
1145
  })
1094
1146
  }, colIdx))
@@ -1937,6 +1989,8 @@ const TabContainer = ({ tabs, statusMessage, expandableStatus = false, store })
1937
1989
  /* @__PURE__ */ jsx(Box, {
1938
1990
  gap: 1,
1939
1991
  paddingX: 1,
1992
+ flexWrap: "wrap",
1993
+ flexShrink: 0,
1940
1994
  children: tabs.map((tab, i) => /* @__PURE__ */ jsx(Text, {
1941
1995
  inverse: i === activeTab,
1942
1996
  color: i === activeTab ? Colors.accent : Colors.muted,
@@ -2330,6 +2384,12 @@ const TIPS = [
2330
2384
  title: "Get way more detail using properties",
2331
2385
  description: "Events and person records can have any properties you want. Track things like how they found your website, what subscription tier they choose, and much more."
2332
2386
  },
2387
+ {
2388
+ id: "slack",
2389
+ title: "Use PostHog in Slack",
2390
+ description: "Connect the PostHog Slack app to analyze data and ship product changes — deploy flags, open PRs, run queries — just by tagging @PostHog:",
2391
+ url: "https://posthog.com/slack-app"
2392
+ },
2333
2393
  {
2334
2394
  id: "stripe",
2335
2395
  title: "You can track Stripe revenue with PostHog",
@@ -3749,6 +3809,13 @@ var neutralCrossSell = [{
3749
3809
  "prompt": "List the top errors my users hit this week.",
3750
3810
  "description": "Built-in error tracking — no separate tool."
3751
3811
  }];
3812
+ var slackApp = {
3813
+ "learnMoreUrl": "https://posthog.com/slack-app",
3814
+ "setupUrl": "https://app.posthog.com/settings/project-integrations#integration-slack",
3815
+ "headline": "Take PostHog to Slack",
3816
+ "pitch": "You can also analyze product data and ship changes.",
3817
+ "capabilities": ["Tag @PostHog with a bug, edit, or a feature idea. It will spin up a sandboxed environment, plan, edit files, run tests, and open a draft PR.", "Tag @PostHog with any data question. It's the same SQL-writing, statistically-minded assistant as PostHog AI, but it responds where you send work memes."]
3818
+ };
3752
3819
  //#endregion
3753
3820
  //#region src/lib/mcp-role-prompts.ts
3754
3821
  /**
@@ -3783,6 +3850,7 @@ const GENERIC_FOLLOW_UPS = genericFollowUps;
3783
3850
  const DEEP_DIVE_FOLLOW_UPS = deepDiveFollowUps;
3784
3851
  const CROSS_SELL_BY_ROLE = crossSellByRole;
3785
3852
  const NEUTRAL_CROSS_SELL = neutralCrossSell;
3853
+ const SLACK_APP = slackApp;
3786
3854
  const INTEGRATION_FAMILY = {
3787
3855
  nextjs: "fullstack",
3788
3856
  nuxt: "fullstack",
@@ -3896,6 +3964,20 @@ function getCrossSellPrompts(role) {
3896
3964
  if (!isTailoredRole(role)) return NEUTRAL_CROSS_SELL;
3897
3965
  return CROSS_SELL_BY_ROLE[role];
3898
3966
  }
3967
+ /**
3968
+ * Resolve the "Take PostHog to Slack" card. Role-independent — the Slack
3969
+ * agent's two capabilities (code/PR + data) describe the product itself,
3970
+ * not role-specific examples.
3971
+ */
3972
+ function getSlackAppCard() {
3973
+ return {
3974
+ headline: SLACK_APP.headline,
3975
+ pitch: SLACK_APP.pitch,
3976
+ learnMoreUrl: SLACK_APP.learnMoreUrl,
3977
+ setupUrl: SLACK_APP.setupUrl,
3978
+ capabilities: SLACK_APP.capabilities
3979
+ };
3980
+ }
3899
3981
  //#endregion
3900
3982
  //#region src/ui/tui/screens/McpSuggestedPromptsScreen.tsx
3901
3983
  /**
@@ -3936,6 +4018,25 @@ function getCrossSellPrompts(role) {
3936
4018
  * forces a successful login first). A defensive throw protects the
3937
4019
  * Running useEffect against a state-machine bug.
3938
4020
  */
4021
+ var Phase = /* @__PURE__ */ function(Phase) {
4022
+ Phase["Choose"] = "choose";
4023
+ Phase["Authenticating"] = "authenticating";
4024
+ Phase["Greeting"] = "greeting";
4025
+ Phase["PromptPicker"] = "prompt-picker";
4026
+ Phase["Running"] = "running";
4027
+ Phase["FollowUp"] = "follow-up";
4028
+ /** Final beat on every dismissal — reminds the user how to keep
4029
+ * talking to PostHog after the tutorial ends. */
4030
+ Phase["Goodbye"] = "goodbye";
4031
+ Phase["Done"] = "done";
4032
+ return Phase;
4033
+ }(Phase || {});
4034
+ var ChoiceValue$1 = /* @__PURE__ */ function(ChoiceValue) {
4035
+ ChoiceValue["Login"] = "login";
4036
+ ChoiceValue["ConnectSlack"] = "connect-slack";
4037
+ ChoiceValue["Exit"] = "exit";
4038
+ return ChoiceValue;
4039
+ }(ChoiceValue$1 || {});
3939
4040
  const MAX_PROMPT_RUNS = 5;
3940
4041
  const FOLLOW_UP_DELAY_MS = 3e3;
3941
4042
  const McpSuggestedPromptsScreen = ({ store, services }) => {
@@ -3944,8 +4045,9 @@ const McpSuggestedPromptsScreen = ({ store, services }) => {
3944
4045
  const kit = getRolePrompts(session.roleAtOrganization, session.integration);
3945
4046
  const crossSell = useMemo(() => getCrossSellPrompts(session.roleAtOrganization), [session.roleAtOrganization]);
3946
4047
  const greeting = useMemo(() => getRoleGreeting(session.roleAtOrganization), [session.roleAtOrganization]);
3947
- const [phase, setPhase] = useState("choose");
4048
+ const [phase, setPhase] = useState(() => store.session.credentials ? "choose" : "authenticating");
3948
4049
  const [loginError, setLoginError] = useState(null);
4050
+ const startedTutorialRef = useRef(false);
3949
4051
  const [runningPrompt, setRunningPrompt] = useState(null);
3950
4052
  const [runChunks, setRunChunks] = useState([]);
3951
4053
  const [runStartedAt, setRunStartedAt] = useState(null);
@@ -3967,7 +4069,7 @@ const McpSuggestedPromptsScreen = ({ store, services }) => {
3967
4069
  store.setRoleAtOrganization(roleAtOrganization);
3968
4070
  store.setApiUser(user);
3969
4071
  store.setLoginUrl(null);
3970
- setPhase("greeting");
4072
+ setPhase(startedTutorialRef.current ? "greeting" : "choose");
3971
4073
  } catch (err) {
3972
4074
  if (cancelled) return;
3973
4075
  const message = err instanceof Error ? err.message : String(err);
@@ -3985,6 +4087,28 @@ const McpSuggestedPromptsScreen = ({ store, services }) => {
3985
4087
  services,
3986
4088
  store
3987
4089
  ]);
4090
+ const credentials = session.credentials;
4091
+ const slackConnected = session.slackConnected;
4092
+ useEffect(() => {
4093
+ if (!credentials || slackConnected !== null) return;
4094
+ let cancelled = false;
4095
+ const controller = new AbortController();
4096
+ services.checkSlackConnected(credentials, controller.signal).then((connected) => {
4097
+ if (!cancelled) store.setSlackConnected(connected);
4098
+ }).catch((err) => {
4099
+ if (cancelled) return;
4100
+ analytics.captureException(err instanceof Error ? err : new Error(String(err)), { step: "slack_connected_check" });
4101
+ });
4102
+ return () => {
4103
+ cancelled = true;
4104
+ controller.abort();
4105
+ };
4106
+ }, [
4107
+ credentials,
4108
+ slackConnected,
4109
+ services,
4110
+ store
4111
+ ]);
3988
4112
  useEffect(() => {
3989
4113
  if (phase !== "running") return;
3990
4114
  if (!runningPrompt) return;
@@ -4070,7 +4194,11 @@ const McpSuggestedPromptsScreen = ({ store, services }) => {
4070
4194
  setLoginError(null);
4071
4195
  if (choice === "login") {
4072
4196
  analytics.wizardCapture("mcp suggested prompts choose", { choice: "login" });
4073
- setPhase("authenticating");
4197
+ startedTutorialRef.current = true;
4198
+ setPhase(session.credentials ? "greeting" : "authenticating");
4199
+ } else if (choice === "connect-slack") {
4200
+ analytics.wizardCapture("mcp suggested prompts choose", { choice: "connect-slack" });
4201
+ opn(getSlackAppCard().setupUrl, { wait: false }).catch(() => {});
4074
4202
  } else {
4075
4203
  analytics.wizardCapture("mcp suggested prompts choose", { choice: "exit" });
4076
4204
  enterGoodbye();
@@ -4106,9 +4234,10 @@ const McpSuggestedPromptsScreen = ({ store, services }) => {
4106
4234
  {
4107
4235
  match: "escape",
4108
4236
  label: "esc",
4109
- action: phase === "goodbye" ? "close" : "exit",
4237
+ action: phase === "goodbye" ? "close" : phase === "authenticating" ? "cancel" : "exit",
4110
4238
  handler: () => {
4111
4239
  if (phase === "goodbye") closeWizard();
4240
+ else if (phase === "authenticating") setPhase("choose");
4112
4241
  else if (phase === "running" || phase === "prompt-picker" || phase === "follow-up" || phase === "greeting") enterGoodbye();
4113
4242
  }
4114
4243
  },
@@ -4142,6 +4271,7 @@ const McpSuggestedPromptsScreen = ({ store, services }) => {
4142
4271
  children: [
4143
4272
  phase === "choose" && /* @__PURE__ */ jsx(ChoosePhase, {
4144
4273
  error: loginError,
4274
+ slackConnected,
4145
4275
  onSelect: handleChoice
4146
4276
  }),
4147
4277
  phase === "authenticating" && /* @__PURE__ */ jsx(AuthenticatingPhase, { loginUrl: session.loginUrl }),
@@ -4204,71 +4334,112 @@ const McpSuggestedPromptsScreen = ({ store, services }) => {
4204
4334
  })
4205
4335
  });
4206
4336
  };
4207
- const ChoosePhase = ({ error, onSelect }) => /* @__PURE__ */ jsxs(Box, {
4208
- flexDirection: "column",
4209
- children: [
4210
- /* @__PURE__ */ jsx(Text, {
4211
- bold: true,
4212
- color: Colors.accent,
4213
- children: "PostHog MCP"
4214
- }),
4215
- /* @__PURE__ */ jsx(Box, {
4216
- marginTop: 1,
4217
- children: /* @__PURE__ */ jsx(Text, { children: "With MCP your agent works directly with the PostHog platform. You can prompt it to:" })
4218
- }),
4219
- /* @__PURE__ */ jsxs(Box, {
4220
- marginTop: 1,
4221
- flexDirection: "column",
4222
- children: [
4223
- /* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
4224
- color: "cyan",
4225
- children: Icons.diamond
4226
- }), " Build dashboards"] }),
4227
- /* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
4228
- color: "cyan",
4229
- children: Icons.diamond
4230
- }), " Run SQL queries"] }),
4231
- /* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
4232
- color: "cyan",
4233
- children: Icons.diamond
4234
- }), " Deploy feature flags"] }),
4235
- /* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
4236
- color: "cyan",
4237
- children: Icons.diamond
4238
- }), " Debug exceptions and errors"] }),
4239
- /* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
4240
- color: "cyan",
4241
- children: Icons.diamond
4242
- }), " And lots more..."] })
4243
- ]
4244
- }),
4245
- /* @__PURE__ */ jsx(Box, {
4246
- marginTop: 1,
4247
- children: /* @__PURE__ */ jsx(Text, { children: "Want a live demo using real data from your project?" })
4248
- }),
4249
- /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(PickerMenu, {
4250
- options: [{
4251
- label: "Start MCP tutorial",
4252
- value: "login"
4253
- }, {
4254
- label: "Exit",
4255
- value: "exit"
4256
- }],
4257
- onSelect
4258
- }) }),
4259
- error && /* @__PURE__ */ jsx(Box, {
4260
- marginTop: 1,
4261
- children: /* @__PURE__ */ jsxs(Text, {
4262
- color: "red",
4337
+ const ChoosePhase = ({ error, slackConnected, onSelect }) => {
4338
+ return /* @__PURE__ */ jsxs(Box, {
4339
+ flexDirection: "column",
4340
+ children: [
4341
+ /* @__PURE__ */ jsx(Text, {
4342
+ bold: true,
4343
+ color: Colors.accent,
4344
+ children: "PostHog MCP"
4345
+ }),
4346
+ /* @__PURE__ */ jsx(Box, {
4347
+ marginTop: 1,
4348
+ children: /* @__PURE__ */ jsx(Text, { children: "With MCP your agent works directly with the PostHog platform. You can prompt it to:" })
4349
+ }),
4350
+ /* @__PURE__ */ jsxs(Box, {
4351
+ marginTop: 1,
4352
+ flexDirection: "column",
4263
4353
  children: [
4264
- "Login failed: ",
4265
- error,
4266
- ". Try again or exit."
4354
+ /* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
4355
+ color: "cyan",
4356
+ children: Icons.diamond
4357
+ }), " Build dashboards"] }),
4358
+ /* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
4359
+ color: "cyan",
4360
+ children: Icons.diamond
4361
+ }), " Run SQL queries"] }),
4362
+ /* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
4363
+ color: "cyan",
4364
+ children: Icons.diamond
4365
+ }), " Deploy feature flags"] }),
4366
+ /* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
4367
+ color: "cyan",
4368
+ children: Icons.diamond
4369
+ }), " Debug exceptions and errors"] }),
4370
+ /* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
4371
+ color: "cyan",
4372
+ children: Icons.diamond
4373
+ }), " And lots more..."] })
4267
4374
  ]
4375
+ }),
4376
+ /* @__PURE__ */ jsx(Box, {
4377
+ marginTop: 1,
4378
+ flexDirection: "column",
4379
+ children: slackConnected ? /* @__PURE__ */ jsxs(Text, { children: [
4380
+ /* @__PURE__ */ jsx(Text, {
4381
+ color: Colors.success,
4382
+ children: Icons.check
4383
+ }),
4384
+ " Slack is connected — analyze data and ship product changes there by tagging",
4385
+ " ",
4386
+ /* @__PURE__ */ jsx(Text, {
4387
+ bold: true,
4388
+ children: "@PostHog"
4389
+ }),
4390
+ "."
4391
+ ] }) : /* @__PURE__ */ jsxs(Text, { children: [
4392
+ "You can also connect PostHog to Slack, so you can analyze data and ship product changes there by tagging ",
4393
+ /* @__PURE__ */ jsx(Text, {
4394
+ bold: true,
4395
+ children: "@PostHog"
4396
+ }),
4397
+ "."
4398
+ ] })
4399
+ }),
4400
+ /* @__PURE__ */ jsx(Box, {
4401
+ marginTop: 1,
4402
+ children: /* @__PURE__ */ jsx(Text, { children: "Want a live demo using real data from your project?" })
4403
+ }),
4404
+ /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(PickerMenu, {
4405
+ options: [
4406
+ {
4407
+ label: "Start MCP tutorial",
4408
+ value: "login"
4409
+ },
4410
+ slackConnected ? {
4411
+ label: "Already connected to Slack",
4412
+ value: "connect-slack",
4413
+ icon: {
4414
+ glyph: Icons.check,
4415
+ color: Colors.success
4416
+ },
4417
+ disabled: true
4418
+ } : {
4419
+ label: "Connect Slack now",
4420
+ value: "connect-slack"
4421
+ },
4422
+ {
4423
+ label: "Exit",
4424
+ value: "exit"
4425
+ }
4426
+ ],
4427
+ onSelect
4428
+ }) }),
4429
+ error && /* @__PURE__ */ jsx(Box, {
4430
+ marginTop: 1,
4431
+ children: /* @__PURE__ */ jsxs(Text, {
4432
+ color: "red",
4433
+ children: [
4434
+ "Login failed: ",
4435
+ error,
4436
+ ". Try again or exit."
4437
+ ]
4438
+ })
4268
4439
  })
4269
- })
4270
- ]
4271
- });
4440
+ ]
4441
+ });
4442
+ };
4272
4443
  const AuthenticatingPhase = ({ loginUrl }) => /* @__PURE__ */ jsxs(Box, {
4273
4444
  flexDirection: "column",
4274
4445
  children: [/* @__PURE__ */ jsx(LoadingBox, { message: "Waiting for authentication..." }), loginUrl && /* @__PURE__ */ jsx(Box, {
@@ -4606,7 +4777,7 @@ const GoodbyePhase = ({ installedClients, role, integration, engaged, onClose })
4606
4777
  label: "Close",
4607
4778
  value: "close"
4608
4779
  }],
4609
- onSelect: onClose
4780
+ onSelect: () => onClose()
4610
4781
  })
4611
4782
  ]
4612
4783
  });
@@ -5472,6 +5643,327 @@ const AUDIT_3000_AREA_SLIDES = [
5472
5643
  }
5473
5644
  ];
5474
5645
  //#endregion
5475
- 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 };
5646
+ //#region src/ui/tui/screens/SlackConnectScreen.tsx
5647
+ /**
5648
+ * SlackConnectScreen — the dedicated "Connect Slack" step shown after the
5649
+ * MCP tutorial (`wizard mcp tutorial`) and after a successful install
5650
+ * (`wizard mcp add`).
5651
+ *
5652
+ * Presents the PostHog Slack app plus role-tailored use-cases. The copy
5653
+ * adapts to whether Slack is already connected (polled while the screen
5654
+ * is up, held as local state):
5655
+ * • not connected (or unknown) — nudge + "Open Slack setup", which
5656
+ * launches the browser at the integration settings page and keeps
5657
+ * the screen alive; the poll flips it to connected once the user
5658
+ * finishes the manual OAuth step in the browser.
5659
+ * • already connected — confirm it and skip the connect CTA, so users
5660
+ * who already have it aren't nagged.
5661
+ * "Skip" / "Done" / esc dismiss the step (`slackStepDismissed`) and let
5662
+ * the router advance to exit.
5663
+ */
5664
+ var ChoiceValue = /* @__PURE__ */ function(ChoiceValue) {
5665
+ ChoiceValue["Open"] = "open";
5666
+ ChoiceValue["Skip"] = "skip";
5667
+ return ChoiceValue;
5668
+ }(ChoiceValue || {});
5669
+ const POLL_INTERVAL_MS = 3e3;
5670
+ const SlackConnectScreen = ({ store }) => {
5671
+ useSyncExternalStore((cb) => store.subscribe(cb), () => store.getSnapshot());
5672
+ const role = store.session.roleAtOrganization;
5673
+ const slack = getSlackAppCard();
5674
+ useEffect(() => {
5675
+ analytics.wizardCapture("slack connect shown", { role });
5676
+ }, []);
5677
+ const connected = store.session.slackConnected === true;
5678
+ const credentials = store.session.credentials;
5679
+ useEffect(() => {
5680
+ if (!credentials || connected) return;
5681
+ let cancelled = false;
5682
+ let timer;
5683
+ const controller = new AbortController();
5684
+ const check = () => {
5685
+ fetchSlackConnected(credentials.accessToken, credentials.projectId, credentials.host, controller.signal).then((isConnected) => {
5686
+ if (cancelled) return;
5687
+ if (isConnected) store.setSlackConnected(true);
5688
+ else timer = setTimeout(check, POLL_INTERVAL_MS);
5689
+ }).catch((err) => {
5690
+ if (cancelled) return;
5691
+ analytics.captureException(err instanceof Error ? err : new Error(String(err)), { step: "slack_connected_check" });
5692
+ });
5693
+ };
5694
+ check();
5695
+ return () => {
5696
+ cancelled = true;
5697
+ if (timer) clearTimeout(timer);
5698
+ controller.abort();
5699
+ };
5700
+ }, [
5701
+ credentials,
5702
+ connected,
5703
+ store
5704
+ ]);
5705
+ const dismiss = () => {
5706
+ analytics.wizardCapture("slack connect skipped", {
5707
+ role,
5708
+ connected
5709
+ });
5710
+ store.setSlackStepDismissed();
5711
+ };
5712
+ const handleSelect = (value) => {
5713
+ if ((Array.isArray(value) ? value[0] : value) === "open") {
5714
+ analytics.wizardCapture("slack connect opened", { role });
5715
+ opn(slack.setupUrl, { wait: false }).catch(() => {});
5716
+ return;
5717
+ }
5718
+ dismiss();
5719
+ };
5720
+ useKeyBindings("slack-connect", [{
5721
+ match: "escape",
5722
+ label: "esc",
5723
+ action: connected ? "done" : "skip",
5724
+ handler: () => dismiss()
5725
+ }]);
5726
+ return /* @__PURE__ */ jsx(Box, {
5727
+ flexDirection: "column",
5728
+ flexGrow: 1,
5729
+ children: /* @__PURE__ */ jsxs(Box, {
5730
+ marginTop: 1,
5731
+ flexDirection: "column",
5732
+ children: [
5733
+ connected ? /* @__PURE__ */ jsxs(Text, {
5734
+ bold: true,
5735
+ color: Colors.success,
5736
+ children: [Icons.check, " Slack connected"]
5737
+ }) : /* @__PURE__ */ jsx(Text, {
5738
+ bold: true,
5739
+ color: Colors.accent,
5740
+ children: slack.headline
5741
+ }),
5742
+ /* @__PURE__ */ jsx(Box, {
5743
+ marginTop: 1,
5744
+ children: /* @__PURE__ */ jsx(Text, { children: connected ? "Slack is connected — here's what you can do:" : slack.pitch })
5745
+ }),
5746
+ /* @__PURE__ */ jsx(Box, {
5747
+ marginTop: 1,
5748
+ flexDirection: "column",
5749
+ children: slack.capabilities.map((capability, i) => /* @__PURE__ */ jsx(Box, {
5750
+ marginTop: i === 0 ? 0 : 1,
5751
+ children: /* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsxs(Text, {
5752
+ color: "cyan",
5753
+ children: [Icons.diamond, " "]
5754
+ }), capability] })
5755
+ }, i))
5756
+ }),
5757
+ /* @__PURE__ */ jsxs(Box, {
5758
+ marginTop: 1,
5759
+ flexDirection: "column",
5760
+ children: [!connected && /* @__PURE__ */ jsxs(Text, {
5761
+ dimColor: true,
5762
+ children: ["Connect it: ", /* @__PURE__ */ jsx(Text, {
5763
+ color: "cyan",
5764
+ children: slack.setupUrl
5765
+ })]
5766
+ }), /* @__PURE__ */ jsxs(Text, {
5767
+ dimColor: true,
5768
+ children: ["Learn more: ", /* @__PURE__ */ jsx(Text, {
5769
+ color: "cyan",
5770
+ children: slack.learnMoreUrl
5771
+ })]
5772
+ })]
5773
+ }),
5774
+ /* @__PURE__ */ jsx(Box, {
5775
+ marginTop: 1,
5776
+ children: /* @__PURE__ */ jsx(PickerMenu, {
5777
+ options: connected ? [{
5778
+ label: "Done",
5779
+ value: "skip"
5780
+ }] : [{
5781
+ label: "Open Slack setup",
5782
+ value: "open"
5783
+ }, {
5784
+ label: "Skip",
5785
+ value: "skip"
5786
+ }],
5787
+ onSelect: handleSelect
5788
+ })
5789
+ })
5790
+ ]
5791
+ })
5792
+ });
5793
+ };
5794
+ //#endregion
5795
+ //#region src/ui/tui/screens/OutroScreen.tsx
5796
+ /**
5797
+ * OutroScreen — Default post-run summary.
5798
+ *
5799
+ * Renders the success / error / cancel views from `outroData`. Programs
5800
+ * that need a different success view (e.g. with extra summary content)
5801
+ * ship their own screen component (see audit/AuditOutroScreen.tsx).
5802
+ */
5803
+ const OutroScreen = ({ store }) => {
5804
+ useSyncExternalStore((cb) => store.subscribe(cb), () => store.getSnapshot());
5805
+ useInput(() => {
5806
+ store.setOutroDismissed();
5807
+ });
5808
+ const outroData = store.session.outroData;
5809
+ if (!outroData) return /* @__PURE__ */ jsx(Box, {
5810
+ flexDirection: "column",
5811
+ flexGrow: 1,
5812
+ children: /* @__PURE__ */ jsx(Text, {
5813
+ dimColor: true,
5814
+ children: "Finishing up..."
5815
+ })
5816
+ });
5817
+ return /* @__PURE__ */ jsxs(Box, {
5818
+ flexDirection: "column",
5819
+ flexGrow: 1,
5820
+ children: [
5821
+ outroData.kind === "success" && /* @__PURE__ */ jsxs(Box, {
5822
+ flexDirection: "column",
5823
+ children: [
5824
+ /* @__PURE__ */ jsxs(Text, {
5825
+ color: "green",
5826
+ bold: true,
5827
+ children: ["✔ ", outroData.message || "Done!"]
5828
+ }),
5829
+ outroData.body && /* @__PURE__ */ jsx(Box, {
5830
+ marginTop: 1,
5831
+ children: /* @__PURE__ */ jsx(Text, {
5832
+ dimColor: true,
5833
+ children: outroData.body
5834
+ })
5835
+ }),
5836
+ outroData.reportFile && /* @__PURE__ */ jsx(Box, {
5837
+ marginTop: 1,
5838
+ children: /* @__PURE__ */ jsxs(Text, { children: [
5839
+ "Check ",
5840
+ /* @__PURE__ */ jsxs(Text, {
5841
+ bold: true,
5842
+ children: ["./", outroData.reportFile]
5843
+ }),
5844
+ " for details"
5845
+ ] })
5846
+ }),
5847
+ outroData.changes && outroData.changes.length > 0 && /* @__PURE__ */ jsxs(Box, {
5848
+ flexDirection: "column",
5849
+ marginTop: 1,
5850
+ children: [/* @__PURE__ */ jsx(Text, {
5851
+ color: "cyan",
5852
+ bold: true,
5853
+ children: "What the agent did:"
5854
+ }), outroData.changes.map((change, i) => /* @__PURE__ */ jsxs(Text, { children: ["• ", change] }, i))]
5855
+ }),
5856
+ store.eventPlan.length > 0 && /* @__PURE__ */ jsxs(Box, {
5857
+ flexDirection: "column",
5858
+ marginTop: 1,
5859
+ children: [/* @__PURE__ */ jsx(Text, {
5860
+ color: "cyan",
5861
+ bold: true,
5862
+ children: "Events added:"
5863
+ }), store.eventPlan.map((event) => /* @__PURE__ */ jsxs(Text, { children: [
5864
+ "• ",
5865
+ /* @__PURE__ */ jsx(Text, {
5866
+ bold: true,
5867
+ children: event.name
5868
+ }),
5869
+ /* @__PURE__ */ jsxs(Text, {
5870
+ dimColor: true,
5871
+ children: [" ", event.description]
5872
+ })
5873
+ ] }, event.name))]
5874
+ }),
5875
+ outroData.dashboardUrl && /* @__PURE__ */ jsx(Box, {
5876
+ marginTop: 1,
5877
+ children: /* @__PURE__ */ jsxs(Text, { children: [
5878
+ "We've also made you a dashboard:",
5879
+ " ",
5880
+ /* @__PURE__ */ jsx(Text, {
5881
+ color: "cyan",
5882
+ children: outroData.dashboardUrl
5883
+ })
5884
+ ] })
5885
+ }),
5886
+ outroData.notebookUrl && /* @__PURE__ */ jsx(Box, {
5887
+ marginTop: 1,
5888
+ children: /* @__PURE__ */ jsxs(Text, { children: [
5889
+ "And uploaded the report to a PostHog notebook:",
5890
+ " ",
5891
+ /* @__PURE__ */ jsx(Text, {
5892
+ color: "cyan",
5893
+ children: outroData.notebookUrl
5894
+ })
5895
+ ] })
5896
+ }),
5897
+ outroData.docsUrl && /* @__PURE__ */ jsx(Box, {
5898
+ marginTop: 1,
5899
+ children: /* @__PURE__ */ jsxs(Text, { children: ["Learn more: ", /* @__PURE__ */ jsx(Text, {
5900
+ color: "cyan",
5901
+ children: outroData.docsUrl
5902
+ })] })
5903
+ }),
5904
+ outroData.continueUrl && /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { children: [
5905
+ "Continue onboarding:",
5906
+ " ",
5907
+ /* @__PURE__ */ jsx(Text, {
5908
+ color: "cyan",
5909
+ children: outroData.continueUrl
5910
+ })
5911
+ ] }) }),
5912
+ /* @__PURE__ */ jsx(Box, {
5913
+ marginTop: 1,
5914
+ children: /* @__PURE__ */ jsx(Text, {
5915
+ dimColor: true,
5916
+ children: "Note: This wizard uses an LLM agent to analyze and modify your project. Please review the changes made."
5917
+ })
5918
+ }),
5919
+ /* @__PURE__ */ jsx(Text, {
5920
+ dimColor: true,
5921
+ children: "How did this work for you? Drop us a line: wizard@posthog.com"
5922
+ })
5923
+ ]
5924
+ }),
5925
+ outroData.kind === "error" && /* @__PURE__ */ jsxs(Box, {
5926
+ flexDirection: "column",
5927
+ children: [
5928
+ /* @__PURE__ */ jsxs(Text, {
5929
+ color: "red",
5930
+ bold: true,
5931
+ children: ["✘ ", outroData.message || "An error occurred"]
5932
+ }),
5933
+ outroData.body && /* @__PURE__ */ jsx(Box, {
5934
+ marginTop: 1,
5935
+ children: /* @__PURE__ */ jsx(Text, {
5936
+ dimColor: true,
5937
+ children: outroData.body
5938
+ })
5939
+ }),
5940
+ outroData.docsUrl && /* @__PURE__ */ jsx(Box, {
5941
+ marginTop: 1,
5942
+ children: /* @__PURE__ */ jsxs(Text, { children: ["Docs: ", /* @__PURE__ */ jsx(Text, {
5943
+ color: "cyan",
5944
+ children: outroData.docsUrl
5945
+ })] })
5946
+ })
5947
+ ]
5948
+ }),
5949
+ outroData.kind === "cancel" && /* @__PURE__ */ jsx(Box, {
5950
+ flexDirection: "column",
5951
+ children: /* @__PURE__ */ jsxs(Text, {
5952
+ color: "yellow",
5953
+ children: ["■ ", outroData.message || "Cancelled"]
5954
+ })
5955
+ }),
5956
+ /* @__PURE__ */ jsx(Box, {
5957
+ marginTop: 1,
5958
+ children: /* @__PURE__ */ jsx(Text, {
5959
+ color: Colors.muted,
5960
+ children: "Press any key to continue"
5961
+ })
5962
+ })
5963
+ ]
5964
+ });
5965
+ };
5966
+ //#endregion
5967
+ export { SplitView as A, ConfirmationInput as C, useKeyBindings as D, PickerMenu as E, WizardStore as M, ProgressList as O, ModalOverlay as S, useStdoutDimensions as T, HNViewer as _, VisualBox as a, EventPlanViewer as b, TAILORED_ROLES as c, SEVERITY_LABEL as d, SEVERITY_ORDER as f, ContentSequencer as g, LearnCard as h, AUDIT_AREA_SLIDES as i, CardLayout as j, LoadingBox as k, McpScreen as l, TipsCard as m, SlackConnectScreen as n, AuditChecksViewer as o, ServiceHealthList as p, AUDIT_3000_AREA_SLIDES as r, McpSuggestedPromptsScreen as s, OutroScreen as t, IssueTable as u, TabContainer as v, GroupedPickerMenu as w, LogViewer as x, ScreenContainer as y };
5476
5968
 
5477
- //# sourceMappingURL=slides-mT2s9wM_.js.map
5969
+ //# sourceMappingURL=OutroScreen-CqF6SdBo.js.map