@posthog/wizard 2.81.1 → 2.82.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/dist/{agent-interface-DMP3DZRd.js → agent-interface-3YfIWZmY.js} +211 -46
- package/dist/agent-interface-3YfIWZmY.js.map +1 -0
- package/dist/{agent-prompt-loader-BrivWIna.js → agent-prompt-loader-hOHONY7u.js} +6 -6
- package/dist/{agent-prompt-loader-BrivWIna.js.map → agent-prompt-loader-hOHONY7u.js.map} +1 -1
- package/dist/{analytics-X7JfAmh6.js → analytics-B_xFshPY.js} +4 -3
- package/dist/analytics-B_xFshPY.js.map +1 -0
- package/dist/analytics-DGDr6-iD.js +2 -0
- package/dist/{api-BkDwZoL4.js → api-C_9KsN-7.js} +71 -3
- package/dist/{api-BkDwZoL4.js.map → api-C_9KsN-7.js.map} +1 -1
- package/dist/api-DhLSO3ai.js +2 -0
- package/dist/api-key-login-DiRuZ8Lm.js +2 -0
- package/dist/{api-key-login-DE0yKkP4.js → api-key-login-oUJQDmOV.js} +5 -5
- package/dist/{api-key-login-DE0yKkP4.js.map → api-key-login-oUJQDmOV.js.map} +1 -1
- package/dist/bin.js +1 -1
- package/dist/{bounded-fs-iDiqDQ9v.js → bounded-fs-iRaQcKYL.js} +6 -4
- package/dist/bounded-fs-iRaQcKYL.js.map +1 -0
- package/dist/{ci-install-BAftKh2Z.js → ci-install-BGlijoTo.js} +4 -4
- package/dist/{ci-install-BAftKh2Z.js.map → ci-install-BGlijoTo.js.map} +1 -1
- package/dist/{debug-C3tLP-ZW.js → debug-BvEbemym.js} +3 -3
- package/dist/{debug-C3tLP-ZW.js.map → debug-BvEbemym.js.map} +1 -1
- package/dist/{gateway-IQjQ582o.js → gateway-CWoYlPz7.js} +5 -5
- package/dist/{gateway-IQjQ582o.js.map → gateway-CWoYlPz7.js.map} +1 -1
- package/dist/{headless-DOhxEmw5.js → headless-Bfi950Qh.js} +2 -2
- package/dist/{headless-DOhxEmw5.js.map → headless-Bfi950Qh.js.map} +1 -1
- package/dist/{headless-XNvdWVEp.js → headless-Gisv3faN.js} +1 -1
- package/dist/{host-resolution-DI2oucSK.js → host-resolution-BxnNn8Jm.js} +4 -4
- package/dist/{host-resolution-DI2oucSK.js.map → host-resolution-BxnNn8Jm.js.map} +1 -1
- package/dist/{install-BixbBDLR.js → install-CDVeUT_5.js} +5 -5
- package/dist/{install-BixbBDLR.js.map → install-CDVeUT_5.js.map} +1 -1
- package/dist/{install-DaZ6pvEl.js → install-CX65IxGa.js} +1 -1
- package/dist/{interactive-WLNQWF0D.js → interactive-5-Numwwb.js} +3 -3
- package/dist/{interactive-WLNQWF0D.js.map → interactive-5-Numwwb.js.map} +1 -1
- package/dist/{links-Bye4fsrj.js → links-Dmj3Wj9X.js} +3 -3
- package/dist/{links-Bye4fsrj.js.map → links-Dmj3Wj9X.js.map} +1 -1
- package/dist/{main-CN8nbuZO.js → main-5KNn80Vt.js} +20 -20
- package/dist/{main-CN8nbuZO.js.map → main-5KNn80Vt.js.map} +1 -1
- package/dist/{mcp-B2o4d9DS.js → mcp-Buf9sfFm.js} +3 -3
- package/dist/{mcp-B2o4d9DS.js.map → mcp-Buf9sfFm.js.map} +1 -1
- package/dist/{mcp-prompt-streaming-COs1DfAm.js → mcp-prompt-streaming-DHPxJK-F.js} +5 -5
- package/dist/{mcp-prompt-streaming-COs1DfAm.js.map → mcp-prompt-streaming-DHPxJK-F.js.map} +1 -1
- package/dist/{models-Cow22jET.js → models-C9rjXPZ6.js} +2 -2
- package/dist/{models-Cow22jET.js.map → models-C9rjXPZ6.js.map} +1 -1
- package/dist/{oauth-session-Bj_-BY7o.js → oauth-session-Bi1MLRCC.js} +45 -3
- package/dist/oauth-session-Bi1MLRCC.js.map +1 -0
- package/dist/{orchestrator-tools-lhFIBGnp.js → orchestrator-tools-DyKws92o.js} +3 -3
- package/dist/{orchestrator-tools-lhFIBGnp.js.map → orchestrator-tools-DyKws92o.js.map} +1 -1
- package/dist/{package-manager-DZ4wcTz3.js → package-manager-DpCdmMmB.js} +4 -4
- package/dist/{package-manager-DZ4wcTz3.js.map → package-manager-DpCdmMmB.js.map} +1 -1
- package/dist/{pi-DREdQRPP.js → pi-DTj1hsJe.js} +32 -15
- package/dist/pi-DTj1hsJe.js.map +1 -0
- package/dist/{playground-CJx3lwTH.js → playground-CiH6zZPb.js} +4 -4
- package/dist/{playground-CJx3lwTH.js.map → playground-CiH6zZPb.js.map} +1 -1
- package/dist/{posthog-integration-DDSPdbpw.js → posthog-integration-CpinLWNO.js} +78 -35
- package/dist/posthog-integration-CpinLWNO.js.map +1 -0
- package/dist/{programs-6SFfUBmm.js → programs-Bq9Ju9xk.js} +28 -23
- package/dist/programs-Bq9Ju9xk.js.map +1 -0
- package/dist/programs-CnOSdQo1.js +3 -0
- package/dist/{provisioning-tRDPH7EQ.js → provisioning-D-AM_7DG.js} +4 -4
- package/dist/{provisioning-tRDPH7EQ.js.map → provisioning-D-AM_7DG.js.map} +1 -1
- package/dist/provisioning-D6Cqbc36.js +2 -0
- package/dist/{queue-tools-DrJKvFHZ.js → queue-tools-BoIITT7w.js} +4 -4
- package/dist/{queue-tools-DrJKvFHZ.js.map → queue-tools-BoIITT7w.js.map} +1 -1
- package/dist/{results-Crcubw0Q.js → results-CDqlHogZ.js} +2 -2
- package/dist/{results-Crcubw0Q.js.map → results-CDqlHogZ.js.map} +1 -1
- package/dist/{run-BrIGaPy7.js → run-CfMArkpV.js} +7 -7
- package/dist/{run-BrIGaPy7.js.map → run-CfMArkpV.js.map} +1 -1
- package/dist/{run-DVFTMbxf.js → run-DcaVJSeI.js} +10 -10
- package/dist/{run-DVFTMbxf.js.map → run-DcaVJSeI.js.map} +1 -1
- package/dist/{run-tool-CxdPXmlY.js → run-tool-DJZWnnR9.js} +13 -13
- package/dist/{run-tool-CxdPXmlY.js.map → run-tool-DJZWnnR9.js.map} +1 -1
- package/dist/run-tool-zMLQroVh.js +2 -0
- package/dist/{runners-loOOmHyc.js → runners-Cvnk9BcA.js} +8 -8
- package/dist/{runners-loOOmHyc.js.map → runners-Cvnk9BcA.js.map} +1 -1
- package/dist/{security-C_grSgIM.js → security-Cz3a-d7r.js} +5 -5
- package/dist/{security-C_grSgIM.js.map → security-Cz3a-d7r.js.map} +1 -1
- package/dist/{setup-utils-BYXbb9NM.js → setup-utils-C7kaDP5X.js} +3 -3
- package/dist/{setup-utils-BYXbb9NM.js.map → setup-utils-C7kaDP5X.js.map} +1 -1
- package/dist/{start-playground-Blh0Swil.js → start-playground-B62_pYfu.js} +7 -7
- package/dist/{start-playground-Blh0Swil.js.map → start-playground-B62_pYfu.js.map} +1 -1
- package/dist/{subagent-DQ_enM8C.js → subagent-BBfETG17.js} +3 -3
- package/dist/{subagent-DQ_enM8C.js.map → subagent-BBfETG17.js.map} +1 -1
- package/dist/{task-Dm9wZbVW.js → task-CmNe3xeg.js} +28 -16
- package/dist/task-CmNe3xeg.js.map +1 -0
- package/dist/{telemetry-NeZhrBeW.js → telemetry-DKM7VGuJ.js} +2 -2
- package/dist/{telemetry-NeZhrBeW.js.map → telemetry-DKM7VGuJ.js.map} +1 -1
- package/dist/{terminal-Z4hCXfie.js → terminal-Bkxwzkhn.js} +22 -23
- package/dist/terminal-Bkxwzkhn.js.map +1 -0
- package/dist/{tools-1aM6bI9Y.js → tools-Bm0FDT6f.js} +15 -11
- package/dist/tools-Bm0FDT6f.js.map +1 -0
- package/dist/{tools-dUJHRo6X.js → tools-DZCEvDv9.js} +13 -13
- package/dist/{tools-dUJHRo6X.js.map → tools-DZCEvDv9.js.map} +1 -1
- package/dist/{tui-Cmi_ckGg.js → tui-B56jvkbi.js} +4 -4
- package/dist/{tui-Cmi_ckGg.js.map → tui-B56jvkbi.js.map} +1 -1
- package/dist/{tui-CCO7VVTA.js → tui-tKI95MSr.js} +1 -1
- package/dist/{upload-step-e2Jp2fcr.js → upload-step-DqTgn6UB.js} +3 -3
- package/dist/{upload-step-e2Jp2fcr.js.map → upload-step-DqTgn6UB.js.map} +1 -1
- package/dist/{urls-Cu4RO30x.js → urls-B82v7gfO.js} +2 -2
- package/dist/{urls-Cu4RO30x.js.map → urls-B82v7gfO.js.map} +1 -1
- package/dist/{wizard-abort-BPEiPCXk.js → wizard-abort-Cd-7sfCw.js} +4 -4
- package/dist/{wizard-abort-BPEiPCXk.js.map → wizard-abort-Cd-7sfCw.js.map} +1 -1
- package/dist/{yara-hooks-canFIYTc.js → yara-hooks-BS0n3ekf.js} +4 -4
- package/dist/{yara-hooks-canFIYTc.js.map → yara-hooks-BS0n3ekf.js.map} +1 -1
- package/dist/{yara-hooks-CFD60h78.js → yara-hooks-CxksH-GZ.js} +1 -1
- package/package.json +1 -1
- package/dist/agent-interface-DMP3DZRd.js.map +0 -1
- package/dist/analytics-X7JfAmh6.js.map +0 -1
- package/dist/analytics-dcL9EQ4r.js +0 -2
- package/dist/api-BrMGAI-b.js +0 -2
- package/dist/api-key-login-CZEgx2jb.js +0 -2
- package/dist/bounded-fs-iDiqDQ9v.js.map +0 -1
- package/dist/oauth-session-Bj_-BY7o.js.map +0 -1
- package/dist/pi-DREdQRPP.js.map +0 -1
- package/dist/posthog-integration-DDSPdbpw.js.map +0 -1
- package/dist/programs-6SFfUBmm.js.map +0 -1
- package/dist/programs-DvlhdeM_.js +0 -3
- package/dist/provisioning-CPGWgv7p.js +0 -2
- package/dist/run-tool-GfISLgEs.js +0 -2
- package/dist/task-Dm9wZbVW.js.map +0 -1
- package/dist/terminal-Z4hCXfie.js.map +0 -1
- package/dist/tools-1aM6bI9Y.js.map +0 -1
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { o as logToFile } from "./debug-
|
|
2
|
-
import { n as analytics } from "./analytics-
|
|
3
|
-
import { n as detectNodePackageManagers } from "./package-manager-
|
|
4
|
-
import { $ as
|
|
5
|
-
import { o as withMode } from "./pi-
|
|
6
|
-
import { _ as makeMutex } from "./queue-tools-
|
|
7
|
-
import { p as scanInstalledSkill, v as installSkillById, x as AUDIT_CHECKS_FILE, y as fetchSkillMenu } from "./yara-hooks-
|
|
1
|
+
import { o as logToFile } from "./debug-BvEbemym.js";
|
|
2
|
+
import { n as analytics } from "./analytics-B_xFshPY.js";
|
|
3
|
+
import { n as detectNodePackageManagers } from "./package-manager-DpCdmMmB.js";
|
|
4
|
+
import { $ as vaultSensitiveAnswers, A as AUDIT_STATUSES, B as checkEnvKeys, D as AUDIT_RESOLVE_CHECKS_PARAM_DESCRIPTION, E as AUDIT_RESOLVE_CHECKS_DESCRIPTION, F as WIZARD_ASK_SENSITIVE_DESCRIPTION, G as mergeEnvValues, H as describeAskCancellation, I as WIZARD_ASK_SUBJECT_DESCRIPTION, J as resolveAuditChecks, K as normaliseAskSubject, L as WIZARD_ASK_TOOL_DESCRIPTION, M as CHECK_ENV_KEYS_FILE_PATH_DESCRIPTION, N as ENV_FILE_PATH_DESCRIPTION, O as AUDIT_SEED_CHECKS_DESCRIPTION, P as WIZARD_ASK_KIND_DESCRIPTION, Q as templateEnvWriteRefusal, R as WIZARD_TOOL_NAMES, T as AUDIT_ADD_CHECKS_PARAM_DESCRIPTION, U as ensureGitignoreCoverage, V as createAskAccounting, W as legacyKeyNameRefusal, X as resolveEnvSecretRefs, Y as resolveEnvPath, Z as seedAuditChecks, _ as createSecretVault, b as PUBLISH_HANDOFF_TOOL_NAME, j as CHECK_ENV_KEYS_DESCRIPTION, k as AUDIT_SEED_CHECKS_PARAM_DESCRIPTION, q as resolveAskQuestionKinds, tt as isFullyCancelled, v as PUBLISH_HANDOFF_CONTENT_DESCRIPTION, w as AUDIT_ADD_CHECKS_DESCRIPTION, x as publishHandoff, y as PUBLISH_HANDOFF_DESCRIPTION, z as addAuditChecks } from "./agent-interface-3YfIWZmY.js";
|
|
5
|
+
import { o as withMode } from "./pi-DTj1hsJe.js";
|
|
6
|
+
import { _ as makeMutex } from "./queue-tools-BoIITT7w.js";
|
|
7
|
+
import { p as scanInstalledSkill, v as installSkillById, x as AUDIT_CHECKS_FILE, y as fetchSkillMenu } from "./yara-hooks-BS0n3ekf.js";
|
|
8
8
|
import fs from "fs";
|
|
9
9
|
import path from "path";
|
|
10
10
|
import { Type } from "typebox";
|
|
@@ -265,10 +265,14 @@ function createWizardPiTools(ctx) {
|
|
|
265
265
|
description: PUBLISH_HANDOFF_DESCRIPTION,
|
|
266
266
|
promptSnippet: "publish_handoff(content) — publish the full report markdown to the wizard session",
|
|
267
267
|
parameters: Type.Object({ content: Type.String({ description: PUBLISH_HANDOFF_CONTENT_DESCRIPTION }) }),
|
|
268
|
-
execute(_id, args) {
|
|
269
|
-
const result = publishHandoff(args.content, ctx.emit, {
|
|
268
|
+
async execute(_id, args) {
|
|
269
|
+
const result = await publishHandoff(args.content, ctx.emit, {
|
|
270
|
+
taskAgent: ctx.taskAgent,
|
|
271
|
+
programId: ctx.programId,
|
|
272
|
+
handoffNotebook: ctx.handoffNotebook
|
|
273
|
+
});
|
|
270
274
|
logToFile(`[pi] publish_handoff: ${result.message}`);
|
|
271
|
-
return
|
|
275
|
+
return text(result.message);
|
|
272
276
|
}
|
|
273
277
|
});
|
|
274
278
|
const tools = [
|
|
@@ -288,4 +292,4 @@ function createWizardPiTools(ctx) {
|
|
|
288
292
|
//#endregion
|
|
289
293
|
export { createWizardPiTools };
|
|
290
294
|
|
|
291
|
-
//# sourceMappingURL=tools-
|
|
295
|
+
//# sourceMappingURL=tools-Bm0FDT6f.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools-Bm0FDT6f.js","names":["checkEnvKeys","checkEnvKeysCore"],"sources":["../src/agent/runner/harness/pi/tools.ts"],"sourcesContent":["/**\n * Wizard capabilities as pi custom tools (#5). pi does not mount MCP servers,\n * so the tools the wizard prompt depends on — skill discovery/install and\n * fenced `.env` edits — are exposed to pi as native `defineTool` tools backed\n * by the same helpers the claude-agent-sdk path uses (`fetchSkillMenu`,\n * `installSkillById`, `checkEnvKeys`, `mergeEnvValues`). Same tool names as the\n * MCP server so the shared prompt is unchanged. `wizard_ask` is wired here too\n * (same schema, caps, and askBridge as the MCP tool) so interactive programs\n * can interview the user on pi; without a bridge (CI) it errors on call.\n * Sensitive answers are vaulted to `{secretRef}` and resolved host-side by\n * set_env_values — the raw value never enters the model conversation.\n */\n\nimport fs from 'fs';\nimport path from 'path';\nimport { Type } from 'typebox';\nimport { defineTool } from '@earendil-works/pi-coding-agent';\nimport type { ToolDefinition } from '@earendil-works/pi-coding-agent';\nimport { analytics } from '@utils/analytics';\nimport { logToFile } from '@utils/debug';\nimport {\n ASK_MAX_QUESTIONS_PER_CALL,\n AUDIT_ADD_CHECKS_DESCRIPTION,\n AUDIT_ADD_CHECKS_PARAM_DESCRIPTION,\n AUDIT_RESOLVE_CHECKS_DESCRIPTION,\n AUDIT_RESOLVE_CHECKS_PARAM_DESCRIPTION,\n AUDIT_SEED_CHECKS_DESCRIPTION,\n AUDIT_SEED_CHECKS_PARAM_DESCRIPTION,\n AUDIT_STATUSES,\n CHECK_ENV_KEYS_DESCRIPTION,\n CHECK_ENV_KEYS_FILE_PATH_DESCRIPTION,\n DEFAULT_ASK_MAX_QUESTIONS,\n ENV_FILE_PATH_DESCRIPTION,\n WIZARD_TOOL_NAMES,\n addAuditChecks,\n checkEnvKeys as checkEnvKeysCore,\n resolveAuditChecks,\n seedAuditChecks,\n createAskAccounting,\n describeAskCancellation,\n ensureGitignoreCoverage,\n mergeEnvValues,\n normaliseAskSubject,\n resolveAskQuestionKinds,\n resolveEnvPath,\n resolveEnvSecretRefs,\n templateEnvWriteRefusal,\n legacyKeyNameRefusal,\n vaultSensitiveAnswers,\n WIZARD_ASK_KIND_DESCRIPTION,\n WIZARD_ASK_SENSITIVE_DESCRIPTION,\n WIZARD_ASK_SUBJECT_DESCRIPTION,\n WIZARD_ASK_TOOL_DESCRIPTION,\n} from '../../../tools/tools';\nimport { fetchSkillMenu } from '@shared/skill-menu';\nimport { installSkillById } from '@shared/skill-install';\nimport type { LLMProvider } from '@posthog/warlock';\nimport { scanInstalledSkill } from '../../../yara-hooks';\nimport type { ProgressEmitter } from '../../../progress';\nimport {\n isFullyCancelled,\n type WizardAskBridge,\n} from '../../../wizard-ask-bridge';\nimport {\n PUBLISH_HANDOFF_CONTENT_DESCRIPTION,\n PUBLISH_HANDOFF_DESCRIPTION,\n PUBLISH_HANDOFF_TOOL_NAME,\n publishHandoff,\n} from '../../../tools/handoff';\nimport { createSecretVault } from '@shared/secret-vault';\nimport {\n AUDIT_CHECKS_FILE,\n type AuditCheck,\n type AuditStatus,\n} from '@shared/audit-ledger';\nimport { makeMutex } from '@utils/atomic-ledger';\nimport { withMode } from './index';\nimport {\n detectNodePackageManagers,\n type PackageManagerDetector,\n} from '@utils/package-manager';\n\nfunction text(s: string): {\n content: [{ type: 'text'; text: string }];\n details: unknown;\n} {\n return { content: [{ type: 'text', text: s }], details: {} };\n}\n\nexport interface PiToolsContext {\n workingDirectory: string;\n skillsBaseUrl: string;\n /** Framework's package-manager detector. Defaults to Node detection. */\n detectPackageManager?: PackageManagerDetector;\n /** Drives the `wizard_ask` overlay. Omitted in CI → the tool errors on call. */\n askBridge?: WizardAskBridge;\n /** Per-run cap on wizard_ask calls. Defaults to {@link DEFAULT_ASK_MAX_QUESTIONS}. */\n maxQuestions?: number;\n /** Overlay open/closed signal — the security gate blocks Write/Edit while open. */\n onAskPendingChange?: (pending: boolean) => void;\n /** Program disallow list; gates wizard_ask here since pi tools carry bare names the MCP-prefixed security gate misses. */\n disallowedTools?: readonly string[];\n /** Scan-triage classifier, resolved once in bootstrap. Absent → scans fail closed. */\n triageProvider?: LLMProvider;\n /** Where `publish_handoff` reports. Absent → the handoff is written but reported nowhere. */\n emit?: ProgressEmitter;\n /** Set for one task of an orchestrated run: `publish_handoff` then reminds it to report with complete_task. */\n taskAgent?: boolean;\n /** The program running, so its `publish_handoff` notebook stays separate from another program's. */\n programId?: string;\n /** The program mirrors the handoff report into a PostHog notebook. */\n handoffNotebook?: boolean;\n}\n\nexport function createWizardPiTools(ctx: PiToolsContext): ToolDefinition[] {\n const {\n workingDirectory,\n skillsBaseUrl,\n askBridge,\n onAskPendingChange,\n triageProvider,\n } = ctx;\n const detectPackageManager =\n ctx.detectPackageManager ?? detectNodePackageManagers;\n const askMaxQuestions = ctx.maxQuestions ?? DEFAULT_ASK_MAX_QUESTIONS;\n // Per-run wizard_ask accounting (total cap + one-time per-subject adjacency\n // nudge). Same shared implementation the MCP server drives, so the two\n // facades cannot diverge on the cap, the nudge or the refund.\n const askAccounting = createAskAccounting(askMaxQuestions);\n // Session-scoped secret vault, same contract as the MCP server: wizard_ask\n // mints `{secretRef}` for sensitive answers, set_env_values resolves them.\n const secretVault = createSecretVault();\n\n // Fetch the skill menu at most once per run — the agent calls load_skill_menu\n // 2-3× otherwise, each a fresh HTTP round-trip (profiled slowness).\n let menuPromise: ReturnType<typeof fetchSkillMenu> | undefined;\n const getSkillMenu = () => (menuPromise ??= fetchSkillMenu(skillsBaseUrl));\n\n const loadSkillMenu = defineTool({\n name: 'load_skill_menu',\n label: 'Load skill menu',\n description:\n 'Load available PostHog skills for a category. Returns skill IDs and names. Call this first, then install_skill with the chosen ID.',\n promptSnippet:\n 'load_skill_menu(category) — list installable PostHog skills',\n parameters: Type.Object({\n category: Type.String({\n description: 'Skill category, e.g. \"integration\"',\n }),\n }),\n async execute(_id, args) {\n const menu = await getSkillMenu();\n if (!menu) return text('Error: could not load the skill menu.');\n const skills = menu.categories[args.category] ?? [];\n if (skills.length === 0) {\n return text(`No skills found for category \"${args.category}\".`);\n }\n logToFile(`[pi] load_skill_menu: ${skills.length} skills`);\n return text(skills.map((s) => `- ${s.id}: ${s.name}`).join('\\n'));\n },\n });\n\n const installSkill = defineTool({\n name: 'install_skill',\n label: 'Install skill',\n description:\n 'Download and install a PostHog skill by ID into .claude/skills/<skillId>/. Call load_skill_menu first. Then read the installed SKILL.md and follow it.',\n promptSnippet:\n 'install_skill(skillId) — install a skill, then read its SKILL.md',\n parameters: Type.Object({\n skillId: Type.String({ description: 'Skill ID from load_skill_menu' }),\n }),\n async execute(_id, args) {\n const result = await installSkillById(\n args.skillId,\n workingDirectory,\n skillsBaseUrl,\n { scan: (dir) => scanInstalledSkill(dir, triageProvider) },\n );\n if (result.kind !== 'ok') {\n logToFile(`[pi] install_skill ${args.skillId}: ${result.kind}`);\n return text(\n `Error installing skill \"${args.skillId}\": ${result.kind}. Use load_skill_menu to see valid IDs.`,\n );\n }\n logToFile(`[pi] install_skill ${args.skillId} -> ${result.path}`);\n return text(\n `Installed \"${args.skillId}\" at ${result.path}. Read ${result.path}/SKILL.md and follow it.`,\n );\n },\n });\n\n const checkEnvKeys = defineTool({\n name: 'check_env_keys',\n label: 'Check env keys',\n description: CHECK_ENV_KEYS_DESCRIPTION,\n promptSnippet:\n 'check_env_keys(keys) — see which .env keys exist, and in which file',\n parameters: Type.Object({\n filePath: Type.Optional(\n Type.String({\n description: CHECK_ENV_KEYS_FILE_PATH_DESCRIPTION,\n }),\n ),\n keys: Type.Array(Type.String(), {\n description: 'Environment variable key names to check',\n }),\n }),\n // `async` with nothing to await, on purpose: it is what turns a thrown\n // error into a rejection. `checkEnvKeys` throws on a filePath that escapes\n // the working directory, and pi wraps `execute` in a plain (non-async)\n // arrow, so without this the throw leaves the tool synchronously instead\n // of arriving as a failed tool call. The scan replaced an awaited read,\n // which is the only reason there is nothing left to await.\n // eslint-disable-next-line @typescript-eslint/require-await\n async execute(_id, args) {\n const results = checkEnvKeysCore(\n workingDirectory,\n args.keys,\n args.filePath,\n );\n return text(JSON.stringify(results, null, 2));\n },\n });\n\n const setEnvValues = defineTool({\n name: 'set_env_values',\n label: 'Set env values',\n description:\n 'Create or update environment variable keys in a .env file (creates the file if missing). Each value is either a literal string or a secret reference `{ \"secretRef\": \"secret:...\" }` returned by wizard_ask — refs are resolved locally, so the actual value is written to the file but never returned to the agent.',\n promptSnippet:\n 'set_env_values(filePath, values) — write .env keys (never hardcode secrets in source)',\n parameters: Type.Object({\n filePath: Type.String({\n description: ENV_FILE_PATH_DESCRIPTION,\n }),\n values: Type.Record(\n Type.String(),\n Type.Union([Type.String(), Type.Object({ secretRef: Type.String() })]),\n {\n description:\n 'Key → (literal string OR { secretRef } pointing to a vaulted secret)',\n },\n ),\n }),\n async execute(_id, args) {\n const keyRefusal = legacyKeyNameRefusal(\n workingDirectory,\n Object.keys(args.values),\n );\n if (keyRefusal) return text(keyRefusal);\n // Resolve secret refs host-side; the value never reaches the agent.\n const resolution = resolveEnvSecretRefs(args.values, secretVault);\n if (!resolution.ok) {\n return text(\n `Error: secret reference \"${resolution.secretRef}\" for key \"${resolution.key}\" is not known to the vault. The ref may have expired, been minted in a different run, or been mistyped.`,\n );\n }\n const resolved = resolveEnvPath(workingDirectory, args.filePath);\n const templateRefusal = templateEnvWriteRefusal(resolved);\n if (templateRefusal) {\n logToFile(`[pi] set_env_values: refused template target ${resolved}`);\n analytics.wizardCapture('set_env_values template target refused', {\n file_name: path.basename(resolved),\n });\n return text(templateRefusal);\n }\n const existing = fs.existsSync(resolved)\n ? await fs.promises.readFile(resolved, 'utf8')\n : '';\n const merged = mergeEnvValues(existing, resolution.values);\n const dir = path.dirname(resolved);\n if (!fs.existsSync(dir))\n await fs.promises.mkdir(dir, { recursive: true });\n await fs.promises.writeFile(resolved, merged, 'utf8');\n // Same post-write pass as the MCP facade: a credential file the\n // project does not ignore yet gets committed by the next `git add`.\n ensureGitignoreCoverage(workingDirectory, path.basename(resolved));\n logToFile(\n `[pi] set_env_values: ${resolved} keys=${Object.keys(args.values).join(\n ',',\n )}`,\n );\n return text(\n `Wrote ${Object.keys(args.values).length} key(s) to ${args.filePath}.`,\n );\n },\n });\n\n // ── Audit ledger ────────────────────────────────────────────────────\n // Native mirror of the three MCP audit tools; pi mounts no MCP server, so\n // without these an audit cannot move a check off pending. Descriptions and\n // write semantics come from the shared helpers, so the facades cannot drift.\n const auditLedgerPath = path.join(workingDirectory, AUDIT_CHECKS_FILE);\n const auditMutex = makeMutex();\n const auditStatus = Type.Union(\n AUDIT_STATUSES.map((s) => Type.Literal(s)),\n { description: 'Check outcome' },\n );\n const auditCheck = Type.Object({\n id: Type.String({ description: 'Stable kebab-case check id' }),\n area: Type.String({ description: 'Short group name, e.g. Installation' }),\n label: Type.String({ description: 'Short human name for the check' }),\n status: auditStatus,\n file: Type.Optional(Type.String({ description: 'Optional path:line' })),\n details: Type.Optional(\n Type.String({ description: 'Optional one-line explanation' }),\n ),\n });\n\n const auditSeedChecks = defineTool({\n name: 'audit_seed_checks',\n label: 'Seed audit checks',\n description: AUDIT_SEED_CHECKS_DESCRIPTION,\n promptSnippet:\n 'audit_seed_checks(checks) — write the full pending checklist to the audit ledger',\n parameters: Type.Object({\n checks: Type.Array(auditCheck, {\n description: AUDIT_SEED_CHECKS_PARAM_DESCRIPTION,\n }),\n }),\n execute: (_id, args) =>\n auditMutex(() => {\n const result = seedAuditChecks(\n auditLedgerPath,\n args.checks as AuditCheck[],\n );\n logToFile(`[pi] audit_seed_checks: ${result.message}`);\n return text(result.message);\n }),\n });\n\n const auditAddChecks = defineTool({\n name: 'audit_add_checks',\n label: 'Add audit checks',\n description: AUDIT_ADD_CHECKS_DESCRIPTION,\n promptSnippet:\n 'audit_add_checks(checks) — append runtime-discovered checks to the ledger',\n parameters: Type.Object({\n checks: Type.Array(auditCheck, {\n minItems: 1,\n description: AUDIT_ADD_CHECKS_PARAM_DESCRIPTION,\n }),\n }),\n execute: (_id, args) =>\n auditMutex(() => {\n const result = addAuditChecks(\n auditLedgerPath,\n args.checks as AuditCheck[],\n );\n logToFile(`[pi] audit_add_checks: ${result.message}`);\n return text(result.message);\n }),\n });\n\n const auditResolveChecks = defineTool({\n name: 'audit_resolve_checks',\n label: 'Resolve audit checks',\n description: AUDIT_RESOLVE_CHECKS_DESCRIPTION,\n promptSnippet:\n 'audit_resolve_checks(updates) — patch each check by id as you finish it',\n parameters: Type.Object({\n updates: Type.Array(\n Type.Object({\n id: Type.String({ description: 'Existing check id' }),\n status: auditStatus,\n file: Type.Optional(\n Type.String({ description: 'Optional path:line' }),\n ),\n details: Type.Optional(\n Type.String({ description: 'Optional one-line explanation' }),\n ),\n }),\n { minItems: 1, description: AUDIT_RESOLVE_CHECKS_PARAM_DESCRIPTION },\n ),\n }),\n execute: (_id, args) =>\n auditMutex(() => {\n const result = resolveAuditChecks(\n auditLedgerPath,\n args.updates as Array<{\n id: string;\n status: AuditStatus;\n file?: string;\n details?: string;\n }>,\n );\n logToFile(`[pi] audit_resolve_checks: ${result.message}`);\n return text(result.message);\n }),\n });\n\n const detectPm = defineTool({\n name: 'detect_package_manager',\n label: 'Detect package manager',\n description:\n \"Detect the project's package manager(s). Returns the name and the install command for each. Call this before installing a dependency, then RUN the returned install command (with the posthog package) via bash — the SDK package must end up in the project manifest, or the app will not build.\",\n promptSnippet:\n 'detect_package_manager() — find the PM + install command, then run it via bash to add the SDK',\n parameters: Type.Object({}),\n async execute() {\n const result = await detectPackageManager(workingDirectory);\n logToFile(\n `[pi] detect_package_manager: ${result.detected.length} detected`,\n );\n return text(JSON.stringify(result, null, 2));\n },\n });\n\n // Native mirror of the MCP `wizard_ask` tool: same name, schema, and\n // askBridge, so the shared prompt is unchanged.\n const wizardAsk = defineTool({\n name: 'wizard_ask',\n label: 'Ask the user',\n description: WIZARD_ASK_TOOL_DESCRIPTION,\n promptSnippet:\n 'wizard_ask(questions, subject) — ask the user structured questions and wait for answers; tag each call with the subject it collects for',\n parameters: Type.Object({\n questions: Type.Array(\n Type.Object({\n id: Type.String({\n description: 'Stable key for the answer in the response map',\n }),\n prompt: Type.String({\n description: 'Question text shown to the user',\n }),\n kind: Type.Optional(\n Type.Union(\n [\n Type.Literal('single'),\n Type.Literal('multi'),\n Type.Literal('text'),\n ],\n { description: WIZARD_ASK_KIND_DESCRIPTION },\n ),\n ),\n options: Type.Optional(\n Type.Array(\n Type.Object({\n label: Type.String(),\n value: Type.String(),\n description: Type.Optional(Type.String()),\n }),\n {\n description:\n 'Required for kind=single|multi; ignored for kind=text',\n },\n ),\n ),\n required: Type.Optional(\n Type.Boolean({ description: 'Defaults to true' }),\n ),\n sensitive: Type.Optional(\n Type.Boolean({\n description: WIZARD_ASK_SENSITIVE_DESCRIPTION,\n }),\n ),\n }),\n { minItems: 1, maxItems: ASK_MAX_QUESTIONS_PER_CALL },\n ),\n subject: Type.Optional(\n Type.String({ description: WIZARD_ASK_SUBJECT_DESCRIPTION }),\n ),\n }),\n async execute(_id, args) {\n if (!askBridge) {\n return text(\n 'Error: wizard_ask is not available in this environment (CI / non-interactive). Proceed with sensible defaults or emit [ABORT] requirements-incomplete.',\n );\n }\n\n const cap = askAccounting.evaluate(args.subject);\n if (cap.kind === 'capped') {\n const { callCount } = askAccounting.snapshot();\n logToFile(\n `[pi] wizard_ask capped: reason=${cap.reason} count=${callCount} subject=${cap.subject} run=${cap.subjectRunLength}`,\n );\n analytics.wizardCapture('wizard_ask capped', {\n reason: cap.reason,\n call_count: callCount,\n max_questions: askMaxQuestions,\n subject: cap.subject,\n subject_run_length: cap.subjectRunLength,\n });\n return text(cap.message);\n }\n\n // A question with no kind takes the one its options imply, so the\n // overlay always has an input to render. See resolveAskQuestionKinds.\n const questions = resolveAskQuestionKinds(args.questions);\n\n // The schema can't enforce per-kind requirements or unique ids.\n const ids = new Set<string>();\n for (const q of questions) {\n if ((q.kind === 'single' || q.kind === 'multi') && !q.options?.length) {\n return text(\n `Error: question \"${q.id}\" has kind=\"${q.kind}\" but no options. Provide at least one { label, value }, or use kind=\"text\".`,\n );\n }\n if (q.sensitive && q.kind !== 'text') {\n return text(\n `Error: question \"${q.id}\" sets sensitive=true but kind=\"${q.kind}\". Only kind=\"text\" answers can be sensitive.`,\n );\n }\n if (ids.has(q.id)) {\n return text(\n `Error: duplicate question id \"${q.id}\". Each question needs a unique id.`,\n );\n }\n ids.add(q.id);\n }\n\n // Optimistically take the slot; refund it on a cancellation or a bridge\n // error so a declined/failed ask doesn't burn the budget for later ones.\n askAccounting.record(args.subject);\n // Block Write/Edit for as long as the overlay is open, so the agent can't\n // mutate files while it's waiting on the user's answer.\n onAskPendingChange?.(true);\n try {\n const { answers, timedOut } = await askBridge.request({\n questions,\n subject: normaliseAskSubject(args.subject),\n });\n if (isFullyCancelled(answers)) askAccounting.refund(args.subject);\n // Sensitive answers go to the vault; the agent sees an opaque ref\n // (same contract as the MCP wizard_ask).\n const sanitised = vaultSensitiveAnswers(\n questions,\n answers,\n secretVault,\n );\n // State an uncollected field as an outcome rather than leaving the\n // agent to recognise a sentinel answer value (same as the MCP facade).\n const cancelled = describeAskCancellation(sanitised, timedOut);\n logToFile(\n `[pi] wizard_ask: resolved ${\n Object.keys(answers).length\n } answer(s) for ${args.questions.length} question(s)${\n cancelled ? `, cancelled: ${cancelled.reason}` : ''\n }`,\n );\n return text(\n JSON.stringify(\n { answers: sanitised, ...(cancelled ? { cancelled } : {}) },\n null,\n 2,\n ),\n );\n } catch (err) {\n askAccounting.refund(args.subject);\n const message = err instanceof Error ? err.message : String(err);\n logToFile(`[pi] wizard_ask: error: ${message}`);\n return text(`Error: wizard_ask failed: ${message}`);\n } finally {\n onAskPendingChange?.(false);\n }\n },\n });\n\n // Native mirror of the MCP `publish_handoff` tool (shared description, so no drift).\n const publishHandoffTool = defineTool({\n name: PUBLISH_HANDOFF_TOOL_NAME,\n label: 'Publish handoff',\n description: PUBLISH_HANDOFF_DESCRIPTION,\n promptSnippet:\n 'publish_handoff(content) — publish the full report markdown to the wizard session',\n parameters: Type.Object({\n content: Type.String({\n description: PUBLISH_HANDOFF_CONTENT_DESCRIPTION,\n }),\n }),\n async execute(_id, args) {\n const result = await publishHandoff(args.content, ctx.emit, {\n taskAgent: ctx.taskAgent,\n programId: ctx.programId,\n handoffNotebook: ctx.handoffNotebook,\n });\n logToFile(`[pi] publish_handoff: ${result.message}`);\n return text(result.message);\n },\n });\n\n const tools = [\n loadSkillMenu,\n installSkill,\n checkEnvKeys,\n setEnvValues,\n detectPm,\n // Parallel: the mutex serializes the writes, so a subagent fan-out is safe.\n withMode(auditSeedChecks, 'parallel'),\n withMode(auditAddChecks, 'parallel'),\n withMode(auditResolveChecks, 'parallel'),\n // Sequential: it publishes the run's handoff.\n withMode(publishHandoffTool, 'sequential'),\n ];\n // Register wizard_ask only when the program allows it. posthog-integration\n // disallows it (runs without structured user input); self-driving keeps it.\n // Sequential: the ask bridge holds a single in-flight question slot, so a\n // batched turn must never dispatch two asks (or an ask + a write) at once.\n const askDisallowed =\n ctx.disallowedTools?.includes(WIZARD_TOOL_NAMES.wizardAsk) ?? false;\n if (!askDisallowed) tools.push(withMode(wizardAsk, 'sequential'));\n return tools;\n}\n"],"mappings":"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"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { n as ErrorCodes, t as emitWizardError } from "./emit-BqLCdV8Y.js";
|
|
2
|
-
import { M as POSTHOG_DOCS_URL, n as analytics, nt as WIZARD_USER_AGENT, rt as getSkillsBaseUrl } from "./analytics-
|
|
3
|
-
import { ft as CLI_STEERING_TARGETS, gt as installSteeringSnippet, ht as installOrUpdatePostHogCli, mt as findTarget, pt as detectTargets } from "./programs-
|
|
2
|
+
import { M as POSTHOG_DOCS_URL, n as analytics, nt as WIZARD_USER_AGENT, rt as getSkillsBaseUrl } from "./analytics-B_xFshPY.js";
|
|
3
|
+
import { ft as CLI_STEERING_TARGETS, gt as installSteeringSnippet, ht as installOrUpdatePostHogCli, mt as findTarget, pt as detectTargets } from "./programs-Bq9Ju9xk.js";
|
|
4
4
|
import "./errors-DhFeR8Sp.js";
|
|
5
|
-
import { t as withProgress } from "./telemetry-
|
|
6
|
-
import "./posthog-integration-
|
|
7
|
-
import { y as fetchSkillMenu } from "./yara-hooks-
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
5
|
+
import { t as withProgress } from "./telemetry-DKM7VGuJ.js";
|
|
6
|
+
import "./posthog-integration-CpinLWNO.js";
|
|
7
|
+
import { y as fetchSkillMenu } from "./yara-hooks-BS0n3ekf.js";
|
|
8
|
+
import { d as handleApiError } from "./api-C_9KsN-7.js";
|
|
9
|
+
import { n as namesWithStatus } from "./results-CDqlHogZ.js";
|
|
10
10
|
import { t as ALL_FEATURE_VALUES } from "./defaults-DDVl3tKN.js";
|
|
11
11
|
import * as path$1 from "node:path";
|
|
12
12
|
import axios from "axios";
|
|
@@ -184,7 +184,7 @@ async function runDoctorReport({ apiKey, projectId, baseUrl }, { log }) {
|
|
|
184
184
|
log.intro("Welcome to the PostHog setup wizard");
|
|
185
185
|
log.log.info("Running posthog-doctor in CI mode");
|
|
186
186
|
try {
|
|
187
|
-
const { resolveApiKeyProject } = await import("./api-key-login-
|
|
187
|
+
const { resolveApiKeyProject } = await import("./api-key-login-DiRuZ8Lm.js");
|
|
188
188
|
const { host, projectId: resolvedProjectId } = await resolveApiKeyProject(apiKey, {
|
|
189
189
|
projectId,
|
|
190
190
|
baseUrl,
|
|
@@ -201,7 +201,7 @@ async function runDoctorReport({ apiKey, projectId, baseUrl }, { log }) {
|
|
|
201
201
|
for (const issue of sorted) log.log.info(` • [${issue.severity}] ${getKindMeta(issue.kind).title}`);
|
|
202
202
|
return 1;
|
|
203
203
|
} catch (error) {
|
|
204
|
-
const { ApiError } = await import("./api-
|
|
204
|
+
const { ApiError } = await import("./api-DhLSO3ai.js");
|
|
205
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
206
|
log.log.error(`Doctor failed: ${message}`);
|
|
207
207
|
emitWizardError({
|
|
@@ -282,7 +282,7 @@ async function flushAnalytics() {
|
|
|
282
282
|
* detected client, so one succeeding would otherwise mask the rest.
|
|
283
283
|
*/
|
|
284
284
|
async function addMCPServerToClientsStep(args, { log }) {
|
|
285
|
-
const { addMCPServer, getSupportedClients } = await import("./install-
|
|
285
|
+
const { addMCPServer, getSupportedClients } = await import("./install-CX65IxGa.js");
|
|
286
286
|
const supportedClients = await getSupportedClients();
|
|
287
287
|
if (supportedClients.length === 0) {
|
|
288
288
|
log.info("No supported MCP clients detected. Skipping MCP installation.");
|
|
@@ -309,7 +309,7 @@ async function addMCPServerToClientsStep(args, { log }) {
|
|
|
309
309
|
const bulletList = (items) => items.map((item) => ` - ${item}`).join("\n");
|
|
310
310
|
/** No exit code on an empty result: nothing to remove is the requested end state. */
|
|
311
311
|
async function removeMCPServerFromClientsStep(args, { log }) {
|
|
312
|
-
const { getInstalledClients, removeMCPServer } = await import("./install-
|
|
312
|
+
const { getInstalledClients, removeMCPServer } = await import("./install-CX65IxGa.js");
|
|
313
313
|
const local = args.local ?? false;
|
|
314
314
|
const installedClients = await getInstalledClients(local);
|
|
315
315
|
if (installedClients.length === 0) {
|
|
@@ -431,7 +431,7 @@ async function promptForTargets(detected, ui) {
|
|
|
431
431
|
/** Resolves 0 once the account exists, else 1. */
|
|
432
432
|
async function runProvision({ email, region, name, baseUrl, jsonMode }, { log }) {
|
|
433
433
|
try {
|
|
434
|
-
const { provisionNewAccount } = await import("./provisioning-
|
|
434
|
+
const { provisionNewAccount } = await import("./provisioning-D6Cqbc36.js");
|
|
435
435
|
if (!jsonMode) log.log.info(`Provisioning account for ${email} in ${region}...`);
|
|
436
436
|
emitResult(await provisionNewAccount(email, name, region, { baseUrl }), jsonMode, log);
|
|
437
437
|
return 0;
|
|
@@ -541,4 +541,4 @@ function getTool(id) {
|
|
|
541
541
|
//#endregion
|
|
542
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
543
|
|
|
544
|
-
//# sourceMappingURL=tools-
|
|
544
|
+
//# sourceMappingURL=tools-DZCEvDv9.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools-dUJHRo6X.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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"}
|
|
1
|
+
{"version":3,"file":"tools-DZCEvDv9.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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"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
//#region src/tui/index.ts
|
|
2
2
|
/** Run `config` in the TUI; resolves with the exit code. */
|
|
3
3
|
async function runTui(config, launch) {
|
|
4
|
-
const { runTui: run } = await import("./run-
|
|
4
|
+
const { runTui: run } = await import("./run-DcaVJSeI.js");
|
|
5
5
|
return run(config, launch);
|
|
6
6
|
}
|
|
7
7
|
/** Run a tool's screens; resolves with the exit code, rejects when the TUI cannot start. */
|
|
8
8
|
async function runTuiTool(toolId, launch) {
|
|
9
|
-
const { runTuiTool: run } = await import("./run-tool-
|
|
9
|
+
const { runTuiTool: run } = await import("./run-tool-zMLQroVh.js");
|
|
10
10
|
return run(toolId, launch);
|
|
11
11
|
}
|
|
12
12
|
/** Pick one of a family's subcommands; resolves with the picked value. */
|
|
@@ -16,10 +16,10 @@ async function renderFamilyPicker(parentLabel, options) {
|
|
|
16
16
|
}
|
|
17
17
|
/** Launch the TUI primitives playground; resolves 0 once it closes. */
|
|
18
18
|
async function runPlayground(version) {
|
|
19
|
-
const { startPlayground } = await import("./start-playground-
|
|
19
|
+
const { startPlayground } = await import("./start-playground-B62_pYfu.js");
|
|
20
20
|
return startPlayground(version);
|
|
21
21
|
}
|
|
22
22
|
//#endregion
|
|
23
23
|
export { runTuiTool as i, runPlayground as n, runTui as r, renderFamilyPicker as t };
|
|
24
24
|
|
|
25
|
-
//# sourceMappingURL=tui-
|
|
25
|
+
//# sourceMappingURL=tui-B56jvkbi.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tui-
|
|
1
|
+
{"version":3,"file":"tui-B56jvkbi.js","names":[],"sources":["../src/tui/index.ts"],"sourcesContent":["/** The TUI's one entry for other layers; each function loads its module on first call. */\nimport type { ProgramId } from '@programs';\nimport type { ProgramConfig } from '@programs/types';\nimport type { ToolId } from '@tools';\nimport type { FamilyPickerOption } from './family-picker.js';\nimport type { FlowStep } from './flow.js';\nimport type { TuiLaunch, TuiToolLaunch } from './launch.js';\nimport type { MountedScreens, MountServices } from './harness.js';\nimport type { WizardStore } from './store.js';\nimport type { TuiState } from './tui-state.js';\n\nexport { Overlay, ScreenId } from './screen-ids.js';\n// The programs' and tools' screen ids, from their leaf modules so the entry stays light.\nexport { AiObservabilityScreenId } from './programs/ai-observability/screen-ids.js';\nexport { AuditScreenId } from './programs/audit/screen-ids.js';\nexport { ErrorTrackingScreenId } from './programs/error-tracking/screen-ids.js';\nexport { SourceMapsScreenId } from './programs/error-tracking-upload-source-maps/screen-ids.js';\nexport { MetricsScreenId } from './programs/metrics/screen-ids.js';\nexport { MigrationScreenId } from './programs/migration/screen-ids.js';\nexport { PostHogIntegrationScreenId } from './programs/posthog-integration/screen-ids.js';\nexport { RevenueAnalyticsScreenId } from './programs/revenue-analytics/screen-ids.js';\nexport { SelfDrivingScreenId } from './programs/self-driving/screen-ids.js';\nexport { SkillScreenId } from './programs/shared/screen-ids.js';\nexport { WarehouseSourceScreenId } from './programs/warehouse-source/screen-ids.js';\nexport { PosthogDoctorScreenId } from './tools/doctor/screen-ids.js';\nexport { McpScreenId } from './tools/mcp/screen-ids.js';\nexport type { FamilyPickerOption } from './family-picker.js';\nexport type { FlowStep } from './flow.js';\nexport type { TuiLaunch, TuiToolLaunch } from './launch.js';\nexport type { McpInstaller } from './services/mcp-installer.js';\nexport type { WizardStore } from './store.js';\nexport type { TuiLaunchChoices } from './tui-state.js';\nexport type { MountedScreens, MountServices } from './harness.js';\n\n/** Run `config` in the TUI; resolves with the exit code. */\nexport async function runTui(\n config: ProgramConfig,\n launch: TuiLaunch,\n): Promise<number> {\n const { runTui: run } = await import('./run.js');\n return run(config, launch);\n}\n\n/** Run a tool's screens; resolves with the exit code, rejects when the TUI cannot start. */\nexport async function runTuiTool(\n toolId: ToolId,\n launch: TuiToolLaunch,\n): Promise<number> {\n const { runTuiTool: run } = await import('./run-tool.js');\n return run(toolId, launch);\n}\n\n/** Pick one of a family's subcommands; resolves with the picked value. */\nexport async function renderFamilyPicker<T>(\n parentLabel: string,\n options: FamilyPickerOption<T>[],\n): Promise<T> {\n const { renderFamilyPicker: render } = await import('./family-picker.js');\n return render(parentLabel, options);\n}\n\n/** Launch the TUI primitives playground; resolves 0 once it closes. */\nexport async function runPlayground(version: string): Promise<number> {\n const { startPlayground } = await import('./playground/start-playground.js');\n return startPlayground(version);\n}\n\n/** A program's TUI screen flow, from the TUI program registry: for walking a flow in tests. */\nexport async function tuiProgramFlow(\n programId: ProgramId,\n): Promise<readonly FlowStep[]> {\n const { getTuiProgram } = await import('./programs/index.js');\n return getTuiProgram(programId).flow;\n}\n\n/** Every screen id the TUI mounts: the core's, the overlays and each program's and tool's own: for checking a table covers them all. */\nexport async function tuiScreenIds(): Promise<string[]> {\n const { tuiScreenIds: ids } = await import('./harness.js');\n return ids();\n}\n\n/** A TUI store for `programId` with no terminal: for walking a flow in tests. */\nexport async function createTuiStore(\n programId: ProgramId,\n): Promise<WizardStore> {\n const { createTuiStore: create } = await import('./harness.js');\n return create(programId);\n}\n\n/** The state only the screens use, as `store` holds it now: for asserting what a commit changed. */\nexport async function readTuiState(store: WizardStore): Promise<TuiState> {\n const { readTuiState: read } = await import('./harness.js');\n return read(store);\n}\n\n/** The real screens `store` shows, on a test terminal that takes the keys a test types: for driving screens by keyboard. */\nexport async function mountScreens(\n store: WizardStore,\n services?: MountServices,\n): Promise<MountedScreens> {\n const { mountScreens: mount } = await import('./harness.js');\n return mount(store, services);\n}\n"],"mappings":";;AAmCA,eAAsB,OACpB,QACA,QACiB;CACjB,MAAM,EAAE,QAAQ,QAAQ,MAAM,OAAO;AACrC,QAAO,IAAI,QAAQ,OAAO;;;AAI5B,eAAsB,WACpB,QACA,QACiB;CACjB,MAAM,EAAE,YAAY,QAAQ,MAAM,OAAO;AACzC,QAAO,IAAI,QAAQ,OAAO;;;AAI5B,eAAsB,mBACpB,aACA,SACY;CACZ,MAAM,EAAE,oBAAoB,WAAW,MAAM,OAAO;AACpD,QAAO,OAAO,aAAa,QAAQ;;;AAIrC,eAAsB,cAAc,SAAkC;CACpE,MAAM,EAAE,oBAAoB,MAAM,OAAO;AACzC,QAAO,gBAAgB,QAAQ"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { i as runTuiTool, r as runTui, t as renderFamilyPicker } from "./tui-
|
|
1
|
+
import { i as runTuiTool, r as runTui, t as renderFamilyPicker } from "./tui-B56jvkbi.js";
|
|
2
2
|
export { renderFamilyPicker, runTui, runTuiTool };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as analytics } from "./analytics-
|
|
2
|
-
import { t as withProgress } from "./telemetry-
|
|
1
|
+
import { n as analytics } from "./analytics-B_xFshPY.js";
|
|
2
|
+
import { t as withProgress } from "./telemetry-DKM7VGuJ.js";
|
|
3
3
|
import * as fs$1 from "fs";
|
|
4
4
|
import * as path$1 from "path";
|
|
5
5
|
import { execSync, spawn, spawnSync } from "child_process";
|
|
@@ -142,4 +142,4 @@ const uploadEnvironmentVariablesStep = async (envVars, { integration, installDir
|
|
|
142
142
|
//#endregion
|
|
143
143
|
export { uploadEnvironmentVariablesStep };
|
|
144
144
|
|
|
145
|
-
//# sourceMappingURL=upload-step-
|
|
145
|
+
//# sourceMappingURL=upload-step-DqTgn6UB.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upload-step-
|
|
1
|
+
{"version":3,"file":"upload-step-DqTgn6UB.js","names":["path","fs"],"sources":["../src/programs/posthog-integration/upload-environment-variables/EnvironmentProvider.ts","../src/programs/posthog-integration/upload-environment-variables/providers/vercel.ts","../src/programs/posthog-integration/upload-environment-variables/upload-step.ts"],"sourcesContent":["import type { RunnerContext } from '../../runner-context';\n\nexport type EnvironmentProviderOptions = {\n installDir: string;\n /** Where the upload reports progress: the running program's runner. */\n runner: Pick<RunnerContext, 'log' | 'spinner'>;\n};\n\nexport abstract class EnvironmentProvider {\n protected options: EnvironmentProviderOptions;\n\n name: string;\n\n constructor(options: EnvironmentProviderOptions) {\n this.options = options;\n }\n\n abstract detect(): Promise<boolean>;\n\n abstract uploadEnvVars(\n vars: Record<string, string>,\n ): Promise<Record<string, boolean>>;\n}\n","import { execSync, spawn, spawnSync } from 'child_process';\nimport {\n EnvironmentProvider,\n type EnvironmentProviderOptions,\n} from '../EnvironmentProvider';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { analytics } from '@utils/analytics';\n\nexport class VercelEnvironmentProvider extends EnvironmentProvider {\n name = 'Vercel';\n environments = ['production', 'preview', 'development'];\n\n constructor(options: EnvironmentProviderOptions) {\n super(options);\n }\n\n // eslint-disable-next-line @typescript-eslint/require-await\n async detect(): Promise<boolean> {\n const vercelDetected =\n this.hasVercelCli() && this.isProjectLinked() && this.isAuthenticated();\n\n analytics.setTag('vercel-detected', vercelDetected);\n\n return vercelDetected;\n }\n\n hasDotVercelDir(): boolean {\n const dotVercelDir = path.join(this.options.installDir, '.vercel');\n return fs.existsSync(dotVercelDir);\n }\n\n hasVercelCli(): boolean {\n try {\n execSync('vercel --version', { stdio: 'ignore' });\n analytics.setTag('vercel-cli-installed', true);\n return true;\n } catch {\n analytics.setTag('vercel-cli-installed', false);\n return false;\n }\n }\n\n isProjectLinked(): boolean {\n const isProjectLinked = fs.existsSync(\n path.join(this.options.installDir, '.vercel', 'project.json'),\n );\n\n analytics.setTag('vercel-project-linked', isProjectLinked);\n\n return isProjectLinked;\n }\n\n isAuthenticated(): boolean {\n const result = spawnSync('vercel', ['whoami'], {\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'], // suppress prompts\n env: {\n ...process.env,\n FORCE_COLOR: '0', // avoid ANSI formatting\n CI: '1', // hint to CLI that it's a non-interactive env\n },\n });\n\n const output = (\n String(result.stdout) + String(result.stderr)\n ).toLowerCase();\n\n if (\n output.includes('log in to vercel') ||\n output.includes('vercel login') ||\n result.status !== 0\n ) {\n analytics.setTag('vercel-authenticated', false);\n return false;\n }\n\n analytics.setTag('vercel-authenticated', true);\n\n return true;\n }\n\n async uploadEnvironmentVariable(\n key: string,\n value: string,\n environment: string,\n ): Promise<void> {\n await new Promise<void>((resolve, reject) => {\n const proc = spawn('vercel', ['env', 'add', key, environment], {\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n let stderr = '';\n proc.stderr.on('data', (data) => {\n stderr += data.toString();\n });\n\n proc.stdin.write(value);\n proc.stdin.end();\n\n proc.on('close', (code) => {\n if (\n stderr.includes('already exists') ||\n stderr.includes('already been added') ||\n stderr.includes('vercel env rm')\n ) {\n reject(\n new Error(\n `❌ Environment variable ${key} already exists in ${this.name}. Please upload it manually.`,\n ),\n );\n } else if (code === 0) {\n resolve();\n } else {\n reject(\n new Error(\n `❌ Failed to upload environment variable ${key} to ${this.name}. Please upload it manually.`,\n ),\n );\n }\n });\n });\n }\n\n async uploadEnvVars(\n vars: Record<string, string>,\n ): Promise<Record<string, boolean>> {\n const results: Record<string, boolean> = {};\n\n for (const [key, value] of Object.entries(vars)) {\n const spinner = this.options.runner.spinner();\n\n spinner.start(`Uploading ${key} to ${this.name}...`);\n await Promise.all(\n this.environments.map((environment) =>\n this.uploadEnvironmentVariable(key, value, environment),\n ),\n )\n .then(() => {\n spinner.stop(`✅ Uploaded ${key} to ${this.name}`);\n results[key] = true;\n })\n .catch((err) => {\n spinner.stop(\n err instanceof Error\n ? err.message\n : `❌ Failed to upload environment variables to ${this.name}. Please upload it manually.`,\n );\n results[key] = false;\n });\n }\n\n return results;\n }\n}\n","import type { Integration } from '@shared/constants';\nimport { withProgress } from '@utils/telemetry';\nimport { analytics } from '@utils/analytics';\nimport type { RunnerContext } from '../../runner-context';\nimport { EnvironmentProvider } from './EnvironmentProvider';\nimport { VercelEnvironmentProvider } from './providers/vercel';\n\nexport const uploadEnvironmentVariablesStep = async (\n envVars: Record<string, string>,\n {\n integration,\n installDir,\n runner,\n }: {\n integration: Integration;\n installDir: string;\n runner: Pick<RunnerContext, 'log' | 'spinner'>;\n },\n): Promise<string[]> => {\n const providers: EnvironmentProvider[] = [\n new VercelEnvironmentProvider({ installDir, runner }),\n ];\n\n let provider: EnvironmentProvider | null = null;\n\n for (const p of providers) {\n if (await p.detect()) {\n provider = p;\n break;\n }\n }\n\n if (!provider) {\n analytics.wizardCapture('env upload skipped', {\n reason: 'no environment provider found',\n integration,\n });\n return [];\n }\n\n // Auto-accept — the agent already wrote env vars via MCP tools\n runner.log.info(`Uploading environment variables to ${provider.name}...`);\n\n const results = await withProgress(\n 'uploading environment variables',\n async () => {\n return await provider.uploadEnvVars(envVars);\n },\n );\n\n analytics.wizardCapture('env uploaded', {\n provider: provider.name,\n integration,\n });\n\n return Object.keys(results).filter((key) => results[key]);\n};\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { nt as WIZARD_USER_AGENT } from "./analytics-
|
|
1
|
+
import { nt as WIZARD_USER_AGENT } from "./analytics-B_xFshPY.js";
|
|
2
2
|
import axios from "axios";
|
|
3
3
|
//#region src/shared/utils/urls.ts
|
|
4
4
|
/**
|
|
@@ -64,4 +64,4 @@ const getIntegrationAuthorizeUrl = (appHost, projectId, kind) => `${appHost.repl
|
|
|
64
64
|
//#endregion
|
|
65
65
|
export { getOAuthUrl as a, getIntegrationAuthorizeUrl as i, getCloudUrl as n, getUiHostFromHost as o, getHost as r, resolveBaseUrl as s, detectRegion as t };
|
|
66
66
|
|
|
67
|
-
//# sourceMappingURL=urls-
|
|
67
|
+
//# sourceMappingURL=urls-B82v7gfO.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"urls-
|
|
1
|
+
{"version":3,"file":"urls-B82v7gfO.js","names":[],"sources":["../src/shared/utils/urls.ts"],"sourcesContent":["import axios from 'axios';\nimport { IS_DEV, WIZARD_USER_AGENT } from '@shared/constants';\nimport type { CloudRegion } from './types';\n\n/**\n * Resolve a pinned PostHog base URL from an optional override. When present, it\n * becomes the single source of truth for every PostHog origin — the\n * API/ingestion host, the cloud/app URL, and the OAuth server — bypassing\n * region resolution entirely.\n *\n * The override lives on the session (`session.baseUrl`, set by `--base-url`) and\n * is threaded in by callers, so there is no hidden module-level state. A `--base-url`\n * value wins; otherwise a dev/test build implies `localhost:8010`; otherwise the\n * result is `undefined`, meaning region-based resolution applies.\n *\n * This is the runtime equivalent of the `IS_DEV` localhost routing: `IS_DEV` is a\n * build-time constant that tsdown compiles out of production builds, so it can't\n * point a shipped wizard at a local stack — `--base-url` can. Both feed this one\n * resolver so every URL helper only asks the question once.\n */\nexport const resolveBaseUrl = (override?: string): string | undefined => {\n return override?.trim() || (IS_DEV ? 'http://localhost:8010' : undefined);\n};\n\nexport const getUiHostFromHost = (host: string) => {\n if (host.includes('us.i.posthog.com')) {\n return 'https://us.posthog.com';\n }\n\n if (host.includes('eu.i.posthog.com')) {\n return 'https://eu.posthog.com';\n }\n\n return host;\n};\n\nexport const getHost = (region: CloudRegion, baseUrl?: string) => {\n const override = resolveBaseUrl(baseUrl);\n if (override) {\n return override;\n }\n\n if (region === 'eu') {\n return 'https://eu.i.posthog.com';\n }\n\n return 'https://us.i.posthog.com';\n};\n\nexport const getCloudUrl = (region: CloudRegion, baseUrl?: string) => {\n const override = resolveBaseUrl(baseUrl);\n if (override) {\n return override;\n }\n\n if (region === 'eu') {\n return 'https://eu.posthog.com';\n }\n\n return 'https://us.posthog.com';\n};\n\nexport async function detectRegion(\n accessToken: string,\n baseUrl?: string,\n): Promise<CloudRegion> {\n // With a pinned base URL there is only one instance to talk to — skip the\n // us/eu probe and default the region label to 'us'. (Covers IS_DEV too, via\n // resolveBaseUrl.) The URLs themselves come from the override, not this label.\n if (resolveBaseUrl(baseUrl)) {\n return 'us';\n }\n\n const headers = {\n Authorization: `Bearer ${accessToken}`,\n 'User-Agent': WIZARD_USER_AGENT,\n };\n\n const [usResult, euResult] = await Promise.allSettled([\n axios.get('https://us.posthog.com/api/users/@me/', { headers }),\n axios.get('https://eu.posthog.com/api/users/@me/', { headers }),\n ]);\n\n if (usResult.status === 'fulfilled') return 'us';\n if (euResult.status === 'fulfilled') return 'eu';\n\n throw new Error(\n 'Could not determine cloud region from access token. Please check your PostHog account.',\n );\n}\n\n/** Region-agnostic prod OAuth server. Resolves to the right region server-side. */\nconst PROD_OAUTH_URL = 'https://oauth.posthog.com';\n\n/**\n * OAuth server URL. Follows the base-URL override (and thus IS_DEV → localhost),\n * otherwise the region-agnostic prod OAuth host.\n */\nexport const getOAuthUrl = (baseUrl?: string): string =>\n resolveBaseUrl(baseUrl) ?? PROD_OAUTH_URL;\n\n/**\n * One-click integration install/authorize deep-link. Opening it in the user's\n * logged-in browser runs the install directly — no settings-page hunting. The\n * one link covers fresh install, link-existing, and re-auth.\n */\nexport const getIntegrationAuthorizeUrl = (\n appHost: string,\n projectId: number,\n kind: string,\n): string =>\n `${appHost.replace(\n /\\/$/,\n '',\n )}/api/environments/${projectId}/integrations/authorize?kind=${kind}`;\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAoBA,MAAa,kBAAkB,aAA0C;AACvE,QAAO,UAAU,MAAM,IAAwC,KAAA;;AAGjE,MAAa,qBAAqB,SAAiB;AACjD,KAAI,KAAK,SAAS,mBAAmB,CACnC,QAAO;AAGT,KAAI,KAAK,SAAS,mBAAmB,CACnC,QAAO;AAGT,QAAO;;AAGT,MAAa,WAAW,QAAqB,YAAqB;CAChE,MAAM,WAAW,eAAe,QAAQ;AACxC,KAAI,SACF,QAAO;AAGT,KAAI,WAAW,KACb,QAAO;AAGT,QAAO;;AAGT,MAAa,eAAe,QAAqB,YAAqB;CACpE,MAAM,WAAW,eAAe,QAAQ;AACxC,KAAI,SACF,QAAO;AAGT,KAAI,WAAW,KACb,QAAO;AAGT,QAAO;;AAGT,eAAsB,aACpB,aACA,SACsB;AAItB,KAAI,eAAe,QAAQ,CACzB,QAAO;CAGT,MAAM,UAAU;EACd,eAAe,UAAU;EACzB,cAAc;EACf;CAED,MAAM,CAAC,UAAU,YAAY,MAAM,QAAQ,WAAW,CACpD,MAAM,IAAI,yCAAyC,EAAE,SAAS,CAAC,EAC/D,MAAM,IAAI,yCAAyC,EAAE,SAAS,CAAC,CAChE,CAAC;AAEF,KAAI,SAAS,WAAW,YAAa,QAAO;AAC5C,KAAI,SAAS,WAAW,YAAa,QAAO;AAE5C,OAAM,IAAI,MACR,yFACD;;;AAIH,MAAM,iBAAiB;;;;;AAMvB,MAAa,eAAe,YAC1B,eAAe,QAAQ,IAAI;;;;;;AAO7B,MAAa,8BACX,SACA,WACA,SAEA,GAAG,QAAQ,QACT,OACA,GACD,CAAC,oBAAoB,UAAU,+BAA+B"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { o as logToFile } from "./debug-
|
|
2
|
-
import { n as analytics } from "./analytics-
|
|
1
|
+
import { o as logToFile } from "./debug-BvEbemym.js";
|
|
2
|
+
import { n as analytics } from "./analytics-B_xFshPY.js";
|
|
3
3
|
import { a as WizardError } from "./errors-DhFeR8Sp.js";
|
|
4
|
-
import { m as runCleanups } from "./agent-interface-
|
|
4
|
+
import { m as runCleanups } from "./agent-interface-3YfIWZmY.js";
|
|
5
5
|
//#region src/host/wizard-abort.ts
|
|
6
6
|
/**
|
|
7
7
|
* Single exit point for the wizard. Use instead of process.exit() directly.
|
|
@@ -81,4 +81,4 @@ async function wizardAbort(host, options) {
|
|
|
81
81
|
//#endregion
|
|
82
82
|
export { startHostExit as n, wizardAbort as r, registerShutdown as t };
|
|
83
83
|
|
|
84
|
-
//# sourceMappingURL=wizard-abort-
|
|
84
|
+
//# sourceMappingURL=wizard-abort-Cd-7sfCw.js.map
|