@posthog/wizard 2.10.4 → 2.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/README.md +48 -7
  2. package/dist/{McpScreen-LqnNwEfV.js → AuditChecksViewer-DsfXIO9e.js} +475 -36
  3. package/dist/AuditChecksViewer-DsfXIO9e.js.map +1 -0
  4. package/dist/{add-mcp-server-to-clients-lfUH2pdU.js → add-mcp-server-to-clients-BKoew3aT.js} +157 -125
  5. package/dist/add-mcp-server-to-clients-BKoew3aT.js.map +1 -0
  6. package/dist/{readiness-Cep84RsR.js → agent-interface-D5W9BAB2.js} +329 -464
  7. package/dist/agent-interface-D5W9BAB2.js.map +1 -0
  8. package/dist/{agent-runner-DHtcWn15.js → agent-runner-B8Cx6X6x.js} +22 -31
  9. package/dist/agent-runner-B8Cx6X6x.js.map +1 -0
  10. package/dist/analytics-DmD31Ssc.js +123 -0
  11. package/dist/analytics-DmD31Ssc.js.map +1 -0
  12. package/dist/analytics-JDitS2JI.js +2 -0
  13. package/dist/bin.js +521 -46
  14. package/dist/bin.js.map +1 -1
  15. package/dist/debug-Bkaqv1ab.js +686 -0
  16. package/dist/debug-Bkaqv1ab.js.map +1 -0
  17. package/dist/{debug-CIyf0ZGx.js → debug-I5sRZubJ.js} +1 -1
  18. package/dist/{defaults-DoVkE0gW.js → defaults-GbLPuHxj.js} +8 -8
  19. package/dist/defaults-GbLPuHxj.js.map +1 -0
  20. package/dist/detection-C_RfYYDe.js +206 -0
  21. package/dist/detection-C_RfYYDe.js.map +1 -0
  22. package/dist/{env-api-key-K8TdTDII.js → env-api-key-D5G2PrXW.js} +1 -1
  23. package/dist/{env-api-key-K8TdTDII.js.map → env-api-key-D5G2PrXW.js.map} +1 -1
  24. package/dist/file-8iNrXHkG.js +16 -0
  25. package/dist/file-8iNrXHkG.js.map +1 -0
  26. package/dist/{file-utils-BWneZy6p.js → file-utils-DnTSiTJw.js} +1 -1
  27. package/dist/{file-utils-BWneZy6p.js.map → file-utils-DnTSiTJw.js.map} +1 -1
  28. package/dist/package-json-BzVey4Bd.js +2 -0
  29. package/dist/{package-json-Ctq6LSl8.js → package-json-F_7oktsp.js} +1 -1
  30. package/dist/{package-json-Ctq6LSl8.js.map → package-json-F_7oktsp.js.map} +1 -1
  31. package/dist/{package-manager-CwU26DwX.js → package-manager-qxP2PpM_.js} +2 -2
  32. package/dist/{package-manager-CwU26DwX.js.map → package-manager-qxP2PpM_.js.map} +1 -1
  33. package/dist/paths-DJS47p5x.js +26 -0
  34. package/dist/paths-DJS47p5x.js.map +1 -0
  35. package/dist/{posthog-integration-HBDZrREG.js → posthog-integration-DX77Msto.js} +43 -14
  36. package/dist/posthog-integration-DX77Msto.js.map +1 -0
  37. package/dist/posthog-vm0k9PKS.js +11 -0
  38. package/dist/posthog-vm0k9PKS.js.map +1 -0
  39. package/dist/provisioning-CHfTOEvg.js +2 -0
  40. package/dist/provisioning-DUj285NO.js +166 -0
  41. package/dist/provisioning-DUj285NO.js.map +1 -0
  42. package/dist/{registry-BIV1wRpo.js → registry-CCtIsqb8.js} +5 -6
  43. package/dist/{registry-BIV1wRpo.js.map → registry-CCtIsqb8.js.map} +1 -1
  44. package/dist/{router-CXjdWNh2.js → router-BTfmEDDJ.js} +4 -3
  45. package/dist/router-BTfmEDDJ.js.map +1 -0
  46. package/dist/{setup-utils-CHojnr4N.js → setup-utils-Bv8z6HMb.js} +17 -150
  47. package/dist/setup-utils-Bv8z6HMb.js.map +1 -0
  48. package/dist/setup-utils-CoX-vLgw.js +2 -0
  49. package/dist/{start-playground-D1iLBvqF.js → start-playground-DYNQ8rOz.js} +181 -9
  50. package/dist/start-playground-DYNQ8rOz.js.map +1 -0
  51. package/dist/{start-tui-DkT_H5zx.js → start-tui-DleQG3La.js} +1290 -163
  52. package/dist/start-tui-DleQG3La.js.map +1 -0
  53. package/dist/{steps-zpqG7W08.js → steps-C-syS8if.js} +8 -8
  54. package/dist/steps-C-syS8if.js.map +1 -0
  55. package/dist/task-stream-CX7Uf6EM.js +61 -0
  56. package/dist/task-stream-CX7Uf6EM.js.map +1 -0
  57. package/dist/{telemetry-CPoSyK0a.js → telemetry-DHZfjgqx.js} +2 -2
  58. package/dist/{telemetry-CPoSyK0a.js.map → telemetry-DHZfjgqx.js.map} +1 -1
  59. package/dist/{wizard-abort-BcEPhAxY.js → wizard-abort-DIhFXJ5N.js} +1 -1
  60. package/dist/{wizard-abort-DKctLd33.js → wizard-abort-DfhWuzaw.js} +6 -4
  61. package/dist/{wizard-abort-DKctLd33.js.map → wizard-abort-DfhWuzaw.js.map} +1 -1
  62. package/dist/wizard-session-BQC9vy9Z.js +2 -0
  63. package/dist/{wizard-session-Db6R023m.js → wizard-session-BcNJTl2I.js} +1 -1
  64. package/dist/{wizard-session-Db6R023m.js.map → wizard-session-BcNJTl2I.js.map} +1 -1
  65. package/dist/wizard-ui-YdGFRyu_.js +14 -0
  66. package/dist/wizard-ui-YdGFRyu_.js.map +1 -0
  67. package/npm-shrinkwrap.json +2 -2
  68. package/package.json +1 -1
  69. package/dist/McpScreen-LqnNwEfV.js.map +0 -1
  70. package/dist/add-mcp-server-to-clients-lfUH2pdU.js.map +0 -1
  71. package/dist/agent-runner-DHtcWn15.js.map +0 -1
  72. package/dist/agent-skill-BVjJqol6.js +0 -59
  73. package/dist/agent-skill-BVjJqol6.js.map +0 -1
  74. package/dist/analytics-Cm6i5_gc.js +0 -207
  75. package/dist/analytics-Cm6i5_gc.js.map +0 -1
  76. package/dist/analytics-CviQ_A9M.js +0 -2
  77. package/dist/debug-CyJ_3dTP.js +0 -201
  78. package/dist/debug-CyJ_3dTP.js.map +0 -1
  79. package/dist/defaults-DoVkE0gW.js.map +0 -1
  80. package/dist/detection-gcQwPKPu.js +0 -122
  81. package/dist/detection-gcQwPKPu.js.map +0 -1
  82. package/dist/package-json-BQgl5C3Z.js +0 -2
  83. package/dist/posthog-integration-HBDZrREG.js.map +0 -1
  84. package/dist/readiness-Cep84RsR.js.map +0 -1
  85. package/dist/router-CXjdWNh2.js.map +0 -1
  86. package/dist/setup-utils-CHojnr4N.js.map +0 -1
  87. package/dist/start-playground-D1iLBvqF.js.map +0 -1
  88. package/dist/start-tui-DkT_H5zx.js.map +0 -1
  89. package/dist/steps-zpqG7W08.js.map +0 -1
  90. package/dist/wizard-session-y7nf6aKH.js +0 -2
