@posthog/wizard 2.80.0 → 2.80.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +187 -57
- package/dist/{PickerMenu-m4CCPX4f.js → PickerMenu-BGGeYqd-.js} +104 -4
- package/dist/PickerMenu-BGGeYqd-.js.map +1 -0
- package/dist/README.md +9 -6
- package/dist/{agent-interface-CzyCmp7q.js → agent-interface-CemBvTAA.js} +115 -346
- package/dist/agent-interface-CemBvTAA.js.map +1 -0
- package/dist/{agent-prompt-loader-4wMxlYSX.js → agent-prompt-loader-DPnj6SwU.js} +6 -5
- package/dist/agent-prompt-loader-DPnj6SwU.js.map +1 -0
- package/dist/analytics-B3ROGuIr.js +2 -0
- package/dist/analytics-D21z3E5l.js +732 -0
- package/dist/analytics-D21z3E5l.js.map +1 -0
- package/dist/{api-C3Dc4LFl.js → api-DtGIqQ2U.js} +2 -3
- package/dist/api-DtGIqQ2U.js.map +1 -0
- package/dist/api-IhROOQNv.js +2 -0
- package/dist/api-key-login-OEntFvu5.js +2 -0
- package/dist/api-key-login-h3E2G3zu.js +55 -0
- package/dist/api-key-login-h3E2G3zu.js.map +1 -0
- package/dist/bin.js +2 -2
- package/dist/bin.js.map +1 -1
- package/dist/{bounded-fs-CC_NDtoP.js → bounded-fs-CAsuF6al.js} +3 -3
- package/dist/{bounded-fs-CC_NDtoP.js.map → bounded-fs-CAsuF6al.js.map} +1 -1
- package/dist/{ci-install-DfcAMhlu.js → ci-install-CEYE02t-.js} +21 -25
- package/dist/ci-install-CEYE02t-.js.map +1 -0
- package/dist/console-log-O828zyiq.js +32 -0
- package/dist/console-log-O828zyiq.js.map +1 -0
- package/dist/{debug-DyARf5TF.js → debug-BfQPD2Hg.js} +18 -52
- package/dist/debug-BfQPD2Hg.js.map +1 -0
- package/dist/{defaults-DpfMnH2q.js → defaults-DDVl3tKN.js} +2 -51
- package/dist/defaults-DDVl3tKN.js.map +1 -0
- package/dist/{emit-BSetXzDV.js → emit-RfAewcWv.js} +1 -1
- package/dist/{emit-BSetXzDV.js.map → emit-RfAewcWv.js.map} +1 -1
- package/dist/{errors-C2domSkK.js → errors-CHrJzAZb.js} +4 -4
- package/dist/{errors-C2domSkK.js.map → errors-CHrJzAZb.js.map} +1 -1
- package/dist/family-picker-BKs-tTyu.js +46 -0
- package/dist/family-picker-BKs-tTyu.js.map +1 -0
- package/dist/{gateway-BmjYUSua.js → gateway-D3gIlR6b.js} +122 -11
- package/dist/gateway-D3gIlR6b.js.map +1 -0
- package/dist/headless-BJjhP0SI.js +10 -0
- package/dist/headless-BJjhP0SI.js.map +1 -0
- package/dist/headless-DIX68UUA.js +3 -0
- package/dist/{host-resolution-DVSb7kXb.js → host-resolution-D8GhEVoX.js} +4 -4
- package/dist/{host-resolution-DVSb7kXb.js.map → host-resolution-D8GhEVoX.js.map} +1 -1
- package/dist/install-Bw8tvDvS.js +2 -0
- package/dist/{install-Bk5TNk27.js → install-paPCzPHI.js} +26 -93
- package/dist/install-paPCzPHI.js.map +1 -0
- package/dist/interactive-tdxZKWax.js +11 -0
- package/dist/interactive-tdxZKWax.js.map +1 -0
- package/dist/{links-9LWZPSCq.js → links-Cyj6v8kg.js} +3 -3
- package/dist/{links-9LWZPSCq.js.map → links-Cyj6v8kg.js.map} +1 -1
- package/dist/{main-DKPjFHEV.js → main-0p-YxUNa.js} +204 -469
- package/dist/main-0p-YxUNa.js.map +1 -0
- package/dist/{mcp-Co8VRF62.js → mcp-D3Z5MXhA.js} +3 -4
- package/dist/{mcp-Co8VRF62.js.map → mcp-D3Z5MXhA.js.map} +1 -1
- package/dist/mcp-install-smoke-test.ts +2 -2
- package/dist/{mcp-prompt-streaming-ljCVoQ9I.js → mcp-prompt-streaming-COVbWnHt.js} +12 -12
- package/dist/mcp-prompt-streaming-COVbWnHt.js.map +1 -0
- package/dist/mode-label-DB3ol_sj.js +9 -0
- package/dist/mode-label-DB3ol_sj.js.map +1 -0
- package/dist/{models-Dba8ITeo.js → models-D1SnCzvl.js} +2 -2
- package/dist/{models-Dba8ITeo.js.map → models-D1SnCzvl.js.map} +1 -1
- package/dist/non-interactive-DxRBc73O.js +18 -0
- package/dist/non-interactive-DxRBc73O.js.map +1 -0
- package/dist/{oauth-session-D-RfcVmr.js → oauth-session-Dde79Ycm.js} +3 -3
- package/dist/{oauth-session-D-RfcVmr.js.map → oauth-session-Dde79Ycm.js.map} +1 -1
- package/dist/{orchestrator-tools-CVJ1F9Ub.js → orchestrator-tools-BSNhzzkT.js} +3 -3
- package/dist/{orchestrator-tools-CVJ1F9Ub.js.map → orchestrator-tools-BSNhzzkT.js.map} +1 -1
- package/dist/{package-json-Cowya9-3.js → package-json-2UrhE6kP.js} +1 -1
- package/dist/{package-json-Cowya9-3.js.map → package-json-2UrhE6kP.js.map} +1 -1
- package/dist/package-json-Dblip2_X.js +2 -0
- package/dist/package-manager-BRXlXo0p.js +105 -0
- package/dist/package-manager-BRXlXo0p.js.map +1 -0
- package/dist/{pi-B5YTBRDv.js → pi-cM_4Gd_9.js} +16 -18
- package/dist/pi-cM_4Gd_9.js.map +1 -0
- package/dist/playground-DTKy0XHT.js +12 -0
- package/dist/playground-DTKy0XHT.js.map +1 -0
- package/dist/posthog-integration-bwHwE87a.js +10291 -0
- package/dist/posthog-integration-bwHwE87a.js.map +1 -0
- package/dist/programs-BhtyA3lE.js +3 -0
- package/dist/programs-SeT1qNik.js +5348 -0
- package/dist/programs-SeT1qNik.js.map +1 -0
- package/dist/provisioning-BcXfeCMc.js +2 -0
- package/dist/{provisioning-CLhuKqXH.js → provisioning-JbJtq7hq.js} +4 -5
- package/dist/{provisioning-CLhuKqXH.js.map → provisioning-JbJtq7hq.js.map} +1 -1
- package/dist/{queue-tools-knnPQP0e.js → queue-tools-BIZSJyt6.js} +6 -8
- package/dist/queue-tools-BIZSJyt6.js.map +1 -0
- package/dist/results-DtKICAdz.js +55 -0
- package/dist/results-DtKICAdz.js.map +1 -0
- package/dist/run-CDurA5tO.js +248 -0
- package/dist/run-CDurA5tO.js.map +1 -0
- package/dist/run-DDCvLILJ.js +246 -0
- package/dist/run-DDCvLILJ.js.map +1 -0
- package/dist/run-tool-CTq9OOdT.js +2 -0
- package/dist/run-tool-DML8JJvt.js +2420 -0
- package/dist/run-tool-DML8JJvt.js.map +1 -0
- package/dist/runners-Dhu4pZTN.js +253 -0
- package/dist/runners-Dhu4pZTN.js.map +1 -0
- package/dist/{security-BvdSFDuM.js → security-DEH8Rn0_.js} +5 -5
- package/dist/security-DEH8Rn0_.js.map +1 -0
- package/dist/setup-utils-C5-WM-hS.js +118 -0
- package/dist/setup-utils-C5-WM-hS.js.map +1 -0
- package/dist/smoke-test.sh +1 -1
- package/dist/{playground-BLsCfHmQ.js → start-playground-DL4mVEUx.js} +43 -34
- package/dist/start-playground-DL4mVEUx.js.map +1 -0
- package/dist/{subagent-D_Sqak94.js → subagent-CnFvAq6E.js} +3 -3
- package/dist/{subagent-D_Sqak94.js.map → subagent-CnFvAq6E.js.map} +1 -1
- package/dist/{task-DiTI6Sak.js → task-BOScSm4W.js} +16 -17
- package/dist/task-BOScSm4W.js.map +1 -0
- package/dist/{tasks-ChZ_F1YP.js → tasks-BfJhVky2.js} +1 -1
- package/dist/tasks-BfJhVky2.js.map +1 -0
- package/dist/{telemetry-BNKsDxNS.js → telemetry-CP4rGicd.js} +2 -2
- package/dist/{telemetry-BNKsDxNS.js.map → telemetry-CP4rGicd.js.map} +1 -1
- package/dist/terminal-J3OD3dN0.js +16162 -0
- package/dist/terminal-J3OD3dN0.js.map +1 -0
- package/dist/tools-CCMV3DmB.js +544 -0
- package/dist/tools-CCMV3DmB.js.map +1 -0
- package/dist/{tools-C8LQ8QFz.js → tools-Cz8tDptL.js} +9 -9
- package/dist/tools-Cz8tDptL.js.map +1 -0
- package/dist/tui-BUZ2PWqN.js +2 -0
- package/dist/tui-Csf7VJxt.js +25 -0
- package/dist/tui-Csf7VJxt.js.map +1 -0
- package/dist/{steps-Hc28zVc_.js → upload-step-CEacB2RV.js} +14 -16
- package/dist/upload-step-CEacB2RV.js.map +1 -0
- package/dist/{urls-BI4kJ4qQ.js → urls-BDELGZHq.js} +2 -2
- package/dist/{urls-BI4kJ4qQ.js.map → urls-BDELGZHq.js.map} +1 -1
- package/dist/warlock-smoke-test.ts +1 -2
- package/dist/{wizard-abort-DBKtfnBR.js → wizard-abort-D3-75KyV.js} +40 -33
- package/dist/wizard-abort-D3-75KyV.js.map +1 -0
- package/dist/yara-hooks-CZ1tKxy_.js +2 -0
- package/dist/{yara-hooks-C3L6lBij.js → yara-hooks-D8YDyX7o.js} +283 -21
- package/dist/yara-hooks-D8YDyX7o.js.map +1 -0
- package/package.json +6 -6
- package/dist/PickerMenu-m4CCPX4f.js.map +0 -1
- package/dist/agent-BkBbVuNq.js +0 -3189
- package/dist/agent-BkBbVuNq.js.map +0 -1
- package/dist/agent-QGK2YzlX.js +0 -6
- package/dist/agent-interface-CzyCmp7q.js.map +0 -1
- package/dist/agent-prompt-loader-4wMxlYSX.js.map +0 -1
- package/dist/analytics-B6q5PN7a.js +0 -301
- package/dist/analytics-B6q5PN7a.js.map +0 -1
- package/dist/analytics-BXtfK9o7.js +0 -2
- package/dist/api-C3Dc4LFl.js.map +0 -1
- package/dist/api-yNjrfZs2.js +0 -2
- package/dist/check-screens.tsx +0 -190
- package/dist/ci-install-DfcAMhlu.js.map +0 -1
- package/dist/constants-DO4X70po.js +0 -260
- package/dist/constants-DO4X70po.js.map +0 -1
- package/dist/debug-BueK5mRR.js +0 -2
- package/dist/debug-DyARf5TF.js.map +0 -1
- package/dist/defaults-DpfMnH2q.js.map +0 -1
- package/dist/endpoints-D-4KxZiB.js +0 -108
- package/dist/endpoints-D-4KxZiB.js.map +0 -1
- package/dist/env-api-key-CHGLe0iz.js +0 -2
- package/dist/env-api-key-COf0U-Au.js +0 -17
- package/dist/env-api-key-COf0U-Au.js.map +0 -1
- package/dist/environment-DrLaSsA8.js +0 -39
- package/dist/environment-DrLaSsA8.js.map +0 -1
- package/dist/environment-hBj7ngmO.js +0 -2
- package/dist/file-CVA9ocIC.js +0 -60
- package/dist/file-CVA9ocIC.js.map +0 -1
- package/dist/file-CmoKK_Pp.js +0 -2
- package/dist/file-watcher-C3Su8vXm.js +0 -123
- package/dist/file-watcher-C3Su8vXm.js.map +0 -1
- package/dist/gateway-BmjYUSua.js.map +0 -1
- package/dist/headless-ui-CUbv12Yx.js +0 -44
- package/dist/headless-ui-CUbv12Yx.js.map +0 -1
- package/dist/install-Bk5TNk27.js.map +0 -1
- package/dist/install-F4wm3RSl.js +0 -2
- package/dist/interactive-C5LNvDj6.js +0 -11
- package/dist/interactive-C5LNvDj6.js.map +0 -1
- package/dist/local-dev-McsurOC-.js +0 -135
- package/dist/local-dev-McsurOC-.js.map +0 -1
- package/dist/logging-ui-p6XKVmTx.js +0 -226
- package/dist/logging-ui-p6XKVmTx.js.map +0 -1
- package/dist/main-DKPjFHEV.js.map +0 -1
- package/dist/mcp-prompt-streaming-ljCVoQ9I.js.map +0 -1
- package/dist/mint-failure-C0HyvEwO.js +0 -6403
- package/dist/mint-failure-C0HyvEwO.js.map +0 -1
- package/dist/non-interactive-CLMJrj_7.js +0 -18
- package/dist/non-interactive-CLMJrj_7.js.map +0 -1
- package/dist/package-json--ppioh2F.js +0 -2
- package/dist/pi-B5YTBRDv.js.map +0 -1
- package/dist/playground-BLsCfHmQ.js.map +0 -1
- package/dist/posthog-B2E0hpZt.js +0 -2
- package/dist/posthog-B42rt_1S.js +0 -124
- package/dist/posthog-B42rt_1S.js.map +0 -1
- package/dist/project-data--L-WZyvj.js +0 -2
- package/dist/project-data-BO9IXn9y.js +0 -1131
- package/dist/project-data-BO9IXn9y.js.map +0 -1
- package/dist/provisioning-C01REIU2.js +0 -2
- package/dist/queue-tools-knnPQP0e.js.map +0 -1
- package/dist/registry-B3rC5U4b.js +0 -3464
- package/dist/registry-B3rC5U4b.js.map +0 -1
- package/dist/registry-BamsM7J9.js +0 -2
- package/dist/run-agent-legacy-CwUmPfQF.js +0 -2
- package/dist/run-agent-legacy-DWBajsMh.js +0 -3467
- package/dist/run-agent-legacy-DWBajsMh.js.map +0 -1
- package/dist/runners-D1PqqpjA.js +0 -834
- package/dist/runners-D1PqqpjA.js.map +0 -1
- package/dist/security-BvdSFDuM.js.map +0 -1
- package/dist/setup-utils-ChXXTi1m.js +0 -301
- package/dist/setup-utils-ChXXTi1m.js.map +0 -1
- package/dist/start-tui-DicLfgsj.js +0 -6964
- package/dist/start-tui-DicLfgsj.js.map +0 -1
- package/dist/steps-Hc28zVc_.js.map +0 -1
- package/dist/store-COCO6U0P.js +0 -5
- package/dist/store-D3509G87.js +0 -1030
- package/dist/store-D3509G87.js.map +0 -1
- package/dist/task-DiTI6Sak.js.map +0 -1
- package/dist/task-status-CmrrR7zo.js +0 -16
- package/dist/task-status-CmrrR7zo.js.map +0 -1
- package/dist/task-stream-BckhG_cB.js +0 -363
- package/dist/task-stream-BckhG_cB.js.map +0 -1
- package/dist/tasks-ChZ_F1YP.js.map +0 -1
- package/dist/terminal-PK9bCLRi.js +0 -7222
- package/dist/terminal-PK9bCLRi.js.map +0 -1
- package/dist/tools-C8LQ8QFz.js.map +0 -1
- package/dist/ui-tPNpM6vj.js +0 -15
- package/dist/ui-tPNpM6vj.js.map +0 -1
- package/dist/version-5_ydHkM6.js +0 -6
- package/dist/version-5_ydHkM6.js.map +0 -1
- package/dist/wizard-abort-BVjqLyeA.js +0 -3
- package/dist/wizard-abort-DBKtfnBR.js.map +0 -1
- package/dist/wizard-session-B7BHnay0.js +0 -2
- package/dist/wizard-session-BYw6LzpS.js +0 -133
- package/dist/wizard-session-BYw6LzpS.js.map +0 -1
- package/dist/yara-hooks-C3L6lBij.js.map +0 -1
- package/dist/yara-hooks-CF_IsoaA.js +0 -2
|
@@ -0,0 +1,544 @@
|
|
|
1
|
+
import { n as ErrorCodes, t as emitWizardError } from "./emit-RfAewcWv.js";
|
|
2
|
+
import { M as POSTHOG_DOCS_URL, n as analytics, nt as WIZARD_USER_AGENT, rt as getSkillsBaseUrl } from "./analytics-D21z3E5l.js";
|
|
3
|
+
import { dt as detectTargets, ft as findTarget, mt as installSteeringSnippet, pt as installOrUpdatePostHogCli, ut as CLI_STEERING_TARGETS } from "./programs-SeT1qNik.js";
|
|
4
|
+
import "./errors-CHrJzAZb.js";
|
|
5
|
+
import { t as withProgress } from "./telemetry-CP4rGicd.js";
|
|
6
|
+
import "./posthog-integration-bwHwE87a.js";
|
|
7
|
+
import { y as fetchSkillMenu } from "./yara-hooks-D8YDyX7o.js";
|
|
8
|
+
import { r as namesWithStatus } from "./results-DtKICAdz.js";
|
|
9
|
+
import { l as handleApiError } from "./api-DtGIqQ2U.js";
|
|
10
|
+
import { t as ALL_FEATURE_VALUES } from "./defaults-DDVl3tKN.js";
|
|
11
|
+
import * as path$1 from "node:path";
|
|
12
|
+
import axios from "axios";
|
|
13
|
+
import { z } from "zod";
|
|
14
|
+
import * as readline from "node:readline/promises";
|
|
15
|
+
//#region src/tools/mcp/index.ts
|
|
16
|
+
const MCP_ADD = {
|
|
17
|
+
id: "mcp-add",
|
|
18
|
+
command: "add",
|
|
19
|
+
parentCommand: "mcp",
|
|
20
|
+
description: "Add PostHog MCP server to supported clients"
|
|
21
|
+
};
|
|
22
|
+
const MCP_REMOVE = {
|
|
23
|
+
id: "mcp-remove",
|
|
24
|
+
command: "remove",
|
|
25
|
+
parentCommand: "mcp",
|
|
26
|
+
description: "Remove PostHog MCP server from supported clients"
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Standalone tutorial flow — boots directly into the Choose phase of
|
|
30
|
+
* McpSuggestedPromptsScreen without going through MCP install first.
|
|
31
|
+
* Useful for users who already installed MCP and want to revisit the
|
|
32
|
+
* tutorial, or anyone who just wants to try the agent against PostHog
|
|
33
|
+
* without touching their IDE config.
|
|
34
|
+
*
|
|
35
|
+
* The screen handles its own OAuth (via services.performLogin) so this
|
|
36
|
+
* tool doesn't pre-populate credentials.
|
|
37
|
+
*/
|
|
38
|
+
const MCP_TUTORIAL = {
|
|
39
|
+
id: "mcp-tutorial",
|
|
40
|
+
command: "tutorial",
|
|
41
|
+
parentCommand: "mcp",
|
|
42
|
+
description: "Try the PostHog MCP with your agent — no install needed"
|
|
43
|
+
};
|
|
44
|
+
//#endregion
|
|
45
|
+
//#region src/tools/slack/index.ts
|
|
46
|
+
const SLACK = {
|
|
47
|
+
id: "slack",
|
|
48
|
+
command: "slack",
|
|
49
|
+
description: "Connect PostHog to your Slack"
|
|
50
|
+
};
|
|
51
|
+
//#endregion
|
|
52
|
+
//#region src/tools/doctor/types.ts
|
|
53
|
+
const HealthIssueSeveritySchema = z.enum([
|
|
54
|
+
"critical",
|
|
55
|
+
"warning",
|
|
56
|
+
"info"
|
|
57
|
+
]);
|
|
58
|
+
const HealthIssueStatusSchema = z.enum(["active", "resolved"]);
|
|
59
|
+
const HealthIssueSchema = z.object({
|
|
60
|
+
id: z.string(),
|
|
61
|
+
kind: z.string(),
|
|
62
|
+
severity: HealthIssueSeveritySchema,
|
|
63
|
+
status: HealthIssueStatusSchema,
|
|
64
|
+
dismissed: z.boolean(),
|
|
65
|
+
created_at: z.string(),
|
|
66
|
+
updated_at: z.string(),
|
|
67
|
+
resolved_at: z.string().nullable().optional()
|
|
68
|
+
});
|
|
69
|
+
const HealthIssueListResponseSchema = z.object({
|
|
70
|
+
results: z.array(HealthIssueSchema),
|
|
71
|
+
count: z.number().optional(),
|
|
72
|
+
next: z.string().nullable().optional(),
|
|
73
|
+
previous: z.string().nullable().optional()
|
|
74
|
+
});
|
|
75
|
+
//#endregion
|
|
76
|
+
//#region src/tools/doctor/fetch.ts
|
|
77
|
+
async function fetchHealthIssues(accessToken, baseUrl, projectId) {
|
|
78
|
+
const endpoint = `/api/environments/${projectId}/health_issues/`;
|
|
79
|
+
const url = `${baseUrl}${endpoint}?status=active&dismissed=false&limit=250`;
|
|
80
|
+
try {
|
|
81
|
+
const response = await axios.get(url, { headers: {
|
|
82
|
+
Authorization: `Bearer ${accessToken}`,
|
|
83
|
+
"User-Agent": WIZARD_USER_AGENT
|
|
84
|
+
} });
|
|
85
|
+
return HealthIssueListResponseSchema.parse(response.data).results;
|
|
86
|
+
} catch (error) {
|
|
87
|
+
const apiError = handleApiError(error, "fetch health issues");
|
|
88
|
+
analytics.captureException(apiError, {
|
|
89
|
+
endpoint,
|
|
90
|
+
baseUrl,
|
|
91
|
+
projectId
|
|
92
|
+
});
|
|
93
|
+
throw apiError;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
//#endregion
|
|
97
|
+
//#region src/tools/doctor/kind-metadata.ts
|
|
98
|
+
const KIND_METADATA = {
|
|
99
|
+
ingestion_lag: {
|
|
100
|
+
title: "Ingestion is delayed",
|
|
101
|
+
description: "Events are being received but are taking longer than usual to appear.",
|
|
102
|
+
docsUrl: `${POSTHOG_DOCS_URL}/support/troubleshooting`
|
|
103
|
+
},
|
|
104
|
+
ingestion_warning: {
|
|
105
|
+
title: "Ingestion warnings on recent events",
|
|
106
|
+
description: "Some recent events were rejected or flagged by the ingestion pipeline.",
|
|
107
|
+
docsUrl: `${POSTHOG_DOCS_URL}/support/troubleshooting`
|
|
108
|
+
},
|
|
109
|
+
sdk_outdated: {
|
|
110
|
+
title: "SDK version is out of date",
|
|
111
|
+
description: "One or more SDKs are running an old version. Upgrade to get the latest fixes.",
|
|
112
|
+
docsUrl: `${POSTHOG_DOCS_URL}/libraries`
|
|
113
|
+
},
|
|
114
|
+
no_live_events: {
|
|
115
|
+
title: "No $pageview or $screen events in the last 30 days",
|
|
116
|
+
description: "PostHog is not receiving page or screen events from this project.",
|
|
117
|
+
docsUrl: `${POSTHOG_DOCS_URL}/getting-started/install`
|
|
118
|
+
},
|
|
119
|
+
no_pageleave_events: {
|
|
120
|
+
title: "$pageleave events not being sent",
|
|
121
|
+
description: "Enable pageleave tracking to power bounce rate and session duration.",
|
|
122
|
+
docsUrl: `${POSTHOG_DOCS_URL}/libraries/js#config`
|
|
123
|
+
},
|
|
124
|
+
scroll_depth: {
|
|
125
|
+
title: "Scroll depth tracking disabled",
|
|
126
|
+
description: "Turn on scroll depth to capture how far users read each page.",
|
|
127
|
+
docsUrl: `${POSTHOG_DOCS_URL}/libraries/js#config`
|
|
128
|
+
},
|
|
129
|
+
authorized_urls: {
|
|
130
|
+
title: "No authorized URLs configured",
|
|
131
|
+
description: "Some web analytics filters require at least one authorized URL to work.",
|
|
132
|
+
docsUrl: `${POSTHOG_DOCS_URL}/web-analytics/faq`
|
|
133
|
+
},
|
|
134
|
+
reverse_proxy: {
|
|
135
|
+
title: "No reverse proxy detected",
|
|
136
|
+
description: "A reverse proxy reduces data loss from ad blockers.",
|
|
137
|
+
docsUrl: `${POSTHOG_DOCS_URL}/advanced/proxy`
|
|
138
|
+
},
|
|
139
|
+
web_vitals: {
|
|
140
|
+
title: "Web Vitals tracking disabled",
|
|
141
|
+
description: "Enable Web Vitals to capture LCP, CLS and other performance metrics.",
|
|
142
|
+
docsUrl: `${POSTHOG_DOCS_URL}/web-analytics/web-vitals`
|
|
143
|
+
},
|
|
144
|
+
materialized_view_failure: {
|
|
145
|
+
title: "A materialized view is failing",
|
|
146
|
+
description: "A data modeling pipeline failed its most recent run.",
|
|
147
|
+
docsUrl: `${POSTHOG_DOCS_URL}/data-warehouse`
|
|
148
|
+
},
|
|
149
|
+
external_data_failure: {
|
|
150
|
+
title: "External data source is failing",
|
|
151
|
+
description: "An external data source sync failed and data may be stale.",
|
|
152
|
+
docsUrl: `${POSTHOG_DOCS_URL}/data-warehouse/sources`
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
const UNKNOWN_KIND_META = {
|
|
156
|
+
title: "Unknown issue",
|
|
157
|
+
description: "PostHog reported an issue kind the wizard does not yet recognize.",
|
|
158
|
+
docsUrl: POSTHOG_DOCS_URL
|
|
159
|
+
};
|
|
160
|
+
function getKindMeta(kind) {
|
|
161
|
+
return KIND_METADATA[kind] ?? {
|
|
162
|
+
...UNKNOWN_KIND_META,
|
|
163
|
+
title: kind
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
//#endregion
|
|
167
|
+
//#region src/tools/doctor/report.ts
|
|
168
|
+
const SEVERITY_ORDER = {
|
|
169
|
+
critical: 0,
|
|
170
|
+
warning: 1,
|
|
171
|
+
info: 2
|
|
172
|
+
};
|
|
173
|
+
/** Resolves 0 when the project is healthy, and 1 on issues, a missing key or a failed fetch. */
|
|
174
|
+
async function runDoctorReport({ apiKey, projectId, baseUrl }, { log }) {
|
|
175
|
+
if (!apiKey) {
|
|
176
|
+
log.intro("PostHog Wizard");
|
|
177
|
+
log.log.error("CI mode requires --api-key (personal API key phx_xxx)");
|
|
178
|
+
emitWizardError({
|
|
179
|
+
code: ErrorCodes.ArgsMissingApiKey,
|
|
180
|
+
message: "CI mode requires --api-key (personal API key phx_xxx)"
|
|
181
|
+
});
|
|
182
|
+
return 1;
|
|
183
|
+
}
|
|
184
|
+
log.intro("Welcome to the PostHog setup wizard");
|
|
185
|
+
log.log.info("Running posthog-doctor in CI mode");
|
|
186
|
+
try {
|
|
187
|
+
const { resolveApiKeyProject } = await import("./api-key-login-OEntFvu5.js");
|
|
188
|
+
const { host, projectId: resolvedProjectId } = await resolveApiKeyProject(apiKey, {
|
|
189
|
+
projectId,
|
|
190
|
+
baseUrl,
|
|
191
|
+
onInfo: (message) => log.log.info(message),
|
|
192
|
+
onWarning: (message) => log.log.warn(message)
|
|
193
|
+
});
|
|
194
|
+
const issues = await fetchHealthIssues(apiKey, host.apiHost, resolvedProjectId);
|
|
195
|
+
if (issues.length === 0) {
|
|
196
|
+
log.log.success("No active issues — your project looks healthy.");
|
|
197
|
+
return 0;
|
|
198
|
+
}
|
|
199
|
+
const sorted = [...issues].sort((a, b) => SEVERITY_ORDER[a.severity] - SEVERITY_ORDER[b.severity]);
|
|
200
|
+
log.log.warn(`${issues.length} active issue${issues.length === 1 ? "" : "s"} found:`);
|
|
201
|
+
for (const issue of sorted) log.log.info(` • [${issue.severity}] ${getKindMeta(issue.kind).title}`);
|
|
202
|
+
return 1;
|
|
203
|
+
} catch (error) {
|
|
204
|
+
const { ApiError } = await import("./api-IhROOQNv.js");
|
|
205
|
+
const message = error instanceof ApiError && error.statusCode === 401 ? "Your PostHog API key is invalid or expired." : error instanceof Error ? error.message : String(error);
|
|
206
|
+
log.log.error(`Doctor failed: ${message}`);
|
|
207
|
+
emitWizardError({
|
|
208
|
+
code: error instanceof ApiError && error.statusCode === 401 ? ErrorCodes.AuthInvalidOrExpired : ErrorCodes.InternalUnhandled,
|
|
209
|
+
message
|
|
210
|
+
});
|
|
211
|
+
return 1;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
//#endregion
|
|
215
|
+
//#region src/tools/doctor/index.ts
|
|
216
|
+
const DOCTOR = {
|
|
217
|
+
id: "posthog-doctor",
|
|
218
|
+
command: "doctor",
|
|
219
|
+
description: "Diagnose your PostHog project setup"
|
|
220
|
+
};
|
|
221
|
+
//#endregion
|
|
222
|
+
//#region src/tools/mcp/scopes.ts
|
|
223
|
+
/**
|
|
224
|
+
* Extra scopes the MCP tutorial needs on top of `WIZARD_OAUTH_SCOPES`.
|
|
225
|
+
*
|
|
226
|
+
* Every scope requested here must stay within the wizard OAuth app's
|
|
227
|
+
* ceiling on the PostHog side (`OAuthApplication.scopes`) — the full
|
|
228
|
+
* list lives in the README under "OAuth app scope ceiling". The
|
|
229
|
+
* tutorial's prompts and follow-ups touch most of the read surface,
|
|
230
|
+
* plus annotation write for the "PostHog wizard install" verify-prompt.
|
|
231
|
+
*
|
|
232
|
+
* Already in the base `WIZARD_OAUTH_SCOPES` (and therefore not
|
|
233
|
+
* repeated here):
|
|
234
|
+
* • user:read, project:read, llm_gateway:read — auth + gateway
|
|
235
|
+
* • query:read — HogQL
|
|
236
|
+
* • dashboard:write, insight:write, notebook:write — Phase-5 persist
|
|
237
|
+
*
|
|
238
|
+
* Deliberately omitted (writes on read-only product surfaces):
|
|
239
|
+
* • feature_flag:write, experiment:write, survey:write,
|
|
240
|
+
* cohort:write, session_recording:write, error_tracking:write,
|
|
241
|
+
* alert:write, subscription:write
|
|
242
|
+
*/
|
|
243
|
+
const MCP_TUTORIAL_SCOPE_ADDITIONS = [
|
|
244
|
+
"dashboard:read",
|
|
245
|
+
"insight:read",
|
|
246
|
+
"notebook:read",
|
|
247
|
+
"feature_flag:read",
|
|
248
|
+
"experiment:read",
|
|
249
|
+
"experiment_saved_metric:read",
|
|
250
|
+
"survey:read",
|
|
251
|
+
"session_recording:read",
|
|
252
|
+
"error_tracking:read",
|
|
253
|
+
"web_analytics:read",
|
|
254
|
+
"llm_analytics:read",
|
|
255
|
+
"cohort:read",
|
|
256
|
+
"person:read",
|
|
257
|
+
"annotation:read",
|
|
258
|
+
"annotation:write",
|
|
259
|
+
"activity_log:read",
|
|
260
|
+
"property_definition:read",
|
|
261
|
+
"event_definition:read",
|
|
262
|
+
"action:read",
|
|
263
|
+
"warehouse_table:read",
|
|
264
|
+
"warehouse_view:read",
|
|
265
|
+
"alert:read",
|
|
266
|
+
"subscription:read",
|
|
267
|
+
"integration:read"
|
|
268
|
+
];
|
|
269
|
+
//#endregion
|
|
270
|
+
//#region src/shared/utils/flush-analytics.ts
|
|
271
|
+
/** Deliver the pending analytics events before the process exits; a failed flush never changes the outcome. */
|
|
272
|
+
async function flushAnalytics() {
|
|
273
|
+
try {
|
|
274
|
+
await analytics.flush();
|
|
275
|
+
} catch {}
|
|
276
|
+
}
|
|
277
|
+
//#endregion
|
|
278
|
+
//#region src/tools/mcp/console.ts
|
|
279
|
+
/**
|
|
280
|
+
* A scripted caller has no screen to read, so this has to be an exit code.
|
|
281
|
+
* Any failure counts, not just a total wipeout: the step installs to every
|
|
282
|
+
* detected client, so one succeeding would otherwise mask the rest.
|
|
283
|
+
*/
|
|
284
|
+
async function addMCPServerToClientsStep(args, { log }) {
|
|
285
|
+
const { addMCPServer, getSupportedClients } = await import("./install-Bw8tvDvS.js");
|
|
286
|
+
const supportedClients = await getSupportedClients();
|
|
287
|
+
if (supportedClients.length === 0) {
|
|
288
|
+
log.info("No supported MCP clients detected. Skipping MCP installation.");
|
|
289
|
+
await flushAnalytics();
|
|
290
|
+
return 1;
|
|
291
|
+
}
|
|
292
|
+
const results = await withProgress("adding mcp servers", () => addMCPServer(supportedClients, args.apiKey, args.features ?? [...ALL_FEATURE_VALUES], args.local ?? false));
|
|
293
|
+
const installed = namesWithStatus(results, "changed");
|
|
294
|
+
const already = namesWithStatus(results, "unchanged");
|
|
295
|
+
const failed = results.filter((r) => r.status === "failed");
|
|
296
|
+
if (installed.length > 0) log.success(`Added the MCP server to:\n${bulletList(installed)}`);
|
|
297
|
+
if (already.length > 0) log.info(`The PostHog MCP server was already installed, so nothing changed for:\n${bulletList(already)}`);
|
|
298
|
+
if (failed.length > 0) log.warn(`Couldn't add the MCP server to:\n${bulletList(failed.map((r) => r.detail ? `${r.name} — ${r.detail}` : r.name))}`);
|
|
299
|
+
const withServer = [...installed, ...already];
|
|
300
|
+
analytics.wizardCapture("mcp servers added", {
|
|
301
|
+
clients: withServer,
|
|
302
|
+
already_installed_clients: already,
|
|
303
|
+
failed_clients: failed.map((r) => r.name),
|
|
304
|
+
attempted_clients: supportedClients.map((c) => c.name)
|
|
305
|
+
});
|
|
306
|
+
await flushAnalytics();
|
|
307
|
+
return failed.length > 0 || withServer.length === 0 ? 1 : 0;
|
|
308
|
+
}
|
|
309
|
+
const bulletList = (items) => items.map((item) => ` - ${item}`).join("\n");
|
|
310
|
+
/** No exit code on an empty result: nothing to remove is the requested end state. */
|
|
311
|
+
async function removeMCPServerFromClientsStep(args, { log }) {
|
|
312
|
+
const { getInstalledClients, removeMCPServer } = await import("./install-Bw8tvDvS.js");
|
|
313
|
+
const local = args.local ?? false;
|
|
314
|
+
const installedClients = await getInstalledClients(local);
|
|
315
|
+
if (installedClients.length === 0) {
|
|
316
|
+
log.info("The PostHog MCP server is not installed for any supported client. Nothing to remove.");
|
|
317
|
+
analytics.wizardCapture("mcp no servers to remove", {});
|
|
318
|
+
await flushAnalytics();
|
|
319
|
+
return 0;
|
|
320
|
+
}
|
|
321
|
+
const results = await withProgress("removing mcp servers", () => removeMCPServer(installedClients, local));
|
|
322
|
+
const removed = namesWithStatus(results, "changed");
|
|
323
|
+
const nothingToDo = namesWithStatus(results, "unchanged");
|
|
324
|
+
const failed = results.filter((r) => r.status === "failed");
|
|
325
|
+
if (removed.length > 0) log.success(`Removed the MCP server from:\n${bulletList(removed)}`);
|
|
326
|
+
if (nothingToDo.length > 0) log.info(`No PostHog MCP entry left to remove for:\n${bulletList(nothingToDo)}`);
|
|
327
|
+
if (failed.length > 0) log.warn(`Couldn't remove the MCP server from:\n${bulletList(failed.map((r) => r.detail ? `${r.name} — ${r.detail}` : r.name))}`);
|
|
328
|
+
analytics.wizardCapture("mcp servers removed", {
|
|
329
|
+
clients: removed,
|
|
330
|
+
nothing_to_remove_clients: nothingToDo,
|
|
331
|
+
failed_clients: failed.map((r) => r.name),
|
|
332
|
+
attempted_clients: installedClients.map((c) => c.name)
|
|
333
|
+
});
|
|
334
|
+
await flushAnalytics();
|
|
335
|
+
return 0;
|
|
336
|
+
}
|
|
337
|
+
//#endregion
|
|
338
|
+
//#region src/tools/cli-steering/index.ts
|
|
339
|
+
/** Resolves 0 when the CLI and every snippet installed, else 1. */
|
|
340
|
+
async function runCliAdd(args, { log: ui }) {
|
|
341
|
+
ui.intro("PostHog CLI setup");
|
|
342
|
+
const files = await resolveTargetFiles(args, ui);
|
|
343
|
+
if (files.length === 0) return 1;
|
|
344
|
+
ui.log.info("Installing or updating PostHog CLI...");
|
|
345
|
+
const cliInstallResult = installOrUpdatePostHogCli();
|
|
346
|
+
if (!cliInstallResult.success) {
|
|
347
|
+
ui.log.error(`Failed to install or update PostHog CLI: ${cliInstallResult.error ?? ""}`);
|
|
348
|
+
analytics.wizardCapture("cli steering installed", {
|
|
349
|
+
files: files.length,
|
|
350
|
+
failures: files.length,
|
|
351
|
+
cli_install_failed: true,
|
|
352
|
+
agent: args.agent
|
|
353
|
+
});
|
|
354
|
+
return 1;
|
|
355
|
+
}
|
|
356
|
+
ui.log.success("Installed or updated PostHog CLI.");
|
|
357
|
+
let failures = 0;
|
|
358
|
+
for (const file of files) {
|
|
359
|
+
const result = installSteeringSnippet(file);
|
|
360
|
+
if (result.success) ui.log.success(`Installed PostHog steering instructions in ${file}`);
|
|
361
|
+
else {
|
|
362
|
+
failures += 1;
|
|
363
|
+
ui.log.error(`Failed to update ${file}: ${result.error ?? ""}`);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
analytics.wizardCapture("cli steering installed", {
|
|
367
|
+
files: files.length,
|
|
368
|
+
failures,
|
|
369
|
+
agent: args.agent
|
|
370
|
+
});
|
|
371
|
+
if (failures > 0) return 1;
|
|
372
|
+
ui.outro("Done. PostHog CLI is installed and your agent will now use `posthog-cli api` for PostHog tasks.");
|
|
373
|
+
return 0;
|
|
374
|
+
}
|
|
375
|
+
/** Resolve which instruction files to write, from flags, detection, or a prompt. */
|
|
376
|
+
async function resolveTargetFiles(args, ui) {
|
|
377
|
+
if (args.path?.trim()) return [path$1.resolve(args.path.trim())];
|
|
378
|
+
if (args.agent !== void 0) {
|
|
379
|
+
const target = findTarget(args.agent);
|
|
380
|
+
if (!target) {
|
|
381
|
+
ui.log.error(`Unsupported agent: ${args.agent}`);
|
|
382
|
+
return [];
|
|
383
|
+
}
|
|
384
|
+
return [target.instructionsPath()];
|
|
385
|
+
}
|
|
386
|
+
const detected = detectTargets();
|
|
387
|
+
if (detected.length === 0) {
|
|
388
|
+
ui.log.error("No supported coding agents detected. Pass --agent <id> or --path <file> to choose a target.");
|
|
389
|
+
ui.log.info(`Supported agents: ${CLI_STEERING_TARGETS.map((t) => t.id).join(", ")}`);
|
|
390
|
+
return [];
|
|
391
|
+
}
|
|
392
|
+
if (args.all === true) {
|
|
393
|
+
ui.log.info(`Installing for all detected agents: ${detected.map((t) => t.name).join(", ")}`);
|
|
394
|
+
return detected.map((target) => target.instructionsPath());
|
|
395
|
+
}
|
|
396
|
+
if (detected.length === 1) {
|
|
397
|
+
ui.log.info(`Detected ${detected[0].name} (${detected[0].instructionsPath()})`);
|
|
398
|
+
return [detected[0].instructionsPath()];
|
|
399
|
+
}
|
|
400
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
401
|
+
ui.log.info(`Installing for all detected agents: ${detected.map((t) => t.name).join(", ")}`);
|
|
402
|
+
return detected.map((target) => target.instructionsPath());
|
|
403
|
+
}
|
|
404
|
+
return (await promptForTargets(detected, ui)).map((target) => target.instructionsPath());
|
|
405
|
+
}
|
|
406
|
+
/** Minimal numbered selection — this command is intentionally not a TUI flow. */
|
|
407
|
+
async function promptForTargets(detected, ui) {
|
|
408
|
+
ui.log.info("Which coding agent are you using?");
|
|
409
|
+
detected.forEach((target, index) => {
|
|
410
|
+
ui.log.info(` ${index + 1}) ${target.name} (${target.instructionsPath()})`);
|
|
411
|
+
});
|
|
412
|
+
ui.log.info(` ${detected.length + 1}) All of the above`);
|
|
413
|
+
const rl = readline.createInterface({
|
|
414
|
+
input: process.stdin,
|
|
415
|
+
output: process.stdout
|
|
416
|
+
});
|
|
417
|
+
try {
|
|
418
|
+
for (;;) {
|
|
419
|
+
const answer = (await rl.question(`Select 1-${detected.length + 1}: `)).trim();
|
|
420
|
+
const choice = Number(answer);
|
|
421
|
+
if (Number.isInteger(choice) && choice >= 1 && choice <= detected.length) return [detected[choice - 1]];
|
|
422
|
+
if (choice === detected.length + 1) return detected;
|
|
423
|
+
ui.log.warn(`Enter a number between 1 and ${detected.length + 1}.`);
|
|
424
|
+
}
|
|
425
|
+
} finally {
|
|
426
|
+
rl.close();
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
//#endregion
|
|
430
|
+
//#region src/tools/provision/index.ts
|
|
431
|
+
/** Resolves 0 once the account exists, else 1. */
|
|
432
|
+
async function runProvision({ email, region, name, baseUrl, jsonMode }, { log }) {
|
|
433
|
+
try {
|
|
434
|
+
const { provisionNewAccount } = await import("./provisioning-BcXfeCMc.js");
|
|
435
|
+
if (!jsonMode) log.log.info(`Provisioning account for ${email} in ${region}...`);
|
|
436
|
+
emitResult(await provisionNewAccount(email, name, region, { baseUrl }), jsonMode, log);
|
|
437
|
+
return 0;
|
|
438
|
+
} catch (error) {
|
|
439
|
+
emitError(error, jsonMode, log);
|
|
440
|
+
return 1;
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
function emitResult(result, jsonMode, log) {
|
|
444
|
+
if (jsonMode) {
|
|
445
|
+
process.stdout.write(`${JSON.stringify(result)}\n`);
|
|
446
|
+
return;
|
|
447
|
+
}
|
|
448
|
+
log.log.success("Account provisioned successfully:");
|
|
449
|
+
log.log.info(` API Key: ${result.projectApiKey}`);
|
|
450
|
+
log.log.info(` Host: ${result.host}`);
|
|
451
|
+
log.log.info(` Project ID: ${result.projectId}`);
|
|
452
|
+
log.log.info(` Account ID: ${result.accountId}`);
|
|
453
|
+
log.log.info(` Access Token: ${result.accessToken}`);
|
|
454
|
+
log.log.info(` Refresh Token: ${result.refreshToken}`);
|
|
455
|
+
if (result.personalApiKey) log.log.info(` Personal API Key: ${result.personalApiKey}`);
|
|
456
|
+
}
|
|
457
|
+
function emitError(error, jsonMode, log) {
|
|
458
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
459
|
+
const code = msg.includes("already associated") ? "email_exists" : "provisioning_failed";
|
|
460
|
+
if (jsonMode) {
|
|
461
|
+
process.stderr.write(`${JSON.stringify({
|
|
462
|
+
error: msg,
|
|
463
|
+
code
|
|
464
|
+
})}\n`);
|
|
465
|
+
return;
|
|
466
|
+
}
|
|
467
|
+
log.log.error(`Provisioning failed: ${msg}`);
|
|
468
|
+
}
|
|
469
|
+
//#endregion
|
|
470
|
+
//#region src/tools/skill-list/index.ts
|
|
471
|
+
/**
|
|
472
|
+
* `wizard skill list` — fetch and print every browsable skill in the catalog.
|
|
473
|
+
*
|
|
474
|
+
* Reads the live `skill-menu.json` so new skills appear immediately after a
|
|
475
|
+
* context-mill release. `internal` skills are excluded from the listing.
|
|
476
|
+
*/
|
|
477
|
+
const BROWSABLE_ROLES = new Set(["command", "skill"]);
|
|
478
|
+
function formatEntry(entry) {
|
|
479
|
+
const path = entry.parentCommand ? `wizard ${entry.parentCommand} ${entry.command}` : entry.command ? `wizard ${entry.command}` : `wizard skill ${entry.skillId}`;
|
|
480
|
+
return ` ${entry.skillId.padEnd(38)} ${path.padEnd(36)} ${entry.description}`;
|
|
481
|
+
}
|
|
482
|
+
/** Resolves 0 once the list is printed, or 1 when the registry is unreachable. */
|
|
483
|
+
async function listSkills() {
|
|
484
|
+
const skillsBaseUrl = getSkillsBaseUrl();
|
|
485
|
+
const menu = await fetchSkillMenu(skillsBaseUrl);
|
|
486
|
+
if (!menu) {
|
|
487
|
+
analytics.wizardCapture("cli dispatch error", {
|
|
488
|
+
reason: "registry unreachable",
|
|
489
|
+
family: "skill",
|
|
490
|
+
sub: "list",
|
|
491
|
+
skillsBaseUrl
|
|
492
|
+
});
|
|
493
|
+
try {
|
|
494
|
+
await analytics.flush();
|
|
495
|
+
} catch {}
|
|
496
|
+
process.stderr.write("\n\x1B[1;91m✖ Couldn't reach the skill registry.\x1B[0m\n Check your network connection and try again.\n\n");
|
|
497
|
+
emitWizardError({
|
|
498
|
+
code: ErrorCodes.SkillMenuFetchFailed,
|
|
499
|
+
message: "Couldn't reach the skill registry."
|
|
500
|
+
});
|
|
501
|
+
return 1;
|
|
502
|
+
}
|
|
503
|
+
const entries = (menu.cliEntries ?? []).filter((e) => BROWSABLE_ROLES.has(e.role));
|
|
504
|
+
if (entries.length === 0) {
|
|
505
|
+
process.stdout.write("No skills found.\n");
|
|
506
|
+
return 0;
|
|
507
|
+
}
|
|
508
|
+
process.stdout.write(`${entries.length} skill${entries.length === 1 ? "" : "s"}:\n`);
|
|
509
|
+
process.stdout.write(` ${"SKILL ID".padEnd(38)} ${"COMMAND".padEnd(36)} DESCRIPTION\n`);
|
|
510
|
+
for (const entry of entries) process.stdout.write(`${formatEntry(entry)}\n`);
|
|
511
|
+
return 0;
|
|
512
|
+
}
|
|
513
|
+
//#endregion
|
|
514
|
+
//#region src/tools/index.ts
|
|
515
|
+
/**
|
|
516
|
+
* The tools' one entry. A tool is a command that does its job without an agent
|
|
517
|
+
* run, so it never goes through `runProgram`: the CLI runs its screens through
|
|
518
|
+
* the TUI's `runTuiTool`, or one of the console runners below. Every runner
|
|
519
|
+
* resolves an exit code and the CLI exits with it.
|
|
520
|
+
*/
|
|
521
|
+
/** The tools with screens, in no particular order; `getTool` finds one by id. */
|
|
522
|
+
const TOOL_REGISTRY = [
|
|
523
|
+
MCP_ADD,
|
|
524
|
+
MCP_REMOVE,
|
|
525
|
+
MCP_TUTORIAL,
|
|
526
|
+
SLACK,
|
|
527
|
+
DOCTOR
|
|
528
|
+
];
|
|
529
|
+
/** Typed tool names, from each config's `id`. */
|
|
530
|
+
const Tool = {
|
|
531
|
+
McpAdd: MCP_ADD.id,
|
|
532
|
+
McpRemove: MCP_REMOVE.id,
|
|
533
|
+
McpTutorial: MCP_TUTORIAL.id,
|
|
534
|
+
SlackConnect: SLACK.id,
|
|
535
|
+
PosthogDoctor: DOCTOR.id
|
|
536
|
+
};
|
|
537
|
+
/** The tool with this id, or undefined for a program's id. */
|
|
538
|
+
function getTool(id) {
|
|
539
|
+
return TOOL_REGISTRY.find((tool) => tool.id === id);
|
|
540
|
+
}
|
|
541
|
+
//#endregion
|
|
542
|
+
export { runCliAdd as a, flushAnalytics as c, runDoctorReport as d, getKindMeta as f, runProvision as i, MCP_TUTORIAL_SCOPE_ADDITIONS as l, getTool as n, addMCPServerToClientsStep as o, fetchHealthIssues as p, listSkills as r, removeMCPServerFromClientsStep as s, Tool as t, DOCTOR as u };
|
|
543
|
+
|
|
544
|
+
//# sourceMappingURL=tools-CCMV3DmB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools-CCMV3DmB.js","names":["path"],"sources":["../src/tools/mcp/index.ts","../src/tools/slack/index.ts","../src/tools/doctor/types.ts","../src/tools/doctor/fetch.ts","../src/tools/doctor/kind-metadata.ts","../src/tools/doctor/report.ts","../src/tools/doctor/index.ts","../src/tools/mcp/scopes.ts","../src/shared/utils/flush-analytics.ts","../src/tools/mcp/console.ts","../src/tools/cli-steering/index.ts","../src/tools/provision/index.ts","../src/tools/skill-list/index.ts","../src/tools/index.ts"],"sourcesContent":["/**\n * The MCP tools: `wizard mcp add`, `mcp remove` and `mcp tutorial`. None runs\n * a program. Their screens live in `src/tui/tools/mcp`; the tutorial's prompts\n * stream through the agent's `streamMcpPrompt`, and `console.ts` installs and\n * removes the server with no screens.\n */\n\nimport type { ToolConfig } from '../types';\n\nexport { streamMcpPrompt } from '@agent';\nexport type { McpPromptChunk } from '@agent/types';\n\nexport const MCP_ADD: ToolConfig = {\n id: 'mcp-add',\n command: 'add',\n parentCommand: 'mcp',\n description: 'Add PostHog MCP server to supported clients',\n};\n\nexport const MCP_REMOVE: ToolConfig = {\n id: 'mcp-remove',\n command: 'remove',\n parentCommand: 'mcp',\n description: 'Remove PostHog MCP server from supported clients',\n};\n\n/**\n * Standalone tutorial flow — boots directly into the Choose phase of\n * McpSuggestedPromptsScreen without going through MCP install first.\n * Useful for users who already installed MCP and want to revisit the\n * tutorial, or anyone who just wants to try the agent against PostHog\n * without touching their IDE config.\n *\n * The screen handles its own OAuth (via services.performLogin) so this\n * tool doesn't pre-populate credentials.\n */\nexport const MCP_TUTORIAL: ToolConfig = {\n id: 'mcp-tutorial',\n command: 'tutorial',\n parentCommand: 'mcp',\n description: 'Try the PostHog MCP with your agent — no install needed',\n};\n","/**\n * Slack connect tool — TUI-only flow invoked by `wizard slack`. One\n * step: the same Connect Slack screen the MCP flows end on. The screen\n * renders the no-creds nudge (marketing copy + \"Open Slack setup\" link);\n * we deliberately don't force OAuth here because connecting Slack itself\n * happens in the browser, so a wizard login adds nothing for the user.\n */\n\nimport type { ToolConfig } from '../types';\n\nexport const SLACK: ToolConfig = {\n id: 'slack',\n command: 'slack',\n description: 'Connect PostHog to your Slack',\n};\n","import { z } from 'zod';\n\nexport const HealthIssueSeveritySchema = z.enum([\n 'critical',\n 'warning',\n 'info',\n]);\nexport type HealthIssueSeverity = z.infer<typeof HealthIssueSeveritySchema>;\n\nexport const HealthIssueStatusSchema = z.enum(['active', 'resolved']);\n\nexport const HealthIssueSchema = z.object({\n id: z.string(),\n kind: z.string(),\n severity: HealthIssueSeveritySchema,\n status: HealthIssueStatusSchema,\n dismissed: z.boolean(),\n created_at: z.string(),\n updated_at: z.string(),\n resolved_at: z.string().nullable().optional(),\n});\nexport type HealthIssue = z.infer<typeof HealthIssueSchema>;\n\nexport const HealthIssueListResponseSchema = z.object({\n results: z.array(HealthIssueSchema),\n count: z.number().optional(),\n next: z.string().nullable().optional(),\n previous: z.string().nullable().optional(),\n});\nexport type HealthIssueListResponse = z.infer<\n typeof HealthIssueListResponseSchema\n>;\n\nexport interface HealthIssueSummary {\n total: number;\n by_severity: Record<HealthIssueSeverity, number>;\n}\n","import axios from 'axios';\nimport { analytics } from '@utils/analytics';\nimport { handleApiError } from '@shared/api';\nimport { WIZARD_USER_AGENT } from '@shared/constants';\nimport { HealthIssueListResponseSchema, type HealthIssue } from './types';\n\nexport async function fetchHealthIssues(\n accessToken: string,\n baseUrl: string,\n projectId: number,\n): Promise<HealthIssue[]> {\n const endpoint = `/api/environments/${projectId}/health_issues/`;\n const url = `${baseUrl}${endpoint}?status=active&dismissed=false&limit=250`;\n try {\n const response = await axios.get(url, {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n 'User-Agent': WIZARD_USER_AGENT,\n },\n });\n return HealthIssueListResponseSchema.parse(response.data).results;\n } catch (error) {\n const apiError = handleApiError(error, 'fetch health issues');\n analytics.captureException(apiError, { endpoint, baseUrl, projectId });\n throw apiError;\n }\n}\n","import { POSTHOG_DOCS_URL } from '@shared/constants';\n\nexport interface KindMeta {\n title: string;\n description: string;\n docsUrl: string;\n}\n\nexport const KIND_METADATA: Record<string, KindMeta> = {\n ingestion_lag: {\n title: 'Ingestion is delayed',\n description:\n 'Events are being received but are taking longer than usual to appear.',\n docsUrl: `${POSTHOG_DOCS_URL}/support/troubleshooting`,\n },\n ingestion_warning: {\n title: 'Ingestion warnings on recent events',\n description:\n 'Some recent events were rejected or flagged by the ingestion pipeline.',\n docsUrl: `${POSTHOG_DOCS_URL}/support/troubleshooting`,\n },\n sdk_outdated: {\n title: 'SDK version is out of date',\n description:\n 'One or more SDKs are running an old version. Upgrade to get the latest fixes.',\n docsUrl: `${POSTHOG_DOCS_URL}/libraries`,\n },\n no_live_events: {\n title: 'No $pageview or $screen events in the last 30 days',\n description:\n 'PostHog is not receiving page or screen events from this project.',\n docsUrl: `${POSTHOG_DOCS_URL}/getting-started/install`,\n },\n no_pageleave_events: {\n title: '$pageleave events not being sent',\n description:\n 'Enable pageleave tracking to power bounce rate and session duration.',\n docsUrl: `${POSTHOG_DOCS_URL}/libraries/js#config`,\n },\n scroll_depth: {\n title: 'Scroll depth tracking disabled',\n description:\n 'Turn on scroll depth to capture how far users read each page.',\n docsUrl: `${POSTHOG_DOCS_URL}/libraries/js#config`,\n },\n authorized_urls: {\n title: 'No authorized URLs configured',\n description:\n 'Some web analytics filters require at least one authorized URL to work.',\n docsUrl: `${POSTHOG_DOCS_URL}/web-analytics/faq`,\n },\n reverse_proxy: {\n title: 'No reverse proxy detected',\n description: 'A reverse proxy reduces data loss from ad blockers.',\n docsUrl: `${POSTHOG_DOCS_URL}/advanced/proxy`,\n },\n web_vitals: {\n title: 'Web Vitals tracking disabled',\n description:\n 'Enable Web Vitals to capture LCP, CLS and other performance metrics.',\n docsUrl: `${POSTHOG_DOCS_URL}/web-analytics/web-vitals`,\n },\n materialized_view_failure: {\n title: 'A materialized view is failing',\n description: 'A data modeling pipeline failed its most recent run.',\n docsUrl: `${POSTHOG_DOCS_URL}/data-warehouse`,\n },\n external_data_failure: {\n title: 'External data source is failing',\n description: 'An external data source sync failed and data may be stale.',\n docsUrl: `${POSTHOG_DOCS_URL}/data-warehouse/sources`,\n },\n};\n\nexport const UNKNOWN_KIND_META: KindMeta = {\n title: 'Unknown issue',\n description:\n 'PostHog reported an issue kind the wizard does not yet recognize.',\n docsUrl: POSTHOG_DOCS_URL,\n};\n\nexport function getKindMeta(kind: string): KindMeta {\n return KIND_METADATA[kind] ?? { ...UNKNOWN_KIND_META, title: kind };\n}\n","import type { ConsoleLog } from '@shared/console-log';\nimport { ErrorCodes, emitWizardError } from '@shared/errors';\nimport { fetchHealthIssues } from './fetch';\nimport { getKindMeta } from './kind-metadata';\n\nconst SEVERITY_ORDER = { critical: 0, warning: 1, info: 2 } as const;\n\n/** Resolves 0 when the project is healthy, and 1 on issues, a missing key or a failed fetch. */\nexport async function runDoctorReport(\n {\n apiKey,\n projectId,\n baseUrl,\n }: { apiKey?: string; projectId?: number; baseUrl?: string },\n { log }: { log: ConsoleLog },\n): Promise<number> {\n if (!apiKey) {\n log.intro('PostHog Wizard');\n log.log.error('CI mode requires --api-key (personal API key phx_xxx)');\n emitWizardError({\n code: ErrorCodes.ArgsMissingApiKey,\n message: 'CI mode requires --api-key (personal API key phx_xxx)',\n });\n return 1;\n }\n\n log.intro('Welcome to the PostHog setup wizard');\n log.log.info('Running posthog-doctor in CI mode');\n\n try {\n const { resolveApiKeyProject } = await import('@shared/api-key-login');\n const { host, projectId: resolvedProjectId } = await resolveApiKeyProject(\n apiKey,\n {\n projectId,\n baseUrl,\n onInfo: (message) => log.log.info(message),\n onWarning: (message) => log.log.warn(message),\n },\n );\n\n const issues = await fetchHealthIssues(\n apiKey,\n host.apiHost,\n resolvedProjectId,\n );\n if (issues.length === 0) {\n log.log.success('No active issues — your project looks healthy.');\n return 0;\n }\n\n const sorted = [...issues].sort(\n (a, b) => SEVERITY_ORDER[a.severity] - SEVERITY_ORDER[b.severity],\n );\n log.log.warn(\n `${issues.length} active issue${issues.length === 1 ? '' : 's'} found:`,\n );\n for (const issue of sorted) {\n log.log.info(` • [${issue.severity}] ${getKindMeta(issue.kind).title}`);\n }\n return 1;\n } catch (error) {\n const { ApiError } = await import('@shared/api');\n const message =\n error instanceof ApiError && error.statusCode === 401\n ? 'Your PostHog API key is invalid or expired.'\n : error instanceof Error\n ? error.message\n : String(error);\n log.log.error(`Doctor failed: ${message}`);\n emitWizardError({\n code:\n error instanceof ApiError && error.statusCode === 401\n ? ErrorCodes.AuthInvalidOrExpired\n : ErrorCodes.InternalUnhandled,\n message,\n });\n return 1;\n }\n}\n","/**\n * `wizard doctor`: the project's active health issues. Its screens live in\n * `src/tui/tools/doctor`; `report.ts` prints them for `--ci`.\n */\n\nimport type { ToolConfig } from '../types';\n\nexport const DOCTOR: ToolConfig = {\n id: 'posthog-doctor',\n command: 'doctor',\n description: 'Diagnose your PostHog project setup',\n};\n\nexport { fetchHealthIssues } from './fetch';\nexport { getKindMeta } from './kind-metadata';\nexport type { HealthIssue, HealthIssueSeverity } from './types';\nexport { runDoctorReport } from './report';\n","/**\n * Extra scopes the MCP tutorial needs on top of `WIZARD_OAUTH_SCOPES`.\n *\n * Every scope requested here must stay within the wizard OAuth app's\n * ceiling on the PostHog side (`OAuthApplication.scopes`) — the full\n * list lives in the README under \"OAuth app scope ceiling\". The\n * tutorial's prompts and follow-ups touch most of the read surface,\n * plus annotation write for the \"PostHog wizard install\" verify-prompt.\n *\n * Already in the base `WIZARD_OAUTH_SCOPES` (and therefore not\n * repeated here):\n * • user:read, project:read, llm_gateway:read — auth + gateway\n * • query:read — HogQL\n * • dashboard:write, insight:write, notebook:write — Phase-5 persist\n *\n * Deliberately omitted (writes on read-only product surfaces):\n * • feature_flag:write, experiment:write, survey:write,\n * cohort:write, session_recording:write, error_tracking:write,\n * alert:write, subscription:write\n */\nexport const MCP_TUTORIAL_SCOPE_ADDITIONS = [\n // Explicit reads on the persistence surfaces. `*:write` usually\n // implies read on PostHog, but the consent flow grants exactly the\n // strings requested — explicit reads avoid a 403 when the agent\n // lists existing dashboards/insights/notebooks before saving.\n 'dashboard:read',\n 'insight:read',\n 'notebook:read',\n\n // Read on every product surface the tutorial demos.\n 'feature_flag:read',\n 'experiment:read',\n 'experiment_saved_metric:read',\n 'survey:read',\n 'session_recording:read',\n 'error_tracking:read',\n 'web_analytics:read',\n 'llm_analytics:read',\n 'cohort:read',\n 'person:read',\n\n // Annotation read + write — the verify prompt's \"annotate today\"\n // is the only mutation the tutorial performs outside the\n // dashboard/insight/notebook persistence triplet.\n 'annotation:read',\n 'annotation:write',\n\n // Metadata / exploration reads — for \"break down by user property\",\n // \"did that change land alongside a deploy\", autocapture actions,\n // etc. Otherwise the agent 403s on the supporting catalog calls\n // even though the parent query has `query:read`.\n 'activity_log:read',\n 'property_definition:read',\n 'event_definition:read',\n 'action:read',\n\n // Data warehouse reads — for the data-role cross-sells that join\n // event data with Stripe / Salesforce / S3.\n 'warehouse_table:read',\n 'warehouse_view:read',\n\n // Inspection-only — we don't write alerts or subscriptions, but the\n // model might want to read existing ones (e.g. \"is there already an\n // alert on this metric?\").\n 'alert:read',\n 'subscription:read',\n 'integration:read',\n] as const;\n","import { analytics } from './analytics';\n\n/** Deliver the pending analytics events before the process exits; a failed flush never changes the outcome. */\nexport async function flushAnalytics(): Promise<void> {\n try {\n await analytics.flush();\n } catch {\n // best-effort\n }\n}\n","/** `mcp add` and `mcp remove` with no screens: install to, or remove from, every detected client and print the outcome. */\n\nimport type { ConsoleLog } from '@shared/console-log';\nimport { ALL_FEATURE_VALUES } from '@shared/mcp-clients/defaults';\nimport { McpClientStatus, namesWithStatus } from '@shared/mcp-clients/results';\nimport { analytics } from '@utils/analytics';\nimport { flushAnalytics } from '@utils/flush-analytics';\nimport { withProgress } from '@utils/telemetry';\n\n/**\n * A scripted caller has no screen to read, so this has to be an exit code.\n * Any failure counts, not just a total wipeout: the step installs to every\n * detected client, so one succeeding would otherwise mask the rest.\n */\nexport async function addMCPServerToClientsStep(\n args: { local?: boolean; features?: string[]; apiKey?: string },\n { log }: { log: ConsoleLog['log'] },\n): Promise<number> {\n const { addMCPServer, getSupportedClients } = await import(\n '@shared/mcp-clients/install'\n );\n const supportedClients = await getSupportedClients();\n\n if (supportedClients.length === 0) {\n log.info('No supported MCP clients detected. Skipping MCP installation.');\n await flushAnalytics();\n return 1;\n }\n\n const results = await withProgress('adding mcp servers', () =>\n addMCPServer(\n supportedClients,\n args.apiKey,\n args.features ?? [...ALL_FEATURE_VALUES],\n args.local ?? false,\n ),\n );\n\n const installed = namesWithStatus(results, McpClientStatus.Changed);\n const already = namesWithStatus(results, McpClientStatus.Unchanged);\n const failed = results.filter((r) => r.status === McpClientStatus.Failed);\n\n // Report each outcome on its own — a blanket \"Added the MCP server to: ...\"\n // hid both the no-op re-runs and the outright failures.\n if (installed.length > 0) {\n log.success(`Added the MCP server to:\\n${bulletList(installed)}`);\n }\n if (already.length > 0) {\n log.info(\n `The PostHog MCP server was already installed, so nothing changed for:\\n${bulletList(\n already,\n )}`,\n );\n }\n if (failed.length > 0) {\n log.warn(\n `Couldn't add the MCP server to:\\n${bulletList(\n failed.map((r) => (r.detail ? `${r.name} — ${r.detail}` : r.name)),\n )}`,\n );\n }\n\n const withServer = [...installed, ...already];\n\n analytics.wizardCapture('mcp servers added', {\n // `clients` stays \"every client that ended up with the MCP server\", which is\n // what it meant before — the new properties break that down.\n clients: withServer,\n already_installed_clients: already,\n failed_clients: failed.map((r) => r.name),\n attempted_clients: supportedClients.map((c) => c.name),\n });\n await flushAnalytics();\n return failed.length > 0 || withServer.length === 0 ? 1 : 0;\n}\n\nconst bulletList = (items: string[]): string =>\n items.map((item) => ` - ${item}`).join('\\n');\n\n/** No exit code on an empty result: nothing to remove is the requested end state. */\nexport async function removeMCPServerFromClientsStep(\n args: { local?: boolean },\n { log }: { log: ConsoleLog['log'] },\n): Promise<number> {\n const { getInstalledClients, removeMCPServer } = await import(\n '@shared/mcp-clients/install'\n );\n const local = args.local ?? false;\n const installedClients = await getInstalledClients(local);\n if (installedClients.length === 0) {\n log.info(\n 'The PostHog MCP server is not installed for any supported client. Nothing to remove.',\n );\n analytics.wizardCapture('mcp no servers to remove', {});\n await flushAnalytics();\n return 0;\n }\n\n const results = await withProgress('removing mcp servers', () =>\n removeMCPServer(installedClients, local),\n );\n\n const removed = namesWithStatus(results, McpClientStatus.Changed);\n const nothingToDo = namesWithStatus(results, McpClientStatus.Unchanged);\n const failed = results.filter((r) => r.status === McpClientStatus.Failed);\n\n // This step used to print nothing at all, so a non-TTY `mcp remove` gave no\n // hint whether anything happened — let alone whether a client failed.\n if (removed.length > 0) {\n log.success(`Removed the MCP server from:\\n${bulletList(removed)}`);\n }\n if (nothingToDo.length > 0) {\n log.info(\n `No PostHog MCP entry left to remove for:\\n${bulletList(nothingToDo)}`,\n );\n }\n if (failed.length > 0) {\n log.warn(\n `Couldn't remove the MCP server from:\\n${bulletList(\n failed.map((r) => (r.detail ? `${r.name} — ${r.detail}` : r.name)),\n )}`,\n );\n }\n\n analytics.wizardCapture('mcp servers removed', {\n clients: removed,\n nothing_to_remove_clients: nothingToDo,\n failed_clients: failed.map((r) => r.name),\n attempted_clients: installedClients.map((c) => c.name),\n });\n await flushAnalytics();\n return 0;\n}\n","import * as path from 'node:path';\nimport * as readline from 'node:readline/promises';\nimport type { ConsoleLog } from '@shared/console-log';\nimport {\n CLI_STEERING_TARGETS,\n type CliSteeringTarget,\n detectTargets,\n findTarget,\n installOrUpdatePostHogCli,\n installSteeringSnippet,\n} from '@shared/install-cli-steering';\nimport { analytics } from '@utils/analytics';\n\nexport type CliAddArgs = { agent?: string; path?: string; all?: boolean };\n\n/** Resolves 0 when the CLI and every snippet installed, else 1. */\nexport async function runCliAdd(\n args: CliAddArgs,\n { log: ui }: { log: ConsoleLog },\n): Promise<number> {\n ui.intro('PostHog CLI setup');\n\n const files = await resolveTargetFiles(args, ui);\n if (files.length === 0) return 1;\n\n ui.log.info('Installing or updating PostHog CLI...');\n const cliInstallResult = installOrUpdatePostHogCli();\n if (!cliInstallResult.success) {\n ui.log.error(\n `Failed to install or update PostHog CLI: ${\n cliInstallResult.error ?? ''\n }`,\n );\n analytics.wizardCapture('cli steering installed', {\n files: files.length,\n failures: files.length,\n cli_install_failed: true,\n agent: args.agent,\n });\n return 1;\n }\n ui.log.success('Installed or updated PostHog CLI.');\n\n let failures = 0;\n for (const file of files) {\n const result = installSteeringSnippet(file);\n if (result.success) {\n ui.log.success(`Installed PostHog steering instructions in ${file}`);\n } else {\n failures += 1;\n ui.log.error(`Failed to update ${file}: ${result.error ?? ''}`);\n }\n }\n\n analytics.wizardCapture('cli steering installed', {\n files: files.length,\n failures,\n agent: args.agent,\n });\n\n if (failures > 0) return 1;\n ui.outro(\n 'Done. PostHog CLI is installed and your agent will now use `posthog-cli api` for PostHog tasks.',\n );\n return 0;\n}\n\n/** Resolve which instruction files to write, from flags, detection, or a prompt. */\nasync function resolveTargetFiles(\n args: CliAddArgs,\n ui: ConsoleLog,\n): Promise<string[]> {\n if (args.path?.trim()) {\n return [path.resolve(args.path.trim())];\n }\n\n if (args.agent !== undefined) {\n // yargs `choices` already rejected unknown ids.\n const target = findTarget(args.agent);\n if (!target) {\n ui.log.error(`Unsupported agent: ${args.agent}`);\n return [];\n }\n return [target.instructionsPath()];\n }\n\n const detected = detectTargets();\n if (detected.length === 0) {\n ui.log.error(\n 'No supported coding agents detected. Pass --agent <id> or --path <file> to choose a target.',\n );\n ui.log.info(\n `Supported agents: ${CLI_STEERING_TARGETS.map((t) => t.id).join(', ')}`,\n );\n return [];\n }\n\n if (args.all === true) {\n ui.log.info(\n `Installing for all detected agents: ${detected\n .map((t) => t.name)\n .join(', ')}`,\n );\n return detected.map((target) => target.instructionsPath());\n }\n\n if (detected.length === 1) {\n ui.log.info(\n `Detected ${detected[0].name} (${detected[0].instructionsPath()})`,\n );\n return [detected[0].instructionsPath()];\n }\n\n // Non-interactive shells can't pick, so install for every detected agent —\n // the snippet is additive and idempotent, mirroring how MCP install treats\n // all supported clients.\n if (!process.stdin.isTTY || !process.stdout.isTTY) {\n ui.log.info(\n `Installing for all detected agents: ${detected\n .map((t) => t.name)\n .join(', ')}`,\n );\n return detected.map((target) => target.instructionsPath());\n }\n\n const selected = await promptForTargets(detected, ui);\n return selected.map((target) => target.instructionsPath());\n}\n\n/** Minimal numbered selection — this command is intentionally not a TUI flow. */\nasync function promptForTargets(\n detected: CliSteeringTarget[],\n ui: ConsoleLog,\n): Promise<CliSteeringTarget[]> {\n ui.log.info('Which coding agent are you using?');\n detected.forEach((target, index) => {\n ui.log.info(\n ` ${index + 1}) ${target.name} (${target.instructionsPath()})`,\n );\n });\n ui.log.info(` ${detected.length + 1}) All of the above`);\n\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n try {\n for (;;) {\n const answer = (\n await rl.question(`Select 1-${detected.length + 1}: `)\n ).trim();\n const choice = Number(answer);\n if (\n Number.isInteger(choice) &&\n choice >= 1 &&\n choice <= detected.length\n ) {\n return [detected[choice - 1]];\n }\n if (choice === detected.length + 1) {\n return detected;\n }\n ui.log.warn(`Enter a number between 1 and ${detected.length + 1}.`);\n }\n } finally {\n rl.close();\n }\n}\n","import type { ConsoleLog } from '@shared/console-log';\nimport type { ProvisioningResult } from '@utils/provisioning';\n\nexport type ProvisionArgs = {\n email: string;\n region: 'US' | 'EU';\n name: string;\n baseUrl?: string;\n jsonMode: boolean;\n};\n\n/** Resolves 0 once the account exists, else 1. */\nexport async function runProvision(\n { email, region, name, baseUrl, jsonMode }: ProvisionArgs,\n { log }: { log: ConsoleLog },\n): Promise<number> {\n try {\n const { provisionNewAccount } = await import('@utils/provisioning');\n if (!jsonMode) {\n log.log.info(`Provisioning account for ${email} in ${region}...`);\n }\n const result = await provisionNewAccount(email, name, region, { baseUrl });\n emitResult(result, jsonMode, log);\n return 0;\n } catch (error) {\n emitError(error, jsonMode, log);\n return 1;\n }\n}\n\nfunction emitResult(\n result: ProvisioningResult,\n jsonMode: boolean,\n log: ConsoleLog,\n): void {\n if (jsonMode) {\n process.stdout.write(`${JSON.stringify(result)}\\n`);\n return;\n }\n log.log.success('Account provisioned successfully:');\n log.log.info(` API Key: ${result.projectApiKey}`);\n log.log.info(` Host: ${result.host}`);\n log.log.info(` Project ID: ${result.projectId}`);\n log.log.info(` Account ID: ${result.accountId}`);\n log.log.info(` Access Token: ${result.accessToken}`);\n log.log.info(` Refresh Token: ${result.refreshToken}`);\n if (result.personalApiKey) {\n log.log.info(` Personal API Key: ${result.personalApiKey}`);\n }\n}\n\nfunction emitError(error: unknown, jsonMode: boolean, log: ConsoleLog): void {\n const msg = error instanceof Error ? error.message : String(error);\n const code = msg.includes('already associated')\n ? 'email_exists'\n : 'provisioning_failed';\n if (jsonMode) {\n process.stderr.write(`${JSON.stringify({ error: msg, code })}\\n`);\n return;\n }\n log.log.error(`Provisioning failed: ${msg}`);\n}\n","/**\n * `wizard skill list` — fetch and print every browsable skill in the catalog.\n *\n * Reads the live `skill-menu.json` so new skills appear immediately after a\n * context-mill release. `internal` skills are excluded from the listing.\n */\n\nimport { getSkillsBaseUrl } from '@shared/constants';\nimport { ErrorCodes, emitWizardError } from '@shared/errors';\nimport { fetchSkillMenu, type CliEntry } from '@shared/skill-menu';\nimport { analytics } from '@utils/analytics';\n\nconst BROWSABLE_ROLES: ReadonlySet<CliEntry['role']> = new Set([\n 'command',\n 'skill',\n]);\n\nfunction formatEntry(entry: CliEntry): string {\n const path = entry.parentCommand\n ? `wizard ${entry.parentCommand} ${entry.command}`\n : entry.command\n ? `wizard ${entry.command}`\n : `wizard skill ${entry.skillId}`;\n return ` ${entry.skillId.padEnd(38)} ${path.padEnd(36)} ${\n entry.description\n }`;\n}\n\n/** Resolves 0 once the list is printed, or 1 when the registry is unreachable. */\nexport async function listSkills(): Promise<number> {\n const skillsBaseUrl = getSkillsBaseUrl();\n const menu = await fetchSkillMenu(skillsBaseUrl);\n if (!menu) {\n analytics.wizardCapture('cli dispatch error', {\n reason: 'registry unreachable',\n family: 'skill',\n sub: 'list',\n skillsBaseUrl,\n });\n try {\n await analytics.flush();\n } catch {\n /* best-effort */\n }\n process.stderr.write(\n `\\n\\x1b[1;91m✖ Couldn't reach the skill registry.\\x1b[0m\\n` +\n ` Check your network connection and try again.\\n\\n`,\n );\n emitWizardError({\n code: ErrorCodes.SkillMenuFetchFailed,\n message: \"Couldn't reach the skill registry.\",\n });\n return 1;\n }\n const entries = (menu.cliEntries ?? []).filter((e) =>\n BROWSABLE_ROLES.has(e.role),\n );\n if (entries.length === 0) {\n process.stdout.write('No skills found.\\n');\n return 0;\n }\n process.stdout.write(\n `${entries.length} skill${entries.length === 1 ? '' : 's'}:\\n`,\n );\n process.stdout.write(\n ` ${'SKILL ID'.padEnd(38)} ${'COMMAND'.padEnd(36)} DESCRIPTION\\n`,\n );\n for (const entry of entries) {\n process.stdout.write(`${formatEntry(entry)}\\n`);\n }\n return 0;\n}\n","/**\n * The tools' one entry. A tool is a command that does its job without an agent\n * run, so it never goes through `runProgram`: the CLI runs its screens through\n * the TUI's `runTuiTool`, or one of the console runners below. Every runner\n * resolves an exit code and the CLI exits with it.\n */\nimport { MCP_ADD, MCP_REMOVE, MCP_TUTORIAL } from './mcp';\nimport { SLACK } from './slack';\nimport { DOCTOR } from './doctor';\nimport type { ToolConfig, ToolId } from './types';\n\nexport type { ToolId };\n/** `wizard doctor`'s config: its help line is the command's. */\nexport { DOCTOR };\n\n/** The tools with screens, in no particular order; `getTool` finds one by id. */\nexport const TOOL_REGISTRY: readonly ToolConfig[] = [\n MCP_ADD,\n MCP_REMOVE,\n MCP_TUTORIAL,\n SLACK,\n DOCTOR,\n];\n\n/** Typed tool names, from each config's `id`. */\nexport const Tool = {\n McpAdd: MCP_ADD.id,\n McpRemove: MCP_REMOVE.id,\n McpTutorial: MCP_TUTORIAL.id,\n SlackConnect: SLACK.id,\n PosthogDoctor: DOCTOR.id,\n} as const;\n\n/** The tool with this id, or undefined for a program's id. */\nexport function getTool(id: string): ToolConfig | undefined {\n return TOOL_REGISTRY.find((tool) => tool.id === id);\n}\n\nexport { streamMcpPrompt, type McpPromptChunk } from './mcp';\nexport { MCP_TUTORIAL_SCOPE_ADDITIONS } from './mcp/scopes';\nexport {\n addMCPServerToClientsStep,\n removeMCPServerFromClientsStep,\n} from './mcp/console';\nexport {\n fetchHealthIssues,\n getKindMeta,\n runDoctorReport,\n type HealthIssue,\n type HealthIssueSeverity,\n} from './doctor';\nexport { runCliAdd } from './cli-steering';\nexport { runProvision } from './provision';\nexport { listSkills } from './skill-list';\n"],"mappings":"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"}
|