@posthog/wizard 2.59.0 → 2.61.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 +33 -6
- package/dist/{add-mcp-server-to-clients-OsyI-Bkn.js → add-mcp-server-to-clients-KNIHRN_m.js} +190 -60
- package/dist/add-mcp-server-to-clients-KNIHRN_m.js.map +1 -0
- package/dist/{agent-interface-DB8B9fET.js → agent-interface-Bm4ZNGGV.js} +7 -7
- package/dist/{agent-interface-DB8B9fET.js.map → agent-interface-Bm4ZNGGV.js.map} +1 -1
- package/dist/{agent-prompt-loader-tcJQ-23m.js → agent-prompt-loader-CsHNQXsY.js} +38 -11
- package/dist/agent-prompt-loader-CsHNQXsY.js.map +1 -0
- package/dist/{agent-runner-2CRvJ1nS.js → agent-runner-DLAvB67P.js} +119 -19
- package/dist/agent-runner-DLAvB67P.js.map +1 -0
- package/dist/{analytics-D8LSdEq7.js → analytics-CkIyBHfd.js} +2 -2
- package/dist/{analytics-D8LSdEq7.js.map → analytics-CkIyBHfd.js.map} +1 -1
- package/dist/analytics-kxgLEv7U.js +2 -0
- package/dist/{api-XEopttY8.js → api-XHQTOfIi.js} +3 -3
- package/dist/{api-XEopttY8.js.map → api-XHQTOfIi.js.map} +1 -1
- package/dist/bin.js +322 -142
- package/dist/bin.js.map +1 -1
- package/dist/{bounded-fs-xzOAybCw.js → bounded-fs-B-qlKB0h.js} +3 -3
- package/dist/{bounded-fs-xzOAybCw.js.map → bounded-fs-B-qlKB0h.js.map} +1 -1
- package/dist/{ci-install-hArQ6Imb.js → ci-install-C9BAoO2n.js} +4 -4
- package/dist/{ci-install-hArQ6Imb.js.map → ci-install-C9BAoO2n.js.map} +1 -1
- package/dist/{debug-CxHQG5NZ.js → debug-8-IIHr5f.js} +6 -3
- package/dist/debug-8-IIHr5f.js.map +1 -0
- package/dist/{debug-BC-RNoVX.js → debug-npp6DzBK.js} +1 -1
- package/dist/{defaults-BWLIffh5.js → defaults-mrAre0xM.js} +28 -2
- package/dist/defaults-mrAre0xM.js.map +1 -0
- package/dist/{environment-D6GAX3yG.js → environment-BffaZJRI.js} +4 -4
- package/dist/{environment-D6GAX3yG.js.map → environment-BffaZJRI.js.map} +1 -1
- package/dist/{file-watcher-Bw5wz1_R.js → file-watcher-BreVxzh0.js} +2 -2
- package/dist/{file-watcher-Bw5wz1_R.js.map → file-watcher-BreVxzh0.js.map} +1 -1
- package/dist/{headless-ui-BGLCn1Dw.js → headless-ui-Dy_l8hCT.js} +2 -2
- package/dist/{headless-ui-BGLCn1Dw.js.map → headless-ui-Dy_l8hCT.js.map} +1 -1
- package/dist/{interactive-DRxZ-vOw.js → interactive-C9vepji1.js} +2 -2
- package/dist/{interactive-DRxZ-vOw.js.map → interactive-C9vepji1.js.map} +1 -1
- package/dist/{mcp-CRYv_nRt.js → mcp-C5Zheplw.js} +2 -2
- package/dist/{mcp-CRYv_nRt.js.map → mcp-C5Zheplw.js.map} +1 -1
- package/dist/{mcp-prompt-streaming-CO28aq_J.js → mcp-prompt-streaming-DEerU5M3.js} +3 -3
- package/dist/{mcp-prompt-streaming-CO28aq_J.js.map → mcp-prompt-streaming-DEerU5M3.js.map} +1 -1
- package/dist/{non-interactive-xhKZWWgs.js → non-interactive-C9vQaJF2.js} +2 -2
- package/dist/{non-interactive-xhKZWWgs.js.map → non-interactive-C9vQaJF2.js.map} +1 -1
- package/dist/{orchestrator-tools-PXqRljoB.js → orchestrator-tools-Bw97ahf6.js} +3 -3
- package/dist/{orchestrator-tools-PXqRljoB.js.map → orchestrator-tools-Bw97ahf6.js.map} +1 -1
- package/dist/{package-manager-C1HqgtVK.js → package-manager-Cm5vbUDR.js} +2 -2
- package/dist/{package-manager-C1HqgtVK.js.map → package-manager-Cm5vbUDR.js.map} +1 -1
- package/dist/{pi-DNkD3usA.js → pi-BocAqBQZ.js} +11 -11
- package/dist/{pi-DNkD3usA.js.map → pi-BocAqBQZ.js.map} +1 -1
- package/dist/{playground-BChSh0sx.js → playground-DmGHAiON.js} +25 -788
- package/dist/playground-DmGHAiON.js.map +1 -0
- package/dist/{posthog-B6grWFSr.js → posthog-BitL59Wc.js} +2 -2
- package/dist/{posthog-B6grWFSr.js.map → posthog-BitL59Wc.js.map} +1 -1
- package/dist/{posthog-integration-D-4mdP4b.js → posthog-integration-DbZ2oza2.js} +110 -33
- package/dist/posthog-integration-DbZ2oza2.js.map +1 -0
- package/dist/{provisioning-C1bETgMf.js → provisioning-CzRepu4H.js} +3 -3
- package/dist/{provisioning-C1bETgMf.js.map → provisioning-CzRepu4H.js.map} +1 -1
- package/dist/{queue-tools-D2FgGSUY.js → queue-tools-OynU-m2F.js} +37 -7
- package/dist/queue-tools-OynU-m2F.js.map +1 -0
- package/dist/{registry-CkGCJVqq.js → registry-eXzDlt51.js} +5 -5
- package/dist/{registry-CkGCJVqq.js.map → registry-eXzDlt51.js.map} +1 -1
- package/dist/{security-Cb5pp8kB.js → security-DqByFEpl.js} +5 -5
- package/dist/{security-Cb5pp8kB.js.map → security-DqByFEpl.js.map} +1 -1
- package/dist/{setup-utils-CcYGniRV.js → setup-utils-C2rGcUFv.js} +30 -13
- package/dist/setup-utils-C2rGcUFv.js.map +1 -0
- package/dist/{start-tui-BqyCxVie.js → start-tui-BYTQwgvK.js} +137 -42
- package/dist/start-tui-BYTQwgvK.js.map +1 -0
- package/dist/{steps-C0bR2Rxg.js → steps-CMIyEySI.js} +7 -7
- package/dist/{steps-C0bR2Rxg.js.map → steps-CMIyEySI.js.map} +1 -1
- package/dist/{store-suEDuCAn.js → store-pBYMaEuj.js} +25 -5
- package/dist/store-pBYMaEuj.js.map +1 -0
- package/dist/{subagent-Dd4Hu0C5.js → subagent-ZDD6XCmm.js} +2 -2
- package/dist/{subagent-Dd4Hu0C5.js.map → subagent-ZDD6XCmm.js.map} +1 -1
- package/dist/{task-CpU_54NS.js → task-1KHCdViK.js} +36 -23
- package/dist/task-1KHCdViK.js.map +1 -0
- package/dist/{task-stream-C_xfqch0.js → task-stream-DAU6Z6u6.js} +5 -5
- package/dist/{task-stream-C_xfqch0.js.map → task-stream-DAU6Z6u6.js.map} +1 -1
- package/dist/{tasks-Bfw6gqOO.js → tasks-BBo0_AZG.js} +2 -2
- package/dist/{tasks-Bfw6gqOO.js.map → tasks-BBo0_AZG.js.map} +1 -1
- package/dist/{telemetry-B62x5mwZ.js → telemetry-DSzPCPtQ.js} +3 -3
- package/dist/{telemetry-B62x5mwZ.js.map → telemetry-DSzPCPtQ.js.map} +1 -1
- package/dist/{terminal-CQjtfQzy.js → terminal-DW8x0UNT.js} +1031 -72
- package/dist/terminal-DW8x0UNT.js.map +1 -0
- package/dist/{tools-CzKtKaI1.js → tools-DCH7Ji4V.js} +6 -6
- package/dist/{tools-CzKtKaI1.js.map → tools-DCH7Ji4V.js.map} +1 -1
- package/dist/{wizard-abort-DPCzBsvy.js → wizard-abort-B_Sa9K3g.js} +1 -1
- package/dist/{wizard-abort-I6tR10Mx.js → wizard-abort-Cz916Qq5.js} +4 -4
- package/dist/{wizard-abort-I6tR10Mx.js.map → wizard-abort-Cz916Qq5.js.map} +1 -1
- package/dist/{wizard-session-CwgR5y3-.js → wizard-session-BUhlJ1b8.js} +2 -1
- package/dist/wizard-session-BUhlJ1b8.js.map +1 -0
- package/dist/{wizard-session-DsK16SGs.js → wizard-session-DZUDtS5d.js} +1 -1
- package/dist/yara-hooks-BVEBOdMu.js +2 -0
- package/dist/{yara-hooks-CpvNIFdW.js → yara-hooks-DgScuNrT.js} +4 -4
- package/dist/{yara-hooks-CpvNIFdW.js.map → yara-hooks-DgScuNrT.js.map} +1 -1
- package/package.json +2 -1
- package/dist/add-mcp-server-to-clients-OsyI-Bkn.js.map +0 -1
- package/dist/agent-prompt-loader-tcJQ-23m.js.map +0 -1
- package/dist/agent-runner-2CRvJ1nS.js.map +0 -1
- package/dist/analytics-fOKMWN6E.js +0 -2
- package/dist/debug-CxHQG5NZ.js.map +0 -1
- package/dist/defaults-BWLIffh5.js.map +0 -1
- package/dist/playground-BChSh0sx.js.map +0 -1
- package/dist/posthog-integration-D-4mdP4b.js.map +0 -1
- package/dist/queue-tools-D2FgGSUY.js.map +0 -1
- package/dist/setup-utils-CcYGniRV.js.map +0 -1
- package/dist/start-tui-BqyCxVie.js.map +0 -1
- package/dist/store-suEDuCAn.js.map +0 -1
- package/dist/task-CpU_54NS.js.map +0 -1
- package/dist/terminal-CQjtfQzy.js.map +0 -1
- package/dist/wizard-session-CwgR5y3-.js.map +0 -1
- package/dist/yara-hooks-lnituYce.js +0 -2
package/dist/bin.js
CHANGED
|
@@ -1,23 +1,24 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { Ct as regionOption, L as Integration, St as isHeadless, U as POSTHOG_DOCS_URL, a as getLogFilePath, f as getUI, ft as WIZARD_USER_AGENT, ht as VERSION, m as LoggingUI, p as setUI, pt as getSkillsBaseUrl, r as debug, s as logToFile, xt as headlessOption } from "./debug-
|
|
3
|
-
import { n as analytics } from "./analytics-
|
|
4
|
-
import { r as setEntryCommand } from "./telemetry-
|
|
5
|
-
import { a as safeReadFile, o as walkProjectFiles } from "./bounded-fs-
|
|
6
|
-
import { n as isUsingTypeScript } from "./setup-utils-
|
|
7
|
-
import { o as handleApiError } from "./api-
|
|
8
|
-
import "./wizard-session-
|
|
9
|
-
import { r as runCleanups } from "./wizard-abort-
|
|
10
|
-
import { n as isNonInteractiveEnvironment } from "./environment-
|
|
11
|
-
import { n as runAgent,
|
|
12
|
-
import {
|
|
13
|
-
import { S as
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
2
|
+
import { Ct as regionOption, L as Integration, St as isHeadless, U as POSTHOG_DOCS_URL, a as getLogFilePath, f as getUI, ft as WIZARD_USER_AGENT, ht as VERSION, m as LoggingUI, p as setUI, pt as getSkillsBaseUrl, r as debug, s as logToFile, xt as headlessOption } from "./debug-8-IIHr5f.js";
|
|
3
|
+
import { n as analytics } from "./analytics-CkIyBHfd.js";
|
|
4
|
+
import { r as setEntryCommand } from "./telemetry-DSzPCPtQ.js";
|
|
5
|
+
import { a as safeReadFile, o as walkProjectFiles } from "./bounded-fs-B-qlKB0h.js";
|
|
6
|
+
import { n as isUsingTypeScript } from "./setup-utils-C2rGcUFv.js";
|
|
7
|
+
import { o as handleApiError } from "./api-XHQTOfIi.js";
|
|
8
|
+
import "./wizard-session-BUhlJ1b8.js";
|
|
9
|
+
import { r as runCleanups } from "./wizard-abort-Cz916Qq5.js";
|
|
10
|
+
import { n as isNonInteractiveEnvironment } from "./environment-BffaZJRI.js";
|
|
11
|
+
import { n as runAgent, s as authenticate } from "./agent-runner-DLAvB67P.js";
|
|
12
|
+
import { d as writeJsonAtomic } from "./queue-tools-OynU-m2F.js";
|
|
13
|
+
import { S as WIZARD_TOOL_NAMES, T as fetchSkillMenu, l as recoverOrphanedSettingsBackups, p as AgentSignals } from "./agent-interface-Bm4ZNGGV.js";
|
|
14
|
+
import { S as SETUP_REPORT_FILE, _ as AUDIT_CHECKS_KEY, g as AUDIT_CHECKS_FILE, v as AUDIT_REPORT_FILE } from "./yara-hooks-DgScuNrT.js";
|
|
15
|
+
import { i as SPINNER_MESSAGE } from "./registry-eXzDlt51.js";
|
|
16
|
+
import { C as resolveProjectDir, _ as WAREHOUSE_ABORT_CASES, a as LINE_CHART_BLOCK, b as detectWarehouseSources, d as isClearBlock, g as HEALTH_CHECK_STEP, h as Icons, i as FUNNEL_BLOCK, m as Colors, n as integrationRunStep, o as PRODUCT_SUITE_BLOCK, r as posthogIntegrationConfig, s as StatusPeekTrigger, u as wordWrap, v as detectWarehousePrerequisites, w as gatherFrameworkContext, x as detectIntegrationProjects, y as getDetectedWarehouseSources } from "./posthog-integration-DbZ2oza2.js";
|
|
16
17
|
import { n as readApiKeyFromEnv } from "./env-api-key-cjD4yfGT.js";
|
|
17
18
|
import { satisfies } from "semver";
|
|
18
19
|
import yargs from "yargs";
|
|
19
20
|
import { hideBin } from "yargs/helpers";
|
|
20
|
-
import
|
|
21
|
+
import { existsSync, readFileSync, readdirSync, statSync } from "fs";
|
|
21
22
|
import path, { join, relative } from "path";
|
|
22
23
|
import * as os from "node:os";
|
|
23
24
|
import * as path$1 from "node:path";
|
|
@@ -27,9 +28,10 @@ import * as fs$1 from "node:fs";
|
|
|
27
28
|
import axios from "axios";
|
|
28
29
|
import { z } from "zod";
|
|
29
30
|
import { Box, Text, render, useInput, useStdout } from "ink";
|
|
30
|
-
import { createContext, createElement, useCallback, useContext, useEffect, useRef, useState } from "react";
|
|
31
|
+
import { createContext, createElement, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
|
|
31
32
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
32
33
|
import { access, rm } from "node:fs/promises";
|
|
34
|
+
import Fuse from "fuse.js";
|
|
33
35
|
import * as readline from "node:readline/promises";
|
|
34
36
|
//#region src/commands/command.ts
|
|
35
37
|
/** Extract the bare command word(s) from a yargs name spec, dropping positionals and aliases' arg syntax. */
|
|
@@ -200,7 +202,7 @@ function runProvision(argv) {
|
|
|
200
202
|
}
|
|
201
203
|
async function provision({ email, region, name, baseUrl, jsonMode }) {
|
|
202
204
|
try {
|
|
203
|
-
const { provisionNewAccount } = await import("./provisioning-
|
|
205
|
+
const { provisionNewAccount } = await import("./provisioning-CzRepu4H.js").then((n) => n.r);
|
|
204
206
|
if (!jsonMode) getUI().log.info(`Provisioning account for ${email} in ${region}...`);
|
|
205
207
|
emitResult(await provisionNewAccount(email, name, region, { baseUrl }), jsonMode);
|
|
206
208
|
process.exit(0);
|
|
@@ -267,22 +269,22 @@ const basicIntegrationCommand = {
|
|
|
267
269
|
setEntryCommand("integrate");
|
|
268
270
|
(async () => {
|
|
269
271
|
if (isHeadless(argv)) {
|
|
270
|
-
const { runHeadlessInstall } = await import("./ci-install-
|
|
272
|
+
const { runHeadlessInstall } = await import("./ci-install-C9BAoO2n.js");
|
|
271
273
|
return runHeadlessInstall(argv);
|
|
272
274
|
}
|
|
273
275
|
if (argv.ci) {
|
|
274
|
-
const { runCIInstall } = await import("./ci-install-
|
|
276
|
+
const { runCIInstall } = await import("./ci-install-C9BAoO2n.js");
|
|
275
277
|
return runCIInstall(argv);
|
|
276
278
|
}
|
|
277
279
|
if (isNonInteractiveEnvironment()) {
|
|
278
|
-
const { failNonInteractive } = await import("./non-interactive-
|
|
280
|
+
const { failNonInteractive } = await import("./non-interactive-C9vQaJF2.js");
|
|
279
281
|
return failNonInteractive();
|
|
280
282
|
}
|
|
281
283
|
if (argv.playground) {
|
|
282
|
-
const { runPlayground } = await import("./playground-
|
|
284
|
+
const { runPlayground } = await import("./playground-DmGHAiON.js");
|
|
283
285
|
return runPlayground();
|
|
284
286
|
}
|
|
285
|
-
const { runInteractive } = await import("./interactive-
|
|
287
|
+
const { runInteractive } = await import("./interactive-C9vepji1.js");
|
|
286
288
|
runInteractive(argv);
|
|
287
289
|
})();
|
|
288
290
|
}
|
|
@@ -665,10 +667,18 @@ const AUDIT_ABORT_CASES = [{
|
|
|
665
667
|
//#endregion
|
|
666
668
|
//#region src/lib/programs/audit/seed.ts
|
|
667
669
|
/**
|
|
668
|
-
* The 10
|
|
669
|
-
*
|
|
670
|
-
* `
|
|
671
|
-
*
|
|
670
|
+
* The 10 source-tree checks the audit runs, plus one row for the PostHog-side
|
|
671
|
+
* sweep and two workflow rows at the end (so the skill's
|
|
672
|
+
* `audit_resolve_checks` calls for `write-report` and `upload-notebook`
|
|
673
|
+
* succeed — the skill writes the report to disk, then mirrors it into a
|
|
674
|
+
* PostHog notebook as its final step).
|
|
675
|
+
*
|
|
676
|
+
* `posthog-side-findings` is a sweep row, not a rule: the skill reads what
|
|
677
|
+
* PostHog itself already computed for this project (error-tracking
|
|
678
|
+
* recommendations, health issues) and appends one row per open finding via
|
|
679
|
+
* `audit_add_checks`. That's why the seed can't enumerate them — the list is
|
|
680
|
+
* whatever the project's data says today, and it grows as PostHog ships new
|
|
681
|
+
* checks, with no wizard release needed.
|
|
672
682
|
*/
|
|
673
683
|
const AUDIT_SEED_CHECKS = [
|
|
674
684
|
{
|
|
@@ -731,6 +741,12 @@ const AUDIT_SEED_CHECKS = [
|
|
|
731
741
|
label: "Key activation events captured",
|
|
732
742
|
status: "pending"
|
|
733
743
|
},
|
|
744
|
+
{
|
|
745
|
+
id: "live-data-findings",
|
|
746
|
+
area: "Live Data",
|
|
747
|
+
label: "Open findings in PostHog",
|
|
748
|
+
status: "pending"
|
|
749
|
+
},
|
|
734
750
|
{
|
|
735
751
|
id: "write-report",
|
|
736
752
|
area: "Write report",
|
|
@@ -752,9 +768,7 @@ const AUDIT_SEED_CHECKS = [
|
|
|
752
768
|
*/
|
|
753
769
|
function seedAuditLedger(installDir, checks = AUDIT_SEED_CHECKS) {
|
|
754
770
|
const target = path.join(installDir, AUDIT_CHECKS_FILE);
|
|
755
|
-
|
|
756
|
-
fs.writeFileSync(tmp, JSON.stringify(checks, null, 2), "utf8");
|
|
757
|
-
fs.renameSync(tmp, target);
|
|
771
|
+
writeJsonAtomic(target, checks);
|
|
758
772
|
logToFile(`seedAuditLedger: wrote ${checks.length} entries to ${target}`);
|
|
759
773
|
}
|
|
760
774
|
//#endregion
|
|
@@ -3058,7 +3072,7 @@ function buildSelfDrivingPrompt(ctx, detectedSources = []) {
|
|
|
3058
3072
|
const inboxUrl = `${projectBase}/inbox`;
|
|
3059
3073
|
const optIn = (value) => value === true ? "ON" : value === false ? "OFF" : "unknown";
|
|
3060
3074
|
const optIns = ctx.teamProductOptIns;
|
|
3061
|
-
return `You are setting up PostHog Self-driving for this project: you will enable the right signal sources, make sure GitHub is connected, tune the scout troop, design custom scouts for what this product uniquely needs, and hand the user a configured inbox.
|
|
3075
|
+
return `You are setting up PostHog Self-driving for this project: you will enable the right signal sources, make sure GitHub is connected, tune the scout troop, design custom scouts for what this product uniquely needs, put Replay Vision scanners on its key flows, and hand the user a configured inbox.
|
|
3062
3076
|
|
|
3063
3077
|
Project URLs:
|
|
3064
3078
|
- Integrations settings: ${integrationsSettingsUrl}
|
|
@@ -3093,6 +3107,7 @@ tasks, in this order:
|
|
|
3093
3107
|
5. Offer issue-tracker integrations
|
|
3094
3108
|
6. Configure the scout troop
|
|
3095
3109
|
6b. Design custom scouts
|
|
3110
|
+
6c. Set up Replay Vision scanners
|
|
3096
3111
|
7. Write report and hand off
|
|
3097
3112
|
Drive the list with TaskUpdate — mark a task in_progress when you start
|
|
3098
3113
|
it and completed when done. If a step turns out to be a no-op (e.g.
|
|
@@ -3183,6 +3198,16 @@ STEP 6 — Configure the scout troop. (skill: "Scouts")
|
|
|
3183
3198
|
whole troop, including step 6b's custom scouts, stays at or under
|
|
3184
3199
|
ten enabled scouts.
|
|
3185
3200
|
|
|
3201
|
+
Then tell the user what the troop is, before STEP 6b asks them to add
|
|
3202
|
+
to it. Scouts are PostHog's built-in ones, and the user has not seen
|
|
3203
|
+
the list: without it, STEP 6b asks them to approve additions to a
|
|
3204
|
+
baseline they cannot picture. Send one short message naming each
|
|
3205
|
+
scout you enabled with a plain one-line description of what it
|
|
3206
|
+
watches, and say how many you left disabled and that they can turn
|
|
3207
|
+
those on later from the inbox. No wizard_ask here, it is not a
|
|
3208
|
+
question. Keep each line to one sentence and do not restate the
|
|
3209
|
+
skill's internals.
|
|
3210
|
+
|
|
3186
3211
|
STEP 6b — Design custom scouts for this product. (skill: "Custom scouts")
|
|
3187
3212
|
You are the only actor that has read this repo — turn that into
|
|
3188
3213
|
coverage per the skill: a real gap analysis of the project's
|
|
@@ -3201,11 +3226,29 @@ STEP 6b — Design custom scouts for this product. (skill: "Custom scouts")
|
|
|
3201
3226
|
no gap at all) is a valid outcome, not an abort. Mark the task
|
|
3202
3227
|
completed either way.
|
|
3203
3228
|
|
|
3229
|
+
STEP 6c — Set up Replay Vision scanners. (skill: "Replay Vision scanners")
|
|
3230
|
+
Create the scanner skeletons the skill defines, filling the per-product
|
|
3231
|
+
blanks it leaves you from this repo's code. Scanners need Session Replay
|
|
3232
|
+
on (STEP 3b). Every failure here — no recordings yet, a backend-only
|
|
3233
|
+
project, the scanner API missing — is a follow-up, never an abort; mark
|
|
3234
|
+
the task completed regardless.
|
|
3235
|
+
|
|
3204
3236
|
STEP 7 — Write the report and hand off. (skill: "Report")
|
|
3205
3237
|
Write the report per the skill, including follow-ups for anything
|
|
3206
3238
|
deferred. Tell the user findings will start appearing in their inbox
|
|
3207
3239
|
at ${inboxUrl} within about 30 minutes.`;
|
|
3208
3240
|
}
|
|
3241
|
+
/** One line, for a screen that only has room to say what it costs. */
|
|
3242
|
+
const PRICING_SHORT = `Agents charge a flat $15 per pull request they ship.`;
|
|
3243
|
+
/** The same fact at length, plus the bit people are surprised by later. */
|
|
3244
|
+
const PRICING_LONG = `A report that ships a pull request costs a flat $15. Everything else follows your usual PostHog usage-based pricing.`;
|
|
3245
|
+
/**
|
|
3246
|
+
* Nothing caps the spend unless you set it, which is worth saying out loud. Checked against
|
|
3247
|
+
* billing: `custom_limits_map` starts empty and a product with no custom limit resolves to
|
|
3248
|
+
* `usage_limit: None`, i.e. uncapped. A free plan is capped by its own allocation instead,
|
|
3249
|
+
* hence the qualifier.
|
|
3250
|
+
*/
|
|
3251
|
+
const NO_DEFAULT_LIMIT = "A paid plan has no monthly cap until you set one. Add a PR limit in your inbox sidebar, and agents pause when they hit it.";
|
|
3209
3252
|
//#endregion
|
|
3210
3253
|
//#region src/lib/programs/self-driving/content/tips.ts
|
|
3211
3254
|
const SELF_DRIVING_TIPS = [
|
|
@@ -3219,6 +3262,11 @@ const SELF_DRIVING_TIPS = [
|
|
|
3219
3262
|
title: "Scout",
|
|
3220
3263
|
description: "An agent on a schedule, watching your sources for anomalies and patterns. Your project gets up to 100 scout runs a day by default."
|
|
3221
3264
|
},
|
|
3265
|
+
{
|
|
3266
|
+
id: "scanner",
|
|
3267
|
+
title: "Scanner",
|
|
3268
|
+
description: "Where a scout reads your data, a scanner watches session recordings — an LLM spotting what broke on screen. It spends Replay Vision quota, so it stays scoped to your key flows."
|
|
3269
|
+
},
|
|
3222
3270
|
{
|
|
3223
3271
|
id: "signal-report",
|
|
3224
3272
|
title: "Signal → report",
|
|
@@ -3232,7 +3280,7 @@ const SELF_DRIVING_TIPS = [
|
|
|
3232
3280
|
{
|
|
3233
3281
|
id: "pricing",
|
|
3234
3282
|
title: "What it costs",
|
|
3235
|
-
description:
|
|
3283
|
+
description: `${PRICING_LONG} ${NO_DEFAULT_LIMIT}`
|
|
3236
3284
|
},
|
|
3237
3285
|
{
|
|
3238
3286
|
id: "work-anywhere",
|
|
@@ -3471,8 +3519,12 @@ const getContentBlocks = (store) => {
|
|
|
3471
3519
|
pause: 6e3
|
|
3472
3520
|
},
|
|
3473
3521
|
{
|
|
3474
|
-
content:
|
|
3475
|
-
pause:
|
|
3522
|
+
content: PRICING_LONG,
|
|
3523
|
+
pause: 5e3
|
|
3524
|
+
},
|
|
3525
|
+
{
|
|
3526
|
+
content: NO_DEFAULT_LIMIT,
|
|
3527
|
+
pause: 5e3
|
|
3476
3528
|
},
|
|
3477
3529
|
CLEAR,
|
|
3478
3530
|
{
|
|
@@ -3607,11 +3659,12 @@ const buildRun = (session) => Promise.resolve({
|
|
|
3607
3659
|
items: [
|
|
3608
3660
|
"Investigate reports with the agent",
|
|
3609
3661
|
"Tag teammates to loop them in",
|
|
3610
|
-
|
|
3662
|
+
`Kick off a PR when you like the proposed fix ($15 flat)`,
|
|
3663
|
+
"Cap the spend with a monthly PR limit in the sidebar",
|
|
3611
3664
|
"Or work from Slack (tag @PostHog) and MCP"
|
|
3612
3665
|
]
|
|
3613
3666
|
},
|
|
3614
|
-
body:
|
|
3667
|
+
body: `${PRICING_LONG} ${NO_DEFAULT_LIMIT}`,
|
|
3615
3668
|
reportFile: REPORT_FILE
|
|
3616
3669
|
};
|
|
3617
3670
|
}
|
|
@@ -3903,6 +3956,17 @@ function getProgramConfig(id) {
|
|
|
3903
3956
|
return PROGRAM_REGISTRY.find((c) => c.id === id);
|
|
3904
3957
|
}
|
|
3905
3958
|
//#endregion
|
|
3959
|
+
//#region src/commands/mcp/tui-availability.ts
|
|
3960
|
+
/**
|
|
3961
|
+
* Ink throws "Raw mode is not supported" when stdin has no TTY (piped input,
|
|
3962
|
+
* CI, some IDE terminals). That is the only TUI failure the mcp commands
|
|
3963
|
+
* degrade to LoggingUI for — any other error from the TUI path is a real bug
|
|
3964
|
+
* and must surface rather than be silently swallowed.
|
|
3965
|
+
*/
|
|
3966
|
+
function isTUIUnavailable(error) {
|
|
3967
|
+
return error instanceof Error && /raw mode is not supported/i.test(error.message);
|
|
3968
|
+
}
|
|
3969
|
+
//#endregion
|
|
3906
3970
|
//#region src/commands/mcp/add.ts
|
|
3907
3971
|
const mcpAddCommand = {
|
|
3908
3972
|
name: "add",
|
|
@@ -3932,8 +3996,8 @@ function runMcpAdd(argv) {
|
|
|
3932
3996
|
const debug = argv.debug;
|
|
3933
3997
|
const localMcp = argv.local;
|
|
3934
3998
|
try {
|
|
3935
|
-
const { startTUI } = await import("./start-tui-
|
|
3936
|
-
const { buildSession } = await import("./wizard-session-
|
|
3999
|
+
const { startTUI } = await import("./start-tui-BYTQwgvK.js");
|
|
4000
|
+
const { buildSession } = await import("./wizard-session-DZUDtS5d.js");
|
|
3937
4001
|
const tui = startTUI(VERSION, Program.McpAdd);
|
|
3938
4002
|
tui.store.session = buildSession({
|
|
3939
4003
|
debug,
|
|
@@ -3945,7 +4009,7 @@ function runMcpAdd(argv) {
|
|
|
3945
4009
|
} catch (error) {
|
|
3946
4010
|
if (!isTUIUnavailable(error)) throw error;
|
|
3947
4011
|
setUI(new LoggingUI());
|
|
3948
|
-
const { addMCPServerToClientsStep } = await import("./add-mcp-server-to-clients-
|
|
4012
|
+
const { addMCPServerToClientsStep } = await import("./add-mcp-server-to-clients-KNIHRN_m.js").then((n) => n.r);
|
|
3949
4013
|
await addMCPServerToClientsStep({
|
|
3950
4014
|
local: localMcp,
|
|
3951
4015
|
features,
|
|
@@ -3954,15 +4018,6 @@ function runMcpAdd(argv) {
|
|
|
3954
4018
|
}
|
|
3955
4019
|
})();
|
|
3956
4020
|
}
|
|
3957
|
-
/**
|
|
3958
|
-
* Ink throws "Raw mode is not supported" when stdin has no TTY (piped input,
|
|
3959
|
-
* CI, some IDE terminals). That is the only TUI failure we degrade to
|
|
3960
|
-
* LoggingUI for — any other error from the TUI path is a real bug and must
|
|
3961
|
-
* surface rather than be silently swallowed.
|
|
3962
|
-
*/
|
|
3963
|
-
function isTUIUnavailable(error) {
|
|
3964
|
-
return error instanceof Error && /raw mode is not supported/i.test(error.message);
|
|
3965
|
-
}
|
|
3966
4021
|
function parseFeatures(raw) {
|
|
3967
4022
|
if (typeof raw !== "string") return void 0;
|
|
3968
4023
|
return raw.split(",").map((s) => s.trim()).filter(Boolean);
|
|
@@ -3984,17 +4039,18 @@ function runMcpRemove(argv) {
|
|
|
3984
4039
|
const debug = argv.debug;
|
|
3985
4040
|
const localMcp = argv.local;
|
|
3986
4041
|
try {
|
|
3987
|
-
const { startTUI } = await import("./start-tui-
|
|
3988
|
-
const { buildSession } = await import("./wizard-session-
|
|
4042
|
+
const { startTUI } = await import("./start-tui-BYTQwgvK.js");
|
|
4043
|
+
const { buildSession } = await import("./wizard-session-DZUDtS5d.js");
|
|
3989
4044
|
const tui = startTUI(VERSION, Program.McpRemove);
|
|
3990
4045
|
tui.store.session = buildSession({
|
|
3991
4046
|
debug,
|
|
3992
4047
|
localMcp,
|
|
3993
4048
|
baseUrl: argv.baseUrl
|
|
3994
4049
|
});
|
|
3995
|
-
} catch {
|
|
4050
|
+
} catch (error) {
|
|
4051
|
+
if (!isTUIUnavailable(error)) throw error;
|
|
3996
4052
|
setUI(new LoggingUI());
|
|
3997
|
-
const { removeMCPServerFromClientsStep } = await import("./add-mcp-server-to-clients-
|
|
4053
|
+
const { removeMCPServerFromClientsStep } = await import("./add-mcp-server-to-clients-KNIHRN_m.js").then((n) => n.r);
|
|
3998
4054
|
await removeMCPServerFromClientsStep({ local: localMcp });
|
|
3999
4055
|
}
|
|
4000
4056
|
})();
|
|
@@ -4016,8 +4072,8 @@ function runMcpTutorial(argv) {
|
|
|
4016
4072
|
const debug = argv.debug;
|
|
4017
4073
|
const localMcp = argv.local;
|
|
4018
4074
|
try {
|
|
4019
|
-
const { startTUI } = await import("./start-tui-
|
|
4020
|
-
const { buildSession } = await import("./wizard-session-
|
|
4075
|
+
const { startTUI } = await import("./start-tui-BYTQwgvK.js");
|
|
4076
|
+
const { buildSession } = await import("./wizard-session-DZUDtS5d.js");
|
|
4021
4077
|
const tui = startTUI(VERSION, Program.McpTutorial);
|
|
4022
4078
|
tui.store.session = buildSession({
|
|
4023
4079
|
debug,
|
|
@@ -4098,10 +4154,10 @@ function runWizard(config, options) {
|
|
|
4098
4154
|
(async () => {
|
|
4099
4155
|
try {
|
|
4100
4156
|
const installDir = options.installDir || process.cwd();
|
|
4101
|
-
const { startTUI } = await import("./start-tui-
|
|
4102
|
-
const { buildSession, RunPhase } = await import("./wizard-session-
|
|
4103
|
-
const { TaskStreamPush } = await import("./task-stream-
|
|
4104
|
-
const { PostHogDestination } = await import("./posthog-
|
|
4157
|
+
const { startTUI } = await import("./start-tui-BYTQwgvK.js");
|
|
4158
|
+
const { buildSession, RunPhase } = await import("./wizard-session-DZUDtS5d.js");
|
|
4159
|
+
const { TaskStreamPush } = await import("./task-stream-DAU6Z6u6.js");
|
|
4160
|
+
const { PostHogDestination } = await import("./posthog-BitL59Wc.js");
|
|
4105
4161
|
tui = startTUI(WIZARD_VERSION, config.id);
|
|
4106
4162
|
const activeTui = tui;
|
|
4107
4163
|
const session = buildSession({
|
|
@@ -4167,7 +4223,7 @@ function runWizard(config, options) {
|
|
|
4167
4223
|
if (shown(step)) await advanceStep(step, activeTui.store, config);
|
|
4168
4224
|
}
|
|
4169
4225
|
else if (skipAgent) {
|
|
4170
|
-
const { getOrAskForProjectData } = await import("./setup-utils-
|
|
4226
|
+
const { getOrAskForProjectData } = await import("./setup-utils-C2rGcUFv.js").then((n) => n.r);
|
|
4171
4227
|
const { projectApiKey, host, accessToken, projectId } = await getOrAskForProjectData({
|
|
4172
4228
|
signup: session.signup,
|
|
4173
4229
|
ci: session.ci,
|
|
@@ -4268,11 +4324,11 @@ function runNonInteractive(config, options, mode) {
|
|
|
4268
4324
|
analytics.setTag("build", mode);
|
|
4269
4325
|
(async () => {
|
|
4270
4326
|
const path = await import("path");
|
|
4271
|
-
const { buildSession, RunPhase, OutroKind } = await import("./wizard-session-
|
|
4272
|
-
const { readEnvironment } = await import("./environment-
|
|
4327
|
+
const { buildSession, RunPhase, OutroKind } = await import("./wizard-session-DZUDtS5d.js");
|
|
4328
|
+
const { readEnvironment } = await import("./environment-BffaZJRI.js").then((n) => n.t);
|
|
4273
4329
|
const { readApiKeyFromEnv } = await import("./env-api-key-cjD4yfGT.js").then((n) => n.t);
|
|
4274
|
-
const { configureLogFileFromEnvironment, logToFile } = await import("./debug-
|
|
4275
|
-
const { wizardAbort, WizardError } = await import("./wizard-abort-
|
|
4330
|
+
const { configureLogFileFromEnvironment, logToFile } = await import("./debug-npp6DzBK.js");
|
|
4331
|
+
const { wizardAbort, WizardError } = await import("./wizard-abort-B_Sa9K3g.js");
|
|
4276
4332
|
configureLogFileFromEnvironment();
|
|
4277
4333
|
const env = readEnvironment();
|
|
4278
4334
|
const apiKey = options.apiKey ?? readApiKeyFromEnv() ?? void 0;
|
|
@@ -4305,9 +4361,9 @@ function runNonInteractive(config, options, mode) {
|
|
|
4305
4361
|
let store = null;
|
|
4306
4362
|
let taskStream = null;
|
|
4307
4363
|
if (mode === "headless") {
|
|
4308
|
-
const { WizardStore } = await import("./store-
|
|
4309
|
-
const { HeadlessUI } = await import("./headless-ui-
|
|
4310
|
-
const { TaskStreamPush, PostHogDestination } = await import("./task-stream-
|
|
4364
|
+
const { WizardStore } = await import("./store-pBYMaEuj.js").then((n) => n.n);
|
|
4365
|
+
const { HeadlessUI } = await import("./headless-ui-Dy_l8hCT.js");
|
|
4366
|
+
const { TaskStreamPush, PostHogDestination } = await import("./task-stream-DAU6Z6u6.js");
|
|
4311
4367
|
store = new WizardStore(config.id);
|
|
4312
4368
|
store.session = session;
|
|
4313
4369
|
setUI(new HeadlessUI(store));
|
|
@@ -4363,7 +4419,7 @@ function runNonInteractive(config, options, mode) {
|
|
|
4363
4419
|
});
|
|
4364
4420
|
}
|
|
4365
4421
|
}
|
|
4366
|
-
const { runAgent } = await import("./agent-runner-
|
|
4422
|
+
const { runAgent } = await import("./agent-runner-DLAvB67P.js").then((n) => n.t);
|
|
4367
4423
|
await runAgent(config, session);
|
|
4368
4424
|
await settleStream(RunPhase.Completed);
|
|
4369
4425
|
} catch (error) {
|
|
@@ -4641,6 +4697,81 @@ function pickerChildrenToShow(children) {
|
|
|
4641
4697
|
return defaults.length > 0 ? [...defaults] : [...children];
|
|
4642
4698
|
}
|
|
4643
4699
|
//#endregion
|
|
4700
|
+
//#region src/ui/tui/primitives/picker-filter.ts
|
|
4701
|
+
/**
|
|
4702
|
+
* Filter-as-you-type matching for PickerMenu. Split out from the component so the
|
|
4703
|
+
* ranking is testable on its own — the component only decides when to call it.
|
|
4704
|
+
*/
|
|
4705
|
+
/**
|
|
4706
|
+
* Fuzzy fallback config. `ignoreLocation` because a term matching at the end of a
|
|
4707
|
+
* description is as good as one at the start, and Fuse's default distance window
|
|
4708
|
+
* would score the late match away. 0.5 is the loosest threshold that still bottoms
|
|
4709
|
+
* out: below it `gthb` misses `GitHub` entirely, which is the whole point of having
|
|
4710
|
+
* a fuzzy pass; above it the tail grows without surfacing anything new at the top.
|
|
4711
|
+
*/
|
|
4712
|
+
const FUSE_OPTIONS = {
|
|
4713
|
+
keys: [
|
|
4714
|
+
{
|
|
4715
|
+
name: "label",
|
|
4716
|
+
weight: 3
|
|
4717
|
+
},
|
|
4718
|
+
{
|
|
4719
|
+
name: "hint",
|
|
4720
|
+
weight: 1
|
|
4721
|
+
},
|
|
4722
|
+
{
|
|
4723
|
+
name: "description",
|
|
4724
|
+
weight: 1
|
|
4725
|
+
}
|
|
4726
|
+
],
|
|
4727
|
+
ignoreLocation: true,
|
|
4728
|
+
threshold: .5,
|
|
4729
|
+
includeScore: true
|
|
4730
|
+
};
|
|
4731
|
+
function buildPickerIndex(options) {
|
|
4732
|
+
return new Fuse(options, FUSE_OPTIONS);
|
|
4733
|
+
}
|
|
4734
|
+
function haystack(option) {
|
|
4735
|
+
return `${option.label} ${option.hint ?? ""} ${option.description ?? ""}`.toLowerCase();
|
|
4736
|
+
}
|
|
4737
|
+
/**
|
|
4738
|
+
* Rank options against a query, best first, or `null` for an empty query.
|
|
4739
|
+
*
|
|
4740
|
+
* Two passes, literal before fuzzy. Anything that literally contains every
|
|
4741
|
+
* whitespace-separated term wins outright, in the list's own order — that covers how
|
|
4742
|
+
* people actually type (`git iss` → `GitHub issues`) and keeps the common case as
|
|
4743
|
+
* tight as a plain substring filter, which fuzzy matching on its own is not: Fuse at
|
|
4744
|
+
* a threshold loose enough to forgive `gthb` also lets a third of the list through
|
|
4745
|
+
* on `replay`.
|
|
4746
|
+
*
|
|
4747
|
+
* Only when nothing matches literally does Fuse get a turn, so a typo degrades to a
|
|
4748
|
+
* ranked guess instead of an empty list. Terms are AND-ed there too, each matched
|
|
4749
|
+
* fuzzily on its own — Fuse's bitap pass over the whole query would otherwise need
|
|
4750
|
+
* `git iss` to be a near-edit of the text it's matching. Scores are distances (0 is
|
|
4751
|
+
* exact) and sum across terms, hence the ascending sort; ties keep the order the
|
|
4752
|
+
* first term put them in, since the sort is stable.
|
|
4753
|
+
*/
|
|
4754
|
+
function rankOptions(fuse, options, query) {
|
|
4755
|
+
const terms = query.toLowerCase().split(/\s+/).filter(Boolean);
|
|
4756
|
+
if (!terms.length) return null;
|
|
4757
|
+
const literal = options.filter((option) => terms.every((term) => haystack(option).includes(term)));
|
|
4758
|
+
if (literal.length) return literal;
|
|
4759
|
+
let surviving = null;
|
|
4760
|
+
for (const term of terms) {
|
|
4761
|
+
const hits = new Map(fuse.search(term).map(({ item, score }) => [item, score ?? 0]));
|
|
4762
|
+
if (surviving === null) {
|
|
4763
|
+
surviving = hits;
|
|
4764
|
+
continue;
|
|
4765
|
+
}
|
|
4766
|
+
for (const [option, total] of surviving) {
|
|
4767
|
+
const score = hits.get(option);
|
|
4768
|
+
if (score === void 0) surviving.delete(option);
|
|
4769
|
+
else surviving.set(option, total + score);
|
|
4770
|
+
}
|
|
4771
|
+
}
|
|
4772
|
+
return [...surviving ?? []].sort(([, a], [, b]) => a - b).map(([option]) => option);
|
|
4773
|
+
}
|
|
4774
|
+
//#endregion
|
|
4644
4775
|
//#region src/ui/tui/primitives/PromptLabel.tsx
|
|
4645
4776
|
/**
|
|
4646
4777
|
* PromptLabel — Compact inline label for input prompts.
|
|
@@ -4722,6 +4853,8 @@ const DEFAULT_PRIORITY = {
|
|
|
4722
4853
|
["leftArrow"]: 1,
|
|
4723
4854
|
["rightArrow"]: 1,
|
|
4724
4855
|
["space"]: 10,
|
|
4856
|
+
["printable"]: 12,
|
|
4857
|
+
["backspace"]: 13,
|
|
4725
4858
|
["escape"]: 20,
|
|
4726
4859
|
["return"]: 21
|
|
4727
4860
|
};
|
|
@@ -4739,6 +4872,8 @@ function matchesKey(m, input, key) {
|
|
|
4739
4872
|
case "return": return !!key.return;
|
|
4740
4873
|
case "escape": return !!key.escape;
|
|
4741
4874
|
case "space": return input === " ";
|
|
4875
|
+
case "backspace": return !!key.backspace || !!key.delete;
|
|
4876
|
+
case "printable": return input.length === 1 && input >= " " && input !== "" && Object.entries(key).every(([flag, on]) => !on || flag === "shift");
|
|
4742
4877
|
default: return input === m;
|
|
4743
4878
|
}
|
|
4744
4879
|
}
|
|
@@ -4931,29 +5066,70 @@ function usePickerViewport(count, rowCost, chromeBelow, enabled, focused) {
|
|
|
4931
5066
|
pageStep: (f, dir) => (Math.floor(f / perPage) + dir + pageCount) % pageCount * perPage
|
|
4932
5067
|
};
|
|
4933
5068
|
}
|
|
4934
|
-
|
|
4935
|
-
|
|
4936
|
-
|
|
5069
|
+
/** Lists at least this long get filtering. Shorter ones fit on a page or two,
|
|
5070
|
+
* where a filter row costs more rows than it saves. */
|
|
5071
|
+
const FILTER_MIN_OPTIONS = 10;
|
|
5072
|
+
const PickerMenu = ({ message, options, mode = "single", centered = false, columns = 1, optionMarginBottom = 0, filterable, onSelect }) => {
|
|
5073
|
+
const canFilter = filterable ?? options.length >= FILTER_MIN_OPTIONS;
|
|
5074
|
+
const [filter, setFilter] = useState("");
|
|
5075
|
+
const fuse = useMemo(() => canFilter ? buildPickerIndex(options) : null, [options, canFilter]);
|
|
5076
|
+
const visible = useMemo(() => fuse ? rankOptions(fuse, options, filter) ?? options : options, [
|
|
5077
|
+
fuse,
|
|
4937
5078
|
options,
|
|
4938
|
-
|
|
4939
|
-
|
|
4940
|
-
|
|
4941
|
-
|
|
4942
|
-
});
|
|
4943
|
-
return /* @__PURE__ */ jsx(SinglePickerMenu, {
|
|
5079
|
+
filter
|
|
5080
|
+
]);
|
|
5081
|
+
const [selected, setSelected] = useState(/* @__PURE__ */ new Set());
|
|
5082
|
+
const shared = {
|
|
4944
5083
|
message,
|
|
4945
|
-
options,
|
|
5084
|
+
options: visible,
|
|
4946
5085
|
centered,
|
|
4947
|
-
columns,
|
|
4948
5086
|
optionMarginBottom,
|
|
4949
|
-
onSelect
|
|
4950
|
-
|
|
5087
|
+
onSelect,
|
|
5088
|
+
filter: canFilter ? filter : null,
|
|
5089
|
+
setFilter,
|
|
5090
|
+
totalCount: options.length
|
|
5091
|
+
};
|
|
5092
|
+
const key = String(filter);
|
|
5093
|
+
if (mode === "multi") return /* @__PURE__ */ jsx(MultiPickerMenu, {
|
|
5094
|
+
...shared,
|
|
5095
|
+
columns,
|
|
5096
|
+
allOptions: options,
|
|
5097
|
+
selected,
|
|
5098
|
+
setSelected
|
|
5099
|
+
}, key);
|
|
5100
|
+
return /* @__PURE__ */ jsx(SinglePickerMenu, {
|
|
5101
|
+
...shared,
|
|
5102
|
+
columns
|
|
5103
|
+
}, key);
|
|
4951
5104
|
};
|
|
5105
|
+
/**
|
|
5106
|
+
* Backspace and free typing. Append these last: `Printable` matches almost any
|
|
5107
|
+
* key, and bindings resolve in order, so anything specific has to be registered
|
|
5108
|
+
* first to keep working. Both share a label/action so the hints bar shows one.
|
|
5109
|
+
*/
|
|
5110
|
+
function filterBindings(filter, setFilter) {
|
|
5111
|
+
return [{
|
|
5112
|
+
match: "backspace",
|
|
5113
|
+
label: "type",
|
|
5114
|
+
action: "filter",
|
|
5115
|
+
handler: () => setFilter(filter.slice(0, -1))
|
|
5116
|
+
}, {
|
|
5117
|
+
match: "printable",
|
|
5118
|
+
label: "type",
|
|
5119
|
+
action: "filter",
|
|
5120
|
+
handler: (input) => setFilter(filter + input)
|
|
5121
|
+
}];
|
|
5122
|
+
}
|
|
5123
|
+
/** The filter row above a filterable list: what's typed, and how much it left. */
|
|
5124
|
+
const FilterRow = ({ filter, shown, total }) => /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Text, {
|
|
5125
|
+
dimColor: true,
|
|
5126
|
+
children: filter ? `Filter: ${filter} (${shown} of ${total})` : `Type to filter ${total} options`
|
|
5127
|
+
}) });
|
|
4952
5128
|
/** Custom single-select with triangle indicator and accent highlight. */
|
|
4953
|
-
const SinglePickerMenu = ({ message, options, centered = false, columns = 1, optionMarginBottom = 0, onSelect }) => {
|
|
5129
|
+
const SinglePickerMenu = ({ message, options, centered = false, columns = 1, optionMarginBottom = 0, filter, setFilter, totalCount, onSelect }) => {
|
|
4954
5130
|
const [focused, setFocused] = useState(() => firstEnabled(options));
|
|
4955
5131
|
const rows = Math.ceil(options.length / columns);
|
|
4956
|
-
const viewport = usePickerViewport(options.length, 1 + optionMarginBottom, 0, columns === 1, focused);
|
|
5132
|
+
const viewport = usePickerViewport(options.length, 1 + optionMarginBottom, filter !== null ? 1 : 0, columns === 1, focused);
|
|
4957
5133
|
useEffect(() => {
|
|
4958
5134
|
if (focused >= options.length || options[focused]?.disabled) setFocused(firstEnabled(options));
|
|
4959
5135
|
}, [options, focused]);
|
|
@@ -4963,22 +5139,10 @@ const SinglePickerMenu = ({ message, options, centered = false, columns = 1, opt
|
|
|
4963
5139
|
label: "↑↓",
|
|
4964
5140
|
action: "navigate",
|
|
4965
5141
|
handler: (_input, key) => {
|
|
4966
|
-
|
|
4967
|
-
if (columns === 1) {
|
|
4968
|
-
const { start, end } = viewport;
|
|
4969
|
-
const span = end - start;
|
|
4970
|
-
let r = focused;
|
|
4971
|
-
for (let i = 0; i < span; i++) {
|
|
4972
|
-
r = start + (r - start + dir + span) % span;
|
|
4973
|
-
if (!options[r]?.disabled) break;
|
|
4974
|
-
}
|
|
4975
|
-
setFocused(r);
|
|
4976
|
-
return;
|
|
4977
|
-
}
|
|
4978
|
-
setFocused(stepEnabled(options, rows, focused, dir));
|
|
5142
|
+
setFocused(stepEnabled(options, rows, focused, key.upArrow ? -1 : 1));
|
|
4979
5143
|
}
|
|
4980
5144
|
},
|
|
4981
|
-
...viewport.needsScroll ? [{
|
|
5145
|
+
...viewport.needsScroll && filter === null ? [{
|
|
4982
5146
|
match: ["n", "p"],
|
|
4983
5147
|
label: "n/p",
|
|
4984
5148
|
action: "page",
|
|
@@ -5017,6 +5181,7 @@ const SinglePickerMenu = ({ message, options, centered = false, columns = 1, opt
|
|
|
5017
5181
|
setFocused(next);
|
|
5018
5182
|
}
|
|
5019
5183
|
});
|
|
5184
|
+
if (filter !== null) bindings.push(...filterBindings(filter, setFilter));
|
|
5020
5185
|
useKeyBindings("single-picker", bindings);
|
|
5021
5186
|
const columnArrays = [];
|
|
5022
5187
|
for (let c = 0; c < columns; c++) columnArrays.push(options.slice(c * rows, c * rows + rows));
|
|
@@ -5050,27 +5215,38 @@ const SinglePickerMenu = ({ message, options, centered = false, columns = 1, opt
|
|
|
5050
5215
|
return /* @__PURE__ */ jsxs(Box, {
|
|
5051
5216
|
flexDirection: "column",
|
|
5052
5217
|
alignItems: align,
|
|
5053
|
-
children: [
|
|
5054
|
-
|
|
5055
|
-
|
|
5056
|
-
|
|
5057
|
-
|
|
5058
|
-
|
|
5059
|
-
|
|
5060
|
-
|
|
5061
|
-
|
|
5062
|
-
|
|
5063
|
-
|
|
5064
|
-
})
|
|
5065
|
-
]
|
|
5066
|
-
}) : /* @__PURE__ */ jsx(Box, {
|
|
5067
|
-
flexDirection: "row",
|
|
5068
|
-
gap: 4,
|
|
5069
|
-
children: columnArrays.map((colOpts, colIdx) => /* @__PURE__ */ jsx(Box, {
|
|
5218
|
+
children: [
|
|
5219
|
+
/* @__PURE__ */ jsx(PromptLabel, { message }),
|
|
5220
|
+
filter !== null && /* @__PURE__ */ jsx(FilterRow, {
|
|
5221
|
+
filter,
|
|
5222
|
+
shown: options.length,
|
|
5223
|
+
total: totalCount
|
|
5224
|
+
}),
|
|
5225
|
+
filter && options.length === 0 ? /* @__PURE__ */ jsx(Text, {
|
|
5226
|
+
dimColor: true,
|
|
5227
|
+
children: "No options match. Backspace to widen the filter."
|
|
5228
|
+
}) : viewport.needsScroll ? /* @__PURE__ */ jsxs(Box, {
|
|
5070
5229
|
flexDirection: "column",
|
|
5071
|
-
children:
|
|
5072
|
-
|
|
5073
|
-
|
|
5230
|
+
children: [
|
|
5231
|
+
/* @__PURE__ */ jsx(Text, {
|
|
5232
|
+
dimColor: true,
|
|
5233
|
+
children: viewport.hiddenAbove > 0 ? `↑ ${viewport.hiddenAbove} more${filter === null ? " [P] for previous page" : ""}` : " "
|
|
5234
|
+
}),
|
|
5235
|
+
options.slice(viewport.start, viewport.end).map((opt, relIdx) => renderOption(opt, viewport.start + relIdx)),
|
|
5236
|
+
/* @__PURE__ */ jsx(Text, {
|
|
5237
|
+
dimColor: true,
|
|
5238
|
+
children: viewport.hiddenBelow > 0 ? `↓ ${viewport.hiddenBelow} more${filter === null ? " [N] for next page" : ""}` : " "
|
|
5239
|
+
})
|
|
5240
|
+
]
|
|
5241
|
+
}) : /* @__PURE__ */ jsx(Box, {
|
|
5242
|
+
flexDirection: "row",
|
|
5243
|
+
gap: 4,
|
|
5244
|
+
children: columnArrays.map((colOpts, colIdx) => /* @__PURE__ */ jsx(Box, {
|
|
5245
|
+
flexDirection: "column",
|
|
5246
|
+
children: colOpts.map((opt, rowIdx) => renderOption(opt, colIdx * rows + rowIdx))
|
|
5247
|
+
}, colIdx))
|
|
5248
|
+
})
|
|
5249
|
+
]
|
|
5074
5250
|
});
|
|
5075
5251
|
};
|
|
5076
5252
|
/**
|
|
@@ -5085,18 +5261,17 @@ const SinglePickerMenu = ({ message, options, centered = false, columns = 1, opt
|
|
|
5085
5261
|
* - moving onto the Confirm button and pressing enter submits the
|
|
5086
5262
|
* current selection.
|
|
5087
5263
|
*/
|
|
5088
|
-
const MultiPickerMenu = ({ message, options, centered = false, columns = 1, optionMarginBottom = 0, onSelect }) => {
|
|
5264
|
+
const MultiPickerMenu = ({ message, options, centered = false, columns = 1, optionMarginBottom = 0, filter, setFilter, totalCount, allOptions, selected, setSelected, onSelect }) => {
|
|
5089
5265
|
const [focused, setFocused] = useState(() => firstEnabled(options));
|
|
5090
5266
|
const [onButton, setOnButton] = useState(false);
|
|
5091
|
-
const [selected, setSelected] = useState(/* @__PURE__ */ new Set());
|
|
5092
5267
|
const rows = Math.ceil(options.length / columns);
|
|
5093
5268
|
const rowCost = options.reduce((max, opt) => Math.max(max, 1 + optionMarginBottom + (opt.description ? wordWrap(opt.description, DESCRIPTION_WIDTH).length : 0)), 1);
|
|
5094
|
-
const viewport = usePickerViewport(options.length, rowCost, CONFIRM_CHROME, columns === 1, focused);
|
|
5269
|
+
const viewport = usePickerViewport(options.length, rowCost, CONFIRM_CHROME + (filter !== null ? 1 : 0), columns === 1, focused);
|
|
5095
5270
|
useEffect(() => {
|
|
5096
5271
|
if (focused >= options.length || options[focused]?.disabled) setFocused(firstEnabled(options));
|
|
5097
5272
|
}, [options, focused]);
|
|
5098
5273
|
const confirm = () => {
|
|
5099
|
-
onSelect(
|
|
5274
|
+
onSelect(allOptions.filter((option) => selected.has(option.label)).map((option) => option.value));
|
|
5100
5275
|
};
|
|
5101
5276
|
const bindings = [
|
|
5102
5277
|
{
|
|
@@ -5110,13 +5285,6 @@ const MultiPickerMenu = ({ message, options, centered = false, columns = 1, opti
|
|
|
5110
5285
|
setFocused(dir === -1 ? lastEnabled(options, viewport.start, viewport.end) : firstEnabled(options, viewport.start, viewport.end));
|
|
5111
5286
|
return;
|
|
5112
5287
|
}
|
|
5113
|
-
if (columns === 1) {
|
|
5114
|
-
let r = focused + dir;
|
|
5115
|
-
while (r >= viewport.start && r < viewport.end && options[r]?.disabled) r += dir;
|
|
5116
|
-
if (r >= viewport.start && r < viewport.end) setFocused(r);
|
|
5117
|
-
else setOnButton(true);
|
|
5118
|
-
return;
|
|
5119
|
-
}
|
|
5120
5288
|
const col = Math.floor(focused / rows);
|
|
5121
5289
|
const row = focused % rows;
|
|
5122
5290
|
const colLen = Math.min(rows, options.length - col * rows);
|
|
@@ -5126,7 +5294,7 @@ const MultiPickerMenu = ({ message, options, centered = false, columns = 1, opti
|
|
|
5126
5294
|
else setOnButton(true);
|
|
5127
5295
|
}
|
|
5128
5296
|
},
|
|
5129
|
-
...viewport.needsScroll ? [{
|
|
5297
|
+
...viewport.needsScroll && filter === null ? [{
|
|
5130
5298
|
match: ["n", "p"],
|
|
5131
5299
|
label: "n/p",
|
|
5132
5300
|
action: "page",
|
|
@@ -5137,7 +5305,7 @@ const MultiPickerMenu = ({ message, options, centered = false, columns = 1, opti
|
|
|
5137
5305
|
}
|
|
5138
5306
|
}] : [],
|
|
5139
5307
|
{
|
|
5140
|
-
match: ["space", "return"],
|
|
5308
|
+
match: filter !== null ? "return" : ["space", "return"],
|
|
5141
5309
|
label: "enter",
|
|
5142
5310
|
action: "select",
|
|
5143
5311
|
handler: () => {
|
|
@@ -5145,16 +5313,18 @@ const MultiPickerMenu = ({ message, options, centered = false, columns = 1, opti
|
|
|
5145
5313
|
confirm();
|
|
5146
5314
|
return;
|
|
5147
5315
|
}
|
|
5148
|
-
|
|
5316
|
+
const option = options[focused];
|
|
5317
|
+
if (!option || option.disabled) return;
|
|
5318
|
+
const label = option.label;
|
|
5149
5319
|
setSelected((prev) => {
|
|
5150
5320
|
const next = new Set(prev);
|
|
5151
|
-
if (next.has(
|
|
5152
|
-
next.delete(
|
|
5321
|
+
if (next.has(label)) {
|
|
5322
|
+
next.delete(label);
|
|
5153
5323
|
return next;
|
|
5154
5324
|
}
|
|
5155
|
-
if (
|
|
5156
|
-
for (const
|
|
5157
|
-
next.add(
|
|
5325
|
+
if (option.exclusive) return new Set([label]);
|
|
5326
|
+
for (const picked of next) if (allOptions.find((o) => o.label === picked)?.exclusive) next.delete(picked);
|
|
5327
|
+
next.add(label);
|
|
5158
5328
|
return next;
|
|
5159
5329
|
});
|
|
5160
5330
|
}
|
|
@@ -5181,12 +5351,13 @@ const MultiPickerMenu = ({ message, options, centered = false, columns = 1, opti
|
|
|
5181
5351
|
setFocused(next);
|
|
5182
5352
|
}
|
|
5183
5353
|
});
|
|
5354
|
+
if (filter !== null) bindings.push(...filterBindings(filter, setFilter));
|
|
5184
5355
|
useKeyBindings("multi-picker", bindings);
|
|
5185
5356
|
const columnArrays = [];
|
|
5186
5357
|
for (let c = 0; c < columns; c++) columnArrays.push(options.slice(c * rows, c * rows + rows));
|
|
5187
5358
|
const renderOption = (opt, flatIdx) => {
|
|
5188
5359
|
const isFocused = !onButton && flatIdx === focused;
|
|
5189
|
-
const isSelected = selected.has(
|
|
5360
|
+
const isSelected = selected.has(opt.label);
|
|
5190
5361
|
const label = opt.hint ? `${opt.label} (${opt.hint})` : opt.label;
|
|
5191
5362
|
const checkbox = isSelected ? Icons.squareFilled : Icons.squareOpen;
|
|
5192
5363
|
return /* @__PURE__ */ jsxs(Box, {
|
|
@@ -5227,6 +5398,15 @@ const MultiPickerMenu = ({ message, options, centered = false, columns = 1, opti
|
|
|
5227
5398
|
alignItems: centered ? "center" : void 0,
|
|
5228
5399
|
children: [
|
|
5229
5400
|
/* @__PURE__ */ jsx(PromptLabel, { message }),
|
|
5401
|
+
filter !== null && /* @__PURE__ */ jsx(FilterRow, {
|
|
5402
|
+
filter,
|
|
5403
|
+
shown: options.length,
|
|
5404
|
+
total: totalCount
|
|
5405
|
+
}),
|
|
5406
|
+
filter && options.length === 0 && /* @__PURE__ */ jsx(Text, {
|
|
5407
|
+
dimColor: true,
|
|
5408
|
+
children: "No options match. Backspace to widen the filter."
|
|
5409
|
+
}),
|
|
5230
5410
|
viewport.needsScroll ? /* @__PURE__ */ jsxs(Box, {
|
|
5231
5411
|
flexDirection: "column",
|
|
5232
5412
|
marginLeft: centered ? 0 : 2,
|
|
@@ -5234,12 +5414,12 @@ const MultiPickerMenu = ({ message, options, centered = false, columns = 1, opti
|
|
|
5234
5414
|
children: [
|
|
5235
5415
|
/* @__PURE__ */ jsx(Text, {
|
|
5236
5416
|
dimColor: true,
|
|
5237
|
-
children: viewport.hiddenAbove > 0 ? `↑ ${viewport.hiddenAbove} more [P] for previous page` : " "
|
|
5417
|
+
children: viewport.hiddenAbove > 0 ? `↑ ${viewport.hiddenAbove} more${filter === null ? " [P] for previous page" : ""}` : " "
|
|
5238
5418
|
}),
|
|
5239
5419
|
options.slice(viewport.start, viewport.end).map((opt, relIdx) => renderOption(opt, viewport.start + relIdx)),
|
|
5240
5420
|
/* @__PURE__ */ jsx(Text, {
|
|
5241
5421
|
dimColor: true,
|
|
5242
|
-
children: viewport.hiddenBelow > 0 ? `↓ ${viewport.hiddenBelow} more [N] for next page` : " "
|
|
5422
|
+
children: viewport.hiddenBelow > 0 ? `↓ ${viewport.hiddenBelow} more${filter === null ? " [N] for next page" : ""}` : " "
|
|
5243
5423
|
})
|
|
5244
5424
|
]
|
|
5245
5425
|
}) : /* @__PURE__ */ jsx(Box, {
|
|
@@ -5445,7 +5625,7 @@ async function runDoctorCI(options) {
|
|
|
5445
5625
|
getUI().intro("Welcome to the PostHog setup wizard");
|
|
5446
5626
|
getUI().log.info("Running posthog-doctor in CI mode");
|
|
5447
5627
|
try {
|
|
5448
|
-
const { getOrAskForProjectData } = await import("./setup-utils-
|
|
5628
|
+
const { getOrAskForProjectData } = await import("./setup-utils-C2rGcUFv.js").then((n) => n.r);
|
|
5449
5629
|
const { host, accessToken, projectId } = await getOrAskForProjectData({
|
|
5450
5630
|
signup: false,
|
|
5451
5631
|
ci: true,
|
|
@@ -5463,7 +5643,7 @@ async function runDoctorCI(options) {
|
|
|
5463
5643
|
for (const issue of sorted) getUI().log.info(` • [${issue.severity}] ${getKindMeta(issue.kind).title}`);
|
|
5464
5644
|
process.exit(1);
|
|
5465
5645
|
} catch (error) {
|
|
5466
|
-
const { ApiError } = await import("./api-
|
|
5646
|
+
const { ApiError } = await import("./api-XHQTOfIi.js").then((n) => n.n);
|
|
5467
5647
|
const message = error instanceof ApiError && error.statusCode === 401 ? "Your PostHog API key is invalid or expired." : error instanceof Error ? error.message : String(error);
|
|
5468
5648
|
getUI().log.error(`Doctor failed: ${message}`);
|
|
5469
5649
|
process.exit(1);
|
|
@@ -5545,8 +5725,8 @@ function runSlackConnect(argv) {
|
|
|
5545
5725
|
(async () => {
|
|
5546
5726
|
const debug = argv.debug;
|
|
5547
5727
|
try {
|
|
5548
|
-
const { startTUI } = await import("./start-tui-
|
|
5549
|
-
const { buildSession } = await import("./wizard-session-
|
|
5728
|
+
const { startTUI } = await import("./start-tui-BYTQwgvK.js");
|
|
5729
|
+
const { buildSession } = await import("./wizard-session-DZUDtS5d.js");
|
|
5550
5730
|
const tui = startTUI(VERSION, Program.SlackConnect);
|
|
5551
5731
|
tui.store.session = buildSession({
|
|
5552
5732
|
debug,
|
|
@@ -5878,6 +6058,6 @@ function resolveInstallDir() {
|
|
|
5878
6058
|
}
|
|
5879
6059
|
Wizard.use(basicIntegrationCommand).use(mcpCommand).use(mcpAnalyticsCommand).use(aiObservabilityCommand).use(cliCommand).use(auditCommand).use(doctorCommand).use(migrateCommand).use(revenueCommand).use(warehouseCommand).use(selfDrivingCommand).use(slackCommand).use(uploadSourcemapsCommand).use(skillCommand).init();
|
|
5880
6060
|
//#endregion
|
|
5881
|
-
export {
|
|
6061
|
+
export { STRIPE_SDKS as A, MANUAL_SDK_VARIANTS as C, fetchHealthIssues as D, getKindMeta as E, getContentBlocks$3 as O, MANUAL_SDK_INSTALL as S, SOURCE_MAPS_CONTEXT_KEYS as T, detectSelfDrivingIntegrationProjects as _, useStdoutDimensions as a, DISPLAY_NAME as b, runWizardHeadless as c, PROGRAM_REGISTRY as d, Program as f, PRICING_SHORT as g, PRICING_LONG as h, useKeyboardHintsContext as i, POSTHOG_SDKS as k, runWizardCI as l, NO_DEFAULT_LIMIT as m, useKeyBindings as n, ConfirmButton as o, getProgramConfig as p, KeyboardHintsProvider as r, PromptLabel as s, PickerMenu as t, runWizard as u, SELF_DRIVING_INTEGRATE_PATH_KEY as v, RUST_SDK_CRATE as w, GO_SDK_MODULE as x, AUTOMATABLE_VARIANTS as y };
|
|
5882
6062
|
|
|
5883
6063
|
//# sourceMappingURL=bin.js.map
|