@@ -1,13 +1,16 @@
1
- import { n as analytics, r as sessionProperties } from "./analytics-Cm6i5_gc.js";
2
- import { r as buildSession } from "./wizard-session-Db6R023m.js";
3
- import { t as SERVICE_LABELS } from "./readiness-Cep84RsR.js";
4
- import { n as AVAILABLE_FEATURES, t as ALL_FEATURE_VALUES } from "./defaults-DoVkE0gW.js";
5
- import { i as WORKFLOW_STEPS, t as WizardRouter } from "./router-CXjdWNh2.js";
1
+ import { d as SERVICE_LABELS } from "./debug-Bkaqv1ab.js";
2
+ import { n as isTaskStatus } from "./wizard-ui-YdGFRyu_.js";
3
+ import { n as analytics, r as sessionProperties } from "./analytics-DmD31Ssc.js";
4
+ import { r as buildSession } from "./wizard-session-BcNJTl2I.js";
5
+ import { g as AUDIT_SEVERITY_STYLE } from "./agent-interface-D5W9BAB2.js";
6
+ import { n 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-BTfmEDDJ.js";
6
9
  import * as fs$1 from "fs";
7
10
  import { Box, Text, measureElement, useInput, useStdout } from "ink";
8
- 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";
9
12
  import { atom, map } from "nanostores";
10
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
13
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
11
14
  import { Spinner } from "@inkjs/ui";
12
15
  //#region src/ui/tui/store.ts
13
16
  /**
@@ -33,6 +36,7 @@ var WizardStore = class {
33
36
  $learnCardBlockIdx = atom(0);
34
37
  $learnCardComplete = atom(false);
35
38
  $version = atom(0);
39
+ _onTasksChanged = null;
36
40
  /** Last screen seen — used to detect screen transitions for analytics. */
37
41
  _lastScreen = null;
38
42
  /** Hooks run when transitioning onto a screen. */
@@ -414,16 +418,24 @@ var WizardStore = class {
414
418
  this.emitChange();
415
419
  }
416
420
  syncTodos(todos) {
417
- const incoming = todos.map((t) => ({
418
- label: t.content,
419
- activeForm: t.activeForm,
420
- status: t.status || "pending",
421
- done: t.status === "completed"
422
- }));
421
+ const incoming = todos.map((t) => {
422
+ const status = isTaskStatus(t.status) ? t.status : "pending";
423
+ return {
424
+ label: t.content,
425
+ activeForm: t.activeForm,
426
+ status,
427
+ done: status === "completed"
428
+ };
429
+ });
423
430
  const incomingLabels = new Set(incoming.map((t) => t.label));
424
431
  const retained = this.$tasks.get().filter((t) => t.done && !incomingLabels.has(t.label));
425
432
  this.$tasks.set([...retained, ...incoming]);
426
433
  this.emitChange();
434
+ this._onTasksChanged?.();
435
+ }
436
+ /** Register a listener for task state changes (e.g. task stream push). */
437
+ set onTasksChanged(fn) {
438
+ this._onTasksChanged = fn;
427
439
  }
428
440
  subscribe(callback) {
429
441
  return this.$version.listen(() => callback());
@@ -514,7 +526,7 @@ const ProgressList = ({ items, title }) => {
514
526
  return /* @__PURE__ */ jsxs(Box, {
515
527
  flexDirection: "column",
516
528
  children: [
517
- title && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Text, {
529
+ title && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Text, {
518
530
  bold: true,
519
531
  children: title
520
532
  }), /* @__PURE__ */ jsx(Text, { children: " " })] }),
@@ -1264,7 +1276,7 @@ const ModalOverlay = ({ borderColor, title, titleColor, width = 68, children, fe
1264
1276
  children: feedback
1265
1277
  })
1266
1278
  }),
1267
- footer && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Box, {
1279
+ footer && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Box, {
1268
1280
  marginY: 1,
1269
1281
  children: /* @__PURE__ */ jsx(Divider, {})
1270
1282
  }), footer] })
