@posthog/wizard 2.15.0 → 2.16.1
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 +0 -4
- package/dist/{TextBlock-B_8bXLLs.js → TextBlock-CdeZog_6.js} +4 -4
- package/dist/TextBlock-CdeZog_6.js.map +1 -0
- package/dist/{add-mcp-server-to-clients-Dq0n2yzq.js → add-mcp-server-to-clients-BS6Rjcwh.js} +6 -6
- package/dist/{add-mcp-server-to-clients-Dq0n2yzq.js.map → add-mcp-server-to-clients-BS6Rjcwh.js.map} +1 -1
- package/dist/{agent-interface-yB_27jG8.js → agent-interface-B4eUlMso.js} +33 -7
- package/dist/agent-interface-B4eUlMso.js.map +1 -0
- package/dist/{agent-runner-C9sSudE0.js → agent-runner-BxqiKVEf.js} +21 -22
- package/dist/{agent-runner-C9sSudE0.js.map → agent-runner-BxqiKVEf.js.map} +1 -1
- package/dist/{analytics-Da4QHjMw.js → analytics-DUuUurR3.js} +3 -3
- package/dist/{analytics-Da4QHjMw.js.map → analytics-DUuUurR3.js.map} +1 -1
- package/dist/api-B8OR0N1V.js +2 -0
- package/dist/api-CGJ1iGps.js +138 -0
- package/dist/api-CGJ1iGps.js.map +1 -0
- package/dist/bin.js +808 -476
- package/dist/bin.js.map +1 -1
- package/dist/ci-install-DD7WMmIF.js +73 -0
- package/dist/ci-install-DD7WMmIF.js.map +1 -0
- package/dist/{debug-D5kt4fxB.js → debug-Cd0hPlZy.js} +1 -1
- package/dist/{debug-DRKLej5r.js → debug-ubpO6102.js} +14 -6
- package/dist/debug-ubpO6102.js.map +1 -0
- package/dist/{defaults-CPH6eWhN.js → defaults-zrYmZ2ID.js} +1 -1
- package/dist/{defaults-CPH6eWhN.js.map → defaults-zrYmZ2ID.js.map} +1 -1
- package/dist/{env-api-key-HFqv1l-z.js → env-api-key-DEl3LJBv.js} +4 -2
- package/dist/{env-api-key-HFqv1l-z.js.map → env-api-key-DEl3LJBv.js.map} +1 -1
- package/dist/environment-BAaC5THg.js +22 -0
- package/dist/environment-BAaC5THg.js.map +1 -0
- package/dist/{file-utils-DnTSiTJw.js → file-utils-DPmgn9Vm.js} +1 -1
- package/dist/{file-utils-DnTSiTJw.js.map → file-utils-DPmgn9Vm.js.map} +1 -1
- package/dist/interactive-BaMAq88Q.js +11 -0
- package/dist/interactive-BaMAq88Q.js.map +1 -0
- package/dist/mcp-prompt-streaming-clGsVw8q.js +200 -0
- package/dist/mcp-prompt-streaming-clGsVw8q.js.map +1 -0
- package/dist/non-interactive-l2AKE3jD.js +12 -0
- package/dist/non-interactive-l2AKE3jD.js.map +1 -0
- package/dist/package-json-CumwmZpv.js +2 -0
- package/dist/{package-json-v_g2YlN1.js → package-json-Cynjr9k4.js} +1 -1
- package/dist/{package-json-v_g2YlN1.js.map → package-json-Cynjr9k4.js.map} +1 -1
- package/dist/{package-manager-DlTISyej.js → package-manager-BqsJK3ej.js} +2 -2
- package/dist/{package-manager-DlTISyej.js.map → package-manager-BqsJK3ej.js.map} +1 -1
- package/dist/{start-playground-Bxd2KG2L.js → playground-DlE5RNfE.js} +297 -8
- package/dist/playground-DlE5RNfE.js.map +1 -0
- package/dist/{posthog-B1G0raJU.js → posthog-DWL8uOcl.js} +1 -1
- package/dist/{posthog-B1G0raJU.js.map → posthog-DWL8uOcl.js.map} +1 -1
- package/dist/{posthog-integration-D-DyEJvz.js → posthog-integration-Bf_vtWI9.js} +229 -21
- package/dist/posthog-integration-Bf_vtWI9.js.map +1 -0
- package/dist/provisioning-BlBnlcFd.js +2 -0
- package/dist/{provisioning-DmN8ZDbE.js → provisioning-D_hAuxUN.js} +3 -3
- package/dist/{provisioning-DmN8ZDbE.js.map → provisioning-D_hAuxUN.js.map} +1 -1
- package/dist/{registry-CofBzIdU.js → registry-DKgYqROt.js} +5 -5
- package/dist/{registry-CofBzIdU.js.map → registry-DKgYqROt.js.map} +1 -1
- package/dist/setup-utils-BHZEdkNZ.js +2 -0
- package/dist/{setup-utils-_P-or31U.js → setup-utils-D-uTycLX.js} +24 -90
- package/dist/setup-utils-D-uTycLX.js.map +1 -0
- package/dist/skill-CnOQAZXp.js +29 -0
- package/dist/skill-CnOQAZXp.js.map +1 -0
- package/dist/{slides-D3I6JzlG.js → slides-CL1mv_Kq.js} +692 -68
- package/dist/slides-CL1mv_Kq.js.map +1 -0
- package/dist/{start-tui-Bl8fCbp_.js → start-tui-DXrv6cof.js} +470 -31
- package/dist/start-tui-DXrv6cof.js.map +1 -0
- package/dist/{steps-B-vmvb2V.js → steps-CgScwqso.js} +6 -6
- package/dist/{steps-B-vmvb2V.js.map → steps-CgScwqso.js.map} +1 -1
- package/dist/{task-stream-z6QFZtpC.js → task-stream-CF6QMVMv.js} +3 -3
- package/dist/{task-stream-z6QFZtpC.js.map → task-stream-CF6QMVMv.js.map} +1 -1
- package/dist/{telemetry-XO0SlTFs.js → telemetry-v6O12Bep.js} +2 -2
- package/dist/{telemetry-XO0SlTFs.js.map → telemetry-v6O12Bep.js.map} +1 -1
- package/dist/{wizard-abort-CuaS1eXn.js → wizard-abort-BGoBKgvC.js} +1 -1
- package/dist/{wizard-abort-uolun8Q3.js → wizard-abort-iTaJ8wC8.js} +3 -3
- package/dist/{wizard-abort-uolun8Q3.js.map → wizard-abort-iTaJ8wC8.js.map} +1 -1
- package/dist/{wizard-session-DxU5ZMBN.js → wizard-session-7tMjgOvP.js} +1 -1
- package/dist/{wizard-session-BlgiX-5d.js → wizard-session-gsn8Z3bZ.js} +5 -3
- package/dist/wizard-session-gsn8Z3bZ.js.map +1 -0
- package/dist/wizard-ui-YdGFRyu_.js.map +1 -1
- package/package.json +1 -1
- package/dist/TextBlock-B_8bXLLs.js.map +0 -1
- package/dist/agent-interface-yB_27jG8.js.map +0 -1
- package/dist/analytics-BnR9904x.js +0 -2
- package/dist/debug-DRKLej5r.js.map +0 -1
- package/dist/detection-0Pz2NncX.js +0 -206
- package/dist/detection-0Pz2NncX.js.map +0 -1
- package/dist/package-json-Cttzi3C8.js +0 -2
- package/dist/posthog-integration-D-DyEJvz.js.map +0 -1
- package/dist/provisioning-COeHnCVG.js +0 -2
- package/dist/setup-utils-C5iSJ3eg.js +0 -2
- package/dist/setup-utils-_P-or31U.js.map +0 -1
- package/dist/slides-D3I6JzlG.js.map +0 -1
- package/dist/start-playground-Bxd2KG2L.js.map +0 -1
- package/dist/start-tui-Bl8fCbp_.js.map +0 -1
- package/dist/wizard-session-BlgiX-5d.js.map +0 -1
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { g as SERVICE_LABELS } from "./debug-
|
|
1
|
+
import { g as SERVICE_LABELS, s as logToFile } from "./debug-ubpO6102.js";
|
|
2
2
|
import { n as isTaskStatus } from "./wizard-ui-YdGFRyu_.js";
|
|
3
|
-
import { n as
|
|
4
|
-
import { i as buildSession } from "./wizard-session-
|
|
5
|
-
import { _ as AUDIT_SEVERITY_STYLE } from "./agent-interface-
|
|
6
|
-
import { a as isObjectBlock, i as isLinesBlock, n as computeVisibleRange, o as Colors, r as isClearBlock, s as Icons, t as TextBlock } from "./TextBlock-
|
|
7
|
-
import {
|
|
8
|
-
import { n as AVAILABLE_FEATURES, t as ALL_FEATURE_VALUES } from "./defaults-
|
|
3
|
+
import { n as sessionProperties, t as analytics } from "./analytics-DUuUurR3.js";
|
|
4
|
+
import { i as buildSession } from "./wizard-session-gsn8Z3bZ.js";
|
|
5
|
+
import { _ as AUDIT_SEVERITY_STYLE } from "./agent-interface-B4eUlMso.js";
|
|
6
|
+
import { a as isObjectBlock, i as isLinesBlock, n as computeVisibleRange, o as Colors, r as isClearBlock, s as Icons, t as TextBlock } from "./TextBlock-CdeZog_6.js";
|
|
7
|
+
import { a as getProgramConfig, i as Program, l as getKindMeta, r as PROGRAM_REGISTRY } from "./bin.js";
|
|
8
|
+
import { n as AVAILABLE_FEATURES, t as ALL_FEATURE_VALUES } from "./defaults-zrYmZ2ID.js";
|
|
9
9
|
import * as fs$1 from "fs";
|
|
10
10
|
import { Box, Text, measureElement, useInput, useStdout } from "ink";
|
|
11
11
|
import { Component, Fragment, createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
@@ -274,6 +274,14 @@ var WizardStore = class {
|
|
|
274
274
|
analytics.wizardCapture("auth complete", { project_id: credentials?.projectId });
|
|
275
275
|
this.emitChange();
|
|
276
276
|
}
|
|
277
|
+
setRoleAtOrganization(role) {
|
|
278
|
+
this.$session.setKey("roleAtOrganization", role);
|
|
279
|
+
this.emitChange();
|
|
280
|
+
}
|
|
281
|
+
setApiUser(user) {
|
|
282
|
+
this.$session.setKey("apiUser", user);
|
|
283
|
+
this.emitChange();
|
|
284
|
+
}
|
|
277
285
|
setFrameworkConfig(integration, config) {
|
|
278
286
|
this.$session.setKey("integration", integration);
|
|
279
287
|
this.$session.setKey("frameworkConfig", config);
|
|
@@ -466,6 +474,10 @@ var WizardStore = class {
|
|
|
466
474
|
});
|
|
467
475
|
this.emitChange();
|
|
468
476
|
}
|
|
477
|
+
setMcpSuggestedPromptsDismissed() {
|
|
478
|
+
this.$session.setKey("mcpSuggestedPromptsDismissed", true);
|
|
479
|
+
this.emitChange();
|
|
480
|
+
}
|
|
469
481
|
setOutroDismissed() {
|
|
470
482
|
this.$session.setKey("outroDismissed", true);
|
|
471
483
|
this.emitChange();
|
|
@@ -475,9 +487,15 @@ var WizardStore = class {
|
|
|
475
487
|
this.emitChange();
|
|
476
488
|
}
|
|
477
489
|
setDashboardUrl(url) {
|
|
490
|
+
logToFile(`store.setDashboardUrl: ${url}`);
|
|
478
491
|
this.$session.setKey("dashboardUrl", url);
|
|
479
492
|
this.emitChange();
|
|
480
493
|
}
|
|
494
|
+
setNotebookUrl(url) {
|
|
495
|
+
logToFile(`store.setNotebookUrl: ${url}`);
|
|
496
|
+
this.$session.setKey("notebookUrl", url);
|
|
497
|
+
this.emitChange();
|
|
498
|
+
}
|
|
481
499
|
setFrameworkContext(key, value) {
|
|
482
500
|
const ctx = {
|
|
483
501
|
...this.$session.get().frameworkContext,
|
|
@@ -774,22 +792,18 @@ function deduplicateAndSort(hints) {
|
|
|
774
792
|
* KeyboardHintsProvider — Context for collecting and displaying keyboard hints.
|
|
775
793
|
*
|
|
776
794
|
* Input components register their hints via useKeyBindings. The provider
|
|
777
|
-
* flattens, deduplicates, and sorts them.
|
|
778
|
-
*
|
|
795
|
+
* flattens, deduplicates, and sorts them. The hints bar stays visible for as
|
|
796
|
+
* long as a screen has registered hints — it never auto-dismisses.
|
|
779
797
|
*/
|
|
780
798
|
const KeyboardHintsContext = createContext({
|
|
781
799
|
register: () => void 0,
|
|
782
800
|
unregister: () => void 0,
|
|
783
|
-
hints: []
|
|
784
|
-
visible: false
|
|
801
|
+
hints: []
|
|
785
802
|
});
|
|
786
803
|
const useKeyboardHintsContext = () => useContext(KeyboardHintsContext);
|
|
787
|
-
const DISMISS_DELAY = 3e3;
|
|
788
804
|
const KeyboardHintsProvider = ({ children }) => {
|
|
789
805
|
const registrationsRef = useRef(/* @__PURE__ */ new Map());
|
|
790
806
|
const [hints, setHints] = useState([]);
|
|
791
|
-
const [visible, setVisible] = useState(true);
|
|
792
|
-
const timerRef = useRef(null);
|
|
793
807
|
const prevHintsKeyRef = useRef("");
|
|
794
808
|
const recompute = useCallback(() => {
|
|
795
809
|
const all = [];
|
|
@@ -799,13 +813,6 @@ const KeyboardHintsProvider = ({ children }) => {
|
|
|
799
813
|
if (newKey !== prevHintsKeyRef.current) {
|
|
800
814
|
prevHintsKeyRef.current = newKey;
|
|
801
815
|
setHints(deduped);
|
|
802
|
-
if (newKey.length > 0) {
|
|
803
|
-
setVisible(true);
|
|
804
|
-
if (timerRef.current) {
|
|
805
|
-
clearTimeout(timerRef.current);
|
|
806
|
-
timerRef.current = null;
|
|
807
|
-
}
|
|
808
|
-
}
|
|
809
816
|
}
|
|
810
817
|
}, []);
|
|
811
818
|
const register = useCallback((id, h) => {
|
|
@@ -816,25 +823,11 @@ const KeyboardHintsProvider = ({ children }) => {
|
|
|
816
823
|
registrationsRef.current.delete(id);
|
|
817
824
|
recompute();
|
|
818
825
|
}, [recompute]);
|
|
819
|
-
useInput(() => {
|
|
820
|
-
if (!visible) return;
|
|
821
|
-
if (timerRef.current) return;
|
|
822
|
-
timerRef.current = setTimeout(() => {
|
|
823
|
-
setVisible(false);
|
|
824
|
-
timerRef.current = null;
|
|
825
|
-
}, DISMISS_DELAY);
|
|
826
|
-
});
|
|
827
|
-
useEffect(() => {
|
|
828
|
-
return () => {
|
|
829
|
-
if (timerRef.current) clearTimeout(timerRef.current);
|
|
830
|
-
};
|
|
831
|
-
}, []);
|
|
832
826
|
return /* @__PURE__ */ jsx(KeyboardHintsContext.Provider, {
|
|
833
827
|
value: {
|
|
834
828
|
register,
|
|
835
829
|
unregister,
|
|
836
|
-
hints
|
|
837
|
-
visible
|
|
830
|
+
hints
|
|
838
831
|
},
|
|
839
832
|
children
|
|
840
833
|
});
|
|
@@ -888,12 +881,13 @@ function useKeyBindings(id, bindings) {
|
|
|
888
881
|
* Key bindings are declared via useKeyBindings, which auto-registers
|
|
889
882
|
* hints in the KeyboardHintsBar.
|
|
890
883
|
*/
|
|
891
|
-
const PickerMenu = ({ message, options, mode = "single", centered = false, columns = 1, onSelect }) => {
|
|
884
|
+
const PickerMenu = ({ message, options, mode = "single", centered = false, columns = 1, optionMarginBottom = 0, onSelect }) => {
|
|
892
885
|
if (mode === "multi") return /* @__PURE__ */ jsx(MultiPickerMenu, {
|
|
893
886
|
message,
|
|
894
887
|
options,
|
|
895
888
|
centered,
|
|
896
889
|
columns,
|
|
890
|
+
optionMarginBottom,
|
|
897
891
|
onSelect
|
|
898
892
|
});
|
|
899
893
|
return /* @__PURE__ */ jsx(SinglePickerMenu, {
|
|
@@ -901,11 +895,12 @@ const PickerMenu = ({ message, options, mode = "single", centered = false, colum
|
|
|
901
895
|
options,
|
|
902
896
|
centered,
|
|
903
897
|
columns,
|
|
898
|
+
optionMarginBottom,
|
|
904
899
|
onSelect
|
|
905
900
|
});
|
|
906
901
|
};
|
|
907
902
|
/** Custom single-select with triangle indicator and accent highlight. */
|
|
908
|
-
const SinglePickerMenu = ({ message, options, centered = false, columns = 1, onSelect }) => {
|
|
903
|
+
const SinglePickerMenu = ({ message, options, centered = false, columns = 1, optionMarginBottom = 0, onSelect }) => {
|
|
909
904
|
const [focused, setFocused] = useState(0);
|
|
910
905
|
const rows = Math.ceil(options.length / columns);
|
|
911
906
|
const bindings = [{
|
|
@@ -966,6 +961,7 @@ const SinglePickerMenu = ({ message, options, centered = false, columns = 1, onS
|
|
|
966
961
|
const label = opt.hint ? `${opt.label} (${opt.hint})` : opt.label;
|
|
967
962
|
return /* @__PURE__ */ jsxs(Box, {
|
|
968
963
|
gap: 1,
|
|
964
|
+
marginBottom: optionMarginBottom,
|
|
969
965
|
children: [/* @__PURE__ */ jsx(Text, {
|
|
970
966
|
color: isFocused ? Colors.accent : void 0,
|
|
971
967
|
dimColor: !isFocused,
|
|
@@ -983,7 +979,7 @@ const SinglePickerMenu = ({ message, options, centered = false, columns = 1, onS
|
|
|
983
979
|
});
|
|
984
980
|
};
|
|
985
981
|
/** Custom multi-select with checkbox glyphs and accent highlight. */
|
|
986
|
-
const MultiPickerMenu = ({ message, options, centered = false, columns = 1, onSelect }) => {
|
|
982
|
+
const MultiPickerMenu = ({ message, options, centered = false, columns = 1, optionMarginBottom = 0, onSelect }) => {
|
|
987
983
|
const [focused, setFocused] = useState(0);
|
|
988
984
|
const [selected, setSelected] = useState(/* @__PURE__ */ new Set());
|
|
989
985
|
const rows = Math.ceil(options.length / columns);
|
|
@@ -1067,6 +1063,7 @@ const MultiPickerMenu = ({ message, options, centered = false, columns = 1, onSe
|
|
|
1067
1063
|
const checkbox = isSelected ? Icons.squareFilled : Icons.squareOpen;
|
|
1068
1064
|
return /* @__PURE__ */ jsxs(Box, {
|
|
1069
1065
|
gap: 1,
|
|
1066
|
+
marginBottom: optionMarginBottom,
|
|
1070
1067
|
children: [/* @__PURE__ */ jsx(Text, {
|
|
1071
1068
|
color: isSelected ? "white" : Colors.muted,
|
|
1072
1069
|
dimColor: !isFocused && !isSelected,
|
|
@@ -1441,40 +1438,92 @@ const ModalOverlay = ({ borderColor, title, titleColor, width = 68, children, fe
|
|
|
1441
1438
|
/**
|
|
1442
1439
|
* LogViewer — Real-time log tail, pinned to available terminal height.
|
|
1443
1440
|
* Only renders the last N lines that fit on screen.
|
|
1441
|
+
*
|
|
1442
|
+
* Reads only the last TAIL_BYTES of the file on each refresh and throttles
|
|
1443
|
+
* fs.watch callbacks to one refresh per WATCH_THROTTLE_MS. Without this,
|
|
1444
|
+
* fs.readFileSync allocates a string the size of the entire log on every
|
|
1445
|
+
* append — during subagent fan-out that's tens of writes per second against
|
|
1446
|
+
* a log that grows into the hundreds of MB, producing OOM-grade allocation
|
|
1447
|
+
* pressure on V8's heap.
|
|
1444
1448
|
*/
|
|
1445
1449
|
/** Rows consumed by TitleBar + spacer + ScreenContainer padding + status bar + tab bar */
|
|
1446
1450
|
const CHROME_ROWS$1 = 8;
|
|
1451
|
+
/** Bytes read from the end of the log per refresh — large enough to contain
|
|
1452
|
+
* any practical visible window of lines, small enough to allocate cheaply. */
|
|
1453
|
+
const TAIL_BYTES = 256 * 1024;
|
|
1454
|
+
/** Minimum gap between watch-triggered refreshes. fs.watch fires on every
|
|
1455
|
+
* append */
|
|
1456
|
+
const WATCH_THROTTLE_MS = 250;
|
|
1457
|
+
function readTailLines(filePath, visibleLines) {
|
|
1458
|
+
const stat = fs$1.statSync(filePath);
|
|
1459
|
+
if (stat.size === 0) return [];
|
|
1460
|
+
const start = Math.max(0, stat.size - TAIL_BYTES);
|
|
1461
|
+
const length = stat.size - start;
|
|
1462
|
+
const buf = Buffer.alloc(length);
|
|
1463
|
+
const fd = fs$1.openSync(filePath, "r");
|
|
1464
|
+
try {
|
|
1465
|
+
fs$1.readSync(fd, buf, 0, length, start);
|
|
1466
|
+
} finally {
|
|
1467
|
+
fs$1.closeSync(fd);
|
|
1468
|
+
}
|
|
1469
|
+
let text = buf.toString("utf-8");
|
|
1470
|
+
if (start > 0) {
|
|
1471
|
+
const firstNewline = text.indexOf("\n");
|
|
1472
|
+
if (firstNewline >= 0) text = text.slice(firstNewline + 1);
|
|
1473
|
+
}
|
|
1474
|
+
return text.split("\n").slice(-visibleLines);
|
|
1475
|
+
}
|
|
1447
1476
|
const LogViewer = ({ filePath, height }) => {
|
|
1448
1477
|
const [, rows] = useStdoutDimensions();
|
|
1449
1478
|
const visibleLines = height ?? Math.max(5, rows - CHROME_ROWS$1);
|
|
1450
1479
|
const [lines, setLines] = useState([]);
|
|
1451
1480
|
useEffect(() => {
|
|
1481
|
+
let lastReadAt = 0;
|
|
1482
|
+
let pendingTimer;
|
|
1452
1483
|
const readTail = () => {
|
|
1453
1484
|
try {
|
|
1454
|
-
setLines(
|
|
1485
|
+
setLines(readTailLines(filePath, visibleLines));
|
|
1455
1486
|
} catch {
|
|
1456
1487
|
setLines(["(No log file found)"]);
|
|
1457
1488
|
}
|
|
1458
1489
|
};
|
|
1490
|
+
const scheduleRead = () => {
|
|
1491
|
+
const now = Date.now();
|
|
1492
|
+
const elapsed = now - lastReadAt;
|
|
1493
|
+
if (elapsed >= WATCH_THROTTLE_MS) {
|
|
1494
|
+
lastReadAt = now;
|
|
1495
|
+
readTail();
|
|
1496
|
+
return;
|
|
1497
|
+
}
|
|
1498
|
+
if (pendingTimer) return;
|
|
1499
|
+
pendingTimer = setTimeout(() => {
|
|
1500
|
+
pendingTimer = void 0;
|
|
1501
|
+
lastReadAt = Date.now();
|
|
1502
|
+
readTail();
|
|
1503
|
+
}, WATCH_THROTTLE_MS - elapsed);
|
|
1504
|
+
};
|
|
1459
1505
|
readTail();
|
|
1506
|
+
lastReadAt = Date.now();
|
|
1460
1507
|
let watcher;
|
|
1461
1508
|
try {
|
|
1462
|
-
watcher = fs$1.watch(filePath, () =>
|
|
1463
|
-
readTail();
|
|
1464
|
-
});
|
|
1509
|
+
watcher = fs$1.watch(filePath, () => scheduleRead());
|
|
1465
1510
|
} catch {
|
|
1466
1511
|
const interval = setInterval(() => {
|
|
1467
1512
|
try {
|
|
1468
1513
|
fs$1.accessSync(filePath);
|
|
1469
1514
|
readTail();
|
|
1470
1515
|
clearInterval(interval);
|
|
1471
|
-
watcher = fs$1.watch(filePath, () =>
|
|
1516
|
+
watcher = fs$1.watch(filePath, () => scheduleRead());
|
|
1472
1517
|
} catch {}
|
|
1473
1518
|
}, 1e3);
|
|
1474
|
-
return () =>
|
|
1519
|
+
return () => {
|
|
1520
|
+
clearInterval(interval);
|
|
1521
|
+
if (pendingTimer) clearTimeout(pendingTimer);
|
|
1522
|
+
};
|
|
1475
1523
|
}
|
|
1476
1524
|
return () => {
|
|
1477
1525
|
watcher?.close();
|
|
1526
|
+
if (pendingTimer) clearTimeout(pendingTimer);
|
|
1478
1527
|
};
|
|
1479
1528
|
}, [filePath, visibleLines]);
|
|
1480
1529
|
return /* @__PURE__ */ jsx(Box, {
|
|
@@ -1656,16 +1705,15 @@ const DissolveTransition = ({ transitionKey, width, height, children, direction
|
|
|
1656
1705
|
/**
|
|
1657
1706
|
* KeyboardHintsBar — Row showing active keyboard shortcuts.
|
|
1658
1707
|
*
|
|
1659
|
-
* Always reserves its row to prevent layout shift
|
|
1660
|
-
*
|
|
1661
|
-
* an empty reserved row.
|
|
1708
|
+
* Always reserves its row to prevent layout shift, and always renders the
|
|
1709
|
+
* active hints (in dimmed grey text) while a screen has registered them.
|
|
1662
1710
|
*/
|
|
1663
1711
|
const KeyboardHintsBar = () => {
|
|
1664
|
-
const { hints
|
|
1712
|
+
const { hints } = useKeyboardHintsContext();
|
|
1665
1713
|
return /* @__PURE__ */ jsx(Box, {
|
|
1666
1714
|
height: 1,
|
|
1667
1715
|
paddingX: 1,
|
|
1668
|
-
children:
|
|
1716
|
+
children: hints.map((hint, i) => /* @__PURE__ */ jsxs(Box, {
|
|
1669
1717
|
marginRight: i < hints.length - 1 ? 2 : 0,
|
|
1670
1718
|
children: [/* @__PURE__ */ jsx(Text, {
|
|
1671
1719
|
bold: true,
|
|
@@ -2184,7 +2232,8 @@ const BlockRenderer = ({ block, active, completed, onComplete, mode, bullet, ani
|
|
|
2184
2232
|
animationInterval: block.animationInterval ?? animationInterval,
|
|
2185
2233
|
sentenceInterval: block.sentenceInterval ?? sentenceInterval,
|
|
2186
2234
|
maxHeight,
|
|
2187
|
-
availableWidth
|
|
2235
|
+
availableWidth,
|
|
2236
|
+
dimWhenComplete: block.dimWhenComplete ?? true
|
|
2188
2237
|
});
|
|
2189
2238
|
return /* @__PURE__ */ jsx(NodeBlock, {
|
|
2190
2239
|
content: block.content,
|
|
@@ -2622,10 +2671,10 @@ const McpScreen = ({ store, installer, mode = "install" }) => {
|
|
|
2622
2671
|
return /* @__PURE__ */ jsxs(Box, {
|
|
2623
2672
|
flexDirection: "column",
|
|
2624
2673
|
flexGrow: 1,
|
|
2625
|
-
children: [/* @__PURE__ */
|
|
2674
|
+
children: [/* @__PURE__ */ jsx(Text, {
|
|
2626
2675
|
bold: true,
|
|
2627
2676
|
color: Colors.accent,
|
|
2628
|
-
children:
|
|
2677
|
+
children: isRemove ? "Remove the PostHog MCP" : "Install the MCP so you can chat to your data"
|
|
2629
2678
|
}), /* @__PURE__ */ jsxs(Box, {
|
|
2630
2679
|
marginTop: 1,
|
|
2631
2680
|
flexDirection: "column",
|
|
@@ -2642,19 +2691,38 @@ const McpScreen = ({ store, installer, mode = "install" }) => {
|
|
|
2642
2691
|
" MCP clients detected. Skipping..."
|
|
2643
2692
|
]
|
|
2644
2693
|
}),
|
|
2645
|
-
phase === "ask" && /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2694
|
+
phase === "ask" && /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
2695
|
+
!isRemove && /* @__PURE__ */ jsx(Box, {
|
|
2696
|
+
flexDirection: "column",
|
|
2697
|
+
marginBottom: 1,
|
|
2698
|
+
children: [
|
|
2699
|
+
"Ask your agent: \"List my feature flags\" — and it does.",
|
|
2700
|
+
"Run SQL, build dashboards, ship flags, all from your IDE.",
|
|
2701
|
+
"No copy-pasting tokens or context. Your agent has the keys."
|
|
2702
|
+
].map((bullet) => /* @__PURE__ */ jsxs(Text, {
|
|
2703
|
+
dimColor: true,
|
|
2704
|
+
children: [
|
|
2705
|
+
"•",
|
|
2706
|
+
" ",
|
|
2707
|
+
bullet
|
|
2708
|
+
]
|
|
2709
|
+
}, bullet))
|
|
2710
|
+
}),
|
|
2711
|
+
/* @__PURE__ */ jsxs(Text, {
|
|
2712
|
+
dimColor: true,
|
|
2713
|
+
children: ["Detected: ", clients.map((c) => c.name).join(", ")]
|
|
2714
|
+
}),
|
|
2715
|
+
/* @__PURE__ */ jsx(Box, {
|
|
2716
|
+
marginTop: 1,
|
|
2717
|
+
children: /* @__PURE__ */ jsx(ConfirmationInput, {
|
|
2718
|
+
message: `${isRemove ? "Remove" : "Install"} the PostHog MCP server${clients.some((c) => c.supportsPlugin) ? " and plugin" : ""}?`,
|
|
2719
|
+
confirmLabel: isRemove ? "Remove" : "Install",
|
|
2720
|
+
cancelLabel: "No thanks",
|
|
2721
|
+
onConfirm: handleConfirm,
|
|
2722
|
+
onCancel: handleSkip
|
|
2723
|
+
})
|
|
2656
2724
|
})
|
|
2657
|
-
|
|
2725
|
+
] }),
|
|
2658
2726
|
phase === "pick" && /* @__PURE__ */ jsx(PickerMenu, {
|
|
2659
2727
|
message: "Select editor to install MCP server",
|
|
2660
2728
|
options: clients.map((c) => ({
|
|
@@ -2706,6 +2774,490 @@ const McpScreen = ({ store, installer, mode = "install" }) => {
|
|
|
2706
2774
|
});
|
|
2707
2775
|
};
|
|
2708
2776
|
//#endregion
|
|
2777
|
+
//#region src/lib/mcp-role-prompts.ts
|
|
2778
|
+
/**
|
|
2779
|
+
* Roles that ship from `role_at_organization` on the PostHog user object.
|
|
2780
|
+
* `security` isn't in the enum upstream — the engineering kit covers that audience.
|
|
2781
|
+
*/
|
|
2782
|
+
const TAILORED_ROLES = [
|
|
2783
|
+
"founder",
|
|
2784
|
+
"product",
|
|
2785
|
+
"leadership",
|
|
2786
|
+
"marketing",
|
|
2787
|
+
"engineering",
|
|
2788
|
+
"data"
|
|
2789
|
+
];
|
|
2790
|
+
const STOCK_MCP_SUGGESTED_PROMPTS = [
|
|
2791
|
+
{
|
|
2792
|
+
prompt: "What are my busiest 10 events and when did each last fire?",
|
|
2793
|
+
description: "Inventories your project’s event stream so you can see what’s being captured at a glance."
|
|
2794
|
+
},
|
|
2795
|
+
{
|
|
2796
|
+
prompt: "Show me daily event volume for the last 30 days.",
|
|
2797
|
+
description: "Charts your event count day by day — a quick read on volume and trend."
|
|
2798
|
+
},
|
|
2799
|
+
{
|
|
2800
|
+
prompt: "Create a dashboard with my top 10 events broken down by day for the last 7 days.",
|
|
2801
|
+
description: "Builds a saved dashboard you can pin and share — written back to your project."
|
|
2802
|
+
}
|
|
2803
|
+
];
|
|
2804
|
+
//#endregion
|
|
2805
|
+
//#region src/ui/tui/screens/McpSuggestedPromptsScreen.tsx
|
|
2806
|
+
/**
|
|
2807
|
+
* McpSuggestedPromptsScreen — shown after MCP install succeeds in the
|
|
2808
|
+
* standalone `wizard mcp add` program.
|
|
2809
|
+
*
|
|
2810
|
+
* Phases:
|
|
2811
|
+
* 1. Choose — opens with a Log in / Exit picker, framed by a
|
|
2812
|
+
* hardcoded teaser of three example prompts.
|
|
2813
|
+
* 2. Authenticating — runs `services.performLogin()` (OAuth in
|
|
2814
|
+
* production, canned values in the playground).
|
|
2815
|
+
* Renders a spinner + login URL inline while the
|
|
2816
|
+
* promise is pending. Errors return to Choose
|
|
2817
|
+
* with an inline error line.
|
|
2818
|
+
* 3. PromptPicker — lists the role-tailored kit; user picks one to
|
|
2819
|
+
* run. The picker has its own "Exit" entry so
|
|
2820
|
+
* dismissal is discoverable without a hidden
|
|
2821
|
+
* hotkey.
|
|
2822
|
+
* 4. Running — streams the agent's response inline via
|
|
2823
|
+
* `services.runPromptStreaming`. `[esc]` aborts
|
|
2824
|
+
* and returns to the picker; `[enter]` after
|
|
2825
|
+
* completion goes back to the picker so the user
|
|
2826
|
+
* can run another or exit.
|
|
2827
|
+
*
|
|
2828
|
+
* Credentials are guaranteed non-null once PromptPicker / Running are
|
|
2829
|
+
* reached (the Choose → Authenticating gate forces a successful login
|
|
2830
|
+
* before getting there). A defensive throw protects the Running
|
|
2831
|
+
* useEffect against a state-machine bug.
|
|
2832
|
+
*/
|
|
2833
|
+
const MAX_PROMPT_RUNS = 3;
|
|
2834
|
+
const McpSuggestedPromptsScreen = ({ store, services }) => {
|
|
2835
|
+
useSyncExternalStore((cb) => store.subscribe(cb), () => store.getSnapshot());
|
|
2836
|
+
const session = store.session;
|
|
2837
|
+
const kit = STOCK_MCP_SUGGESTED_PROMPTS;
|
|
2838
|
+
const [phase, setPhase] = useState("choose");
|
|
2839
|
+
const [loginError, setLoginError] = useState(null);
|
|
2840
|
+
const [runningPrompt, setRunningPrompt] = useState(null);
|
|
2841
|
+
const [runChunks, setRunChunks] = useState([]);
|
|
2842
|
+
const [runStartedAt, setRunStartedAt] = useState(null);
|
|
2843
|
+
const [runCount, setRunCount] = useState(0);
|
|
2844
|
+
const canPickAnother = runCount < MAX_PROMPT_RUNS;
|
|
2845
|
+
const runAbortRef = useRef(null);
|
|
2846
|
+
useEffect(() => {
|
|
2847
|
+
if (phase !== "authenticating") return;
|
|
2848
|
+
let cancelled = false;
|
|
2849
|
+
(async () => {
|
|
2850
|
+
try {
|
|
2851
|
+
const { credentials, roleAtOrganization, user } = await services.performLogin();
|
|
2852
|
+
if (cancelled) return;
|
|
2853
|
+
store.setCredentials(credentials);
|
|
2854
|
+
store.setRoleAtOrganization(roleAtOrganization);
|
|
2855
|
+
store.setApiUser(user);
|
|
2856
|
+
store.setLoginUrl(null);
|
|
2857
|
+
setPhase("prompt-picker");
|
|
2858
|
+
} catch (err) {
|
|
2859
|
+
if (cancelled) return;
|
|
2860
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
2861
|
+
logToFile(`[McpSuggestedPromptsScreen] login failed: ${message}`);
|
|
2862
|
+
store.setLoginUrl(null);
|
|
2863
|
+
setLoginError(message);
|
|
2864
|
+
setPhase("choose");
|
|
2865
|
+
}
|
|
2866
|
+
})();
|
|
2867
|
+
return () => {
|
|
2868
|
+
cancelled = true;
|
|
2869
|
+
};
|
|
2870
|
+
}, [
|
|
2871
|
+
phase,
|
|
2872
|
+
services,
|
|
2873
|
+
store
|
|
2874
|
+
]);
|
|
2875
|
+
useEffect(() => {
|
|
2876
|
+
if (phase !== "running") return;
|
|
2877
|
+
if (!runningPrompt) return;
|
|
2878
|
+
if (!session.credentials) throw new Error("[McpSuggestedPromptsScreen] Running phase reached without credentials. The Choose gate should have prevented this.");
|
|
2879
|
+
const controller = new AbortController();
|
|
2880
|
+
runAbortRef.current = controller;
|
|
2881
|
+
const startedAt = Date.now();
|
|
2882
|
+
setRunStartedAt(startedAt);
|
|
2883
|
+
setRunChunks([]);
|
|
2884
|
+
(async () => {
|
|
2885
|
+
const credentials = session.credentials;
|
|
2886
|
+
if (!credentials) return;
|
|
2887
|
+
try {
|
|
2888
|
+
for await (const chunk of services.runPromptStreaming({
|
|
2889
|
+
prompt: runningPrompt,
|
|
2890
|
+
credentials,
|
|
2891
|
+
signal: controller.signal
|
|
2892
|
+
})) {
|
|
2893
|
+
if (controller.signal.aborted) return;
|
|
2894
|
+
setRunChunks((prev) => [...prev, chunk]);
|
|
2895
|
+
if (chunk.kind === "done") {
|
|
2896
|
+
analytics.wizardCapture("mcp suggested prompts run", {
|
|
2897
|
+
prompt: runningPrompt,
|
|
2898
|
+
durationMs: Date.now() - startedAt
|
|
2899
|
+
});
|
|
2900
|
+
return;
|
|
2901
|
+
}
|
|
2902
|
+
if (chunk.kind === "error") {
|
|
2903
|
+
analytics.wizardCapture("mcp suggested prompts run failed", {
|
|
2904
|
+
prompt: runningPrompt,
|
|
2905
|
+
error: chunk.text
|
|
2906
|
+
});
|
|
2907
|
+
return;
|
|
2908
|
+
}
|
|
2909
|
+
}
|
|
2910
|
+
} catch (err) {
|
|
2911
|
+
if (controller.signal.aborted) return;
|
|
2912
|
+
const text = err instanceof Error ? err.message : String(err);
|
|
2913
|
+
setRunChunks((prev) => [...prev, {
|
|
2914
|
+
kind: "error",
|
|
2915
|
+
text
|
|
2916
|
+
}]);
|
|
2917
|
+
analytics.wizardCapture("mcp suggested prompts run failed", {
|
|
2918
|
+
prompt: runningPrompt,
|
|
2919
|
+
error: text
|
|
2920
|
+
});
|
|
2921
|
+
}
|
|
2922
|
+
})();
|
|
2923
|
+
return () => {
|
|
2924
|
+
controller.abort();
|
|
2925
|
+
if (runAbortRef.current === controller) runAbortRef.current = null;
|
|
2926
|
+
};
|
|
2927
|
+
}, [
|
|
2928
|
+
phase,
|
|
2929
|
+
runningPrompt,
|
|
2930
|
+
services,
|
|
2931
|
+
session.credentials
|
|
2932
|
+
]);
|
|
2933
|
+
const dismiss = () => {
|
|
2934
|
+
setPhase("done");
|
|
2935
|
+
setTimeout(() => {
|
|
2936
|
+
store.setMcpSuggestedPromptsDismissed();
|
|
2937
|
+
}, 0);
|
|
2938
|
+
};
|
|
2939
|
+
const handleChoice = (value) => {
|
|
2940
|
+
const choice = Array.isArray(value) ? value[0] : value;
|
|
2941
|
+
setLoginError(null);
|
|
2942
|
+
if (choice === "login") {
|
|
2943
|
+
analytics.wizardCapture("mcp suggested prompts choose", { choice: "login" });
|
|
2944
|
+
setPhase("authenticating");
|
|
2945
|
+
} else {
|
|
2946
|
+
analytics.wizardCapture("mcp suggested prompts choose", { choice: "exit" });
|
|
2947
|
+
dismiss();
|
|
2948
|
+
}
|
|
2949
|
+
};
|
|
2950
|
+
const handlePromptPick = (value) => {
|
|
2951
|
+
setRunningPrompt(Array.isArray(value) ? value[0] : value);
|
|
2952
|
+
setRunCount((c) => c + 1);
|
|
2953
|
+
setPhase("running");
|
|
2954
|
+
};
|
|
2955
|
+
useKeyBindings("mcp-suggested-prompts", [{
|
|
2956
|
+
match: "escape",
|
|
2957
|
+
label: "esc",
|
|
2958
|
+
action: phase === "prompt-picker" ? "exit" : "exit",
|
|
2959
|
+
handler: () => {
|
|
2960
|
+
if (phase === "running") {
|
|
2961
|
+
runAbortRef.current?.abort();
|
|
2962
|
+
dismiss();
|
|
2963
|
+
} else if (phase === "prompt-picker") dismiss();
|
|
2964
|
+
}
|
|
2965
|
+
}, {
|
|
2966
|
+
match: "p",
|
|
2967
|
+
label: "p",
|
|
2968
|
+
action: canPickAnother ? "pick new prompt" : "cap reached",
|
|
2969
|
+
handler: () => {
|
|
2970
|
+
if (phase !== "running") return;
|
|
2971
|
+
if (!canPickAnother) return;
|
|
2972
|
+
runAbortRef.current?.abort();
|
|
2973
|
+
setPhase("prompt-picker");
|
|
2974
|
+
}
|
|
2975
|
+
}]);
|
|
2976
|
+
return /* @__PURE__ */ jsx(Box, {
|
|
2977
|
+
flexDirection: "column",
|
|
2978
|
+
flexGrow: 1,
|
|
2979
|
+
children: /* @__PURE__ */ jsxs(Box, {
|
|
2980
|
+
marginTop: 1,
|
|
2981
|
+
flexDirection: "column",
|
|
2982
|
+
children: [
|
|
2983
|
+
phase === "choose" && /* @__PURE__ */ jsx(ChoosePhase, {
|
|
2984
|
+
error: loginError,
|
|
2985
|
+
onSelect: handleChoice
|
|
2986
|
+
}),
|
|
2987
|
+
phase === "authenticating" && /* @__PURE__ */ jsx(AuthenticatingPhase, { loginUrl: session.loginUrl }),
|
|
2988
|
+
phase === "prompt-picker" && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Box, {
|
|
2989
|
+
marginBottom: 1,
|
|
2990
|
+
children: /* @__PURE__ */ jsx(Text, {
|
|
2991
|
+
bold: true,
|
|
2992
|
+
color: Colors.accent,
|
|
2993
|
+
children: "MCP tutorial"
|
|
2994
|
+
})
|
|
2995
|
+
}), /* @__PURE__ */ jsx(PromptPickerPhase, {
|
|
2996
|
+
promptKit: kit,
|
|
2997
|
+
userDisplayName: session.apiUser?.first_name || null,
|
|
2998
|
+
onSelect: handlePromptPick
|
|
2999
|
+
})] }),
|
|
3000
|
+
phase === "running" && runningPrompt && /* @__PURE__ */ jsx(RunningPhase, {
|
|
3001
|
+
prompt: runningPrompt,
|
|
3002
|
+
chunks: runChunks,
|
|
3003
|
+
startedAt: runStartedAt,
|
|
3004
|
+
canPickAnother,
|
|
3005
|
+
runCount,
|
|
3006
|
+
maxRuns: MAX_PROMPT_RUNS
|
|
3007
|
+
})
|
|
3008
|
+
]
|
|
3009
|
+
})
|
|
3010
|
+
});
|
|
3011
|
+
};
|
|
3012
|
+
const ChoosePhase = ({ error, onSelect }) => /* @__PURE__ */ jsxs(Box, {
|
|
3013
|
+
flexDirection: "column",
|
|
3014
|
+
children: [
|
|
3015
|
+
/* @__PURE__ */ jsx(Text, {
|
|
3016
|
+
bold: true,
|
|
3017
|
+
color: Colors.accent,
|
|
3018
|
+
children: "PostHog MCP"
|
|
3019
|
+
}),
|
|
3020
|
+
/* @__PURE__ */ jsx(Box, {
|
|
3021
|
+
marginTop: 1,
|
|
3022
|
+
children: /* @__PURE__ */ jsx(Text, { children: "With MCP your agent works directly with the PostHog platform. You can prompt it to:" })
|
|
3023
|
+
}),
|
|
3024
|
+
/* @__PURE__ */ jsxs(Box, {
|
|
3025
|
+
marginTop: 1,
|
|
3026
|
+
flexDirection: "column",
|
|
3027
|
+
children: [
|
|
3028
|
+
/* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
|
|
3029
|
+
color: "cyan",
|
|
3030
|
+
children: Icons.diamond
|
|
3031
|
+
}), " Build dashboards"] }),
|
|
3032
|
+
/* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
|
|
3033
|
+
color: "cyan",
|
|
3034
|
+
children: Icons.diamond
|
|
3035
|
+
}), " Run SQL queries"] }),
|
|
3036
|
+
/* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
|
|
3037
|
+
color: "cyan",
|
|
3038
|
+
children: Icons.diamond
|
|
3039
|
+
}), " Deploy feature flags"] }),
|
|
3040
|
+
/* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
|
|
3041
|
+
color: "cyan",
|
|
3042
|
+
children: Icons.diamond
|
|
3043
|
+
}), " Debug exceptions and errors"] }),
|
|
3044
|
+
/* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
|
|
3045
|
+
color: "cyan",
|
|
3046
|
+
children: Icons.diamond
|
|
3047
|
+
}), " And lots more..."] })
|
|
3048
|
+
]
|
|
3049
|
+
}),
|
|
3050
|
+
/* @__PURE__ */ jsx(Box, {
|
|
3051
|
+
marginTop: 1,
|
|
3052
|
+
children: /* @__PURE__ */ jsx(Text, { children: "Want a live demo using real data from your project?" })
|
|
3053
|
+
}),
|
|
3054
|
+
/* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(PickerMenu, {
|
|
3055
|
+
options: [{
|
|
3056
|
+
label: "Start MCP tutorial",
|
|
3057
|
+
value: "login"
|
|
3058
|
+
}, {
|
|
3059
|
+
label: "Exit",
|
|
3060
|
+
value: "exit"
|
|
3061
|
+
}],
|
|
3062
|
+
onSelect
|
|
3063
|
+
}) }),
|
|
3064
|
+
error && /* @__PURE__ */ jsx(Box, {
|
|
3065
|
+
marginTop: 1,
|
|
3066
|
+
children: /* @__PURE__ */ jsxs(Text, {
|
|
3067
|
+
color: "red",
|
|
3068
|
+
children: [
|
|
3069
|
+
"Login failed: ",
|
|
3070
|
+
error,
|
|
3071
|
+
". Try again or exit."
|
|
3072
|
+
]
|
|
3073
|
+
})
|
|
3074
|
+
})
|
|
3075
|
+
]
|
|
3076
|
+
});
|
|
3077
|
+
const AuthenticatingPhase = ({ loginUrl }) => /* @__PURE__ */ jsxs(Box, {
|
|
3078
|
+
flexDirection: "column",
|
|
3079
|
+
children: [/* @__PURE__ */ jsx(LoadingBox, { message: "Waiting for authentication..." }), loginUrl && /* @__PURE__ */ jsx(Box, {
|
|
3080
|
+
marginTop: 1,
|
|
3081
|
+
marginBottom: 1,
|
|
3082
|
+
flexDirection: "column",
|
|
3083
|
+
children: /* @__PURE__ */ jsxs(Text, { children: [
|
|
3084
|
+
/* @__PURE__ */ jsx(Text, {
|
|
3085
|
+
dimColor: true,
|
|
3086
|
+
children: "If the browser didn't open, copy and paste:"
|
|
3087
|
+
}),
|
|
3088
|
+
"\n\n",
|
|
3089
|
+
/* @__PURE__ */ jsx(Text, {
|
|
3090
|
+
color: "cyan",
|
|
3091
|
+
children: loginUrl
|
|
3092
|
+
})
|
|
3093
|
+
] })
|
|
3094
|
+
})]
|
|
3095
|
+
});
|
|
3096
|
+
const PromptPickerPhase = ({ promptKit, userDisplayName, onSelect }) => {
|
|
3097
|
+
const options = promptKit.map((p) => ({
|
|
3098
|
+
label: p.prompt,
|
|
3099
|
+
value: p.prompt
|
|
3100
|
+
}));
|
|
3101
|
+
return /* @__PURE__ */ jsx(Box, {
|
|
3102
|
+
flexDirection: "column",
|
|
3103
|
+
children: /* @__PURE__ */ jsx(ContentSequencer, {
|
|
3104
|
+
blocks: [
|
|
3105
|
+
{
|
|
3106
|
+
content: `Hello there, ${userDisplayName || "there"}!`,
|
|
3107
|
+
mode: 0,
|
|
3108
|
+
animationInterval: 100,
|
|
3109
|
+
pause: 1200,
|
|
3110
|
+
dimWhenComplete: false
|
|
3111
|
+
},
|
|
3112
|
+
{
|
|
3113
|
+
content: "Pick a prompt to see the PostHog MCP in action.",
|
|
3114
|
+
mode: 0,
|
|
3115
|
+
animationInterval: 50,
|
|
3116
|
+
pause: 1e3,
|
|
3117
|
+
dimWhenComplete: false
|
|
3118
|
+
},
|
|
3119
|
+
{
|
|
3120
|
+
content: /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(PickerMenu, {
|
|
3121
|
+
options,
|
|
3122
|
+
optionMarginBottom: 1,
|
|
3123
|
+
onSelect
|
|
3124
|
+
}), /* @__PURE__ */ jsx(Box, {
|
|
3125
|
+
marginTop: 2,
|
|
3126
|
+
children: /* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
|
|
3127
|
+
bold: true,
|
|
3128
|
+
children: "[esc]"
|
|
3129
|
+
}), /* @__PURE__ */ jsx(Text, { children: " to exit" })] })
|
|
3130
|
+
})] }),
|
|
3131
|
+
persist: true
|
|
3132
|
+
}
|
|
3133
|
+
],
|
|
3134
|
+
mode: 0,
|
|
3135
|
+
blockInterval: 350
|
|
3136
|
+
})
|
|
3137
|
+
});
|
|
3138
|
+
};
|
|
3139
|
+
const RunningPhase = ({ prompt, chunks, startedAt, canPickAnother, runCount, maxRuns }) => {
|
|
3140
|
+
const isDone = chunks.some((c) => c.kind === "done");
|
|
3141
|
+
const errorChunk = chunks.find((c) => c.kind === "error");
|
|
3142
|
+
const finished = isDone || !!errorChunk;
|
|
3143
|
+
const elapsed = startedAt ? Math.round((Date.now() - startedAt) / 1e3) : 0;
|
|
3144
|
+
const visibleChunks = finished ? chunks.filter((c) => c.kind === "text" || c.kind === "error") : chunks;
|
|
3145
|
+
const cappedChunks = finished ? capTextChunks(visibleChunks) : visibleChunks;
|
|
3146
|
+
return /* @__PURE__ */ jsxs(Box, {
|
|
3147
|
+
flexDirection: "column",
|
|
3148
|
+
children: [
|
|
3149
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
3150
|
+
/* @__PURE__ */ jsx(Text, {
|
|
3151
|
+
bold: true,
|
|
3152
|
+
children: "Prompt:"
|
|
3153
|
+
}),
|
|
3154
|
+
" ",
|
|
3155
|
+
/* @__PURE__ */ jsx(Text, {
|
|
3156
|
+
color: Colors.accent,
|
|
3157
|
+
children: prompt
|
|
3158
|
+
})
|
|
3159
|
+
] }),
|
|
3160
|
+
/* @__PURE__ */ jsxs(Box, {
|
|
3161
|
+
marginTop: 1,
|
|
3162
|
+
gap: 1,
|
|
3163
|
+
children: [
|
|
3164
|
+
!finished && /* @__PURE__ */ jsx(Spinner, {}),
|
|
3165
|
+
/* @__PURE__ */ jsx(Text, {
|
|
3166
|
+
bold: finished,
|
|
3167
|
+
children: finished ? errorChunk ? `Failed after ${elapsed}s.` : `Done in ${elapsed}s.` : "Streaming from PostHog MCP"
|
|
3168
|
+
}),
|
|
3169
|
+
/* @__PURE__ */ jsxs(Text, {
|
|
3170
|
+
dimColor: true,
|
|
3171
|
+
children: [
|
|
3172
|
+
"(",
|
|
3173
|
+
runCount,
|
|
3174
|
+
"/",
|
|
3175
|
+
maxRuns,
|
|
3176
|
+
" prompts)"
|
|
3177
|
+
]
|
|
3178
|
+
})
|
|
3179
|
+
]
|
|
3180
|
+
}),
|
|
3181
|
+
/* @__PURE__ */ jsx(Box, {
|
|
3182
|
+
marginTop: 1,
|
|
3183
|
+
flexDirection: "column",
|
|
3184
|
+
children: cappedChunks.map((chunk, idx) => /* @__PURE__ */ jsx(ChunkLine, { chunk }, idx))
|
|
3185
|
+
}),
|
|
3186
|
+
finished && !canPickAnother && /* @__PURE__ */ jsx(Box, {
|
|
3187
|
+
marginTop: 1,
|
|
3188
|
+
children: /* @__PURE__ */ jsxs(Text, { children: [
|
|
3189
|
+
/* @__PURE__ */ jsxs(Text, {
|
|
3190
|
+
dimColor: true,
|
|
3191
|
+
children: [
|
|
3192
|
+
"You've hit the ",
|
|
3193
|
+
maxRuns,
|
|
3194
|
+
"-prompt tutorial cap. Press",
|
|
3195
|
+
" "
|
|
3196
|
+
]
|
|
3197
|
+
}),
|
|
3198
|
+
/* @__PURE__ */ jsx(Text, {
|
|
3199
|
+
bold: true,
|
|
3200
|
+
dimColor: true,
|
|
3201
|
+
children: "[esc]"
|
|
3202
|
+
}),
|
|
3203
|
+
/* @__PURE__ */ jsx(Text, {
|
|
3204
|
+
dimColor: true,
|
|
3205
|
+
children: " to exit."
|
|
3206
|
+
})
|
|
3207
|
+
] })
|
|
3208
|
+
})
|
|
3209
|
+
]
|
|
3210
|
+
});
|
|
3211
|
+
};
|
|
3212
|
+
/**
|
|
3213
|
+
* Belt-and-suspenders fallback for runs where Claude ignored the
|
|
3214
|
+
* terminal-fit system prompt and produced an overlong response. Joins
|
|
3215
|
+
* all text chunks, slices to the last N lines that fit in the current
|
|
3216
|
+
* terminal, and prepends an indicator showing how many lines got cut.
|
|
3217
|
+
* Errors are preserved separately so failures don't disappear into the
|
|
3218
|
+
* truncation.
|
|
3219
|
+
*/
|
|
3220
|
+
function capTextChunks(chunks) {
|
|
3221
|
+
const rows = process.stdout.rows ?? 24;
|
|
3222
|
+
const maxMessageRows = Math.max(6, rows - 8);
|
|
3223
|
+
const textChunks = chunks.filter((c) => c.kind === "text");
|
|
3224
|
+
const errors = chunks.filter((c) => c.kind === "error");
|
|
3225
|
+
if (textChunks.length === 0) return chunks;
|
|
3226
|
+
const lines = textChunks.map((c) => c.text).join("").split("\n");
|
|
3227
|
+
if (lines.length <= maxMessageRows) return chunks;
|
|
3228
|
+
const hidden = lines.length - maxMessageRows;
|
|
3229
|
+
const tail = lines.slice(-maxMessageRows).join("\n");
|
|
3230
|
+
return [{
|
|
3231
|
+
kind: "text",
|
|
3232
|
+
text: `[${hidden} line${hidden === 1 ? "" : "s"} above — expand terminal to see more]\n\n${tail}`
|
|
3233
|
+
}, ...errors];
|
|
3234
|
+
}
|
|
3235
|
+
const ChunkLine = ({ chunk }) => {
|
|
3236
|
+
if (chunk.kind === "text") return /* @__PURE__ */ jsx(Text, { children: chunk.text });
|
|
3237
|
+
if (chunk.kind === "tool-call") return /* @__PURE__ */ jsxs(Text, { children: [
|
|
3238
|
+
" ",
|
|
3239
|
+
/* @__PURE__ */ jsxs(Text, {
|
|
3240
|
+
color: "cyan",
|
|
3241
|
+
children: ["↳ ", chunk.toolName]
|
|
3242
|
+
}),
|
|
3243
|
+
chunk.detail ? ` ${chunk.detail}` : ""
|
|
3244
|
+
] });
|
|
3245
|
+
if (chunk.kind === "tool-result") return /* @__PURE__ */ jsxs(Text, { children: [
|
|
3246
|
+
" ",
|
|
3247
|
+
/* @__PURE__ */ jsx(Text, {
|
|
3248
|
+
color: "green",
|
|
3249
|
+
children: "✓"
|
|
3250
|
+
}),
|
|
3251
|
+
" ",
|
|
3252
|
+
chunk.detail
|
|
3253
|
+
] });
|
|
3254
|
+
if (chunk.kind === "error") return /* @__PURE__ */ jsxs(Text, {
|
|
3255
|
+
color: "red",
|
|
3256
|
+
children: ["Error: ", chunk.text]
|
|
3257
|
+
});
|
|
3258
|
+
return null;
|
|
3259
|
+
};
|
|
3260
|
+
//#endregion
|
|
2709
3261
|
//#region src/ui/tui/screens/audit/AuditChecksViewer/AreaHeaderRow.tsx
|
|
2710
3262
|
/** Sub-header row inside the scrollable body — one per area group. */
|
|
2711
3263
|
const AreaHeaderRow = ({ area, resolved, total }) => /* @__PURE__ */ jsxs(Box, {
|
|
@@ -3317,11 +3869,83 @@ const EventCaptureSlide = {
|
|
|
3317
3869
|
docsUrl: "https://posthog.com/docs/product-analytics/capture-events"
|
|
3318
3870
|
};
|
|
3319
3871
|
//#endregion
|
|
3872
|
+
//#region src/ui/tui/screens/audit/slides/writeReport.tsx
|
|
3873
|
+
const ReportVisual = () => /* @__PURE__ */ jsxs(VisualBox, { children: [
|
|
3874
|
+
/* @__PURE__ */ jsx(Text, {
|
|
3875
|
+
dimColor: true,
|
|
3876
|
+
children: "posthog-audit-report.md"
|
|
3877
|
+
}),
|
|
3878
|
+
/* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
|
|
3879
|
+
dimColor: true,
|
|
3880
|
+
children: " # "
|
|
3881
|
+
}), /* @__PURE__ */ jsx(Text, { children: "Summary" })] }),
|
|
3882
|
+
/* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
|
|
3883
|
+
dimColor: true,
|
|
3884
|
+
children: " # "
|
|
3885
|
+
}), /* @__PURE__ */ jsx(Text, { children: "Recommended actions" })] }),
|
|
3886
|
+
/* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
|
|
3887
|
+
dimColor: true,
|
|
3888
|
+
children: " # "
|
|
3889
|
+
}), /* @__PURE__ */ jsx(Text, { children: "Full audit" })] })
|
|
3890
|
+
] });
|
|
3891
|
+
const WriteReportSlide = {
|
|
3892
|
+
area: "Write report",
|
|
3893
|
+
intro: [
|
|
3894
|
+
"Now we write an audit report at ./posthog-audit-report.md. that summarizes our findings.",
|
|
3895
|
+
"The report leads with a summary, then a prioritized list of fixes with file:line citations, then every check we ran grouped by area so nothing is hidden.",
|
|
3896
|
+
"We will upload the report into a PostHog notebook in the next step."
|
|
3897
|
+
],
|
|
3898
|
+
visual: /* @__PURE__ */ jsx(ReportVisual, {}),
|
|
3899
|
+
docsUrl: "https://posthog.com/docs/product-analytics/best-practices"
|
|
3900
|
+
};
|
|
3901
|
+
//#endregion
|
|
3902
|
+
//#region src/ui/tui/screens/audit/slides/uploadNotebook.tsx
|
|
3903
|
+
const NotebookVisual = () => /* @__PURE__ */ jsxs(VisualBox, { children: [
|
|
3904
|
+
/* @__PURE__ */ jsx(Text, {
|
|
3905
|
+
dimColor: true,
|
|
3906
|
+
children: "posthog-audit-report.md"
|
|
3907
|
+
}),
|
|
3908
|
+
/* @__PURE__ */ jsx(Text, {
|
|
3909
|
+
dimColor: true,
|
|
3910
|
+
children: " │"
|
|
3911
|
+
}),
|
|
3912
|
+
/* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
|
|
3913
|
+
dimColor: true,
|
|
3914
|
+
children: " ▼ "
|
|
3915
|
+
}), /* @__PURE__ */ jsx(Text, {
|
|
3916
|
+
color: "cyan",
|
|
3917
|
+
children: "PostHog notebook"
|
|
3918
|
+
})] }),
|
|
3919
|
+
/* @__PURE__ */ jsx(Text, {
|
|
3920
|
+
dimColor: true,
|
|
3921
|
+
children: " # Summary"
|
|
3922
|
+
}),
|
|
3923
|
+
/* @__PURE__ */ jsx(Text, {
|
|
3924
|
+
dimColor: true,
|
|
3925
|
+
children: " # Recommended actions"
|
|
3926
|
+
}),
|
|
3927
|
+
/* @__PURE__ */ jsx(Text, {
|
|
3928
|
+
dimColor: true,
|
|
3929
|
+
children: " # Full audit"
|
|
3930
|
+
})
|
|
3931
|
+
] });
|
|
3932
|
+
//#endregion
|
|
3320
3933
|
//#region src/ui/tui/screens/audit/slides/index.ts
|
|
3321
3934
|
const AUDIT_AREA_SLIDES = [
|
|
3322
3935
|
InstallationSlide,
|
|
3323
3936
|
IdentificationSlide,
|
|
3324
|
-
EventCaptureSlide
|
|
3937
|
+
EventCaptureSlide,
|
|
3938
|
+
WriteReportSlide,
|
|
3939
|
+
{
|
|
3940
|
+
area: "Upload notebook",
|
|
3941
|
+
intro: [
|
|
3942
|
+
"Next we upload the report into a PostHog notebook so you can share it with your team as a URL.",
|
|
3943
|
+
"Hang tight.",
|
|
3944
|
+
"The markdown file on disk is still there for you to read locally."
|
|
3945
|
+
],
|
|
3946
|
+
visual: /* @__PURE__ */ jsx(NotebookVisual, {}),
|
|
3947
|
+
docsUrl: "https://posthog.com/docs/notebooks"
|
|
3948
|
+
}
|
|
3325
3949
|
];
|
|
3326
3950
|
//#endregion
|
|
3327
3951
|
//#region src/ui/tui/screens/audit-3000/slides/eventQuality.tsx
|
|
@@ -3494,6 +4118,6 @@ const AUDIT_3000_AREA_SLIDES = [
|
|
|
3494
4118
|
}
|
|
3495
4119
|
];
|
|
3496
4120
|
//#endregion
|
|
3497
|
-
export {
|
|
4121
|
+
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 };
|
|
3498
4122
|
|
|
3499
|
-
//# sourceMappingURL=slides-
|
|
4123
|
+
//# sourceMappingURL=slides-CL1mv_Kq.js.map
|