@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.
- package/README.md +11 -0
- package/dist/{slides-mT2s9wM_.js → OutroScreen-CqF6SdBo.js} +614 -122
- package/dist/OutroScreen-CqF6SdBo.js.map +1 -0
- package/dist/{add-mcp-server-to-clients-CjnvTVj0.js → add-mcp-server-to-clients-DQHGhzt6.js} +4 -4
- package/dist/{add-mcp-server-to-clients-CjnvTVj0.js.map → add-mcp-server-to-clients-DQHGhzt6.js.map} +1 -1
- package/dist/{agent-interface-CQU6x4Hj.js → agent-interface-DE7txTqh.js} +163 -52
- package/dist/agent-interface-DE7txTqh.js.map +1 -0
- package/dist/{agent-runner-Cj7saDkL.js → agent-runner-DUZ5OD6e.js} +10 -9
- package/dist/{agent-runner-Cj7saDkL.js.map → agent-runner-DUZ5OD6e.js.map} +1 -1
- package/dist/{analytics-Df-Xb81i.js → analytics-Bl5DPj_0.js} +2 -2
- package/dist/{analytics-Df-Xb81i.js.map → analytics-Bl5DPj_0.js.map} +1 -1
- package/dist/{api-Dw6_orDE.js → api-DuA0_88V.js} +25 -4
- package/dist/{api-Dw6_orDE.js.map → api-DuA0_88V.js.map} +1 -1
- package/dist/bin.js +74 -47
- package/dist/bin.js.map +1 -1
- package/dist/check-screens.tsx +124 -0
- package/dist/{ci-install-BKAvFfK6.js → ci-install-BnOYI4mZ.js} +4 -4
- package/dist/{ci-install-BKAvFfK6.js.map → ci-install-BnOYI4mZ.js.map} +1 -1
- package/dist/{debug-Cp_wNn8i.js → debug-BVC48wlb.js} +1 -1
- package/dist/{debug-DnMO6O8O.js → debug-h7Z9zEbD.js} +2 -2
- package/dist/{debug-DnMO6O8O.js.map → debug-h7Z9zEbD.js.map} +1 -1
- package/dist/{environment-Ls0H9ljT.js → environment-uaLmtlH_.js} +3 -3
- package/dist/{environment-Ls0H9ljT.js.map → environment-uaLmtlH_.js.map} +1 -1
- package/dist/{interactive-D15byhpc.js → interactive-CW5gjyDd.js} +2 -2
- package/dist/{interactive-D15byhpc.js.map → interactive-CW5gjyDd.js.map} +1 -1
- package/dist/{mcp-prompt-streaming-DQOTQfW1.js → mcp-prompt-streaming-DMDwaark.js} +4 -4
- package/dist/{mcp-prompt-streaming-DQOTQfW1.js.map → mcp-prompt-streaming-DMDwaark.js.map} +1 -1
- package/dist/{non-interactive-DcFLJtl_.js → non-interactive-DJrVQ4nS.js} +2 -2
- package/dist/{non-interactive-DcFLJtl_.js.map → non-interactive-DJrVQ4nS.js.map} +1 -1
- package/dist/{package-manager-DUPgLGpQ.js → package-manager-DCUBRbr-.js} +2 -2
- package/dist/{package-manager-DUPgLGpQ.js.map → package-manager-DCUBRbr-.js.map} +1 -1
- package/dist/{playground-BZ0hGjbL.js → playground-DCVaVeVD.js} +138 -9
- package/dist/playground-DCVaVeVD.js.map +1 -0
- package/dist/{posthog-integration-C8qhJnI3.js → posthog-integration-ChdwFPMj.js} +17 -11
- package/dist/posthog-integration-ChdwFPMj.js.map +1 -0
- package/dist/{provisioning-C-2ExcqY.js → provisioning-GeMkBMSR.js} +3 -3
- package/dist/{provisioning-C-2ExcqY.js.map → provisioning-GeMkBMSR.js.map} +1 -1
- package/dist/{registry-hBUgaWFx.js → registry-VSSRH3sU.js} +4 -4
- package/dist/{registry-hBUgaWFx.js.map → registry-VSSRH3sU.js.map} +1 -1
- package/dist/{setup-utils-DetnhXo0.js → setup-utils-BfV4pydt.js} +12 -10
- package/dist/setup-utils-BfV4pydt.js.map +1 -0
- package/dist/{start-tui-BfXoErKg.js → start-tui-BRvm5VP9.js} +93 -228
- package/dist/start-tui-BRvm5VP9.js.map +1 -0
- package/dist/{steps-SoDXSUxe.js → steps-DA4uvSbg.js} +6 -6
- package/dist/{steps-SoDXSUxe.js.map → steps-DA4uvSbg.js.map} +1 -1
- package/dist/{task-stream-CZRj6auI.js → task-stream-CZawuzlz.js} +2 -2
- package/dist/{task-stream-CZRj6auI.js.map → task-stream-CZawuzlz.js.map} +1 -1
- package/dist/{telemetry-CPcMFxcO.js → telemetry-BRAonUea.js} +2 -2
- package/dist/{telemetry-CPcMFxcO.js.map → telemetry-BRAonUea.js.map} +1 -1
- package/dist/{urls-BO7doNJG.js → urls-B66Ib2jT.js} +2 -2
- package/dist/{urls-BO7doNJG.js.map → urls-B66Ib2jT.js.map} +1 -1
- package/dist/{wizard-abort-CDXufkqJ.js → wizard-abort-D1_DnFjm.js} +12 -7
- package/dist/wizard-abort-D1_DnFjm.js.map +1 -0
- package/dist/wizard-abort-gMB1eV6T.js +2 -0
- package/dist/{wizard-session-d27JGRGi.js → wizard-session-G3VWD6hv.js} +3 -1
- package/dist/{wizard-session-d27JGRGi.js.map → wizard-session-G3VWD6hv.js.map} +1 -1
- package/dist/{wizard-session-y304gEEI.js → wizard-session-wPJtNl4c.js} +1 -1
- package/dist/wizard-ui-YdGFRyu_.js.map +1 -1
- package/package.json +4 -2
- package/dist/agent-interface-CQU6x4Hj.js.map +0 -1
- package/dist/playground-BZ0hGjbL.js.map +0 -1
- package/dist/posthog-integration-C8qhJnI3.js.map +0 -1
- package/dist/setup-utils-DetnhXo0.js.map +0 -1
- package/dist/slides-mT2s9wM_.js.map +0 -1
- package/dist/start-tui-BfXoErKg.js.map +0 -1
- package/dist/wizard-abort-CDXufkqJ.js.map +0 -1
- package/dist/wizard-abort-CtMY57ZE.js +0 -2
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
import { g as SERVICE_LABELS, s as logToFile } from "./debug-
|
|
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-
|
|
4
|
-
import { i as
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
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
|
|
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(
|
|
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
|
-
|
|
922
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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: [
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
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(
|
|
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
|
-
|
|
1003
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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: [
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
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
|
-
|
|
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 }) =>
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
|
|
4211
|
-
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
|
|
4221
|
-
|
|
4222
|
-
|
|
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
|
-
|
|
4265
|
-
|
|
4266
|
-
|
|
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
|
-
|
|
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=
|
|
5969
|
+
//# sourceMappingURL=OutroScreen-CqF6SdBo.js.map
|