@@ -1279,10 +1291,10 @@ const ModalOverlay = ({ borderColor, title, titleColor, width = 68, children, fe
1279
1291
  * Only renders the last N lines that fit on screen.
1280
1292
  */
1281
1293
  /** Rows consumed by TitleBar + spacer + ScreenContainer padding + status bar + tab bar */
1282
- const CHROME_ROWS = 8;
1294
+ const CHROME_ROWS$1 = 8;
1283
1295
  const LogViewer = ({ filePath, height }) => {
1284
1296
  const [, rows] = useStdoutDimensions();
1285
- const visibleLines = height ?? Math.max(5, rows - CHROME_ROWS);
1297
+ const visibleLines = height ?? Math.max(5, rows - CHROME_ROWS$1);
1286
1298
  const [lines, setLines] = useState([]);
1287
1299
  useEffect(() => {
1288
1300
  const readTail = () => {
@@ -1450,7 +1462,7 @@ const DissolveTransition = ({ transitionKey, width, height, children, direction
1450
1462
  maxTicks,
1451
1463
  width
1452
1464
  ]);
1453
- if (phase === "idle") return /* @__PURE__ */ jsx(Fragment, { children: displayChildren });
1465
+ if (phase === "idle") return /* @__PURE__ */ jsx(Fragment$1, { children: displayChildren });
1454
1466
  const easedValue = easeInOutCirc(Math.min(tick / easerSteps, 1));
1455
1467
  const activatedCount = Math.floor(easedValue * width);
1456
1468
  const columnOrder = [];
@@ -1565,11 +1577,10 @@ var ScreenErrorBoundary = class extends Component {
1565
1577
  * screen content (inside the transition area) so all screens get it.
1566
1578
  */
1567
1579
  const MIN_WIDTH = 80;
1568
- const MAX_WIDTH = 120;
1569
1580
  /** Use terminal width when small so we don't overflow; otherwise clamp to [MIN_WIDTH, MAX_WIDTH]. */
1570
1581
  function getContentWidth(terminalColumns) {
1571
1582
  if (terminalColumns < MIN_WIDTH) return terminalColumns;
1572
- return Math.min(MAX_WIDTH, terminalColumns);
1583
+ return Math.min(120, terminalColumns);
1573
1584
  }
1574
1585
  const ScreenContainer = ({ store, screens }) => {
1575
1586
  const [columns, rows] = useStdoutDimensions();
@@ -2093,7 +2104,7 @@ const NodeBlock = ({ content, active, completed, onComplete }) => {
2093
2104
  dimColor: true,
2094
2105
  children: content
2095
2106
  });
2096
- return /* @__PURE__ */ jsx(Fragment, { children: content });
2107
+ return /* @__PURE__ */ jsx(Fragment$1, { children: content });
2097
2108
  };
2098
2109
  //#endregion
2099
2110
  //#region src/ui/tui/primitives/ContentSequencer.tsx
@@ -3087,7 +3098,7 @@ const TipsCard = ({ store }) => {
3087
3098
  ]
3088
3099
  }) : /* @__PURE__ */ jsxs(Text, {
3089
3100
  dimColor: true,
3090
- 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, {
3091
3102
  color: "cyan",
3092
3103
  children: tip.url
3093
3104
  })] })]
@@ -3185,6 +3196,120 @@ const ServiceHealthList = ({ health, filterKeys, showHealthy = true }) => {
3185
3196
  });
