@posthog/wizard 2.38.0 → 2.38.2
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/{add-mcp-server-to-clients-CeoyDLC-.js → add-mcp-server-to-clients-CHSzsAG8.js} +6 -6
- package/dist/{add-mcp-server-to-clients-CeoyDLC-.js.map → add-mcp-server-to-clients-CHSzsAG8.js.map} +1 -1
- package/dist/{agent-interface-BAodys0H.js → agent-interface-DExARWay.js} +13 -11
- package/dist/{agent-interface-BAodys0H.js.map → agent-interface-DExARWay.js.map} +1 -1
- package/dist/{agent-runner-BMuJP8fb.js → agent-runner-CMfTmM3B.js} +20 -18
- package/dist/{agent-runner-BMuJP8fb.js.map → agent-runner-CMfTmM3B.js.map} +1 -1
- package/dist/{analytics-CvIK_07d.js → analytics-Ciob-x8a.js} +3 -3
- package/dist/{analytics-CvIK_07d.js.map → analytics-Ciob-x8a.js.map} +1 -1
- package/dist/analytics-DbfiRvPS.js +2 -0
- package/dist/{api-CyA47qug.js → api-T_WHs3qZ.js} +3 -3
- package/dist/{api-CyA47qug.js.map → api-T_WHs3qZ.js.map} +1 -1
- package/dist/bin.js +176 -82
- package/dist/bin.js.map +1 -1
- package/dist/{ci-install-C_o0Q7Fg.js → ci-install-DJN5aT7W.js} +4 -4
- package/dist/{ci-install-C_o0Q7Fg.js.map → ci-install-DJN5aT7W.js.map} +1 -1
- package/dist/{debug-BhGq9rn9.js → debug-Cne-cLxd.js} +1 -1
- package/dist/{debug-CgdI7Rd-.js → debug-D1lORUFs.js} +41 -19
- package/dist/debug-D1lORUFs.js.map +1 -0
- package/dist/{defaults-b2Bo9Wid.js → defaults-a0e6IRjP.js} +1 -1
- package/dist/{defaults-b2Bo9Wid.js.map → defaults-a0e6IRjP.js.map} +1 -1
- package/dist/{env-api-key-Bezg_uXQ.js → env-api-key-DEl3LJBv.js} +1 -1
- package/dist/{env-api-key-Bezg_uXQ.js.map → env-api-key-DEl3LJBv.js.map} +1 -1
- package/dist/{environment-v22_Genm.js → environment-BEsDCA2q.js} +3 -3
- package/dist/{environment-v22_Genm.js.map → environment-BEsDCA2q.js.map} +1 -1
- package/dist/{file-utils-Gvc2Ysa_.js → file-utils-Cn3dzlo-.js} +2 -2
- package/dist/{file-utils-Gvc2Ysa_.js.map → file-utils-Cn3dzlo-.js.map} +1 -1
- package/dist/{headless-ui-BtBcuxOj.js → headless-ui-DGunpK-s.js} +2 -2
- package/dist/{headless-ui-BtBcuxOj.js.map → headless-ui-DGunpK-s.js.map} +1 -1
- package/dist/{host-resolution-CUjt6efz.js → host-resolution-BnUJZKId.js} +3 -3
- package/dist/{host-resolution-CUjt6efz.js.map → host-resolution-BnUJZKId.js.map} +1 -1
- package/dist/{interactive-CRdgBMxk.js → interactive-BB2IDSWP.js} +2 -2
- package/dist/{interactive-CRdgBMxk.js.map → interactive-BB2IDSWP.js.map} +1 -1
- package/dist/{mcp-XWzcKTeK.js → mcp-CgA5vyiS.js} +2 -2
- package/dist/{mcp-XWzcKTeK.js.map → mcp-CgA5vyiS.js.map} +1 -1
- package/dist/{mcp-prompt-streaming-DeC85Icy.js → mcp-prompt-streaming-CGAkq9qR.js} +4 -4
- package/dist/{mcp-prompt-streaming-DeC85Icy.js.map → mcp-prompt-streaming-CGAkq9qR.js.map} +1 -1
- package/dist/{non-interactive-B-Ku4EOx.js → non-interactive-Dko5F3vh.js} +2 -2
- package/dist/{non-interactive-B-Ku4EOx.js.map → non-interactive-Dko5F3vh.js.map} +1 -1
- package/dist/{package-json-DCuoye-H.js → package-json-CDs1ZVKu.js} +1 -1
- package/dist/{package-json-DCuoye-H.js.map → package-json-CDs1ZVKu.js.map} +1 -1
- package/dist/{package-manager-Dj6dTKlK.js → package-manager-WKKQADHM.js} +2 -2
- package/dist/{package-manager-Dj6dTKlK.js.map → package-manager-WKKQADHM.js.map} +1 -1
- package/dist/{playground-CmKFAlCE.js → playground-UtT6zbjE.js} +6 -6
- package/dist/{playground-CmKFAlCE.js.map → playground-UtT6zbjE.js.map} +1 -1
- package/dist/{posthog-Dnl6wsYc.js → posthog-BESrI6-T.js} +1 -1
- package/dist/{posthog-Dnl6wsYc.js.map → posthog-BESrI6-T.js.map} +1 -1
- package/dist/{posthog-integration-CcJWXPDa.js → posthog-integration-CWXSng0W.js} +41 -22
- package/dist/posthog-integration-CWXSng0W.js.map +1 -0
- package/dist/{provisioning-BIuAPRcH.js → provisioning-CgomM26T.js} +4 -4
- package/dist/{provisioning-BIuAPRcH.js.map → provisioning-CgomM26T.js.map} +1 -1
- package/dist/{registry-ByrVTIE9.js → registry-BQIX-25O.js} +12 -9
- package/dist/{registry-ByrVTIE9.js.map → registry-BQIX-25O.js.map} +1 -1
- package/dist/{security-uSP4HiC0.js → security-pJOYY5LO.js} +3 -3
- package/dist/{security-uSP4HiC0.js.map → security-pJOYY5LO.js.map} +1 -1
- package/dist/{setup-utils-DhmigSLO.js → setup-utils-DLGNk8T6.js} +9 -9
- package/dist/{setup-utils-DhmigSLO.js.map → setup-utils-DLGNk8T6.js.map} +1 -1
- package/dist/{start-tui-DKHnPg5a.js → start-tui-BjCKghQq.js} +133 -73
- package/dist/start-tui-BjCKghQq.js.map +1 -0
- package/dist/{steps-BBzIrOMY.js → steps-XjV9CiqH.js} +7 -7
- package/dist/{steps-BBzIrOMY.js.map → steps-XjV9CiqH.js.map} +1 -1
- package/dist/{store-BV1a-8Wp.js → store-CDIxU0rr.js} +8 -6
- package/dist/{store-BV1a-8Wp.js.map → store-CDIxU0rr.js.map} +1 -1
- package/dist/{subagent-fP1QmYBX.js → subagent-S5Yh16IJ.js} +2 -2
- package/dist/{subagent-fP1QmYBX.js.map → subagent-S5Yh16IJ.js.map} +1 -1
- package/dist/{task-stream-C6s7qUCE.js → task-stream-rC4IEUHC.js} +3 -3
- package/dist/{task-stream-C6s7qUCE.js.map → task-stream-rC4IEUHC.js.map} +1 -1
- package/dist/{tasks-YFkqfEio.js → tasks-wbjOdifO.js} +2 -2
- package/dist/{tasks-YFkqfEio.js.map → tasks-wbjOdifO.js.map} +1 -1
- package/dist/{telemetry-wOdXbZLp.js → telemetry-BfnR7gtf.js} +3 -3
- package/dist/{telemetry-wOdXbZLp.js.map → telemetry-BfnR7gtf.js.map} +1 -1
- package/dist/{terminal-IAHPQoAT.js → terminal-BvRwVeQp.js} +13 -13
- package/dist/{terminal-IAHPQoAT.js.map → terminal-BvRwVeQp.js.map} +1 -1
- package/dist/{tools-DdzmiBKF.js → tools-CbtYlZV4.js} +4 -4
- package/dist/{tools-DdzmiBKF.js.map → tools-CbtYlZV4.js.map} +1 -1
- package/dist/{urls-BR7jQgQp.js → urls-CilgPbS-.js} +2 -2
- package/dist/{urls-BR7jQgQp.js.map → urls-CilgPbS-.js.map} +1 -1
- package/dist/{wizard-abort-bulz-_og.js → wizard-abort-Cp5Y7f8C.js} +4 -4
- package/dist/{wizard-abort-bulz-_og.js.map → wizard-abort-Cp5Y7f8C.js.map} +1 -1
- package/dist/{wizard-abort-lbH6n2WG.js → wizard-abort-DHrEGqaC.js} +1 -1
- package/dist/{wizard-session-DWeUEncV.js → wizard-session-BoXAZEOf.js} +1 -1
- package/dist/{wizard-session-DWeUEncV.js.map → wizard-session-BoXAZEOf.js.map} +1 -1
- package/dist/{wizard-session-B1ZM4OBv.js → wizard-session-C8W_6X0j.js} +1 -1
- package/dist/{wizard-tools-CGrE1O_b.js → wizard-tools-DQTfAzSV.js} +53 -32
- package/dist/wizard-tools-DQTfAzSV.js.map +1 -0
- package/package.json +2 -1
- package/dist/debug-CgdI7Rd-.js.map +0 -1
- package/dist/posthog-integration-CcJWXPDa.js.map +0 -1
- package/dist/start-tui-DKHnPg5a.js.map +0 -1
- package/dist/wizard-tools-CGrE1O_b.js.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { s as logToFile } from "./debug-
|
|
2
|
-
import { a as installSkillById, c as resolveEnvPath, i as fetchSkillMenu, o as mergeEnvValues, s as parseEnvKeys } from "./wizard-tools-
|
|
3
|
-
import { r as detectNodePackageManagers } from "./package-manager-
|
|
1
|
+
import { s as logToFile } from "./debug-D1lORUFs.js";
|
|
2
|
+
import { a as installSkillById, c as resolveEnvPath, i as fetchSkillMenu, o as mergeEnvValues, s as parseEnvKeys } from "./wizard-tools-DQTfAzSV.js";
|
|
3
|
+
import { r as detectNodePackageManagers } from "./package-manager-WKKQADHM.js";
|
|
4
4
|
import fs from "fs";
|
|
5
5
|
import path from "path";
|
|
6
6
|
import { Type } from "typebox";
|
|
@@ -119,4 +119,4 @@ function createWizardPiTools(ctx) {
|
|
|
119
119
|
//#endregion
|
|
120
120
|
export { createWizardPiTools };
|
|
121
121
|
|
|
122
|
-
//# sourceMappingURL=tools-
|
|
122
|
+
//# sourceMappingURL=tools-CbtYlZV4.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools-DdzmiBKF.js","names":[],"sources":["../src/lib/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`, `parseEnvKeys`, `mergeEnvValues`). Same tool names as the\n * MCP server so the shared prompt is unchanged.\n *\n * v1 covers the four tools a framework integration needs. `wizard_ask` is\n * interactive-only (disabled in CI) and the secret-vault `secretRef` path is a\n * follow-up — CI passes literal values.\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 { logToFile } from '@utils/debug';\nimport {\n fetchSkillMenu,\n installSkillById,\n mergeEnvValues,\n parseEnvKeys,\n resolveEnvPath,\n} from '@lib/wizard-tools';\nimport {\n detectNodePackageManagers,\n type PackageManagerDetector,\n} from '@lib/detection/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}\n\nexport function createWizardPiTools(ctx: PiToolsContext): ToolDefinition[] {\n const { workingDirectory, skillsBaseUrl } = ctx;\n const detectPackageManager =\n ctx.detectPackageManager ?? detectNodePackageManagers;\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 );\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:\n 'Check which environment variable keys are present or missing in a .env file. Never reveals values.',\n promptSnippet: 'check_env_keys(filePath, keys) — see which .env keys exist',\n parameters: Type.Object({\n filePath: Type.String({\n description: 'Path to the .env file, relative to the project root',\n }),\n keys: Type.Array(Type.String(), {\n description: 'Environment variable key names to check',\n }),\n }),\n async execute(_id, args) {\n const resolved = resolveEnvPath(workingDirectory, args.filePath);\n const existing = fs.existsSync(resolved)\n ? parseEnvKeys(await fs.promises.readFile(resolved, 'utf8'))\n : new Set<string>();\n const results: Record<string, 'present' | 'missing'> = {};\n for (const key of args.keys) {\n results[key] = existing.has(key) ? 'present' : 'missing';\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). Pass literal string values.',\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: 'Path to the .env file, relative to the project root',\n }),\n values: Type.Record(Type.String(), Type.String(), {\n description: 'Key → literal value',\n }),\n }),\n async execute(_id, args) {\n const forbidden = Object.keys(args.values).find(\n (k) => k.toUpperCase() === 'POSTHOG_KEY',\n );\n if (forbidden) {\n return text(\n `Error: \"${forbidden}\" is not a valid PostHog env var name. Use the framework-specific key (e.g. NEXT_PUBLIC_POSTHOG_PROJECT_TOKEN).`,\n );\n }\n const resolved = resolveEnvPath(workingDirectory, args.filePath);\n const existing = fs.existsSync(resolved)\n ? await fs.promises.readFile(resolved, 'utf8')\n : '';\n const merged = mergeEnvValues(existing, args.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 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 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 return [loadSkillMenu, installSkill, checkEnvKeys, setEnvValues, detectPm];\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tools-CbtYlZV4.js","names":[],"sources":["../src/lib/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`, `parseEnvKeys`, `mergeEnvValues`). Same tool names as the\n * MCP server so the shared prompt is unchanged.\n *\n * v1 covers the four tools a framework integration needs. `wizard_ask` is\n * interactive-only (disabled in CI) and the secret-vault `secretRef` path is a\n * follow-up — CI passes literal values.\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 { logToFile } from '@utils/debug';\nimport {\n fetchSkillMenu,\n installSkillById,\n mergeEnvValues,\n parseEnvKeys,\n resolveEnvPath,\n} from '@lib/wizard-tools';\nimport {\n detectNodePackageManagers,\n type PackageManagerDetector,\n} from '@lib/detection/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}\n\nexport function createWizardPiTools(ctx: PiToolsContext): ToolDefinition[] {\n const { workingDirectory, skillsBaseUrl } = ctx;\n const detectPackageManager =\n ctx.detectPackageManager ?? detectNodePackageManagers;\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 );\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:\n 'Check which environment variable keys are present or missing in a .env file. Never reveals values.',\n promptSnippet: 'check_env_keys(filePath, keys) — see which .env keys exist',\n parameters: Type.Object({\n filePath: Type.String({\n description: 'Path to the .env file, relative to the project root',\n }),\n keys: Type.Array(Type.String(), {\n description: 'Environment variable key names to check',\n }),\n }),\n async execute(_id, args) {\n const resolved = resolveEnvPath(workingDirectory, args.filePath);\n const existing = fs.existsSync(resolved)\n ? parseEnvKeys(await fs.promises.readFile(resolved, 'utf8'))\n : new Set<string>();\n const results: Record<string, 'present' | 'missing'> = {};\n for (const key of args.keys) {\n results[key] = existing.has(key) ? 'present' : 'missing';\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). Pass literal string values.',\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: 'Path to the .env file, relative to the project root',\n }),\n values: Type.Record(Type.String(), Type.String(), {\n description: 'Key → literal value',\n }),\n }),\n async execute(_id, args) {\n const forbidden = Object.keys(args.values).find(\n (k) => k.toUpperCase() === 'POSTHOG_KEY',\n );\n if (forbidden) {\n return text(\n `Error: \"${forbidden}\" is not a valid PostHog env var name. Use the framework-specific key (e.g. NEXT_PUBLIC_POSTHOG_PROJECT_TOKEN).`,\n );\n }\n const resolved = resolveEnvPath(workingDirectory, args.filePath);\n const existing = fs.existsSync(resolved)\n ? await fs.promises.readFile(resolved, 'utf8')\n : '';\n const merged = mergeEnvValues(existing, args.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 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 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 return [loadSkillMenu, installSkill, checkEnvKeys, setEnvValues, detectPm];\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { st as WIZARD_USER_AGENT } from "./debug-D1lORUFs.js";
|
|
2
2
|
import axios from "axios";
|
|
3
3
|
//#region src/utils/urls.ts
|
|
4
4
|
/**
|
|
@@ -64,4 +64,4 @@ const getOAuthUrl = (baseUrl) => resolveBaseUrl(baseUrl) ?? PROD_OAUTH_URL;
|
|
|
64
64
|
//#endregion
|
|
65
65
|
export { getOAuthUrl as a, getLlmGatewayUrl 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-CilgPbS-.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"urls-
|
|
1
|
+
{"version":3,"file":"urls-CilgPbS-.js","names":[],"sources":["../src/utils/urls.ts"],"sourcesContent":["import axios from 'axios';\nimport { IS_DEV, WIZARD_USER_AGENT } from '@lib/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\nexport const getLlmGatewayUrl = (host: string) => {\n if (host.includes('host.docker.internal')) {\n return 'http://host.docker.internal:3308/wizard';\n }\n\n if (host.includes('localhost')) {\n return 'http://localhost:3308/wizard';\n }\n\n if (host.includes('eu.posthog.com') || host.includes('eu.i.posthog.com')) {\n return 'https://gateway.eu.posthog.com/wizard';\n }\n\n return 'https://gateway.us.posthog.com/wizard';\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"],"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;;AAGH,MAAa,oBAAoB,SAAiB;AAChD,KAAI,KAAK,SAAS,uBAAuB,CACvC,QAAO;AAGT,KAAI,KAAK,SAAS,YAAY,CAC5B,QAAO;AAGT,KAAI,KAAK,SAAS,iBAAiB,IAAI,KAAK,SAAS,mBAAmB,CACtE,QAAO;AAGT,QAAO;;;AAIT,MAAM,iBAAiB;;;;;AAMvB,MAAa,eAAe,YAC1B,eAAe,QAAQ,IAAI"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import "./wizard-session-
|
|
1
|
+
import { f as getUI, s as logToFile } from "./debug-D1lORUFs.js";
|
|
2
|
+
import { n as analytics } from "./analytics-Ciob-x8a.js";
|
|
3
|
+
import "./wizard-session-BoXAZEOf.js";
|
|
4
4
|
//#region src/utils/wizard-abort.ts
|
|
5
5
|
/**
|
|
6
6
|
* Single exit point for the wizard. Use instead of process.exit() directly.
|
|
@@ -46,4 +46,4 @@ async function wizardAbort(options) {
|
|
|
46
46
|
//#endregion
|
|
47
47
|
export { wizardAbort as i, registerCleanup as n, runCleanups as r, WizardError as t };
|
|
48
48
|
|
|
49
|
-
//# sourceMappingURL=wizard-abort-
|
|
49
|
+
//# sourceMappingURL=wizard-abort-Cp5Y7f8C.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wizard-abort-
|
|
1
|
+
{"version":3,"file":"wizard-abort-Cp5Y7f8C.js","names":[],"sources":["../src/utils/wizard-abort.ts"],"sourcesContent":["/**\n * Single exit point for the wizard. Use instead of process.exit() directly.\n *\n * Sequence: cleanup -> error capture (optional) -> analytics shutdown -> outro -> process.exit\n *\n * WizardError is a data carrier passed to wizardAbort() for analytics context, never thrown.\n * The legacy abort() in setup-utils.ts delegates here.\n */\nimport { analytics } from './analytics';\nimport { logToFile } from './debug';\nimport { getUI } from '@ui';\nimport { OutroKind, type OutroData } from '@lib/wizard-session';\n\nexport class WizardError extends Error {\n constructor(\n message: string,\n public readonly context?: Record<string, unknown>,\n ) {\n super(message);\n this.name = 'WizardError';\n }\n}\n\ninterface WizardAbortOptions {\n message?: string;\n /** Structured error data. Renders via `outroError` instead of `outro`. */\n outroData?: OutroData;\n error?: Error | WizardError;\n exitCode?: number;\n}\n\nconst cleanupFns: Array<() => void> = [];\n\nexport function registerCleanup(fn: () => void): void {\n cleanupFns.push(fn);\n}\n\nexport function clearCleanup(): void {\n cleanupFns.length = 0;\n}\n\n/** Runs all registered cleanup functions and drains the array. */\nexport function runCleanups(): void {\n const fns = cleanupFns.splice(0);\n for (const fn of fns) {\n try {\n fn();\n } catch {\n /* cleanup should not prevent exit */\n }\n }\n}\n\nexport async function wizardAbort(\n options?: WizardAbortOptions,\n): Promise<never> {\n const {\n message = 'Wizard setup cancelled.',\n outroData,\n error,\n exitCode = 1,\n } = options ?? {};\n\n logToFile(`[wizard-abort] exitCode=${exitCode}, message: ${message}`);\n if (error) {\n logToFile('[wizard-abort] error:', error);\n }\n\n // 1. Run registered cleanup functions\n runCleanups();\n\n // 2. Capture error in analytics (if provided)\n if (error) {\n analytics.captureException(error, {\n ...((error instanceof WizardError && error.context) || {}),\n });\n }\n\n // 3. Shutdown analytics\n await analytics.shutdown(error ? 'error' : 'cancelled');\n\n // 4. Render the error outro. Synthesize OutroData from `message`\n // when the caller didn't provide structured data.\n const ui = getUI();\n ui.outroError(outroData ?? { kind: OutroKind.Error, message });\n\n // 5. Wait for the user to dismiss the outro screen. In a TUI this gives\n // them time to read the error; in non-TUI environments it resolves\n // immediately.\n await ui.waitForOutroDismissed();\n\n // 6. Exit (fires 'exit' event so TUI cleanup runs)\n return process.exit(exitCode);\n}\n"],"mappings":";;;;;;;;;;;;AAaA,IAAa,cAAb,cAAiC,MAAM;CACrC,YACE,SACA,SACA;AACA,QAAM,QAAQ;AAFE,OAAA,UAAA;AAGhB,OAAK,OAAO;;;AAYhB,MAAM,aAAgC,EAAE;AAExC,SAAgB,gBAAgB,IAAsB;AACpD,YAAW,KAAK,GAAG;;;AAQrB,SAAgB,cAAoB;CAClC,MAAM,MAAM,WAAW,OAAO,EAAE;AAChC,MAAK,MAAM,MAAM,IACf,KAAI;AACF,MAAI;SACE;;AAMZ,eAAsB,YACpB,SACgB;CAChB,MAAM,EACJ,UAAU,2BACV,WACA,OACA,WAAW,MACT,WAAW,EAAE;AAEjB,WAAU,2BAA2B,SAAS,aAAa,UAAU;AACrE,KAAI,MACF,WAAU,yBAAyB,MAAM;AAI3C,cAAa;AAGb,KAAI,MACF,WAAU,iBAAiB,OAAO,EAChC,GAAK,iBAAiB,eAAe,MAAM,WAAY,EAAE,EAC1D,CAAC;AAIJ,OAAM,UAAU,SAAS,QAAQ,UAAU,YAAY;CAIvD,MAAM,KAAK,OAAO;AAClB,IAAG,WAAW,aAAa;EAAE,MAAA;EAAuB;EAAS,CAAC;AAK9D,OAAM,GAAG,uBAAuB;AAGhC,QAAO,QAAQ,KAAK,SAAS"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { i as wizardAbort, t as WizardError } from "./wizard-abort-
|
|
1
|
+
import { i as wizardAbort, t as WizardError } from "./wizard-abort-Cp5Y7f8C.js";
|
|
2
2
|
export { WizardError, wizardAbort };
|
|
@@ -96,4 +96,4 @@ function buildSession(args) {
|
|
|
96
96
|
//#endregion
|
|
97
97
|
export { buildSession as a, RunPhase as i, ADDITIONAL_FEATURE_PROMPTS as n, OutroKind as r, ADDITIONAL_FEATURE_LABELS as t };
|
|
98
98
|
|
|
99
|
-
//# sourceMappingURL=wizard-session-
|
|
99
|
+
//# sourceMappingURL=wizard-session-BoXAZEOf.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wizard-session-DWeUEncV.js","names":[],"sources":["../src/lib/wizard-session.ts"],"sourcesContent":["/**\n * WizardSession — single source of truth for every decision the wizard needs.\n *\n * Populated in layers:\n * CLI args / env vars → populate fields directly\n * Auto-detection → framework, typescript, package manager\n * TUI screens → region, framework disambiguation, etc.\n * OAuth → credentials\n *\n * Business logic reads from the session. Never calls a prompt.\n */\n\nimport type { Harness, Integration, Sequence } from './constants';\nimport type { FrameworkConfig } from './framework-config';\nimport type { WizardReadinessResult } from './health-checks/readiness';\nimport type { SettingsConflict } from './agent/claude-settings';\nimport type { ApiUser, ApiProject } from './api';\n\nexport interface Credentials {\n accessToken: string;\n projectApiKey: string;\n host: string;\n projectId: number;\n}\n\nfunction parseProjectIdArg(value: string | undefined): number | undefined {\n if (value === undefined || value === '') return undefined;\n const n = Number(value);\n return Number.isInteger(n) && n > 0 ? n : undefined;\n}\n\nexport type CloudRegion = 'us' | 'eu';\n\n/** Lifecycle phase of the main work (agent run, MCP install, etc.) */\nexport enum RunPhase {\n /** Still gathering input (intro, setup screens) */\n Idle = 'idle',\n /** Main work is in progress */\n Running = 'running',\n /** Main work finished successfully */\n Completed = 'completed',\n /** Main work finished with an error */\n Error = 'error',\n}\n\n/** Features discovered by the feature-discovery subagent */\nexport enum DiscoveredFeature {\n Stripe = 'stripe',\n LLM = 'llm',\n}\n\n/** Additional features the agent can integrate after the main setup */\nexport enum AdditionalFeature {\n LLM = 'llm',\n}\n\n/** Human-readable labels for additional features (used in TUI progress) */\nexport const ADDITIONAL_FEATURE_LABELS: Record<AdditionalFeature, string> = {\n [AdditionalFeature.LLM]: 'LLM analytics',\n};\n\n/** Agent prompts for each additional feature, injected via the stop hook */\nexport const ADDITIONAL_FEATURE_PROMPTS: Record<AdditionalFeature, string> = {\n [AdditionalFeature.LLM]: `Now integrate LLM analytics with PostHog. Use the PostHog MCP server to find the appropriate LLM analytics skill, install it, and follow its workflow. PostHog basics are already installed. Update the setup report markdown file when complete with additions from this task. `,\n};\n\n/** Outcome of the MCP server installation step */\nexport enum McpOutcome {\n NoClients = 'no_clients',\n Skipped = 'skipped',\n Installed = 'installed',\n Failed = 'failed',\n}\n\n/** Outcome kind for the outro screen */\nexport enum OutroKind {\n Success = 'success',\n Error = 'error',\n Cancel = 'cancel',\n}\n\nexport interface OutroData {\n kind: OutroKind;\n /** Main headline (green check for Success, red X for Error, etc.) */\n message?: string;\n /** Free-form body text shown under the headline. Use \\n for paragraph breaks. */\n body?: string;\n /** Success-only: bulleted list of \"what the agent did\" */\n changes?: string[];\n /**\n * Success-only: a prominent, labeled link to where the user should go\n * next (e.g. an inbox the program just configured). Rendered right under\n * the headline and shown verbatim — no UTM tagging — so the URL stays\n * clean and copy-pasteable. Set per-program in buildOutroData.\n */\n primaryLink?: { label: string; url: string };\n /**\n * Success-only: a short \"what to do next\" checklist with its own heading,\n * rendered as a bulleted list. Distinct from `changes`, which recaps what\n * the agent already did.\n */\n nextSteps?: { heading: string; items: string[] };\n docsUrl?: string;\n continueUrl?: string;\n /** Report file the agent wrote (e.g. \"posthog-setup-report.md\") */\n reportFile?: string;\n /** PostHog dashboard URL the program created on the user's behalf. */\n dashboardUrl?: string;\n /** PostHog notebook URL the program uploaded the report to. */\n notebookUrl?: string;\n /**\n * Copy-paste prompt the operator hands to their coding agent to finish the\n * job (work the report's checklist). Printed to the terminal's main buffer on\n * exit (see getExitLine in start-tui.ts) — the TUI's alternate screen is wiped\n * on exit, so the scrollback line is where it survives and can be\n * triple-click-selected. Set per-program in buildOutroData.\n */\n handoffPrompt?: string;\n}\n\n/** A single question rendered by the WizardAsk overlay. */\nexport interface AskQuestion {\n /** Key for the response map */\n id: string;\n prompt: string;\n /** text = single-line free input; single/multi = picker */\n kind: 'single' | 'multi' | 'text';\n /** Required for `single` and `multi`. Ignored for `text`. */\n options?: { label: string; value: string; description?: string }[];\n /** Defaults to true */\n required?: boolean;\n /**\n * Only meaningful for kind='text'. When true, the wizard-tools `wizard_ask`\n * tool stores the user's answer in the session secret vault and returns\n * `{ secretRef }` to the agent instead of the plain string — so the value\n * never enters the LLM conversation. The TUI may also mask input\n * accordingly. See `secret-vault.ts`.\n */\n sensitive?: boolean;\n}\n\n/** Map of question id → answer (string for single/text, string[] for multi). */\nexport type AskAnswers = Record<string, string | string[]>;\n\n/** A pending wizard_ask request held by the store. */\nexport interface PendingQuestion {\n id: string;\n questions: AskQuestion[];\n /** Skill id of the caller. Set by the wizard from session.skillId. */\n source: string;\n /**\n * When true, the ask overlay renders standalone URLs in prompt text as\n * OSC 8 hyperlinks and copies a lone URL to the clipboard. Opt-in per\n * program (set from `ProgramRun.richLinks` via the ask bridge); defaults\n * to false so existing flows render prompts exactly as before. See\n * `LinkText` / `link-helpers`.\n */\n richLinks?: boolean;\n}\n\n/**\n * PostHog dashboard URL emitted by the agent during a program run.\n * Populated via the `[DASHBOARD_URL]` text marker in agent assistant messages\n * — see `handleSDKMessage` in `agent/agent-interface.ts`. Read by programs\n * (e.g. events-audit) inside `buildOutroData` to surface a dashboard link\n * the agent actually created.\n */\n\nexport interface WizardSession {\n // From CLI args\n debug: boolean;\n installDir: string;\n ci: boolean;\n signup: boolean;\n localMcp: boolean;\n mcpFeatures?: string[];\n apiKey?: string;\n email?: string;\n region?: CloudRegion;\n /**\n * Explicit PostHog base URL (`--base-url`). When set, it pins every PostHog\n * origin — API host, cloud/app URL, OAuth server — and `region` is ignored.\n * The runtime equivalent of the dev-build localhost routing; lets the shipped\n * wizard target a local/self-hosted stack. Threaded into the URL helpers in\n * `@utils/urls`. Empty/unset → region-based resolution.\n */\n baseUrl?: string;\n benchmark: boolean;\n yaraReport: boolean;\n projectId?: number;\n noTelemetry: boolean;\n\n /** `--harness` override, read by `resolveHarness`. Wins over the runner flag. */\n harness?: Harness;\n /** `--sequence` override, read in `runProgram`. Wins over the orchestrator flag. */\n sequence?: Sequence;\n /** `--model` override (gateway id), read by `resolveHarness`. Wins over the binding's model. */\n model?: string;\n\n // From detection + screens\n setupConfirmed: boolean;\n integration: Integration | null;\n frameworkContext: Record<string, unknown>;\n typescript: boolean;\n\n /** Human-readable label for the detected framework variant (e.g., \"Django with Wagtail CMS\") */\n detectedFrameworkLabel: string | null;\n\n /** True once framework detection has run (whether it found something or not) */\n detectionComplete: boolean;\n\n /** Set when the detected framework version is too old for the wizard */\n unsupportedVersion: {\n current: string;\n minimum: string;\n docsUrl: string;\n } | null;\n\n // From OAuth\n credentials: Credentials | null;\n\n /**\n * `role_at_organization` from `/api/users/@me/`. Null when the upstream\n * value is missing (older accounts, fresh signups before onboarding).\n * Drives role-tailored MCP prompt suggestions on the McpSuggestedPromptsScreen.\n *\n * Mirrors `apiUser?.role_at_organization` — kept as a top-level convenience\n * because it has dedicated UI semantics (role-tailored kits) and pre-dates\n * the broader `apiUser` plumbing.\n */\n roleAtOrganization: string | null;\n\n /**\n * Full user payload from `/api/users/@me/` — identifiers, profile,\n * current team + organization, preferences, etc. Null until OAuth /\n * CI-key auth populates it. Schema lives in `src/lib/api.ts` and\n * passes through unknown upstream fields so downstream features can\n * read account context (plan, org name, email, etc.) without\n * re-fetching.\n */\n apiUser: ApiUser | null;\n\n /**\n * Cloud region and project payload resolved at authentication, kept so a\n * second agent run in the same invocation (e.g. self-driving's integration\n * phase) reuses the first login wholesale instead of re-authenticating.\n */\n cloudRegion: CloudRegion | null;\n apiProject: ApiProject | null;\n\n // Lifecycle\n runPhase: RunPhase;\n loginUrl: string | null;\n // Direct PostHog authorize URL, shown in the manual-paste modal for\n // headless/remote shells (the localhost loginUrl is unreachable there).\n authorizeUrl: string | null;\n\n // Feature discovery\n discoveredFeatures: DiscoveredFeature[];\n llmOptIn: boolean;\n\n // ScreenId completion\n mcpComplete: boolean;\n mcpOutcome: McpOutcome | null;\n mcpInstalledClients: string[];\n mcpSuggestedPromptsDismissed: boolean;\n /** True once the user has acted on (opened or skipped) the Connect-Slack step. */\n slackStepDismissed: boolean;\n /**\n * Whether the project already has a Slack integration connected.\n * `null` until detected. Prefetched by the tutorial screen as soon as\n * credentials exist so the Connect-Slack step renders the right\n * variant immediately instead of flashing the nudge first.\n */\n slackConnected: boolean | null;\n skillsComplete: boolean;\n outroDismissed: boolean;\n\n /**\n * Self-driving only: whether to integrate PostHog as part of this run.\n * `null` until decided — the integration-check screen asks \"do you already\n * have PostHog?\" and sets it (No → true, Yes → false). The `--integrate`\n * flag pre-sets it to `true`, skipping the question. When `true`, the\n * self-driving prompt has the agent set up the SDK before the Self-driving\n * steps. Unused by other programs.\n */\n integrate: boolean | null;\n\n /**\n * Ids of composed run steps that have completed — e.g. self-driving's\n * `integrate-run`. Lets a run step's `isComplete` hold after it ran,\n * independent of the shared `runPhase`.\n */\n completedRuns: string[];\n\n /**\n * Self-driving only: whether the user confirmed the handoff screen shown\n * after the integration run (\"PostHog is installed — now set up Self-driving\").\n * Gates the Self-driving run so it doesn't start until acknowledged. Only\n * reached in the integrate path; the already-has-PostHog path skips it.\n */\n selfDrivingHandoffConfirmed: boolean;\n\n // Runtime\n readinessResult: WizardReadinessResult | null;\n outageDismissed: boolean;\n settingsOverrideKeys: string[] | null;\n settingsConflicts: SettingsConflict[] | null;\n authErrorDetail: {\n hasSettingsConflict: boolean;\n conflicts?: SettingsConflict[];\n logFilePath: string;\n } | null;\n portConflictProcess: {\n command: string;\n pid: string;\n port: number;\n user: string;\n } | null;\n outroData: OutroData | null;\n dashboardUrl: string | null;\n notebookUrl: string | null;\n\n // Additional features queue (drained via stop hook after main integration)\n additionalFeatureQueue: AdditionalFeature[];\n\n // Program metadata (set by runWizard in bin.ts)\n programLabel: string | null;\n skillId: string | null;\n\n // Resolved framework config (set after integration is known)\n frameworkConfig: FrameworkConfig | null;\n\n /** Active wizard_ask request, set by the bridge when the agent calls the tool. */\n pendingQuestion: PendingQuestion | null;\n}\n\n/**\n * Build a WizardSession from CLI args, pre-populating whatever is known.\n */\nexport function buildSession(args: {\n debug?: boolean;\n installDir?: string;\n ci?: boolean;\n signup?: boolean;\n localMcp?: boolean;\n mcpFeatures?: string[];\n apiKey?: string;\n email?: string;\n region?: CloudRegion;\n baseUrl?: string;\n integration?: Integration;\n benchmark?: boolean;\n yaraReport?: boolean;\n projectId?: string;\n noTelemetry?: boolean;\n harness?: Harness;\n sequence?: Sequence;\n model?: string;\n integrate?: boolean;\n}): WizardSession {\n return {\n debug: args.debug ?? false,\n installDir: args.installDir ?? process.cwd(),\n ci: args.ci ?? false,\n signup: args.signup ?? false,\n localMcp: args.localMcp ?? false,\n mcpFeatures: args.mcpFeatures,\n apiKey: args.apiKey,\n email: args.email,\n region: args.region,\n baseUrl: args.baseUrl,\n benchmark: args.benchmark ?? false,\n yaraReport: args.yaraReport ?? false,\n projectId: parseProjectIdArg(args.projectId),\n noTelemetry: args.noTelemetry ?? false,\n harness: args.harness,\n sequence: args.sequence,\n model: args.model,\n\n setupConfirmed: false,\n integration: args.integration ?? null,\n frameworkContext: {},\n typescript: false,\n detectedFrameworkLabel: null,\n detectionComplete: false,\n unsupportedVersion: null,\n\n runPhase: RunPhase.Idle,\n discoveredFeatures: [],\n llmOptIn: false,\n mcpComplete: false,\n mcpOutcome: null,\n mcpInstalledClients: [],\n mcpSuggestedPromptsDismissed: false,\n slackStepDismissed: false,\n slackConnected: null,\n skillsComplete: false,\n outroDismissed: false,\n // `--integrate` forces integration (skip the question); otherwise the\n // integration-check screen resolves it from null.\n integrate: args.integrate === true ? true : null,\n completedRuns: [],\n selfDrivingHandoffConfirmed: false,\n loginUrl: null,\n authorizeUrl: null,\n credentials: null,\n roleAtOrganization: null,\n apiUser: null,\n cloudRegion: null,\n apiProject: null,\n readinessResult: null,\n outageDismissed: false,\n settingsOverrideKeys: null,\n settingsConflicts: null,\n authErrorDetail: null,\n portConflictProcess: null,\n outroData: null,\n dashboardUrl: null,\n notebookUrl: null,\n additionalFeatureQueue: [],\n programLabel: null,\n skillId: null,\n frameworkConfig: null,\n pendingQuestion: null,\n };\n}\n"],"mappings":";AAyBA,SAAS,kBAAkB,OAA+C;AACxE,KAAI,UAAU,KAAA,KAAa,UAAU,GAAI,QAAO,KAAA;CAChD,MAAM,IAAI,OAAO,MAAM;AACvB,QAAO,OAAO,UAAU,EAAE,IAAI,IAAI,IAAI,IAAI,KAAA;;;AAM5C,IAAY,WAAL,yBAAA,UAAA;;AAEL,UAAA,UAAA;;AAEA,UAAA,aAAA;;AAEA,UAAA,eAAA;;AAEA,UAAA,WAAA;;KACD;;AAcD,MAAa,4BAA+D,GAAA,QACjD,iBAC1B;;AAGD,MAAa,6BAAgE,GAAA,QAClD,oRAC1B;;AAWD,IAAY,YAAL,yBAAA,WAAA;AACL,WAAA,aAAA;AACA,WAAA,WAAA;AACA,WAAA,YAAA;;KACD;;;;AAqQD,SAAgB,aAAa,MAoBX;AAChB,QAAO;EACL,OAAO,KAAK,SAAS;EACrB,YAAY,KAAK,cAAc,QAAQ,KAAK;EAC5C,IAAI,KAAK,MAAM;EACf,QAAQ,KAAK,UAAU;EACvB,UAAU,KAAK,YAAY;EAC3B,aAAa,KAAK;EAClB,QAAQ,KAAK;EACb,OAAO,KAAK;EACZ,QAAQ,KAAK;EACb,SAAS,KAAK;EACd,WAAW,KAAK,aAAa;EAC7B,YAAY,KAAK,cAAc;EAC/B,WAAW,kBAAkB,KAAK,UAAU;EAC5C,aAAa,KAAK,eAAe;EACjC,SAAS,KAAK;EACd,UAAU,KAAK;EACf,OAAO,KAAK;EAEZ,gBAAgB;EAChB,aAAa,KAAK,eAAe;EACjC,kBAAkB,EAAE;EACpB,YAAY;EACZ,wBAAwB;EACxB,mBAAmB;EACnB,oBAAoB;EAEpB,UAAA;EACA,oBAAoB,EAAE;EACtB,UAAU;EACV,aAAa;EACb,YAAY;EACZ,qBAAqB,EAAE;EACvB,8BAA8B;EAC9B,oBAAoB;EACpB,gBAAgB;EAChB,gBAAgB;EAChB,gBAAgB;EAGhB,WAAW,KAAK,cAAc,OAAO,OAAO;EAC5C,eAAe,EAAE;EACjB,6BAA6B;EAC7B,UAAU;EACV,cAAc;EACd,aAAa;EACb,oBAAoB;EACpB,SAAS;EACT,aAAa;EACb,YAAY;EACZ,iBAAiB;EACjB,iBAAiB;EACjB,sBAAsB;EACtB,mBAAmB;EACnB,iBAAiB;EACjB,qBAAqB;EACrB,WAAW;EACX,cAAc;EACd,aAAa;EACb,wBAAwB,EAAE;EAC1B,cAAc;EACd,SAAS;EACT,iBAAiB;EACjB,iBAAiB;EAClB"}
|
|
1
|
+
{"version":3,"file":"wizard-session-BoXAZEOf.js","names":[],"sources":["../src/lib/wizard-session.ts"],"sourcesContent":["/**\n * WizardSession — single source of truth for every decision the wizard needs.\n *\n * Populated in layers:\n * CLI args / env vars → populate fields directly\n * Auto-detection → framework, typescript, package manager\n * TUI screens → region, framework disambiguation, etc.\n * OAuth → credentials\n *\n * Business logic reads from the session. Never calls a prompt.\n */\n\nimport type { Harness, Integration, Sequence } from './constants';\nimport type { FrameworkConfig } from './framework-config';\nimport type { WizardReadinessResult } from './health-checks/readiness';\nimport type { SettingsConflict } from './agent/claude-settings';\nimport type { ApiUser, ApiProject } from './api';\n\nexport interface Credentials {\n accessToken: string;\n projectApiKey: string;\n host: string;\n projectId: number;\n}\n\nfunction parseProjectIdArg(value: string | undefined): number | undefined {\n if (value === undefined || value === '') return undefined;\n const n = Number(value);\n return Number.isInteger(n) && n > 0 ? n : undefined;\n}\n\nexport type CloudRegion = 'us' | 'eu';\n\n/** Lifecycle phase of the main work (agent run, MCP install, etc.) */\nexport enum RunPhase {\n /** Still gathering input (intro, setup screens) */\n Idle = 'idle',\n /** Main work is in progress */\n Running = 'running',\n /** Main work finished successfully */\n Completed = 'completed',\n /** Main work finished with an error */\n Error = 'error',\n}\n\n/** Features discovered by the feature-discovery subagent */\nexport enum DiscoveredFeature {\n Stripe = 'stripe',\n LLM = 'llm',\n}\n\n/** Additional features the agent can integrate after the main setup */\nexport enum AdditionalFeature {\n LLM = 'llm',\n}\n\n/** Human-readable labels for additional features (used in TUI progress) */\nexport const ADDITIONAL_FEATURE_LABELS: Record<AdditionalFeature, string> = {\n [AdditionalFeature.LLM]: 'LLM analytics',\n};\n\n/** Agent prompts for each additional feature, injected via the stop hook */\nexport const ADDITIONAL_FEATURE_PROMPTS: Record<AdditionalFeature, string> = {\n [AdditionalFeature.LLM]: `Now integrate LLM analytics with PostHog. Use the PostHog MCP server to find the appropriate LLM analytics skill, install it, and follow its workflow. PostHog basics are already installed. Update the setup report markdown file when complete with additions from this task. `,\n};\n\n/** Outcome of the MCP server installation step */\nexport enum McpOutcome {\n NoClients = 'no_clients',\n Skipped = 'skipped',\n Installed = 'installed',\n Failed = 'failed',\n}\n\n/** Outcome kind for the outro screen */\nexport enum OutroKind {\n Success = 'success',\n Error = 'error',\n Cancel = 'cancel',\n}\n\nexport interface OutroData {\n kind: OutroKind;\n /** Main headline (green check for Success, red X for Error, etc.) */\n message?: string;\n /** Free-form body text shown under the headline. Use \\n for paragraph breaks. */\n body?: string;\n /** Success-only: bulleted list of \"what the agent did\" */\n changes?: string[];\n /**\n * Success-only: a prominent, labeled link to where the user should go\n * next (e.g. an inbox the program just configured). Rendered right under\n * the headline and shown verbatim — no UTM tagging — so the URL stays\n * clean and copy-pasteable. Set per-program in buildOutroData.\n */\n primaryLink?: { label: string; url: string };\n /**\n * Success-only: a short \"what to do next\" checklist with its own heading,\n * rendered as a bulleted list. Distinct from `changes`, which recaps what\n * the agent already did.\n */\n nextSteps?: { heading: string; items: string[] };\n docsUrl?: string;\n continueUrl?: string;\n /** Report file the agent wrote (e.g. \"posthog-setup-report.md\") */\n reportFile?: string;\n /** PostHog dashboard URL the program created on the user's behalf. */\n dashboardUrl?: string;\n /** PostHog notebook URL the program uploaded the report to. */\n notebookUrl?: string;\n /**\n * Copy-paste prompt the operator hands to their coding agent to finish the\n * job (work the report's checklist). Printed to the terminal's main buffer on\n * exit (see getExitLine in start-tui.ts) — the TUI's alternate screen is wiped\n * on exit, so the scrollback line is where it survives and can be\n * triple-click-selected. Set per-program in buildOutroData.\n */\n handoffPrompt?: string;\n}\n\n/** A single question rendered by the WizardAsk overlay. */\nexport interface AskQuestion {\n /** Key for the response map */\n id: string;\n prompt: string;\n /** text = single-line free input; single/multi = picker */\n kind: 'single' | 'multi' | 'text';\n /** Required for `single` and `multi`. Ignored for `text`. */\n options?: { label: string; value: string; description?: string }[];\n /** Defaults to true */\n required?: boolean;\n /**\n * Only meaningful for kind='text'. When true, the wizard-tools `wizard_ask`\n * tool stores the user's answer in the session secret vault and returns\n * `{ secretRef }` to the agent instead of the plain string — so the value\n * never enters the LLM conversation. The TUI may also mask input\n * accordingly. See `secret-vault.ts`.\n */\n sensitive?: boolean;\n}\n\n/** Map of question id → answer (string for single/text, string[] for multi). */\nexport type AskAnswers = Record<string, string | string[]>;\n\n/** A pending wizard_ask request held by the store. */\nexport interface PendingQuestion {\n id: string;\n questions: AskQuestion[];\n /** Skill id of the caller. Set by the wizard from session.skillId. */\n source: string;\n /**\n * When true, the ask overlay renders standalone URLs in prompt text as\n * OSC 8 hyperlinks and copies a lone URL to the clipboard. Opt-in per\n * program (set from `ProgramRun.richLinks` via the ask bridge); defaults\n * to false so existing flows render prompts exactly as before. See\n * `LinkText` / `link-helpers`.\n */\n richLinks?: boolean;\n}\n\n/**\n * PostHog dashboard URL emitted by the agent during a program run.\n * Populated via the `[DASHBOARD_URL]` text marker in agent assistant messages\n * — see `handleSDKMessage` in `agent/agent-interface.ts`. Read by programs\n * (e.g. events-audit) inside `buildOutroData` to surface a dashboard link\n * the agent actually created.\n */\n\nexport interface WizardSession {\n // From CLI args\n debug: boolean;\n installDir: string;\n ci: boolean;\n signup: boolean;\n localMcp: boolean;\n mcpFeatures?: string[];\n apiKey?: string;\n email?: string;\n region?: CloudRegion;\n /**\n * Explicit PostHog base URL (`--base-url`). When set, it pins every PostHog\n * origin — API host, cloud/app URL, OAuth server — and `region` is ignored.\n * The runtime equivalent of the dev-build localhost routing; lets the shipped\n * wizard target a local/self-hosted stack. Threaded into the URL helpers in\n * `@utils/urls`. Empty/unset → region-based resolution.\n */\n baseUrl?: string;\n benchmark: boolean;\n yaraReport: boolean;\n projectId?: number;\n noTelemetry: boolean;\n\n /** `--harness` override, read by `resolveHarness`. Wins over the runner flag. */\n harness?: Harness;\n /** `--sequence` override, read in `runProgram`. Wins over the orchestrator flag. */\n sequence?: Sequence;\n /** `--model` override (gateway id), read by `resolveHarness`. Wins over the binding's model. */\n model?: string;\n\n // From detection + screens\n setupConfirmed: boolean;\n integration: Integration | null;\n frameworkContext: Record<string, unknown>;\n typescript: boolean;\n\n /** Human-readable label for the detected framework variant (e.g., \"Django with Wagtail CMS\") */\n detectedFrameworkLabel: string | null;\n\n /** True once framework detection has run (whether it found something or not) */\n detectionComplete: boolean;\n\n /** Set when the detected framework version is too old for the wizard */\n unsupportedVersion: {\n current: string;\n minimum: string;\n docsUrl: string;\n } | null;\n\n // From OAuth\n credentials: Credentials | null;\n\n /**\n * `role_at_organization` from `/api/users/@me/`. Null when the upstream\n * value is missing (older accounts, fresh signups before onboarding).\n * Drives role-tailored MCP prompt suggestions on the McpSuggestedPromptsScreen.\n *\n * Mirrors `apiUser?.role_at_organization` — kept as a top-level convenience\n * because it has dedicated UI semantics (role-tailored kits) and pre-dates\n * the broader `apiUser` plumbing.\n */\n roleAtOrganization: string | null;\n\n /**\n * Full user payload from `/api/users/@me/` — identifiers, profile,\n * current team + organization, preferences, etc. Null until OAuth /\n * CI-key auth populates it. Schema lives in `src/lib/api.ts` and\n * passes through unknown upstream fields so downstream features can\n * read account context (plan, org name, email, etc.) without\n * re-fetching.\n */\n apiUser: ApiUser | null;\n\n /**\n * Cloud region and project payload resolved at authentication, kept so a\n * second agent run in the same invocation (e.g. self-driving's integration\n * phase) reuses the first login wholesale instead of re-authenticating.\n */\n cloudRegion: CloudRegion | null;\n apiProject: ApiProject | null;\n\n // Lifecycle\n runPhase: RunPhase;\n loginUrl: string | null;\n // Direct PostHog authorize URL, shown in the manual-paste modal for\n // headless/remote shells (the localhost loginUrl is unreachable there).\n authorizeUrl: string | null;\n\n // Feature discovery\n discoveredFeatures: DiscoveredFeature[];\n llmOptIn: boolean;\n\n // ScreenId completion\n mcpComplete: boolean;\n mcpOutcome: McpOutcome | null;\n mcpInstalledClients: string[];\n mcpSuggestedPromptsDismissed: boolean;\n /** True once the user has acted on (opened or skipped) the Connect-Slack step. */\n slackStepDismissed: boolean;\n /**\n * Whether the project already has a Slack integration connected.\n * `null` until detected. Prefetched by the tutorial screen as soon as\n * credentials exist so the Connect-Slack step renders the right\n * variant immediately instead of flashing the nudge first.\n */\n slackConnected: boolean | null;\n skillsComplete: boolean;\n outroDismissed: boolean;\n\n /**\n * Self-driving only: whether to integrate PostHog as part of this run.\n * `null` until decided — the integration-check screen asks \"do you already\n * have PostHog?\" and sets it (No → true, Yes → false). The `--integrate`\n * flag pre-sets it to `true`, skipping the question. When `true`, the\n * self-driving prompt has the agent set up the SDK before the Self-driving\n * steps. Unused by other programs.\n */\n integrate: boolean | null;\n\n /**\n * Ids of composed run steps that have completed — e.g. self-driving's\n * `integrate-run`. Lets a run step's `isComplete` hold after it ran,\n * independent of the shared `runPhase`.\n */\n completedRuns: string[];\n\n /**\n * Self-driving only: whether the user confirmed the handoff screen shown\n * after the integration run (\"PostHog is installed — now set up Self-driving\").\n * Gates the Self-driving run so it doesn't start until acknowledged. Only\n * reached in the integrate path; the already-has-PostHog path skips it.\n */\n selfDrivingHandoffConfirmed: boolean;\n\n // Runtime\n readinessResult: WizardReadinessResult | null;\n outageDismissed: boolean;\n settingsOverrideKeys: string[] | null;\n settingsConflicts: SettingsConflict[] | null;\n authErrorDetail: {\n hasSettingsConflict: boolean;\n conflicts?: SettingsConflict[];\n logFilePath: string;\n } | null;\n portConflictProcess: {\n command: string;\n pid: string;\n port: number;\n user: string;\n } | null;\n outroData: OutroData | null;\n dashboardUrl: string | null;\n notebookUrl: string | null;\n\n // Additional features queue (drained via stop hook after main integration)\n additionalFeatureQueue: AdditionalFeature[];\n\n // Program metadata (set by runWizard in bin.ts)\n programLabel: string | null;\n skillId: string | null;\n\n // Resolved framework config (set after integration is known)\n frameworkConfig: FrameworkConfig | null;\n\n /** Active wizard_ask request, set by the bridge when the agent calls the tool. */\n pendingQuestion: PendingQuestion | null;\n}\n\n/**\n * Build a WizardSession from CLI args, pre-populating whatever is known.\n */\nexport function buildSession(args: {\n debug?: boolean;\n installDir?: string;\n ci?: boolean;\n signup?: boolean;\n localMcp?: boolean;\n mcpFeatures?: string[];\n apiKey?: string;\n email?: string;\n region?: CloudRegion;\n baseUrl?: string;\n integration?: Integration;\n benchmark?: boolean;\n yaraReport?: boolean;\n projectId?: string;\n noTelemetry?: boolean;\n harness?: Harness;\n sequence?: Sequence;\n model?: string;\n integrate?: boolean;\n}): WizardSession {\n return {\n debug: args.debug ?? false,\n installDir: args.installDir ?? process.cwd(),\n ci: args.ci ?? false,\n signup: args.signup ?? false,\n localMcp: args.localMcp ?? false,\n mcpFeatures: args.mcpFeatures,\n apiKey: args.apiKey,\n email: args.email,\n region: args.region,\n baseUrl: args.baseUrl,\n benchmark: args.benchmark ?? false,\n yaraReport: args.yaraReport ?? false,\n projectId: parseProjectIdArg(args.projectId),\n noTelemetry: args.noTelemetry ?? false,\n harness: args.harness,\n sequence: args.sequence,\n model: args.model,\n\n setupConfirmed: false,\n integration: args.integration ?? null,\n frameworkContext: {},\n typescript: false,\n detectedFrameworkLabel: null,\n detectionComplete: false,\n unsupportedVersion: null,\n\n runPhase: RunPhase.Idle,\n discoveredFeatures: [],\n llmOptIn: false,\n mcpComplete: false,\n mcpOutcome: null,\n mcpInstalledClients: [],\n mcpSuggestedPromptsDismissed: false,\n slackStepDismissed: false,\n slackConnected: null,\n skillsComplete: false,\n outroDismissed: false,\n // `--integrate` forces integration (skip the question); otherwise the\n // integration-check screen resolves it from null.\n integrate: args.integrate === true ? true : null,\n completedRuns: [],\n selfDrivingHandoffConfirmed: false,\n loginUrl: null,\n authorizeUrl: null,\n credentials: null,\n roleAtOrganization: null,\n apiUser: null,\n cloudRegion: null,\n apiProject: null,\n readinessResult: null,\n outageDismissed: false,\n settingsOverrideKeys: null,\n settingsConflicts: null,\n authErrorDetail: null,\n portConflictProcess: null,\n outroData: null,\n dashboardUrl: null,\n notebookUrl: null,\n additionalFeatureQueue: [],\n programLabel: null,\n skillId: null,\n frameworkConfig: null,\n pendingQuestion: null,\n };\n}\n"],"mappings":";AAyBA,SAAS,kBAAkB,OAA+C;AACxE,KAAI,UAAU,KAAA,KAAa,UAAU,GAAI,QAAO,KAAA;CAChD,MAAM,IAAI,OAAO,MAAM;AACvB,QAAO,OAAO,UAAU,EAAE,IAAI,IAAI,IAAI,IAAI,KAAA;;;AAM5C,IAAY,WAAL,yBAAA,UAAA;;AAEL,UAAA,UAAA;;AAEA,UAAA,aAAA;;AAEA,UAAA,eAAA;;AAEA,UAAA,WAAA;;KACD;;AAcD,MAAa,4BAA+D,GAAA,QACjD,iBAC1B;;AAGD,MAAa,6BAAgE,GAAA,QAClD,oRAC1B;;AAWD,IAAY,YAAL,yBAAA,WAAA;AACL,WAAA,aAAA;AACA,WAAA,WAAA;AACA,WAAA,YAAA;;KACD;;;;AAqQD,SAAgB,aAAa,MAoBX;AAChB,QAAO;EACL,OAAO,KAAK,SAAS;EACrB,YAAY,KAAK,cAAc,QAAQ,KAAK;EAC5C,IAAI,KAAK,MAAM;EACf,QAAQ,KAAK,UAAU;EACvB,UAAU,KAAK,YAAY;EAC3B,aAAa,KAAK;EAClB,QAAQ,KAAK;EACb,OAAO,KAAK;EACZ,QAAQ,KAAK;EACb,SAAS,KAAK;EACd,WAAW,KAAK,aAAa;EAC7B,YAAY,KAAK,cAAc;EAC/B,WAAW,kBAAkB,KAAK,UAAU;EAC5C,aAAa,KAAK,eAAe;EACjC,SAAS,KAAK;EACd,UAAU,KAAK;EACf,OAAO,KAAK;EAEZ,gBAAgB;EAChB,aAAa,KAAK,eAAe;EACjC,kBAAkB,EAAE;EACpB,YAAY;EACZ,wBAAwB;EACxB,mBAAmB;EACnB,oBAAoB;EAEpB,UAAA;EACA,oBAAoB,EAAE;EACtB,UAAU;EACV,aAAa;EACb,YAAY;EACZ,qBAAqB,EAAE;EACvB,8BAA8B;EAC9B,oBAAoB;EACpB,gBAAgB;EAChB,gBAAgB;EAChB,gBAAgB;EAGhB,WAAW,KAAK,cAAc,OAAO,OAAO;EAC5C,eAAe,EAAE;EACjB,6BAA6B;EAC7B,UAAU;EACV,cAAc;EACd,aAAa;EACb,oBAAoB;EACpB,SAAS;EACT,aAAa;EACb,YAAY;EACZ,iBAAiB;EACjB,iBAAiB;EACjB,sBAAsB;EACtB,mBAAmB;EACnB,iBAAiB;EACjB,qBAAqB;EACrB,WAAW;EACX,cAAc;EACd,aAAa;EACb,wBAAwB,EAAE;EAC1B,cAAc;EACd,SAAS;EACT,iBAAiB;EACjB,iBAAiB;EAClB"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as buildSession, i as RunPhase, r as OutroKind } from "./wizard-session-
|
|
1
|
+
import { a as buildSession, i as RunPhase, r as OutroKind } from "./wizard-session-BoXAZEOf.js";
|
|
2
2
|
export { OutroKind, RunPhase, buildSession };
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { s as logToFile } from "./debug-D1lORUFs.js";
|
|
2
|
+
import { n as analytics } from "./analytics-Ciob-x8a.js";
|
|
3
3
|
import * as fs$1 from "fs";
|
|
4
4
|
import fs from "fs";
|
|
5
5
|
import * as path$1 from "path";
|
|
6
6
|
import path from "path";
|
|
7
7
|
import { z } from "zod";
|
|
8
|
-
import {
|
|
8
|
+
import { unzipSync } from "fflate";
|
|
9
9
|
import { randomUUID } from "crypto";
|
|
10
10
|
//#region src/utils/atomic-ledger.ts
|
|
11
11
|
/**
|
|
@@ -554,36 +554,49 @@ async function fetchSkillMenu(skillsBaseUrl) {
|
|
|
554
554
|
return null;
|
|
555
555
|
}
|
|
556
556
|
}
|
|
557
|
+
/** Extract a zip buffer, refusing entries that escape destDir (zip-slip). */
|
|
558
|
+
function extractZipArchive(zip, destDir) {
|
|
559
|
+
const root = path.resolve(destDir);
|
|
560
|
+
let written = 0;
|
|
561
|
+
for (const [entryPath, data] of Object.entries(unzipSync(zip))) {
|
|
562
|
+
const target = path.resolve(root, entryPath);
|
|
563
|
+
if (target !== root && !target.startsWith(root + path.sep)) throw new Error(`zip entry escapes destination: ${entryPath}`);
|
|
564
|
+
if (entryPath.endsWith("/")) {
|
|
565
|
+
fs.mkdirSync(target, { recursive: true });
|
|
566
|
+
continue;
|
|
567
|
+
}
|
|
568
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
569
|
+
fs.writeFileSync(target, data);
|
|
570
|
+
written++;
|
|
571
|
+
}
|
|
572
|
+
return written;
|
|
573
|
+
}
|
|
557
574
|
/**
|
|
558
575
|
* Download and extract a skill.
|
|
559
576
|
* By default installs to `<installDir>/.claude/skills/<id>/`.
|
|
560
577
|
* Pass `skillsRoot` to override the base directory (e.g. `.posthog/skills`).
|
|
561
578
|
*/
|
|
562
|
-
function downloadSkill(skillEntry, installDir, skillsRoot) {
|
|
579
|
+
async function downloadSkill(skillEntry, installDir, skillsRoot) {
|
|
563
580
|
const skillDir = skillsRoot ? path.join(installDir, skillsRoot, skillEntry.id) : path.join(installDir, ".claude", "skills", skillEntry.id);
|
|
564
|
-
|
|
581
|
+
let step = "download";
|
|
565
582
|
try {
|
|
566
583
|
fs.mkdirSync(skillDir, { recursive: true });
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
], { timeout: 3e4 });
|
|
573
|
-
execFileSync("unzip", [
|
|
574
|
-
"-o",
|
|
575
|
-
tmpFile,
|
|
576
|
-
"-d",
|
|
577
|
-
skillDir
|
|
578
|
-
], { timeout: 3e4 });
|
|
584
|
+
const resp = await fetch(skillEntry.downloadUrl, { signal: AbortSignal.timeout(3e4) });
|
|
585
|
+
if (!resp.ok) throw new Error(`download failed with HTTP ${resp.status}`);
|
|
586
|
+
const zip = new Uint8Array(await resp.arrayBuffer());
|
|
587
|
+
step = "extract";
|
|
588
|
+
const fileCount = extractZipArchive(zip, skillDir);
|
|
579
589
|
fs.writeFileSync(path.join(skillDir, ".posthog-wizard"), "");
|
|
580
|
-
|
|
581
|
-
fs.unlinkSync(tmpFile);
|
|
582
|
-
} catch {}
|
|
583
|
-
logToFile(`downloadSkill: installed ${skillEntry.id} from ${skillEntry.downloadUrl}`);
|
|
590
|
+
logToFile(`downloadSkill: installed ${skillEntry.id} from ${skillEntry.downloadUrl} (${fileCount} files)`);
|
|
584
591
|
return { success: true };
|
|
585
592
|
} catch (err) {
|
|
586
593
|
logToFile(`downloadSkill: error: ${err.message}`);
|
|
594
|
+
analytics.wizardCapture("skill install failed", {
|
|
595
|
+
skill_id: skillEntry.id,
|
|
596
|
+
step,
|
|
597
|
+
platform: process.platform,
|
|
598
|
+
error: String(err.message).slice(0, 500)
|
|
599
|
+
});
|
|
587
600
|
return {
|
|
588
601
|
success: false,
|
|
589
602
|
error: err.message
|
|
@@ -603,7 +616,7 @@ async function installSkillById(skillId, installDir, skillsBaseUrl, skillsRoot)
|
|
|
603
616
|
kind: "skill-not-found",
|
|
604
617
|
skillId
|
|
605
618
|
};
|
|
606
|
-
const result = downloadSkill(skill, installDir, skillsRoot);
|
|
619
|
+
const result = await downloadSkill(skill, installDir, skillsRoot);
|
|
607
620
|
if (!result.success) return {
|
|
608
621
|
kind: "download-failed",
|
|
609
622
|
message: result.error ?? "unknown"
|
|
@@ -885,7 +898,7 @@ async function createWizardToolsServer(options) {
|
|
|
885
898
|
text: menuText
|
|
886
899
|
}] };
|
|
887
900
|
});
|
|
888
|
-
const installSkill = tool("install_skill", "Download and install a PostHog skill by ID. Call load_skill_menu first to see available skills. Extracts the skill to .claude/skills/<skillId>/.", { skillId: z.string().describe("Skill ID from the skill menu (e.g., \"integration-nextjs-app-router\")") }, (args) => {
|
|
901
|
+
const installSkill = tool("install_skill", "Download and install a PostHog skill by ID. Call load_skill_menu first to see available skills. Extracts the skill to .claude/skills/<skillId>/.", { skillId: z.string().describe("Skill ID from the skill menu (e.g., \"integration-nextjs-app-router\")") }, async (args) => {
|
|
889
902
|
if (!/^[a-z0-9][a-z0-9_-]*$/.test(args.skillId)) return {
|
|
890
903
|
content: [{
|
|
891
904
|
type: "text",
|
|
@@ -901,18 +914,26 @@ async function createWizardToolsServer(options) {
|
|
|
901
914
|
}],
|
|
902
915
|
isError: true
|
|
903
916
|
};
|
|
904
|
-
const result = downloadSkill(skill, workingDirectory);
|
|
917
|
+
const result = await downloadSkill(skill, workingDirectory);
|
|
905
918
|
if (result.success) return { content: [{
|
|
906
919
|
type: "text",
|
|
907
920
|
text: `Skill installed to .claude/skills/${args.skillId}/`
|
|
908
921
|
}] };
|
|
909
|
-
else
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
922
|
+
else {
|
|
923
|
+
analytics.captureException(/* @__PURE__ */ new Error("Skill install failed: download-failed"), {
|
|
924
|
+
source: "install_skill_tool",
|
|
925
|
+
skill_id: args.skillId,
|
|
926
|
+
error_detail: String(result.error).slice(0, 500),
|
|
927
|
+
platform: process.platform
|
|
928
|
+
});
|
|
929
|
+
return {
|
|
930
|
+
content: [{
|
|
931
|
+
type: "text",
|
|
932
|
+
text: `Error installing skill: ${result.error}`
|
|
933
|
+
}],
|
|
934
|
+
isError: true
|
|
935
|
+
};
|
|
936
|
+
}
|
|
916
937
|
});
|
|
917
938
|
const auditLedgerPath = path.join(workingDirectory, AUDIT_CHECKS_FILE);
|
|
918
939
|
const auditMutex = makeMutex();
|
|
@@ -1104,4 +1125,4 @@ const WIZARD_TOOL_NAMES = {
|
|
|
1104
1125
|
//#endregion
|
|
1105
1126
|
export { coerceAuditChecks as _, installSkillById as a, resolveEnvPath as c, TaskStatus as d, createWizardAskBridge as f, AUDIT_SEVERITY_STYLE as g, AUDIT_REPORT_FILE as h, fetchSkillMenu as i, QUEUE_DIR_NAME as l, AUDIT_CHECKS_KEY as m, createWizardToolsServer as n, mergeEnvValues as o, AUDIT_CHECKS_FILE as p, downloadSkill as r, parseEnvKeys as s, WIZARD_TOOL_NAMES as t, QueueStore as u, getAuditChecks as v };
|
|
1106
1127
|
|
|
1107
|
-
//# sourceMappingURL=wizard-tools-
|
|
1128
|
+
//# sourceMappingURL=wizard-tools-DQTfAzSV.js.map
|