@posthog/wizard 2.11.0 → 2.13.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 +48 -7
- package/dist/{McpScreen-DvUncZBi.js → AuditChecksViewer-B0J7zcY2.js} +434 -22
- package/dist/AuditChecksViewer-B0J7zcY2.js.map +1 -0
- package/dist/{add-mcp-server-to-clients-Br1hDRiB.js → add-mcp-server-to-clients-CUNR00bB.js} +5 -5
- package/dist/{add-mcp-server-to-clients-Br1hDRiB.js.map → add-mcp-server-to-clients-CUNR00bB.js.map} +1 -1
- package/dist/{readiness-gQvQNCeL.js → agent-interface-CV0-vtxj.js} +328 -462
- package/dist/agent-interface-CV0-vtxj.js.map +1 -0
- package/dist/{agent-runner-fWYFO4H0.js → agent-runner-LvVQH31D.js} +21 -31
- package/dist/{agent-runner-fWYFO4H0.js.map → agent-runner-LvVQH31D.js.map} +1 -1
- package/dist/analytics-BH7bEHQR.js +2 -0
- package/dist/analytics-VM7laaFx.js +123 -0
- package/dist/analytics-VM7laaFx.js.map +1 -0
- package/dist/bin.js +529 -42
- package/dist/bin.js.map +1 -1
- package/dist/{debug-D-0xueVl.js → debug-BdcTB7EF.js} +1 -1
- package/dist/debug-Cqi6nVfX.js +686 -0
- package/dist/debug-Cqi6nVfX.js.map +1 -0
- package/dist/{defaults-CPH6eWhN.js → defaults-GbLPuHxj.js} +1 -1
- package/dist/{defaults-CPH6eWhN.js.map → defaults-GbLPuHxj.js.map} +1 -1
- package/dist/{detection-B7GNzve-.js → detection-CSjmal-X.js} +3 -3
- package/dist/{detection-B7GNzve-.js.map → detection-CSjmal-X.js.map} +1 -1
- package/dist/{env-api-key-DU8uIEvo.js → env-api-key-D5G2PrXW.js} +1 -1
- package/dist/{env-api-key-DU8uIEvo.js.map → env-api-key-D5G2PrXW.js.map} +1 -1
- package/dist/{file-DhSBlq-x.js → file-8iNrXHkG.js} +2 -2
- package/dist/{file-DhSBlq-x.js.map → file-8iNrXHkG.js.map} +1 -1
- package/dist/{file-utils-Dy9JncCo.js → file-utils-DnTSiTJw.js} +1 -1
- package/dist/{file-utils-Dy9JncCo.js.map → file-utils-DnTSiTJw.js.map} +1 -1
- package/dist/{package-manager-D3Lo6nXf.js → package-manager-CD8RQW-e.js} +2 -2
- package/dist/{package-manager-D3Lo6nXf.js.map → package-manager-CD8RQW-e.js.map} +1 -1
- package/dist/paths-DJS47p5x.js +26 -0
- package/dist/paths-DJS47p5x.js.map +1 -0
- package/dist/{posthog-integration-D4SRhJIQ.js → posthog-integration-BL21S3T6.js} +41 -13
- package/dist/posthog-integration-BL21S3T6.js.map +1 -0
- package/dist/{posthog-ByrpqEjN.js → posthog-vm0k9PKS.js} +1 -1
- package/dist/{posthog-ByrpqEjN.js.map → posthog-vm0k9PKS.js.map} +1 -1
- package/dist/provisioning-BdQ1ONIg.js +2 -0
- package/dist/provisioning-g9aoVIEd.js +166 -0
- package/dist/provisioning-g9aoVIEd.js.map +1 -0
- package/dist/{registry-DaPKstG3.js → registry-BaMEaAKd.js} +4 -5
- package/dist/{registry-DaPKstG3.js.map → registry-BaMEaAKd.js.map} +1 -1
- package/dist/{router-SgzmfLGi.js → router-COhhuIW3.js} +4 -3
- package/dist/router-COhhuIW3.js.map +1 -0
- package/dist/{setup-utils-y4s-3uKT.js → setup-utils-CNV7FSlY.js} +11 -150
- package/dist/setup-utils-CNV7FSlY.js.map +1 -0
- package/dist/setup-utils-CU4FIqjB.js +2 -0
- package/dist/{start-playground-g1TxpCZ5.js → start-playground-C9GWnVdM.js} +102 -7
- package/dist/start-playground-C9GWnVdM.js.map +1 -0
- package/dist/start-tui-B_zwutLe.js +4195 -0
- package/dist/start-tui-B_zwutLe.js.map +1 -0
- package/dist/{steps-D1zKDqAo.js → steps-Dawz7k3T.js} +8 -8
- package/dist/steps-Dawz7k3T.js.map +1 -0
- package/dist/{task-stream-DX_jKDQu.js → task-stream-CX7Uf6EM.js} +4 -4
- package/dist/{task-stream-DX_jKDQu.js.map → task-stream-CX7Uf6EM.js.map} +1 -1
- package/dist/{telemetry-CyUUSAYy.js → telemetry-D6bjWA-A.js} +2 -2
- package/dist/{telemetry-CyUUSAYy.js.map → telemetry-D6bjWA-A.js.map} +1 -1
- package/dist/{wizard-abort-Buodno3f.js → wizard-abort-CJkNkSjT.js} +6 -4
- package/dist/{wizard-abort-Buodno3f.js.map → wizard-abort-CJkNkSjT.js.map} +1 -1
- package/dist/{wizard-abort-DZmO_sIZ.js → wizard-abort-Dl0BkqhT.js} +1 -1
- package/dist/wizard-session-BQC9vy9Z.js +2 -0
- package/dist/{wizard-session-D5bggSsu.js → wizard-session-BcNJTl2I.js} +1 -1
- package/dist/{wizard-session-D5bggSsu.js.map → wizard-session-BcNJTl2I.js.map} +1 -1
- package/dist/{wizard-ui-BExOjdjA.js → wizard-ui-YdGFRyu_.js} +1 -1
- package/dist/wizard-ui-YdGFRyu_.js.map +1 -0
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/dist/McpScreen-DvUncZBi.js.map +0 -1
- package/dist/agent-skill-DJOzDaQV.js +0 -59
- package/dist/agent-skill-DJOzDaQV.js.map +0 -1
- package/dist/analytics-CfAUlt6-.js +0 -2
- package/dist/analytics-D3rY3TaN.js +0 -210
- package/dist/analytics-D3rY3TaN.js.map +0 -1
- package/dist/debug-gWEjmYVV.js +0 -203
- package/dist/debug-gWEjmYVV.js.map +0 -1
- package/dist/paths-BL-x2rFy.js +0 -16
- package/dist/paths-BL-x2rFy.js.map +0 -1
- package/dist/posthog-integration-D4SRhJIQ.js.map +0 -1
- package/dist/readiness-gQvQNCeL.js.map +0 -1
- package/dist/router-SgzmfLGi.js.map +0 -1
- package/dist/setup-utils-_ONxN-TT.js +0 -2
- package/dist/setup-utils-y4s-3uKT.js.map +0 -1
- package/dist/start-playground-g1TxpCZ5.js.map +0 -1
- package/dist/start-tui-CQef69NR.js +0 -2167
- package/dist/start-tui-CQef69NR.js.map +0 -1
- package/dist/steps-D1zKDqAo.js.map +0 -1
- package/dist/wizard-session-COhklXAF.js +0 -2
- package/dist/wizard-ui-BExOjdjA.js.map +0 -1
package/README.md
CHANGED
|
@@ -2,11 +2,14 @@
|
|
|
2
2
|
<img alt="posthoglogo" src="https://user-images.githubusercontent.com/65415371/205059737-c8a4f836-4889-4654-902e-f302b187b6a0.png">
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
|
|
6
6
|
> have any feedback, please drop an email to **[wizard@posthog.com](mailto:wizard@posthog.com)**.
|
|
7
7
|
|
|
8
8
|
<h1>PostHog wizard ✨</h1>
|
|
9
|
-
|
|
9
|
+
|
|
10
|
+
The PostHog wizard helps you quickly add PostHog to your project using AI.
|
|
11
|
+
|
|
12
|
+