3186
3197
  };
3187
3198
  //#endregion
3199
+ //#region src/ui/tui/screens/doctor/IssueTable.tsx
3200
+ const SEVERITY_ORDER = [
3201
+ "critical",
3202
+ "warning",
3203
+ "info"
3204
+ ];
3205
+ const SEVERITY_COLOR = {
3206
+ critical: Colors.error,
3207
+ warning: Colors.accent,
3208
+ info: Colors.primary
3209
+ };
3210
+ const SEVERITY_LABEL = {
3211
+ critical: "Critical",
3212
+ warning: "Warning",
3213
+ info: "Info"
3214
+ };
3215
+ const ICON_COL = 2;
3216
+ const ROW_GAP = 2;
3217
+ const NARROW_TERM_THRESHOLD = 90;
3218
+ const MAX_DOCS_WIDTH = 50;
3219
+ const MIN_DOCS_WIDTH = 20;
3220
+ function computeDocsWidth(termCols) {
3221
+ if (termCols < NARROW_TERM_THRESHOLD) return 0;
3222
+ const inner = termCols - 12;
3223
+ return Math.min(MAX_DOCS_WIDTH, Math.max(MIN_DOCS_WIDTH, Math.floor(inner * .45)));
3224
+ }
3225
+ const IssueTable = ({ issues }) => {
3226
+ const [termCols] = useStdoutDimensions();
3227
+ const docsWidth = computeDocsWidth(termCols);
3228
+ const grouped = {};
3229
+ for (const issue of issues) (grouped[issue.severity] ??= []).push(issue);
3230
+ return /* @__PURE__ */ jsx(Box, {
3231
+ flexDirection: "column",
3232
+ children: SEVERITY_ORDER.map((sev) => {
3233
+ const list = grouped[sev];
3234
+ if (!list || list.length === 0) return null;
3235
+ return /* @__PURE__ */ jsxs(Box, {
3236
+ flexDirection: "column",
3237
+ marginTop: 1,
3238
+ children: [/* @__PURE__ */ jsxs(Text, {
3239
+ bold: true,
3240
+ color: SEVERITY_COLOR[sev],
3241
+ children: [
3242
+ SEVERITY_LABEL[sev],
3243
+ " (",
3244
+ list.length,
3245
+ ")"
3246
+ ]
3247
+ }), list.map((issue) => /* @__PURE__ */ jsx(IssueRow, {
3248
+ issue,
3249
+ docsWidth
3250
+ }, issue.id))]
3251
+ }, sev);
3252
+ })
3253
+ });
3254
+ };
3255
+ const IssueRow = ({ issue, docsWidth }) => {
3256
+ const meta = getKindMeta(issue.kind);
3257
+ const sevColor = SEVERITY_COLOR[issue.severity];
3258
+ if (docsWidth === 0) return /* @__PURE__ */ jsxs(Box, {
3259
+ flexDirection: "column",
3260
+ children: [/* @__PURE__ */ jsxs(Box, { children: [/* @__PURE__ */ jsx(Box, {
3261
+ width: ICON_COL,
3262
+ children: /* @__PURE__ */ jsx(Text, {
3263
+ color: sevColor,
3264
+ children: Icons.squareFilled
3265
+ })
3266
+ }), /* @__PURE__ */ jsx(Box, {
3267
+ flexGrow: 1,
3268
+ flexShrink: 1,
3269
+ overflow: "hidden",
3270
+ children: /* @__PURE__ */ jsx(Text, {
3271
+ wrap: "truncate",
3272
+ children: meta.title
3273
+ })
3274
+ })] }), /* @__PURE__ */ jsx(Box, {
3275
+ paddingLeft: ICON_COL,
3276
+ children: /* @__PURE__ */ jsx(Text, {
3277
+ color: Colors.primary,
3278
+ wrap: "truncate",
3279
+ children: meta.docsUrl
3280
+ })
3281
+ })]
3282
+ });
3283
+ return /* @__PURE__ */ jsxs(Box, { children: [
3284
+ /* @__PURE__ */ jsx(Box, {
3285
+ width: ICON_COL,
3286
+ children: /* @__PURE__ */ jsx(Text, {
3287
+ color: sevColor,
3288
+ children: Icons.squareFilled
3289
+ })
3290
+ }),
3291
+ /* @__PURE__ */ jsx(Box, {
3292
+ flexGrow: 1,
3293
+ flexShrink: 1,
3294
+ overflow: "hidden",
3295
+ marginRight: ROW_GAP,
3296
+ children: /* @__PURE__ */ jsx(Text, {
3297
+ wrap: "truncate",
3298
+ children: meta.title
3299
+ })
3300
+ }),
3301
+ /* @__PURE__ */ jsx(Box, {
3302
+ width: docsWidth,
3303
+ flexShrink: 0,
3304
+ children: /* @__PURE__ */ jsx(Text, {
3305
+ color: Colors.primary,
3306
+ wrap: "truncate",
3307
+ children: meta.docsUrl
3308
+ })
3309
+ })
3310
+ ] });
3311
+ };
3312
+ //#endregion
3188
3313
  //#region src/ui/tui/screens/McpScreen.tsx
3189
3314
  /**
3190
3315
  * McpScreen — MCP server install/remove flow.
@@ -3209,6 +3334,7 @@ const McpScreen = ({ store, installer, mode = "install" }) => {
3209
3334
  const [clients, setClients] = useState([]);
3210
3335
  const [selectedClientNames, setSelectedClientNames] = useState([]);
3211
3336
  const [resultClients, setResultClients] = useState([]);
3337
+ const [pluginClients, setPluginClients] = useState([]);
3212
3338
  useEffect(() => {
3213
3339
  (async () => {
3214
3340
  try {
@@ -3241,16 +3367,19 @@ const McpScreen = ({ store, installer, mode = "install" }) => {
3241
3367
  };
3242
3368
  const doInstall = async (names, features) => {
3243
3369
  setPhase("working");
3244
- let result = [];
3370
+ let mcpResult = [];
3371
+ let pluginResult = [];
3245
3372
  try {
3246
- result = await installer.install(names, features, store.session.apiKey);
3247
- setResultClients(result);
3248
- } catch {
3249
- setResultClients([]);
3250
- }
3373
+ mcpResult = await installer.install(names, features, store.session.apiKey);
3374
+ } catch {}
3375
+ try {
3376
+ pluginResult = await installer.installPlugins(names);
3377
+ } catch {}
3378
+ setResultClients(mcpResult);
3379
+ setPluginClients(pluginResult);
3251
3380
  setPhase("done");
3252
- const outcome = result.length > 0 ? "installed" : "failed";
3253
- setTimeout(() => markDone(store, outcome, result), 2e3);
3381
+ const outcome = mcpResult.length > 0 ? "installed" : "failed";
3382
+ setTimeout(() => markDone(store, outcome, mcpResult), 2e3);
3254
3383
  };
3255
3384
  const doRemove = async () => {
3256
3385
  setPhase("working");
@@ -3288,14 +3417,14 @@ const McpScreen = ({ store, installer, mode = "install" }) => {
3288
3417
  " MCP clients detected. Skipping..."
3289
3418
  ]
3290
3419
  }),
3291
- phase === "ask" && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs(Text, {
3420
+ phase === "ask" && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs(Text, {
3292
3421
  dimColor: true,
3293
3422
  children: ["Detected: ", clients.map((c) => c.name).join(", ")]
3294
3423
  }), /* @__PURE__ */ jsx(Box, {
3295
3424
  marginTop: 1,
3296
3425
  children: /* @__PURE__ */ jsx(ConfirmationInput, {
3297
- message: isRemove ? "Remove the PostHog MCP server from your editor?" : "Install the PostHog MCP server to your editor?",
3298
- confirmLabel: isRemove ? "Remove MCP" : "Install MCP",
3426
+ message: `${isRemove ? "Remove" : "Install"} the PostHog MCP server${clients.some((c) => c.supportsPlugin) ? " and plugin" : ""}?`,
3427
+ confirmLabel: isRemove ? "Remove" : "Install",
3299
3428
  cancelLabel: "No thanks",
3300
3429
  onConfirm: handleConfirm,
3301
3430
  onCancel: handleSkip
@@ -3326,12 +3455,13 @@ const McpScreen = ({ store, installer, mode = "install" }) => {
3326
3455
  }),
3327
3456
  phase === "done" && /* @__PURE__ */ jsx(Box, {
3328
3457
  flexDirection: "column",
3329
- children: resultClients.length > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs(Text, {
3458
+ children: resultClients.length > 0 ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs(Text, {
3330
3459
  color: "green",
3331
3460
  bold: true,
3332
3461
  children: [
3333
3462
  "✔",
3334
3463
  " MCP server",
3464
+ !isRemove && pluginClients.length > 0 ? " and plugin" : "",
3335
3465
  " ",
3336
3466
  isRemove ? "removed from" : "installed for",
3337
3467
  ":"
@@ -3350,7 +3480,316 @@ const McpScreen = ({ store, installer, mode = "install" }) => {
3350
3480
  })]
3351
3481
  });
3352
3482
  };
3483
+ /** ScreenContainer wraps content in paddingX={1} inside a width capped at
3484
+ * MAX_WIDTH, so the actual width available to the viewer is
3485
+ * min(cols, MAX_WIDTH) - 2. */
3486
+ function getViewerWidth(rawCols) {
3487
+ return Math.min(120, rawCols) - 2;
3488
+ }
3489
+ function computeLayout(rawCols, termRows) {
3490
+ const cols = getViewerWidth(rawCols);
3491
+ const padding = 2;
3492
+ const statusWidth = 2;
3493
+ const fixedExceptLabel = padding + statusWidth + 2 + 18 + 2 + 2;
3494
+ const labelWidth = Math.max(28, cols - fixedExceptLabel);
3495
+ const detailIndent = statusWidth + 2 + 18 + 2;
3496
+ const viewerChrome = 9;
3497
+ return {
3498
+ cols,
3499
+ visibleHeight: Math.max(5, termRows - 10 - viewerChrome),
3500
+ viewerChrome,
3501
+ padding,
3502
+ statusWidth,
3503
+ areaWidth: 18,
3504
+ labelWidth,
3505
+ colGap: 2,
3506
+ dividerWidth: Math.max(20, cols - padding),
3507
+ detailIndent,
3508
+ detailWidth: Math.max(20, cols - detailIndent - padding)
3509
+ };
3510
+ }
3511
+ function truncate(text, max) {
3512
+ if (max <= 0) return "";
3513
+ if (text.length <= max) return text;
3514
+ return text.slice(0, Math.max(1, max - 1)) + "…";
3515
+ }
3516
+ //#endregion
3517
+ //#region src/ui/tui/screens/audit/AuditChecksViewer/CheckRow.tsx
3518
+ const CheckRow = ({ item, layout }) => {
3519
+ const style = AUDIT_SEVERITY_STYLE[item.status];
3520
+ return /* @__PURE__ */ jsxs(Box, {
3521
+ flexShrink: 0,
3522
+ children: [
3523
+ /* @__PURE__ */ jsx(Box, {
3524
+ width: layout.statusWidth + layout.colGap,
3525
+ children: /* @__PURE__ */ jsx(Text, {
3526
+ color: style.color,
3527
+ children: style.glyph
3528
+ })
3529
+ }),
3530
+ /* @__PURE__ */ jsx(Box, {
3531
+ width: layout.areaWidth + layout.colGap,
3532
+ children: /* @__PURE__ */ jsx(Text, {
3533
+ dimColor: true,
3534
+ children: truncate(item.area, layout.areaWidth)
3535
+ })
3536
+ }),
3537
+ /* @__PURE__ */ jsx(Box, {
3538
+ width: layout.labelWidth + layout.colGap,
3539
+ children: /* @__PURE__ */ jsx(Text, {
3540
+ bold: item.status !== "pending",
3541
+ dimColor: item.status === "pending",
3542
+ children: truncate(item.label, layout.labelWidth)
3543
+ })
3544
+ })
3545
+ ]
3546
+ });
3547
+ };
3548
+ //#endregion
3549
+ //#region src/ui/tui/screens/audit/AuditChecksViewer/DetailRow.tsx
3550
+ /** Indented under the CHECK column; wrap continuation aligns with the prefix. */
3551
+ const DetailRow = ({ item, layout }) => /* @__PURE__ */ jsxs(Box, {
3552
+ flexShrink: 0,
3553
+ children: [/* @__PURE__ */ jsx(Box, { width: layout.detailIndent }), /* @__PURE__ */ jsxs(Box, {
3554
+ flexDirection: "column",
3555
+ width: layout.detailWidth,
3556
+ children: [item.file && /* @__PURE__ */ jsx(Text, {
3557
+ dimColor: true,
3558
+ wrap: "wrap",
3559
+ children: `↳ File: ${item.file}`
3560
+ }), item.details && /* @__PURE__ */ jsx(Text, {
3561
+ dimColor: true,
3562
+ italic: true,
3563
+ wrap: "wrap",
3564
+ children: `${item.file ? " " : "↳ "}Details: ${item.details}`
3565
+ })]
3566
+ })]
3567
+ });
3568
+ //#endregion
3569
+ //#region src/ui/tui/screens/audit/AuditChecksViewer/Legend.tsx
3570
+ const Legend = () => /* @__PURE__ */ jsxs(Text, { children: [
3571
+ /* @__PURE__ */ jsx(Text, {
3572
+ color: "green",
3573
+ children: "✔ pass"
3574
+ }),
3575
+ /* @__PURE__ */ jsx(Text, {
3576
+ dimColor: true,
3577
+ children: " · "
3578
+ }),
3579
+ /* @__PURE__ */ jsx(Text, {
3580
+ color: "red",
3581
+ children: "✘ error"
3582
+ }),
3583
+ /* @__PURE__ */ jsx(Text, {
3584
+ dimColor: true,
3585
+ children: " · "
3586
+ }),
3587
+ /* @__PURE__ */ jsx(Text, {
3588
+ color: "yellow",
3589
+ children: "⚠ warning"
3590
+ }),
3591
+ /* @__PURE__ */ jsx(Text, {
3592
+ dimColor: true,
3593
+ children: " · "
3594
+ }),
3595
+ /* @__PURE__ */ jsx(Text, {
3596
+ color: "cyan",
3597
+ children: "• suggestion"
3598
+ })
3599
+ ] });
3600
+ //#endregion
3601
+ //#region src/ui/tui/screens/audit/AuditChecksViewer/Header.tsx
3602
+ function statusCounts(checks) {
3603
+ const out = {
3604
+ pending: 0,
3605
+ pass: 0,
3606
+ error: 0,
3607
+ warning: 0,
3608
+ suggestion: 0
3609
+ };
3610
+ for (const c of checks) out[c.status] += 1;
3611
+ return out;
3612
+ }
3613
+ const Header = ({ layout }) => /* @__PURE__ */ jsxs(Box, { children: [
3614
+ /* @__PURE__ */ jsx(Box, {
3615
+ width: layout.statusWidth + layout.colGap,
3616
+ children: /* @__PURE__ */ jsx(Text, {
3617
+ dimColor: true,
3618
+ bold: true,
3619
+ children: " "
3620
+ })
3621
+ }),
3622
+ /* @__PURE__ */ jsx(Box, {
3623
+ width: layout.areaWidth + layout.colGap,
3624
+ children: /* @__PURE__ */ jsx(Text, {
3625
+ dimColor: true,
3626
+ bold: true,
3627
+ children: "AREA"
3628
+ })
3629
+ }),
3630
+ /* @__PURE__ */ jsx(Box, {
3631
+ width: layout.labelWidth + layout.colGap,
3632
+ children: /* @__PURE__ */ jsx(Text, {
3633
+ dimColor: true,
3634
+ bold: true,
3635
+ children: "CHECK"
3636
+ })
3637
+ })
3638
+ ] });
3639
+ const Summary = ({ total, counts }) => /* @__PURE__ */ jsxs(Text, {
3640
+ dimColor: true,
3641
+ children: [
3642
+ total,
3643
+ " total · ",
3644
+ counts.pending,
3645
+ " pending · ",
3646
+ counts.error,
3647
+ " errors ·",
3648
+ " ",
3649
+ counts.warning,
3650
+ " warnings · ",
3651
+ counts.suggestion,
3652
+ " suggestions · ",
3653
+ counts.pass,
3654
+ " ",
3655
+ "passes"
3656
+ ]
3657
+ });
3658
+ //#endregion
3659
+ //#region src/ui/tui/screens/audit/AuditChecksViewer/Footer.tsx
3660
+ const Footer = ({ total, counts }) => /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Legend, {}), /* @__PURE__ */ jsx(Summary, {
3661
+ total,
3662
+ counts
3663
+ })] });
3664
+ //#endregion
3665
+ //#region src/ui/tui/screens/audit/AuditChecksViewer/sort.ts
3666
+ const STATUS_ORDER = {
3667
+ error: 0,
3668
+ warning: 1,
3669
+ suggestion: 2,
3670
+ pass: 3,
3671
+ pending: 4
3672
+ };
3673
+ /** Issues at the top (error → warning → suggestion), then passes, then pending todos. */
3674
+ function sortChecks(checks) {
3675
+ return [...checks].sort((a, b) => {
3676
+ const da = STATUS_ORDER[a.status] - STATUS_ORDER[b.status];
3677
+ if (da !== 0) return da;
3678
+ return a.area.localeCompare(b.area);
3679
+ });
3680
+ }
3681
+ //#endregion
3682
+ //#region src/ui/tui/screens/audit/AuditChecksViewer/AuditChecksViewer.tsx
3683
+ /**
3684
+ * AuditChecksViewer — "Audit plan" tab.
3685
+ *
3686
+ * Renders the full audit ledger as a scrollable table grouped by status:
3687
+ * resolved checks (issues + passes, sorted by severity) on top, pending
3688
+ * checks at the bottom, separated by a blank row.
3689
+ *
3690
+ * Two interactions, both registered via `useKeyBindings`:
3691
+ * - `e` — toggle detail rows (file:line + agent's `details` text)
3692
+ * - `↑` / `↓` — scroll one row at a time, clamped to content bounds
3693
+ *
3694
+ * Auto-expands on first mount when the ledger contains any issue, since
3695
+ * the AuditAreaPane's `[→] View issues` hint sends users here precisely
3696
+ * to read those details.
3697
+ */
3698
+ const AuditChecksViewer = ({ checks }) => {
3699
+ const [rawCols, termRows] = useStdoutDimensions();
3700
+ const layout = computeLayout(rawCols, termRows);
3701
+ const totalHeight = layout.visibleHeight + layout.viewerChrome;
3702
+ const sorted = useMemo(() => sortChecks(checks), [checks]);
3703
+ const resolved = sorted.filter((c) => c.status !== "pending");
3704
+ const pending = sorted.filter((c) => c.status === "pending");
3705
+ const hasExpandable = sorted.some((c) => Boolean(c.details || c.file));
3706
+ const [expanded, setExpanded] = useState(sorted.some((c) => c.status === "error" || c.status === "warning" || c.status === "suggestion") && hasExpandable);
3707
+ const allRows = useMemo(() => {
3708
+ const rows = [];
3709
+ const buildRow = (item) => {
3710
+ rows.push(/* @__PURE__ */ jsx(CheckRow, {
3711
+ item,
3712
+ layout
3713
+ }, item.id));
3714
+ if (expanded && (item.details || item.file)) rows.push(/* @__PURE__ */ jsx(DetailRow, {
3715
+ item,
3716
+ layout
3717
+ }, `${item.id}-detail`));
3718
+ };
3719
+ resolved.forEach(buildRow);
3720
+ if (resolved.length > 0 && pending.length > 0) rows.push(/* @__PURE__ */ jsx(Box, { height: 1 }, "separator"));
3721
+ pending.forEach(buildRow);
3722
+ return rows;
3723
+ }, [
3724
+ resolved,
3725
+ pending,
3726
+ expanded,
3727
+ layout
3728
+ ]);
3729
+ const [offset, setOffset] = useState(0);
3730
+ const maxOffset = Math.max(0, allRows.length - layout.visibleHeight);
3731
+ const clampedOffset = Math.min(offset, maxOffset);
3732
+ const hiddenAbove = clampedOffset;
3733
+ const hiddenBelow = Math.max(0, allRows.length - clampedOffset - layout.visibleHeight);
3734
+ const bindings = [];
3735
+ if (hasExpandable) bindings.push({
3736
+ match: "e",
3737
+ label: "e",
3738
+ action: expanded ? "collapse details" : "expand details",
3739
+ handler: () => setExpanded((prev) => !prev)
3740
+ });
3741
+ bindings.push({
3742
+ match: ["upArrow", "downArrow"],
3743
+ label: "↑↓",
3744
+ action: "scroll",
3745
+ handler: (_input, key) => {
3746
+ if (key.upArrow) setOffset((o) => Math.max(0, o - 1));
3747
+ else if (key.downArrow) setOffset((o) => Math.min(maxOffset, o + 1));
3748
+ }
3749
+ });
3750
+ useKeyBindings("audit-checks-viewer", bindings);
3751
+ const visibleRows = allRows.slice(clampedOffset, clampedOffset + layout.visibleHeight);
3752
+ return /* @__PURE__ */ jsxs(Box, {
3753
+ flexDirection: "column",
3754
+ paddingX: 1,
3755
+ height: totalHeight,
3756
+ children: [
3757
+ /* @__PURE__ */ jsx(Text, {
3758
+ bold: true,
3759
+ children: "Audit plan"
3760
+ }),
3761
+ /* @__PURE__ */ jsx(Text, {
3762
+ dimColor: true,
3763
+ children: "Read-only review of installation, identification, and event capture"
3764
+ }),
3765
+ /* @__PURE__ */ jsx(Box, { height: 1 }),
3766
+ /* @__PURE__ */ jsx(Header, { layout }),
3767
+ /* @__PURE__ */ jsx(Text, {
3768
+ dimColor: true,
3769
+ children: "─".repeat(layout.dividerWidth)
3770
+ }),
3771
+ /* @__PURE__ */ jsx(Text, {
3772
+ dimColor: true,
3773
+ children: hiddenAbove > 0 ? `↑ ${hiddenAbove} more` : " "
3774
+ }),
3775
+ /* @__PURE__ */ jsx(Box, {
3776
+ flexDirection: "column",
3777
+ height: layout.visibleHeight,
3778
+ overflow: "hidden",
3779
+ children: visibleRows.map((node, i) => /* @__PURE__ */ jsx(Fragment, { children: node }, `row-${clampedOffset + i}`))
3780
+ }),
3781
+ /* @__PURE__ */ jsx(Text, {
3782
+ dimColor: true,
3783
+ children: hiddenBelow > 0 ? `↓ ${hiddenBelow} more` : " "
3784
+ }),
3785
+ /* @__PURE__ */ jsx(Footer, {
3786
+ total: checks.length,
3787
+ counts: statusCounts(checks)
3788
+ })
3789
+ ]
3790
+ });
3791
+ };
3353
3792
  //#endregion
3354
- export { SplitView as _, HNViewer as a, Icons as b, EventPlanViewer as c, ConfirmationInput as d, GroupedPickerMenu as f, LoadingBox as g, ProgressList as h, LearnCard as i, LogViewer as l, PickerMenu as m, ServiceHealthList as n, TabContainer as o, useStdoutDimensions as p, TipsCard as r, ScreenContainer as s, McpScreen as t, ModalOverlay as u, CardLayout as v, WizardStore as x, Colors as y };
3793
+ export { Colors as C, CardLayout as S, WizardStore as T, useStdoutDimensions as _, SEVERITY_ORDER as a, LoadingBox 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, Icons as w, SplitView as x, ProgressList as y };
3355
3794
 
3356
- //# sourceMappingURL=McpScreen-LqnNwEfV.js.map
3795
+ //# sourceMappingURL=AuditChecksViewer-DsfXIO9e.js.map