|
|
10
13
|
|
|
11
14
|
# Usage
|
|
12
15
|
|
|
@@ -16,10 +19,11 @@ To use the wizard, you can run it directly using:
|
|
|
16
19
|
npx @posthog/wizard
|
|
17
20
|
```
|
|
18
21
|
|
|
19
|
-
Currently the wizard can be used for
|
|
20
|
-
Native** projects. If you have other integrations you would like the wizard to
|
|
22
|
+
Currently the wizard can be used for over 16 frameworks for frontend, backend, and mobile applications. If you have other integrations you would like the wizard to
|
|
21
23
|
support, please open a [GitHub issue](https://github.com/posthog/wizard/issues)!
|
|
22
24
|
|
|
25
|
+
Visit our [docs](https://posthog.com/docs/ai-engineering/ai-wizard) to learn more.
|
|
26
|
+
|
|
23
27
|
## MCP Commands
|
|
24
28
|
|
|
25
29
|
The wizard also includes commands for managing PostHog MCP (Model Context
|
|
@@ -44,6 +48,46 @@ npx @posthog/wizard revenue
|
|
|
44
48
|
Requires PostHog and Stripe SDKs already installed. Supports `--ci` with the
|
|
45
49
|
same flags as the main wizard.
|
|
46
50
|
|
|
51
|
+
## Headless signup + install (agents / CI)
|
|
52
|
+
|
|
53
|
+
For a fully non-interactive first-run (no existing PostHog account, no TTY,
|
|
54
|
+
no browser), combine `--ci --signup --email`. The wizard provisions a new
|
|
55
|
+
account, uses the returned personal API key to run the normal CI install,
|
|
56
|
+
and wires PostHog into the project at `--install-dir`:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
npx @posthog/wizard --ci --signup \
|
|
60
|
+
--email you@example.com \
|
|
61
|
+
--install-dir .
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Optional flags: `--name "Your Name"`, `--region eu` (default `us`),
|
|
65
|
+
`--integration nextjs` (else auto-detected).
|
|
66
|
+
|
|
67
|
+
### Provision only
|
|
68
|
+
|
|
69
|
+
If you just want credentials — for tests, pre-flight checks, or wiring up
|
|
70
|
+
PostHog yourself — use the `provision` subcommand, which emits a structured
|
|
71
|
+
`ProvisioningResult` and does nothing else:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
# Human-readable (when stdout is a TTY)
|
|
75
|
+
npx @posthog/wizard provision --email user@example.com --region us
|
|
76
|
+
|
|
77
|
+
# Machine-readable — auto when stdout is piped, or force with --json
|
|
78
|
+
npx @posthog/wizard provision --email user@example.com --region eu --json
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Success prints the full `ProvisioningResult` (`projectApiKey`, `host`,
|
|
82
|
+
`projectId`, `accountId`, `accessToken`, `refreshToken`, and
|
|
83
|
+
`personalApiKey` if present). Failure exits 1; in `--json` mode the error
|
|
84
|
+
is emitted to stderr as `{"error":"...","code":"..."}`, with `code` set to
|
|
85
|
+
`email_exists` when the address is already registered.
|
|
86
|
+
|
|
87
|
+
> ⚠️ **Output contains live credentials.** Pipe it into a secrets store —
|
|
88
|
+
> do not let it be captured by shared CI logs. Mask the step output or
|
|
89
|
+
> redirect stdout to a file your job reads and discards.
|
|
90
|
+
|
|
47
91
|
# Options
|
|
48
92
|
|
|
49
93
|
The following CLI arguments are available:
|
|
@@ -62,9 +106,6 @@ The following CLI arguments are available:
|
|
|
62
106
|
| `--ci` | Enable CI mode for non-interactive execution | boolean | `false` | | `POSTHOG_WIZARD_CI` |
|
|
63
107
|
| `--api-key` | PostHog personal API key (phx_xxx) for authentication | string | | | `POSTHOG_WIZARD_API_KEY` |
|
|
64
108
|
|
|
65
|
-
> Note: A large amount of the scaffolding for this came from the amazing Sentry
|
|
66
|
-
> wizard, which you can find [here](https://github.com/getsentry/sentry-wizard)
|
|
67
|
-
> 💖
|
|
68
109
|
|
|
69
110
|
# CI Mode
|
|
70
111
|
|
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { n as isTaskStatus } from "./wizard-ui-
|
|
3
|
-
import { r as
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
1
|
+
import { d as SERVICE_LABELS } from "./debug-Cqi6nVfX.js";
|
|
2
|
+
import { n as isTaskStatus } from "./wizard-ui-YdGFRyu_.js";
|
|
3
|
+
import { n as analytics, r as sessionProperties } from "./analytics-VM7laaFx.js";
|
|
4
|
+
import { r as buildSession } from "./wizard-session-BcNJTl2I.js";
|
|
5
|
+
import { g as AUDIT_SEVERITY_STYLE } from "./agent-interface-CV0-vtxj.js";
|
|
6
|
+
import { r as getKindMeta } from "./bin.js";
|
|
7
|
+
import { n as AVAILABLE_FEATURES, t as ALL_FEATURE_VALUES } from "./defaults-GbLPuHxj.js";
|
|
8
|
+
import { i as WORKFLOW_STEPS, t as WizardRouter } from "./router-COhhuIW3.js";
|
|
8
9
|
import * as fs$1 from "fs";
|
|
9
10
|
import { Box, Text, measureElement, useInput, useStdout } from "ink";
|
|
10
|
-
import { Component, createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
11
|
+
import { Component, Fragment, createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
11
12
|
import { atom, map } from "nanostores";
|
|
12
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
13
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
13
14
|
import { Spinner } from "@inkjs/ui";
|
|
14
15
|
//#region src/ui/tui/store.ts
|
|
15
16
|
/**
|
|
@@ -525,7 +526,7 @@ const ProgressList = ({ items, title }) => {
|
|
|
525
526
|
return /* @__PURE__ */ jsxs(Box, {
|
|
526
527
|
flexDirection: "column",
|
|
527
528
|
children: [
|
|
528
|
-
title && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Text, {
|
|
529
|
+
title && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Text, {
|
|
529
530
|
bold: true,
|
|
530
531
|
children: title
|
|
531
532
|
}), /* @__PURE__ */ jsx(Text, { children: " " })] }),
|
|
@@ -1275,7 +1276,7 @@ const ModalOverlay = ({ borderColor, title, titleColor, width = 68, children, fe
|
|
|
1275
1276
|
children: feedback
|
|
1276
1277
|
})
|
|
1277
1278
|
}),
|
|
1278
|
-
footer && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Box, {
|
|
1279
|
+
footer && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Box, {
|
|
1279
1280
|
marginY: 1,
|
|
1280
1281
|
children: /* @__PURE__ */ jsx(Divider, {})
|
|
1281
1282
|
}), footer] })
|
|
@@ -1290,10 +1291,10 @@ const ModalOverlay = ({ borderColor, title, titleColor, width = 68, children, fe
|
|
|
1290
1291
|
* Only renders the last N lines that fit on screen.
|
|
1291
1292
|
*/
|
|
1292
1293
|
/** Rows consumed by TitleBar + spacer + ScreenContainer padding + status bar + tab bar */
|
|
1293
|
-
const CHROME_ROWS = 8;
|
|
1294
|
+
const CHROME_ROWS$1 = 8;
|
|
1294
1295
|
const LogViewer = ({ filePath, height }) => {
|
|
1295
1296
|
const [, rows] = useStdoutDimensions();
|
|
1296
|
-
const visibleLines = height ?? Math.max(5, rows - CHROME_ROWS);
|
|
1297
|
+
const visibleLines = height ?? Math.max(5, rows - CHROME_ROWS$1);
|
|
1297
1298
|
const [lines, setLines] = useState([]);
|
|
1298
1299
|
useEffect(() => {
|
|
1299
1300
|
const readTail = () => {
|
|
@@ -1461,7 +1462,7 @@ const DissolveTransition = ({ transitionKey, width, height, children, direction
|
|
|
1461
1462
|
maxTicks,
|
|
1462
1463
|
width
|
|
1463
1464
|
]);
|
|
1464
|
-
if (phase === "idle") return /* @__PURE__ */ jsx(Fragment, { children: displayChildren });
|
|
1465
|
+
if (phase === "idle") return /* @__PURE__ */ jsx(Fragment$1, { children: displayChildren });
|
|
1465
1466
|
const easedValue = easeInOutCirc(Math.min(tick / easerSteps, 1));
|
|
1466
1467
|
const activatedCount = Math.floor(easedValue * width);
|
|
1467
1468
|
const columnOrder = [];
|
|
@@ -1576,11 +1577,10 @@ var ScreenErrorBoundary = class extends Component {
|
|
|
1576
1577
|
* screen content (inside the transition area) so all screens get it.
|
|
1577
1578
|
*/
|
|
1578
1579
|
const MIN_WIDTH = 80;
|
|
1579
|
-
const MAX_WIDTH = 120;
|
|
1580
1580
|
/** Use terminal width when small so we don't overflow; otherwise clamp to [MIN_WIDTH, MAX_WIDTH]. */
|
|
1581
1581
|
function getContentWidth(terminalColumns) {
|
|
1582
1582
|
if (terminalColumns < MIN_WIDTH) return terminalColumns;
|
|
1583
|
-
return Math.min(
|
|
1583
|
+
return Math.min(120, terminalColumns);
|
|
1584
1584
|
}
|
|
1585
1585
|
const ScreenContainer = ({ store, screens }) => {
|
|
1586
1586
|
const [columns, rows] = useStdoutDimensions();
|
|
@@ -2104,7 +2104,7 @@ const NodeBlock = ({ content, active, completed, onComplete }) => {
|
|
|
2104
2104
|
dimColor: true,
|
|
2105
2105
|
children: content
|
|
2106
2106
|
});
|
|
2107
|
-
return /* @__PURE__ */ jsx(Fragment, { children: content });
|
|
2107
|
+
return /* @__PURE__ */ jsx(Fragment$1, { children: content });
|
|
2108
2108
|
};
|
|
2109
2109
|
//#endregion
|
|
2110
2110
|
//#region src/ui/tui/primitives/ContentSequencer.tsx
|
|
@@ -3098,7 +3098,7 @@ const TipsCard = ({ store }) => {
|
|
|
3098
3098
|
]
|
|
3099
3099
|
}) : /* @__PURE__ */ jsxs(Text, {
|
|
3100
3100
|
dimColor: true,
|
|
3101
|
-
children: [tip.description, tip.url && /* @__PURE__ */ jsxs(Fragment, { children: [" ", /* @__PURE__ */ jsx(Text, {
|
|
3101
|
+
children: [tip.description, tip.url && /* @__PURE__ */ jsxs(Fragment$1, { children: [" ", /* @__PURE__ */ jsx(Text, {
|
|
3102
3102
|
color: "cyan",
|
|
3103
3103
|
children: tip.url
|
|
3104
3104
|
})] })]
|
|
@@ -3417,7 +3417,7 @@ const McpScreen = ({ store, installer, mode = "install" }) => {
|
|
|
3417
3417
|
" MCP clients detected. Skipping..."
|
|
3418
3418
|
]
|
|
3419
3419
|
}),
|
|
3420
|
-
phase === "ask" && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs(Text, {
|
|
3420
|
+
phase === "ask" && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs(Text, {
|
|
3421
3421
|
dimColor: true,
|
|
3422
3422
|
children: ["Detected: ", clients.map((c) => c.name).join(", ")]
|
|
3423
3423
|
}), /* @__PURE__ */ jsx(Box, {
|
|
@@ -3455,7 +3455,7 @@ const McpScreen = ({ store, installer, mode = "install" }) => {
|
|
|
3455
3455
|
}),
|
|
3456
3456
|
phase === "done" && /* @__PURE__ */ jsx(Box, {
|
|
3457
3457
|
flexDirection: "column",
|
|
3458
|
-
children: resultClients.length > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs(Text, {
|
|
3458
|
+
children: resultClients.length > 0 ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs(Text, {
|
|
3459
3459
|
color: "green",
|
|
3460
3460
|
bold: true,
|
|
3461
3461
|
children: [
|
|
@@ -3481,6 +3481,418 @@ const McpScreen = ({ store, installer, mode = "install" }) => {
|
|
|
3481
3481
|
});
|
|
3482
3482
|
};
|
|
3483
3483
|
//#endregion
|
|
3484
|
-
|
|
3484
|
+
//#region src/ui/tui/screens/audit/AuditChecksViewer/AreaHeaderRow.tsx
|
|
3485
|
+
/** Sub-header row inside the scrollable body — one per area group. */
|
|
3486
|
+
const AreaHeaderRow = ({ area, resolved, total }) => /* @__PURE__ */ jsxs(Box, {
|
|
3487
|
+
flexShrink: 0,
|
|
3488
|
+
marginTop: 1,
|
|
3489
|
+
children: [/* @__PURE__ */ jsxs(Text, {
|
|
3490
|
+
bold: true,
|
|
3491
|
+
color: "cyan",
|
|
3492
|
+
children: [area, " "]
|
|
3493
|
+
}), /* @__PURE__ */ jsxs(Text, {
|
|
3494
|
+
dimColor: true,
|
|
3495
|
+
children: [
|
|
3496
|
+
"(",
|
|
3497
|
+
resolved,
|
|
3498
|
+
"/",
|
|
3499
|
+
total,
|
|
3500
|
+
")"
|
|
3501
|
+
]
|
|
3502
|
+
})]
|
|
3503
|
+
});
|
|
3504
|
+
/** ScreenContainer wraps content in paddingX={1} inside a width capped at
|
|
3505
|
+
* MAX_WIDTH, so the actual width available to the viewer is
|
|
3506
|
+
* min(cols, MAX_WIDTH) - 2. */
|
|
3507
|
+
function getViewerWidth(rawCols) {
|
|
3508
|
+
return Math.min(120, rawCols) - 2;
|
|
3509
|
+
}
|
|
3510
|
+
function computeLayout(rawCols, termRows) {
|
|
3511
|
+
const cols = getViewerWidth(rawCols);
|
|
3512
|
+
const padding = 2;
|
|
3513
|
+
const statusWidth = 2;
|
|
3514
|
+
const fixedExceptLabel = padding + statusWidth + 2 + 18 + 2 + 2;
|
|
3515
|
+
const labelWidth = Math.max(28, cols - fixedExceptLabel);
|
|
3516
|
+
const detailIndent = statusWidth + 2 + 18 + 2;
|
|
3517
|
+
const viewerChrome = 10;
|
|
3518
|
+
return {
|
|
3519
|
+
cols,
|
|
3520
|
+
visibleHeight: Math.max(5, termRows - 10 - viewerChrome),
|
|
3521
|
+
viewerChrome,
|
|
3522
|
+
padding,
|
|
3523
|
+
statusWidth,
|
|
3524
|
+
areaWidth: 18,
|
|
3525
|
+
labelWidth,
|
|
3526
|
+
colGap: 2,
|
|
3527
|
+
dividerWidth: Math.max(20, cols - padding),
|
|
3528
|
+
detailIndent,
|
|
3529
|
+
detailWidth: Math.max(20, cols - detailIndent - padding)
|
|
3530
|
+
};
|
|
3531
|
+
}
|
|
3532
|
+
function truncate(text, max) {
|
|
3533
|
+
if (max <= 0) return "";
|
|
3534
|
+
if (text.length <= max) return text;
|
|
3535
|
+
return text.slice(0, Math.max(1, max - 1)) + "…";
|
|
3536
|
+
}
|
|
3537
|
+
//#endregion
|
|
3538
|
+
//#region src/ui/tui/screens/audit/AuditChecksViewer/CheckRow.tsx
|
|
3539
|
+
const CheckRow = ({ item, layout }) => {
|
|
3540
|
+
const style = AUDIT_SEVERITY_STYLE[item.status];
|
|
3541
|
+
return /* @__PURE__ */ jsxs(Box, {
|
|
3542
|
+
flexShrink: 0,
|
|
3543
|
+
children: [
|
|
3544
|
+
/* @__PURE__ */ jsx(Box, {
|
|
3545
|
+
width: layout.statusWidth + layout.colGap,
|
|
3546
|
+
children: /* @__PURE__ */ jsx(Text, {
|
|
3547
|
+
color: style.color,
|
|
3548
|
+
children: style.glyph
|
|
3549
|
+
})
|
|
3550
|
+
}),
|
|
3551
|
+
/* @__PURE__ */ jsx(Box, {
|
|
3552
|
+
width: layout.areaWidth + layout.colGap,
|
|
3553
|
+
children: /* @__PURE__ */ jsx(Text, {
|
|
3554
|
+
dimColor: true,
|
|
3555
|
+
children: truncate(item.area, layout.areaWidth)
|
|
3556
|
+
})
|
|
3557
|
+
}),
|
|
3558
|
+
/* @__PURE__ */ jsx(Box, {
|
|
3559
|
+
width: layout.labelWidth + layout.colGap,
|
|
3560
|
+
children: /* @__PURE__ */ jsx(Text, {
|
|
3561
|
+
bold: item.status !== "pending",
|
|
3562
|
+
dimColor: item.status === "pending",
|
|
3563
|
+
children: truncate(item.label, layout.labelWidth)
|
|
3564
|
+
})
|
|
3565
|
+
})
|
|
3566
|
+
]
|
|
3567
|
+
});
|
|
3568
|
+
};
|
|
3569
|
+
//#endregion
|
|
3570
|
+
//#region src/ui/tui/screens/audit/AuditChecksViewer/DetailRow.tsx
|
|
3571
|
+
/** Format a `details` string. If it parses as a JSON object, render it as
|
|
3572
|
+
* indented key: value lines (skipping huge nested arrays/objects which we
|
|
3573
|
+
* truncate). Otherwise return the original text. v3000 emits structured
|
|
3574
|
+
* JSON for several event-quality checks — a raw dump is unreadable. */
|
|
3575
|
+
function formatDetails(raw) {
|
|
3576
|
+
const trimmed = raw.trim();
|
|
3577
|
+
if (!trimmed.startsWith("{") && !trimmed.startsWith("[")) return [raw];
|
|
3578
|
+
let parsed;
|
|
3579
|
+
try {
|
|
3580
|
+
parsed = JSON.parse(trimmed);
|
|
3581
|
+
} catch {
|
|
3582
|
+
return [raw];
|
|
3583
|
+
}
|
|
3584
|
+
if (parsed === null || typeof parsed !== "object") return [raw];
|
|
3585
|
+
const lines = [];
|
|
3586
|
+
const renderValue = (v) => {
|
|
3587
|
+
if (v === null) return "null";
|
|
3588
|
+
if (typeof v === "string") return v;
|
|
3589
|
+
if (typeof v === "number" || typeof v === "boolean") return String(v);
|
|
3590
|
+
if (Array.isArray(v)) {
|
|
3591
|
+
if (v.length === 0) return "[]";
|
|
3592
|
+
if (v.every((e) => e === null || typeof e !== "object")) return v.map(renderValue).join(", ");
|
|
3593
|
+
return `[${v.length} item${v.length === 1 ? "" : "s"}]`;
|
|
3594
|
+
}
|
|
3595
|
+
if (typeof v === "object") {
|
|
3596
|
+
const keys = Object.keys(v);
|
|
3597
|
+
return `{${keys.length} field${keys.length === 1 ? "" : "s"}}`;
|
|
3598
|
+
}
|
|
3599
|
+
return String(v);
|
|
3600
|
+
};
|
|
3601
|
+
for (const [key, value] of Object.entries(parsed)) lines.push(`${key}: ${renderValue(value)}`);
|
|
3602
|
+
return lines.length > 0 ? lines : [raw];
|
|
3603
|
+
}
|
|
3604
|
+
/** Indented under the CHECK column; wrap continuation aligns with the prefix. */
|
|
3605
|
+
const DetailRow = ({ item, layout }) => {
|
|
3606
|
+
const detailLines = item.details ? formatDetails(item.details) : [];
|
|
3607
|
+
return /* @__PURE__ */ jsxs(Box, {
|
|
3608
|
+
flexShrink: 0,
|
|
3609
|
+
children: [/* @__PURE__ */ jsx(Box, { width: layout.detailIndent }), /* @__PURE__ */ jsxs(Box, {
|
|
3610
|
+
flexDirection: "column",
|
|
3611
|
+
width: layout.detailWidth,
|
|
3612
|
+
children: [item.file && /* @__PURE__ */ jsx(Text, {
|
|
3613
|
+
dimColor: true,
|
|
3614
|
+
wrap: "wrap",
|
|
3615
|
+
children: `↳ File: ${item.file}`
|
|
3616
|
+
}), detailLines.map((line, i) => /* @__PURE__ */ jsx(Text, {
|
|
3617
|
+
dimColor: true,
|
|
3618
|
+
italic: true,
|
|
3619
|
+
wrap: "wrap",
|
|
3620
|
+
children: i === 0 ? `${item.file ? " " : "↳ "}${line}` : ` ${line}`
|
|
3621
|
+
}, i))]
|
|
3622
|
+
})]
|
|
3623
|
+
});
|
|
3624
|
+
};
|
|
3625
|
+
//#endregion
|
|
3626
|
+
//#region src/ui/tui/screens/audit/AuditChecksViewer/Legend.tsx
|
|
3627
|
+
const Legend = () => /* @__PURE__ */ jsxs(Text, { children: [
|
|
3628
|
+
/* @__PURE__ */ jsx(Text, {
|
|
3629
|
+
color: "green",
|
|
3630
|
+
children: "✔ pass"
|
|
3631
|
+
}),
|
|
3632
|
+
/* @__PURE__ */ jsx(Text, {
|
|
3633
|
+
dimColor: true,
|
|
3634
|
+
children: " · "
|
|
3635
|
+
}),
|
|
3636
|
+
/* @__PURE__ */ jsx(Text, {
|
|
3637
|
+
color: "red",
|
|
3638
|
+
children: "✘ error"
|
|
3639
|
+
}),
|
|
3640
|
+
/* @__PURE__ */ jsx(Text, {
|
|
3641
|
+
dimColor: true,
|
|
3642
|
+
children: " · "
|
|
3643
|
+
}),
|
|
3644
|
+
/* @__PURE__ */ jsx(Text, {
|
|
3645
|
+
color: "yellow",
|
|
3646
|
+
children: "⚠ warning"
|
|
3647
|
+
}),
|
|
3648
|
+
/* @__PURE__ */ jsx(Text, {
|
|
3649
|
+
dimColor: true,
|
|
3650
|
+
children: " · "
|
|
3651
|
+
}),
|
|
3652
|
+
/* @__PURE__ */ jsx(Text, {
|
|
3653
|
+
color: "cyan",
|
|
3654
|
+
children: "• suggestion"
|
|
3655
|
+
})
|
|
3656
|
+
] });
|
|
3657
|
+
//#endregion
|
|
3658
|
+
//#region src/ui/tui/screens/audit/AuditChecksViewer/Header.tsx
|
|
3659
|
+
function statusCounts(checks) {
|
|
3660
|
+
const out = {
|
|
3661
|
+
pending: 0,
|
|
3662
|
+
pass: 0,
|
|
3663
|
+
error: 0,
|
|
3664
|
+
warning: 0,
|
|
3665
|
+
suggestion: 0
|
|
3666
|
+
};
|
|
3667
|
+
for (const c of checks) out[c.status] += 1;
|
|
3668
|
+
return out;
|
|
3669
|
+
}
|
|
3670
|
+
const Header = ({ layout }) => /* @__PURE__ */ jsxs(Box, { children: [
|
|
3671
|
+
/* @__PURE__ */ jsx(Box, {
|
|
3672
|
+
width: layout.statusWidth + layout.colGap,
|
|
3673
|
+
children: /* @__PURE__ */ jsx(Text, {
|
|
3674
|
+
dimColor: true,
|
|
3675
|
+
bold: true,
|
|
3676
|
+
children: " "
|
|
3677
|
+
})
|
|
3678
|
+
}),
|
|
3679
|
+
/* @__PURE__ */ jsx(Box, {
|
|
3680
|
+
width: layout.areaWidth + layout.colGap,
|
|
3681
|
+
children: /* @__PURE__ */ jsx(Text, {
|
|
3682
|
+
dimColor: true,
|
|
3683
|
+
bold: true,
|
|
3684
|
+
children: "AREA"
|
|
3685
|
+
})
|
|
3686
|
+
}),
|
|
3687
|
+
/* @__PURE__ */ jsx(Box, {
|
|
3688
|
+
width: layout.labelWidth + layout.colGap,
|
|
3689
|
+
children: /* @__PURE__ */ jsx(Text, {
|
|
3690
|
+
dimColor: true,
|
|
3691
|
+
bold: true,
|
|
3692
|
+
children: "CHECK"
|
|
3693
|
+
})
|
|
3694
|
+
})
|
|
3695
|
+
] });
|
|
3696
|
+
const Summary = ({ total, counts }) => /* @__PURE__ */ jsxs(Text, {
|
|
3697
|
+
dimColor: true,
|
|
3698
|
+
children: [
|
|
3699
|
+
total,
|
|
3700
|
+
" total · ",
|
|
3701
|
+
counts.pending,
|
|
3702
|
+
" pending · ",
|
|
3703
|
+
counts.error,
|
|
3704
|
+
" errors ·",
|
|
3705
|
+
" ",
|
|
3706
|
+
counts.warning,
|
|
3707
|
+
" warnings · ",
|
|
3708
|
+
counts.suggestion,
|
|
3709
|
+
" suggestions · ",
|
|
3710
|
+
counts.pass,
|
|
3711
|
+
" ",
|
|
3712
|
+
"passes"
|
|
3713
|
+
]
|
|
3714
|
+
});
|
|
3715
|
+
//#endregion
|
|
3716
|
+
//#region src/ui/tui/screens/audit/AuditChecksViewer/Footer.tsx
|
|
3717
|
+
const Footer = ({ total, counts }) => /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Legend, {}), /* @__PURE__ */ jsx(Summary, {
|
|
3718
|
+
total,
|
|
3719
|
+
counts
|
|
3720
|
+
})] });
|
|
3721
|
+
//#endregion
|
|
3722
|
+
//#region src/ui/tui/screens/audit/AuditChecksViewer/sort.ts
|
|
3723
|
+
const STATUS_ORDER = {
|
|
3724
|
+
error: 0,
|
|
3725
|
+
warning: 1,
|
|
3726
|
+
suggestion: 2,
|
|
3727
|
+
pass: 3,
|
|
3728
|
+
pending: 4
|
|
3729
|
+
};
|
|
3730
|
+
/** Audit areas in the order they should be displayed. Areas not listed
|
|
3731
|
+
* here fall through to alphabetical order at the end. Mirrors the
|
|
3732
|
+
* Full audit section grouping in the generated report. */
|
|
3733
|
+
const AREA_ORDER = [
|
|
3734
|
+
"Installation",
|
|
3735
|
+
"Identification",
|
|
3736
|
+
"Event Capture",
|
|
3737
|
+
"Event Quality",
|
|
3738
|
+
"Feature Flags",
|
|
3739
|
+
"Session Replay",
|
|
3740
|
+
"Session Replay — Optimize",
|
|
3741
|
+
"Use Case: Expansion",
|
|
3742
|
+
"Additional Sections"
|
|
3743
|
+
];
|
|
3744
|
+
function areaRank(area) {
|
|
3745
|
+
const idx = AREA_ORDER.indexOf(area);
|
|
3746
|
+
return idx === -1 ? AREA_ORDER.length : idx;
|
|
3747
|
+
}
|
|
3748
|
+
/** Group checks by area, in AREA_ORDER. Within each area, sort by status. */
|
|
3749
|
+
function groupChecksByArea(checks) {
|
|
3750
|
+
const byArea = /* @__PURE__ */ new Map();
|
|
3751
|
+
for (const c of checks) {
|
|
3752
|
+
const list = byArea.get(c.area);
|
|
3753
|
+
if (list) list.push(c);
|
|
3754
|
+
else byArea.set(c.area, [c]);
|
|
3755
|
+
}
|
|
3756
|
+
const groups = [];
|
|
3757
|
+
for (const [area, areaChecks] of byArea) {
|
|
3758
|
+
const sorted = [...areaChecks].sort((a, b) => STATUS_ORDER[a.status] - STATUS_ORDER[b.status]);
|
|
3759
|
+
const resolved = sorted.filter((c) => c.status !== "pending").length;
|
|
3760
|
+
groups.push({
|
|
3761
|
+
area,
|
|
3762
|
+
checks: sorted,
|
|
3763
|
+
counts: {
|
|
3764
|
+
total: sorted.length,
|
|
3765
|
+
resolved
|
|
3766
|
+
}
|
|
3767
|
+
});
|
|
3768
|
+
}
|
|
3769
|
+
groups.sort((a, b) => {
|
|
3770
|
+
const dr = areaRank(a.area) - areaRank(b.area);
|
|
3771
|
+
if (dr !== 0) return dr;
|
|
3772
|
+
return a.area.localeCompare(b.area);
|
|
3773
|
+
});
|
|
3774
|
+
return groups;
|
|
3775
|
+
}
|
|
3776
|
+
//#endregion
|
|
3777
|
+
//#region src/ui/tui/screens/audit/AuditChecksViewer/AuditChecksViewer.tsx
|
|
3778
|
+
/**
|
|
3779
|
+
* AuditChecksViewer — "Audit plan" tab.
|
|
3780
|
+
*
|
|
3781
|
+
* Renders the full audit ledger as a scrollable, area-grouped list that
|
|
3782
|
+
* mirrors the structure of the final report. Each area gets a sub-header
|
|
3783
|
+
* with a resolved/total count; checks within an area are sorted by
|
|
3784
|
+
* severity (error → warning → suggestion → pass → pending).
|
|
3785
|
+
*
|
|
3786
|
+
* Two interactions, both registered via `useKeyBindings`:
|
|
3787
|
+
* - `e` — toggle detail rows (file:line + agent's `details` text)
|
|
3788
|
+
* - `↑` / `↓` — scroll one row at a time, clamped to content bounds
|
|
3789
|
+
*
|
|
3790
|
+
* Auto-expands on first mount when the ledger contains any issue, since
|
|
3791
|
+
* the AuditAreaPane's `[→] View issues` hint sends users here precisely
|
|
3792
|
+
* to read those details.
|
|
3793
|
+
*/
|
|
3794
|
+
const AuditChecksViewer = ({ checks }) => {
|
|
3795
|
+
const [rawCols, termRows] = useStdoutDimensions();
|
|
3796
|
+
const layout = computeLayout(rawCols, termRows);
|
|
3797
|
+
const totalHeight = layout.visibleHeight + layout.viewerChrome;
|
|
3798
|
+
const groups = useMemo(() => groupChecksByArea(checks), [checks]);
|
|
3799
|
+
const counts = useMemo(() => statusCounts(checks), [checks]);
|
|
3800
|
+
const hasExpandable = checks.some((c) => Boolean(c.details || c.file));
|
|
3801
|
+
const [expanded, setExpanded] = useState(checks.some((c) => c.status === "error" || c.status === "warning" || c.status === "suggestion") && hasExpandable);
|
|
3802
|
+
const allRows = useMemo(() => {
|
|
3803
|
+
const rows = [];
|
|
3804
|
+
for (const group of groups) {
|
|
3805
|
+
rows.push(/* @__PURE__ */ jsx(AreaHeaderRow, {
|
|
3806
|
+
area: group.area,
|
|
3807
|
+
resolved: group.counts.resolved,
|
|
3808
|
+
total: group.counts.total
|
|
3809
|
+
}, `header-${group.area}`));
|
|
3810
|
+
for (const item of group.checks) {
|
|
3811
|
+
rows.push(/* @__PURE__ */ jsx(CheckRow, {
|
|
3812
|
+
item,
|
|
3813
|
+
layout
|
|
3814
|
+
}, item.id));
|
|
3815
|
+
if (expanded && (item.details || item.file)) rows.push(/* @__PURE__ */ jsx(DetailRow, {
|
|
3816
|
+
item,
|
|
3817
|
+
layout
|
|
3818
|
+
}, `${item.id}-detail`));
|
|
3819
|
+
}
|
|
3820
|
+
}
|
|
3821
|
+
return rows;
|
|
3822
|
+
}, [
|
|
3823
|
+
groups,
|
|
3824
|
+
expanded,
|
|
3825
|
+
layout
|
|
3826
|
+
]);
|
|
3827
|
+
const [offset, setOffset] = useState(0);
|
|
3828
|
+
const maxOffset = Math.max(0, allRows.length - layout.visibleHeight);
|
|
3829
|
+
const clampedOffset = Math.min(offset, maxOffset);
|
|
3830
|
+
const hiddenAbove = clampedOffset;
|
|
3831
|
+
const hiddenBelow = Math.max(0, allRows.length - clampedOffset - layout.visibleHeight);
|
|
3832
|
+
const bindings = [];
|
|
3833
|
+
if (hasExpandable) bindings.push({
|
|
3834
|
+
match: "e",
|
|
3835
|
+
label: "e",
|
|
3836
|
+
action: expanded ? "collapse details" : "expand details",
|
|
3837
|
+
handler: () => setExpanded((prev) => !prev)
|
|
3838
|
+
});
|
|
3839
|
+
bindings.push({
|
|
3840
|
+
match: ["upArrow", "downArrow"],
|
|
3841
|
+
label: "↑↓",
|
|
3842
|
+
action: "scroll",
|
|
3843
|
+
handler: (_input, key) => {
|
|
3844
|
+
if (key.upArrow) setOffset((o) => Math.max(0, o - 1));
|
|
3845
|
+
else if (key.downArrow) setOffset((o) => Math.min(maxOffset, o + 1));
|
|
3846
|
+
}
|
|
3847
|
+
});
|
|
3848
|
+
useKeyBindings("audit-checks-viewer", bindings);
|
|
3849
|
+
const visibleRows = allRows.slice(clampedOffset, clampedOffset + layout.visibleHeight);
|
|
3850
|
+
const subtitle = groups.length === 0 ? "No checks yet." : `Review across ${groups.length} ${groups.length === 1 ? "area" : "areas"} — mirrors the final report.`;
|
|
3851
|
+
return /* @__PURE__ */ jsxs(Box, {
|
|
3852
|
+
flexDirection: "column",
|
|
3853
|
+
paddingX: 1,
|
|
3854
|
+
height: totalHeight,
|
|
3855
|
+
children: [
|
|
3856
|
+
/* @__PURE__ */ jsx(Text, {
|
|
3857
|
+
bold: true,
|
|
3858
|
+
children: "Audit plan"
|
|
3859
|
+
}),
|
|
3860
|
+
/* @__PURE__ */ jsx(Text, {
|
|
3861
|
+
dimColor: true,
|
|
3862
|
+
children: subtitle
|
|
3863
|
+
}),
|
|
3864
|
+
/* @__PURE__ */ jsx(Summary, {
|
|
3865
|
+
total: checks.length,
|
|
3866
|
+
counts
|
|
3867
|
+
}),
|
|
3868
|
+
/* @__PURE__ */ jsx(Box, { height: 1 }),
|
|
3869
|
+
/* @__PURE__ */ jsx(Header, { layout }),
|
|
3870
|
+
/* @__PURE__ */ jsx(Text, {
|
|
3871
|
+
dimColor: true,
|
|
3872
|
+
children: "─".repeat(layout.dividerWidth)
|
|
3873
|
+
}),
|
|
3874
|
+
/* @__PURE__ */ jsx(Text, {
|
|
3875
|
+
dimColor: true,
|
|
3876
|
+
children: hiddenAbove > 0 ? `↑ ${hiddenAbove} more` : " "
|
|
3877
|
+
}),
|
|
3878
|
+
/* @__PURE__ */ jsx(Box, {
|
|
3879
|
+
flexDirection: "column",
|
|
3880
|
+
height: layout.visibleHeight,
|
|
3881
|
+
overflow: "hidden",
|
|
3882
|
+
children: visibleRows.map((node, i) => /* @__PURE__ */ jsx(Fragment, { children: node }, `row-${clampedOffset + i}`))
|
|
3883
|
+
}),
|
|
3884
|
+
/* @__PURE__ */ jsx(Text, {
|
|
3885
|
+
dimColor: true,
|
|
3886
|
+
children: hiddenBelow > 0 ? `↓ ${hiddenBelow} more` : " "
|
|
3887
|
+
}),
|
|
3888
|
+
/* @__PURE__ */ jsx(Footer, {
|
|
3889
|
+
total: checks.length,
|
|
3890
|
+
counts
|
|
3891
|
+
})
|
|
3892
|
+
]
|
|
3893
|
+
});
|
|
3894
|
+
};
|
|
3895
|
+
//#endregion
|
|
3896
|
+
export { CardLayout as C, WizardStore as E, SplitView as S, Icons as T, useStdoutDimensions as _, SEVERITY_ORDER as a, ProgressList as b, LearnCard as c, ScreenContainer as d, EventPlanViewer as f, GroupedPickerMenu as g, ConfirmationInput as h, SEVERITY_LABEL as i, HNViewer as l, ModalOverlay as m, McpScreen as n, ServiceHealthList as o, LogViewer as p, IssueTable as r, TipsCard as s, AuditChecksViewer as t, TabContainer as u, PickerMenu as v, Colors as w, LoadingBox as x, useKeyBindings as y };
|
|
3485
3897
|
|
|
3486
|
-
//# sourceMappingURL=
|
|
3898
|
+
//# sourceMappingURL=AuditChecksViewer-B0J7zcY2.js.map
|