@posthog/wizard 2.16.1 → 2.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/dist/{TextBlock-CdeZog_6.js → TextBlock-D0Ep3zC9.js} +2 -2
  2. package/dist/{TextBlock-CdeZog_6.js.map → TextBlock-D0Ep3zC9.js.map} +1 -1
  3. package/dist/{add-mcp-server-to-clients-BS6Rjcwh.js → add-mcp-server-to-clients-D4PK6ulR.js} +38 -5
  4. package/dist/add-mcp-server-to-clients-D4PK6ulR.js.map +1 -0
  5. package/dist/{agent-interface-B4eUlMso.js → agent-interface-7t5DBo2A.js} +7 -7
  6. package/dist/{agent-interface-B4eUlMso.js.map → agent-interface-7t5DBo2A.js.map} +1 -1
  7. package/dist/{agent-runner-BxqiKVEf.js → agent-runner-CTkKLVhp.js} +8 -7
  8. package/dist/{agent-runner-BxqiKVEf.js.map → agent-runner-CTkKLVhp.js.map} +1 -1
  9. package/dist/{analytics-DUuUurR3.js → analytics-DN_Gy87F.js} +2 -2
  10. package/dist/{analytics-DUuUurR3.js.map → analytics-DN_Gy87F.js.map} +1 -1
  11. package/dist/{api-CGJ1iGps.js → api-serd0SMY.js} +14 -4
  12. package/dist/{api-CGJ1iGps.js.map → api-serd0SMY.js.map} +1 -1
  13. package/dist/bin.js +44 -43
  14. package/dist/bin.js.map +1 -1
  15. package/dist/{ci-install-DD7WMmIF.js → ci-install-BbJ7c3WK.js} +4 -4
  16. package/dist/{ci-install-DD7WMmIF.js.map → ci-install-BbJ7c3WK.js.map} +1 -1
  17. package/dist/{debug-Cd0hPlZy.js → debug-BI-Js0PB.js} +1 -1
  18. package/dist/{debug-ubpO6102.js → debug-Bx7nvCWW.js} +2 -2
  19. package/dist/{debug-ubpO6102.js.map → debug-Bx7nvCWW.js.map} +1 -1
  20. package/dist/{defaults-zrYmZ2ID.js → defaults-CPH6eWhN.js} +1 -1
  21. package/dist/{defaults-zrYmZ2ID.js.map → defaults-CPH6eWhN.js.map} +1 -1
  22. package/dist/{env-api-key-DEl3LJBv.js → env-api-key-B3gE9Un0.js} +1 -1
  23. package/dist/{env-api-key-DEl3LJBv.js.map → env-api-key-B3gE9Un0.js.map} +1 -1
  24. package/dist/{environment-BAaC5THg.js → environment-CiZVSSYt.js} +3 -3
  25. package/dist/{environment-BAaC5THg.js.map → environment-CiZVSSYt.js.map} +1 -1
  26. package/dist/{file-utils-DPmgn9Vm.js → file-utils-Dy9JncCo.js} +1 -1
  27. package/dist/{file-utils-DPmgn9Vm.js.map → file-utils-Dy9JncCo.js.map} +1 -1
  28. package/dist/{interactive-BaMAq88Q.js → interactive-BwIzklw0.js} +2 -2
  29. package/dist/{interactive-BaMAq88Q.js.map → interactive-BwIzklw0.js.map} +1 -1
  30. package/dist/{mcp-prompt-streaming-clGsVw8q.js → mcp-prompt-streaming-8U9Qs9EV.js} +62 -12
  31. package/dist/mcp-prompt-streaming-8U9Qs9EV.js.map +1 -0
  32. package/dist/{non-interactive-l2AKE3jD.js → non-interactive-DTaZnVq_.js} +2 -2
  33. package/dist/{non-interactive-l2AKE3jD.js.map → non-interactive-DTaZnVq_.js.map} +1 -1
  34. package/dist/{package-json-Cynjr9k4.js → package-json-DCuoye-H.js} +8 -2
  35. package/dist/{package-json-Cynjr9k4.js.map → package-json-DCuoye-H.js.map} +1 -1
  36. package/dist/{package-manager-BqsJK3ej.js → package-manager-CKQLR20D.js} +2 -2
  37. package/dist/{package-manager-BqsJK3ej.js.map → package-manager-CKQLR20D.js.map} +1 -1
  38. package/dist/{playground-DlE5RNfE.js → playground-CR81Mwe3.js} +21 -10
  39. package/dist/playground-CR81Mwe3.js.map +1 -0
  40. package/dist/{posthog-DWL8uOcl.js → posthog-BrLFkaji.js} +1 -1
  41. package/dist/{posthog-DWL8uOcl.js.map → posthog-BrLFkaji.js.map} +1 -1
  42. package/dist/{posthog-integration-Bf_vtWI9.js → posthog-integration-Bv7987YJ.js} +13 -12
  43. package/dist/{posthog-integration-Bf_vtWI9.js.map → posthog-integration-Bv7987YJ.js.map} +1 -1
  44. package/dist/{provisioning-D_hAuxUN.js → provisioning-C96Kw-9D.js} +9 -4
  45. package/dist/{provisioning-D_hAuxUN.js.map → provisioning-C96Kw-9D.js.map} +1 -1
  46. package/dist/{registry-DKgYqROt.js → registry-B9k73FKR.js} +5 -5
  47. package/dist/{registry-DKgYqROt.js.map → registry-B9k73FKR.js.map} +1 -1
  48. package/dist/{setup-utils-D-uTycLX.js → setup-utils-Bpfsap9L.js} +80 -39
  49. package/dist/setup-utils-Bpfsap9L.js.map +1 -0
  50. package/dist/{skill-CnOQAZXp.js → skill-CPqcV8zp.js} +2 -2
  51. package/dist/{skill-CnOQAZXp.js.map → skill-CPqcV8zp.js.map} +1 -1
  52. package/dist/{slides-CL1mv_Kq.js → slides-DRbBgsdd.js} +1426 -181
  53. package/dist/slides-DRbBgsdd.js.map +1 -0
  54. package/dist/{start-tui-DXrv6cof.js → start-tui-BZ7rEf3e.js} +28 -17
  55. package/dist/start-tui-BZ7rEf3e.js.map +1 -0
  56. package/dist/{steps-CgScwqso.js → steps-DDx35170.js} +6 -6
  57. package/dist/{steps-CgScwqso.js.map → steps-DDx35170.js.map} +1 -1
  58. package/dist/{task-stream-CF6QMVMv.js → task-stream-BI8rJg9H.js} +3 -3
  59. package/dist/{task-stream-CF6QMVMv.js.map → task-stream-BI8rJg9H.js.map} +1 -1
  60. package/dist/{telemetry-v6O12Bep.js → telemetry-ByYtIfW0.js} +2 -2
  61. package/dist/{telemetry-v6O12Bep.js.map → telemetry-ByYtIfW0.js.map} +1 -1
  62. package/dist/urls-CTCJIxbR.js +35 -0
  63. package/dist/urls-CTCJIxbR.js.map +1 -0
  64. package/dist/{wizard-abort-iTaJ8wC8.js → wizard-abort-CY0ibdq1.js} +3 -3
  65. package/dist/{wizard-abort-iTaJ8wC8.js.map → wizard-abort-CY0ibdq1.js.map} +1 -1
  66. package/dist/{wizard-abort-BGoBKgvC.js → wizard-abort-QdRxGQp_.js} +1 -1
  67. package/dist/{wizard-session-gsn8Z3bZ.js → wizard-session-d27JGRGi.js} +1 -1
  68. package/dist/{wizard-session-gsn8Z3bZ.js.map → wizard-session-d27JGRGi.js.map} +1 -1
  69. package/dist/{wizard-session-7tMjgOvP.js → wizard-session-y304gEEI.js} +1 -1
  70. package/package.json +1 -1
  71. package/dist/add-mcp-server-to-clients-BS6Rjcwh.js.map +0 -1
  72. package/dist/api-B8OR0N1V.js +0 -2
  73. package/dist/mcp-prompt-streaming-clGsVw8q.js.map +0 -1
  74. package/dist/package-json-CumwmZpv.js +0 -2
  75. package/dist/playground-DlE5RNfE.js.map +0 -1
  76. package/dist/provisioning-BlBnlcFd.js +0 -2
  77. package/dist/setup-utils-BHZEdkNZ.js +0 -2
  78. package/dist/setup-utils-D-uTycLX.js.map +0 -1
  79. package/dist/slides-CL1mv_Kq.js.map +0 -1
  80. package/dist/start-tui-DXrv6cof.js.map +0 -1
@@ -1,8 +1,8 @@
1
- import { p as getUI } from "./debug-ubpO6102.js";
2
- import { t as analytics } from "./analytics-DUuUurR3.js";
3
- import { t as withProgress } from "./telemetry-v6O12Bep.js";
4
- import "./setup-utils-D-uTycLX.js";
5
- import "./add-mcp-server-to-clients-BS6Rjcwh.js";
1
+ import { p as getUI } from "./debug-Bx7nvCWW.js";
2
+ import { t as analytics } from "./analytics-DN_Gy87F.js";
3
+ import { t as withProgress } from "./telemetry-ByYtIfW0.js";
4
+ import "./setup-utils-Bpfsap9L.js";
5
+ import "./add-mcp-server-to-clients-D4PK6ulR.js";
6
6
  import * as fs$1 from "fs";
7
7
  import * as path$1 from "path";
8
8
  import "path";
@@ -143,4 +143,4 @@ const uploadEnvironmentVariablesStep = async (envVars, { integration, session })
143
143
  //#endregion
144
144
  export { uploadEnvironmentVariablesStep };
145
145
 
146
- //# sourceMappingURL=steps-CgScwqso.js.map
146
+ //# sourceMappingURL=steps-DDx35170.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"steps-CgScwqso.js","names":["path","fs","spawnSync","spawn"],"sources":["../src/steps/upload-environment-variables/EnvironmentProvider.ts","../src/steps/upload-environment-variables/providers/vercel.ts","../src/steps/upload-environment-variables/index.ts"],"sourcesContent":["export abstract class EnvironmentProvider {\n protected options: { installDir: string };\n\n name: string;\n\n constructor(options: { installDir: string }) {\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 { EnvironmentProvider } from '@steps/upload-environment-variables/EnvironmentProvider';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { getUI } from '@ui';\nimport { analytics } from '@utils/analytics';\n\nexport class VercelEnvironmentProvider extends EnvironmentProvider {\n name = 'Vercel';\n environments = ['production', 'preview', 'development'];\n\n constructor(options: { installDir: string }) {\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 = getUI().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 '@lib/constants';\nimport { withProgress } from '../../telemetry';\nimport { analytics } from '@utils/analytics';\nimport { getUI } from '@ui';\nimport type { WizardSession } from '@lib/wizard-session';\nimport { EnvironmentProvider } from './EnvironmentProvider';\nimport { VercelEnvironmentProvider } from './providers/vercel';\n\nexport const uploadEnvironmentVariablesStep = async (\n envVars: Record<string, string>,\n {\n integration,\n session,\n }: {\n integration: Integration;\n session: WizardSession;\n },\n): Promise<string[]> => {\n const providers: EnvironmentProvider[] = [\n new VercelEnvironmentProvider({ installDir: session.installDir }),\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 getUI().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
+ {"version":3,"file":"steps-DDx35170.js","names":["path","fs","spawnSync","spawn"],"sources":["../src/steps/upload-environment-variables/EnvironmentProvider.ts","../src/steps/upload-environment-variables/providers/vercel.ts","../src/steps/upload-environment-variables/index.ts"],"sourcesContent":["export abstract class EnvironmentProvider {\n protected options: { installDir: string };\n\n name: string;\n\n constructor(options: { installDir: string }) {\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 { EnvironmentProvider } from '@steps/upload-environment-variables/EnvironmentProvider';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { getUI } from '@ui';\nimport { analytics } from '@utils/analytics';\n\nexport class VercelEnvironmentProvider extends EnvironmentProvider {\n name = 'Vercel';\n environments = ['production', 'preview', 'development'];\n\n constructor(options: { installDir: string }) {\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 = getUI().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 '@lib/constants';\nimport { withProgress } from '../../telemetry';\nimport { analytics } from '@utils/analytics';\nimport { getUI } from '@ui';\nimport type { WizardSession } from '@lib/wizard-session';\nimport { EnvironmentProvider } from './EnvironmentProvider';\nimport { VercelEnvironmentProvider } from './providers/vercel';\n\nexport const uploadEnvironmentVariablesStep = async (\n envVars: Record<string, string>,\n {\n integration,\n session,\n }: {\n integration: Integration;\n session: WizardSession;\n },\n): Promise<string[]> => {\n const providers: EnvironmentProvider[] = [\n new VercelEnvironmentProvider({ installDir: session.installDir }),\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 getUI().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,6 +1,6 @@
1
1
  import "./wizard-ui-YdGFRyu_.js";
2
- import "./wizard-session-gsn8Z3bZ.js";
3
- import "./posthog-DWL8uOcl.js";
2
+ import "./wizard-session-d27JGRGi.js";
3
+ import "./posthog-BrLFkaji.js";
4
4
  //#region src/lib/task-stream/task-stream-push.ts
5
5
  /** Trailing-edge debounce window for non-phase-change emits. */
6
6
  const DEBOUNCE_MS = 250;
@@ -192,4 +192,4 @@ var TaskStreamPush = class {
192
192
  //#endregion
193
193
  export { TaskStreamPush };
194
194
 
195
- //# sourceMappingURL=task-stream-CF6QMVMv.js.map
195
+ //# sourceMappingURL=task-stream-BI8rJg9H.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"task-stream-CF6QMVMv.js","names":[],"sources":["../src/lib/task-stream/task-stream-push.ts"],"sourcesContent":["/**\n * Task-stream push — subscribes to WizardStore, builds payloads,\n * and fans out async to all registered destinations.\n *\n * Behaviour:\n * - `attach(store)` subscribe to store changes\n * - task updates debounced 250ms (trailing edge)\n * - phase transitions flush immediately, bypass debounce\n * - RunPhase.Idle skipped (no push)\n * - enabled === false attach is a no-op\n * - shutdown(timeoutMs) cancel pending, flush terminal phase\n * with timeout, never throw\n *\n * Concurrency: only one fan-out at a time. Emits during an in-flight\n * push are coalesced — at most one follow-up push fires with the\n * latest state once the current one settles.\n */\n\nimport type { WizardStore, TaskItem } from '@ui/tui/store';\nimport { TaskStatus } from '@ui/wizard-ui';\nimport { RunPhase, OutroKind, type OutroData } from '@lib/wizard-session';\nimport {\n type TaskStreamDestination,\n type TaskStreamUpdate,\n type StreamTask,\n type TaskStreamError,\n StreamTaskStatus,\n StreamEvent,\n} from './types';\n\n/** Trailing-edge debounce window for non-phase-change emits. */\nconst DEBOUNCE_MS = 250;\n/** Default shutdown timeout for the final terminal flush. */\nconst DEFAULT_SHUTDOWN_TIMEOUT_MS = 2000;\n\nconst STATUS_MAP: Record<TaskStatus, StreamTaskStatus> = {\n [TaskStatus.Pending]: StreamTaskStatus.Pending,\n [TaskStatus.InProgress]: StreamTaskStatus.InProgress,\n [TaskStatus.Completed]: StreamTaskStatus.Completed,\n};\n\nfunction buildTasks(items: TaskItem[]): StreamTask[] {\n return items.map((item, i) => ({\n id: String(i),\n title: item.label,\n status: STATUS_MAP[item.status] ?? StreamTaskStatus.Pending,\n }));\n}\n\n/** Drop \".SSSZ\" → \"Z\" so session_id segments stay routing-safe. */\nfunction secondPrecisionIso(d: Date): string {\n return d.toISOString().replace(/\\.\\d{3}Z$/, 'Z');\n}\n\n/**\n * `workflow_id` and `skill_id` end up unescaped in Redis pub/sub\n * channel names, so the backend rejects anything outside\n * `^[A-Za-z0-9_.-]{1,255}$` with a 400. All current values already\n * comply; this is defence in depth in case a future caller passes\n * something with `:`, spaces, or other separators.\n */\nfunction sanitizeChannelId(value: string): string {\n return value.replace(/[^A-Za-z0-9_.-]/g, '-').slice(0, 255);\n}\n\nfunction buildError(\n phase: RunPhase,\n outroData: OutroData | null,\n): TaskStreamError | undefined {\n if (phase !== RunPhase.Error) return undefined;\n if (outroData?.kind === OutroKind.Error) {\n const message = outroData.message ?? outroData.body ?? 'Wizard run failed';\n return { type: 'wizard_error', message };\n }\n return { type: 'wizard_error', message: 'Wizard run failed' };\n}\n\nexport interface TaskStreamPushOptions {\n store: WizardStore;\n programId: string;\n destinations: TaskStreamDestination[];\n /** When false, `attach` is a no-op and no destination ever fires. */\n enabled?: boolean;\n}\n\nexport class TaskStreamPush {\n private readonly store: WizardStore;\n private readonly destinations: TaskStreamDestination[];\n private readonly startedAt: string;\n private readonly programId: string;\n private readonly sessionId: string;\n\n private enabled: boolean;\n private created = false;\n private lastPushedPhase: RunPhase | null = null;\n\n private unsubscribe: (() => void) | null = null;\n private debounceTimer: ReturnType<typeof setTimeout> | null = null;\n private inFlight: Promise<void> | null = null;\n private needsAnotherPush = false;\n private shuttingDown = false;\n\n constructor(opts: TaskStreamPushOptions) {\n this.store = opts.store;\n this.programId = sanitizeChannelId(opts.programId);\n this.destinations = opts.destinations;\n this.enabled = opts.enabled ?? true;\n this.startedAt = secondPrecisionIso(new Date());\n // skillId may not be set yet — fall back to programId so the\n // session_id is stable for the whole run regardless of when the\n // program metadata is populated.\n const skillId = sanitizeChannelId(\n this.store.session.skillId ?? this.programId,\n );\n this.sessionId = `${this.programId}-${skillId}-${this.startedAt}`;\n }\n\n /**\n * Subscribe to store changes. No-op when `enabled === false`.\n * Idempotent — repeat calls are ignored.\n */\n attach(store?: WizardStore): void {\n if (!this.enabled) return;\n if (this.unsubscribe) return;\n const target = store ?? this.store;\n this.unsubscribe = target.subscribe(() => this.onStoreChange());\n }\n\n /** Stop subscribing. Does not flush. */\n detach(): void {\n if (this.unsubscribe) {\n this.unsubscribe();\n this.unsubscribe = null;\n }\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n this.debounceTimer = null;\n }\n }\n\n /**\n * Cancel pending debounce, flush one final push if the current\n * phase is terminal, and resolve. Never throws. Bounded by\n * `timeoutMs` — if a destination hangs, this returns anyway.\n */\n async shutdown(\n timeoutMs: number = DEFAULT_SHUTDOWN_TIMEOUT_MS,\n ): Promise<void> {\n this.shuttingDown = true;\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n this.debounceTimer = null;\n }\n this.detach();\n if (!this.enabled) return;\n\n const phase = this.store.session.runPhase;\n const isTerminal = phase === RunPhase.Completed || phase === RunPhase.Error;\n if (!isTerminal) return;\n\n const flush = this.flush();\n if (timeoutMs <= 0) return;\n await Promise.race([\n flush,\n new Promise<void>((resolve) => setTimeout(resolve, timeoutMs)),\n ]);\n }\n\n /**\n * Imperative push — fires immediately regardless of phase. Kept as\n * the building block for both subscription-driven and direct calls.\n */\n async push(): Promise<void> {\n await this.flush();\n }\n\n // ── Internal ────────────────────────────────────────────────────\n\n private onStoreChange(): void {\n if (!this.enabled || this.shuttingDown) return;\n const phase = this.store.session.runPhase;\n if (phase === RunPhase.Idle) return;\n\n // A push is already in flight — coalesce. The in-flight push's\n // settle handler will trigger one follow-up with the latest state.\n if (this.inFlight) {\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n this.debounceTimer = null;\n }\n this.needsAnotherPush = true;\n return;\n }\n\n const phaseChanged = phase !== this.lastPushedPhase;\n if (phaseChanged) {\n // Phase transitions bypass the debounce: the web app needs to\n // see Running → Completed as soon as it lands.\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n this.debounceTimer = null;\n }\n void this.flush();\n return;\n }\n\n // Task updates can arrive faster than we want to push. Debounce\n // them — the last update in a burst wins.\n if (this.debounceTimer) return;\n this.debounceTimer = setTimeout(() => {\n this.debounceTimer = null;\n void this.flush();\n }, DEBOUNCE_MS);\n }\n\n /**\n * Fan out the current state to every destination. Serialized — if\n * a flush is already running, mark \"needs another\" and let the\n * in-flight one schedule the follow-up when it settles.\n */\n private flush(): Promise<void> {\n if (this.inFlight) {\n this.needsAnotherPush = true;\n return this.inFlight;\n }\n\n const run = async (): Promise<void> => {\n try {\n await this.sendOnce();\n } finally {\n this.inFlight = null;\n if (this.needsAnotherPush) {\n this.needsAnotherPush = false;\n // Re-enter to push the latest snapshot.\n await this.flush();\n }\n }\n };\n\n this.inFlight = run();\n return this.inFlight;\n }\n\n private async sendOnce(): Promise<void> {\n const { session, tasks, eventPlan } = this.store;\n const skillId = sanitizeChannelId(session.skillId ?? this.programId);\n const phase = session.runPhase;\n\n const payload: TaskStreamUpdate = {\n session_id: this.sessionId,\n workflow_id: this.programId,\n skill_id: skillId,\n started_at: this.startedAt,\n run_phase: phase,\n tasks: buildTasks(tasks),\n event_plan: eventPlan.length > 0 ? { events: eventPlan } : undefined,\n error: buildError(phase, session.outroData),\n timestamp: new Date().toISOString(),\n };\n\n let event: StreamEvent;\n if (!this.created) {\n this.created = true;\n event = StreamEvent.Create;\n } else if (phase === RunPhase.Completed) {\n event = StreamEvent.Complete;\n } else if (phase === RunPhase.Error) {\n event = StreamEvent.Error;\n } else {\n event = StreamEvent.Update;\n }\n\n this.lastPushedPhase = phase;\n\n await Promise.all(\n this.destinations.map((d) =>\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n d.send(event, payload).catch(() => {}),\n ),\n );\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"task-stream-BI8rJg9H.js","names":[],"sources":["../src/lib/task-stream/task-stream-push.ts"],"sourcesContent":["/**\n * Task-stream push — subscribes to WizardStore, builds payloads,\n * and fans out async to all registered destinations.\n *\n * Behaviour:\n * - `attach(store)` subscribe to store changes\n * - task updates debounced 250ms (trailing edge)\n * - phase transitions flush immediately, bypass debounce\n * - RunPhase.Idle skipped (no push)\n * - enabled === false attach is a no-op\n * - shutdown(timeoutMs) cancel pending, flush terminal phase\n * with timeout, never throw\n *\n * Concurrency: only one fan-out at a time. Emits during an in-flight\n * push are coalesced — at most one follow-up push fires with the\n * latest state once the current one settles.\n */\n\nimport type { WizardStore, TaskItem } from '@ui/tui/store';\nimport { TaskStatus } from '@ui/wizard-ui';\nimport { RunPhase, OutroKind, type OutroData } from '@lib/wizard-session';\nimport {\n type TaskStreamDestination,\n type TaskStreamUpdate,\n type StreamTask,\n type TaskStreamError,\n StreamTaskStatus,\n StreamEvent,\n} from './types';\n\n/** Trailing-edge debounce window for non-phase-change emits. */\nconst DEBOUNCE_MS = 250;\n/** Default shutdown timeout for the final terminal flush. */\nconst DEFAULT_SHUTDOWN_TIMEOUT_MS = 2000;\n\nconst STATUS_MAP: Record<TaskStatus, StreamTaskStatus> = {\n [TaskStatus.Pending]: StreamTaskStatus.Pending,\n [TaskStatus.InProgress]: StreamTaskStatus.InProgress,\n [TaskStatus.Completed]: StreamTaskStatus.Completed,\n};\n\nfunction buildTasks(items: TaskItem[]): StreamTask[] {\n return items.map((item, i) => ({\n id: String(i),\n title: item.label,\n status: STATUS_MAP[item.status] ?? StreamTaskStatus.Pending,\n }));\n}\n\n/** Drop \".SSSZ\" → \"Z\" so session_id segments stay routing-safe. */\nfunction secondPrecisionIso(d: Date): string {\n return d.toISOString().replace(/\\.\\d{3}Z$/, 'Z');\n}\n\n/**\n * `workflow_id` and `skill_id` end up unescaped in Redis pub/sub\n * channel names, so the backend rejects anything outside\n * `^[A-Za-z0-9_.-]{1,255}$` with a 400. All current values already\n * comply; this is defence in depth in case a future caller passes\n * something with `:`, spaces, or other separators.\n */\nfunction sanitizeChannelId(value: string): string {\n return value.replace(/[^A-Za-z0-9_.-]/g, '-').slice(0, 255);\n}\n\nfunction buildError(\n phase: RunPhase,\n outroData: OutroData | null,\n): TaskStreamError | undefined {\n if (phase !== RunPhase.Error) return undefined;\n if (outroData?.kind === OutroKind.Error) {\n const message = outroData.message ?? outroData.body ?? 'Wizard run failed';\n return { type: 'wizard_error', message };\n }\n return { type: 'wizard_error', message: 'Wizard run failed' };\n}\n\nexport interface TaskStreamPushOptions {\n store: WizardStore;\n programId: string;\n destinations: TaskStreamDestination[];\n /** When false, `attach` is a no-op and no destination ever fires. */\n enabled?: boolean;\n}\n\nexport class TaskStreamPush {\n private readonly store: WizardStore;\n private readonly destinations: TaskStreamDestination[];\n private readonly startedAt: string;\n private readonly programId: string;\n private readonly sessionId: string;\n\n private enabled: boolean;\n private created = false;\n private lastPushedPhase: RunPhase | null = null;\n\n private unsubscribe: (() => void) | null = null;\n private debounceTimer: ReturnType<typeof setTimeout> | null = null;\n private inFlight: Promise<void> | null = null;\n private needsAnotherPush = false;\n private shuttingDown = false;\n\n constructor(opts: TaskStreamPushOptions) {\n this.store = opts.store;\n this.programId = sanitizeChannelId(opts.programId);\n this.destinations = opts.destinations;\n this.enabled = opts.enabled ?? true;\n this.startedAt = secondPrecisionIso(new Date());\n // skillId may not be set yet — fall back to programId so the\n // session_id is stable for the whole run regardless of when the\n // program metadata is populated.\n const skillId = sanitizeChannelId(\n this.store.session.skillId ?? this.programId,\n );\n this.sessionId = `${this.programId}-${skillId}-${this.startedAt}`;\n }\n\n /**\n * Subscribe to store changes. No-op when `enabled === false`.\n * Idempotent — repeat calls are ignored.\n */\n attach(store?: WizardStore): void {\n if (!this.enabled) return;\n if (this.unsubscribe) return;\n const target = store ?? this.store;\n this.unsubscribe = target.subscribe(() => this.onStoreChange());\n }\n\n /** Stop subscribing. Does not flush. */\n detach(): void {\n if (this.unsubscribe) {\n this.unsubscribe();\n this.unsubscribe = null;\n }\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n this.debounceTimer = null;\n }\n }\n\n /**\n * Cancel pending debounce, flush one final push if the current\n * phase is terminal, and resolve. Never throws. Bounded by\n * `timeoutMs` — if a destination hangs, this returns anyway.\n */\n async shutdown(\n timeoutMs: number = DEFAULT_SHUTDOWN_TIMEOUT_MS,\n ): Promise<void> {\n this.shuttingDown = true;\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n this.debounceTimer = null;\n }\n this.detach();\n if (!this.enabled) return;\n\n const phase = this.store.session.runPhase;\n const isTerminal = phase === RunPhase.Completed || phase === RunPhase.Error;\n if (!isTerminal) return;\n\n const flush = this.flush();\n if (timeoutMs <= 0) return;\n await Promise.race([\n flush,\n new Promise<void>((resolve) => setTimeout(resolve, timeoutMs)),\n ]);\n }\n\n /**\n * Imperative push — fires immediately regardless of phase. Kept as\n * the building block for both subscription-driven and direct calls.\n */\n async push(): Promise<void> {\n await this.flush();\n }\n\n // ── Internal ────────────────────────────────────────────────────\n\n private onStoreChange(): void {\n if (!this.enabled || this.shuttingDown) return;\n const phase = this.store.session.runPhase;\n if (phase === RunPhase.Idle) return;\n\n // A push is already in flight — coalesce. The in-flight push's\n // settle handler will trigger one follow-up with the latest state.\n if (this.inFlight) {\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n this.debounceTimer = null;\n }\n this.needsAnotherPush = true;\n return;\n }\n\n const phaseChanged = phase !== this.lastPushedPhase;\n if (phaseChanged) {\n // Phase transitions bypass the debounce: the web app needs to\n // see Running → Completed as soon as it lands.\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n this.debounceTimer = null;\n }\n void this.flush();\n return;\n }\n\n // Task updates can arrive faster than we want to push. Debounce\n // them — the last update in a burst wins.\n if (this.debounceTimer) return;\n this.debounceTimer = setTimeout(() => {\n this.debounceTimer = null;\n void this.flush();\n }, DEBOUNCE_MS);\n }\n\n /**\n * Fan out the current state to every destination. Serialized — if\n * a flush is already running, mark \"needs another\" and let the\n * in-flight one schedule the follow-up when it settles.\n */\n private flush(): Promise<void> {\n if (this.inFlight) {\n this.needsAnotherPush = true;\n return this.inFlight;\n }\n\n const run = async (): Promise<void> => {\n try {\n await this.sendOnce();\n } finally {\n this.inFlight = null;\n if (this.needsAnotherPush) {\n this.needsAnotherPush = false;\n // Re-enter to push the latest snapshot.\n await this.flush();\n }\n }\n };\n\n this.inFlight = run();\n return this.inFlight;\n }\n\n private async sendOnce(): Promise<void> {\n const { session, tasks, eventPlan } = this.store;\n const skillId = sanitizeChannelId(session.skillId ?? this.programId);\n const phase = session.runPhase;\n\n const payload: TaskStreamUpdate = {\n session_id: this.sessionId,\n workflow_id: this.programId,\n skill_id: skillId,\n started_at: this.startedAt,\n run_phase: phase,\n tasks: buildTasks(tasks),\n event_plan: eventPlan.length > 0 ? { events: eventPlan } : undefined,\n error: buildError(phase, session.outroData),\n timestamp: new Date().toISOString(),\n };\n\n let event: StreamEvent;\n if (!this.created) {\n this.created = true;\n event = StreamEvent.Create;\n } else if (phase === RunPhase.Completed) {\n event = StreamEvent.Complete;\n } else if (phase === RunPhase.Error) {\n event = StreamEvent.Error;\n } else {\n event = StreamEvent.Update;\n }\n\n this.lastPushedPhase = phase;\n\n await Promise.all(\n this.destinations.map((d) =>\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n d.send(event, payload).catch(() => {}),\n ),\n );\n }\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { t as analytics } from "./analytics-DUuUurR3.js";
1
+ import { t as analytics } from "./analytics-DN_Gy87F.js";
2
2
  //#region src/telemetry.ts
3
3
  function withProgress(step, callback) {
4
4
  updateProgress(step);
@@ -10,4 +10,4 @@ function updateProgress(step) {
10
10
  //#endregion
11
11
  export { withProgress as t };
12
12
 
13
- //# sourceMappingURL=telemetry-v6O12Bep.js.map
13
+ //# sourceMappingURL=telemetry-ByYtIfW0.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"telemetry-v6O12Bep.js","names":[],"sources":["../src/telemetry.ts"],"sourcesContent":["import { analytics } from '@utils/analytics';\n\nexport function withProgress<T>(step: string, callback: () => T): T {\n updateProgress(step);\n return callback();\n}\n\nexport function updateProgress(step: string) {\n analytics.setTag('progress', step);\n}\n"],"mappings":";;AAEA,SAAgB,aAAgB,MAAc,UAAsB;AAClE,gBAAe,KAAK;AACpB,QAAO,UAAU;;AAGnB,SAAgB,eAAe,MAAc;AAC3C,WAAU,OAAO,YAAY,KAAK"}
1
+ {"version":3,"file":"telemetry-ByYtIfW0.js","names":[],"sources":["../src/telemetry.ts"],"sourcesContent":["import { analytics } from '@utils/analytics';\n\nexport function withProgress<T>(step: string, callback: () => T): T {\n updateProgress(step);\n return callback();\n}\n\nexport function updateProgress(step: string) {\n analytics.setTag('progress', step);\n}\n"],"mappings":";;AAEA,SAAgB,aAAgB,MAAc,UAAsB;AAClE,gBAAe,KAAK;AACpB,QAAO,UAAU;;AAGnB,SAAgB,eAAe,MAAc;AAC3C,WAAU,OAAO,YAAY,KAAK"}
@@ -0,0 +1,35 @@
1
+ import { W as WIZARD_USER_AGENT } from "./debug-Bx7nvCWW.js";
2
+ import axios from "axios";
3
+ //#region src/utils/urls.ts
4
+ const getUiHostFromHost = (host) => {
5
+ if (host.includes("us.i.posthog.com")) return "https://us.posthog.com";
6
+ if (host.includes("eu.i.posthog.com")) return "https://eu.posthog.com";
7
+ return host;
8
+ };
9
+ const getHostFromRegion = (region) => {
10
+ if (region === "eu") return "https://eu.i.posthog.com";
11
+ return "https://us.i.posthog.com";
12
+ };
13
+ const getCloudUrlFromRegion = (region) => {
14
+ if (region === "eu") return "https://eu.posthog.com";
15
+ return "https://us.posthog.com";
16
+ };
17
+ async function detectRegionFromToken(accessToken) {
18
+ const headers = {
19
+ Authorization: `Bearer ${accessToken}`,
20
+ "User-Agent": WIZARD_USER_AGENT
21
+ };
22
+ const [usResult, euResult] = await Promise.allSettled([axios.get("https://us.posthog.com/api/users/@me/", { headers }), axios.get("https://eu.posthog.com/api/users/@me/", { headers })]);
23
+ if (usResult.status === "fulfilled") return "us";
24
+ if (euResult.status === "fulfilled") return "eu";
25
+ throw new Error("Could not determine cloud region from access token. Please check your PostHog account.");
26
+ }
27
+ const getLlmGatewayUrlFromHost = (host) => {
28
+ if (host.includes("localhost")) return "http://localhost:3308/wizard";
29
+ if (host.includes("eu.posthog.com") || host.includes("eu.i.posthog.com")) return "https://gateway.eu.posthog.com/wizard";
30
+ return "https://gateway.us.posthog.com/wizard";
31
+ };
32
+ //#endregion
33
+ export { getUiHostFromHost as a, getLlmGatewayUrlFromHost as i, getCloudUrlFromRegion as n, getHostFromRegion as r, detectRegionFromToken as t };
34
+
35
+ //# sourceMappingURL=urls-CTCJIxbR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"urls-CTCJIxbR.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\nexport const getAssetHostFromHost = (host: string) => {\n if (host.includes('us.i.posthog.com')) {\n return 'https://us-assets.i.posthog.com';\n }\n\n if (host.includes('eu.i.posthog.com')) {\n return 'https://eu-assets.i.posthog.com';\n }\n\n return host;\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 getHostFromRegion = (region: CloudRegion) => {\n if (IS_DEV) {\n return 'http://localhost:8010';\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 getCloudUrlFromRegion = (region: CloudRegion) => {\n if (IS_DEV) {\n return 'http://localhost:8010';\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 detectRegionFromToken(\n accessToken: string,\n): Promise<CloudRegion> {\n if (IS_DEV) {\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 getLlmGatewayUrlFromHost = (host: string) => {\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"],"mappings":";;;AAgBA,MAAa,qBAAqB,SAAiB;AACjD,KAAI,KAAK,SAAS,mBAAmB,CACnC,QAAO;AAGT,KAAI,KAAK,SAAS,mBAAmB,CACnC,QAAO;AAGT,QAAO;;AAGT,MAAa,qBAAqB,WAAwB;AAKxD,KAAI,WAAW,KACb,QAAO;AAGT,QAAO;;AAGT,MAAa,yBAAyB,WAAwB;AAK5D,KAAI,WAAW,KACb,QAAO;AAGT,QAAO;;AAGT,eAAsB,sBACpB,aACsB;CAKtB,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,4BAA4B,SAAiB;AACxD,KAAI,KAAK,SAAS,YAAY,CAC5B,QAAO;AAGT,KAAI,KAAK,SAAS,iBAAiB,IAAI,KAAK,SAAS,mBAAmB,CACtE,QAAO;AAGT,QAAO"}
@@ -1,5 +1,5 @@
1
- import { p as getUI } from "./debug-ubpO6102.js";
2
- import { t as analytics } from "./analytics-DUuUurR3.js";
1
+ import { p as getUI } from "./debug-Bx7nvCWW.js";
2
+ import { t as analytics } from "./analytics-DN_Gy87F.js";
3
3
  //#region src/utils/wizard-abort.ts
4
4
  /**
5
5
  * Single exit point for the wizard. Use instead of process.exit() directly.
@@ -38,4 +38,4 @@ async function wizardAbort(options) {
38
38
  //#endregion
39
39
  export { registerCleanup as n, wizardAbort as r, WizardError as t };
40
40
 
41
- //# sourceMappingURL=wizard-abort-iTaJ8wC8.js.map
41
+ //# sourceMappingURL=wizard-abort-CY0ibdq1.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"wizard-abort-iTaJ8wC8.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 { 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\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 // 1. Run registered cleanup functions\n for (const fn of cleanupFns) {\n try {\n fn();\n } catch {\n /* cleanup should not prevent exit */\n }\n }\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":";;;;;;;;;;;AAYA,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;;AAOrB,eAAsB,YACpB,SACgB;CAChB,MAAM,EACJ,UAAU,2BACV,WACA,OACA,WAAW,MACT,WAAW,EAAE;AAGjB,MAAK,MAAM,MAAM,WACf,KAAI;AACF,MAAI;SACE;AAMV,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
+ {"version":3,"file":"wizard-abort-CY0ibdq1.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 { 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\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 // 1. Run registered cleanup functions\n for (const fn of cleanupFns) {\n try {\n fn();\n } catch {\n /* cleanup should not prevent exit */\n }\n }\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":";;;;;;;;;;;AAYA,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;;AAOrB,eAAsB,YACpB,SACgB;CAChB,MAAM,EACJ,UAAU,2BACV,WACA,OACA,WAAW,MACT,WAAW,EAAE;AAGjB,MAAK,MAAM,MAAM,WACf,KAAI;AACF,MAAI;SACE;AAMV,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 { r as wizardAbort, t as WizardError } from "./wizard-abort-iTaJ8wC8.js";
1
+ import { r as wizardAbort, t as WizardError } from "./wizard-abort-CY0ibdq1.js";
2
2
  export { WizardError, wizardAbort };
@@ -78,4 +78,4 @@ function buildSession(args) {
78
78
  //#endregion
79
79
  export { buildSession as i, ADDITIONAL_FEATURE_PROMPTS as n, RunPhase as r, ADDITIONAL_FEATURE_LABELS as t };
80
80
 
81
- //# sourceMappingURL=wizard-session-gsn8Z3bZ.js.map
81
+ //# sourceMappingURL=wizard-session-d27JGRGi.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"wizard-session-gsn8Z3bZ.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 { Integration } from './constants';\nimport type { FrameworkConfig } from './framework-config';\nimport type { WizardReadinessResult } from './health-checks/readiness';\nimport type { SettingsConflict } from './agent/agent-interface';\nimport type { ApiUser } 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 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\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 }[];\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\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 benchmark: boolean;\n yaraReport: boolean;\n projectId?: number;\n noTelemetry: boolean;\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 // 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 skillsComplete: boolean;\n outroDismissed: 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 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 integration?: Integration;\n benchmark?: boolean;\n yaraReport?: boolean;\n projectId?: string;\n noTelemetry?: 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 benchmark: args.benchmark ?? false,\n yaraReport: args.yaraReport ?? false,\n projectId: parseProjectIdArg(args.projectId),\n noTelemetry: args.noTelemetry ?? false,\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 skillsComplete: false,\n outroDismissed: false,\n loginUrl: null,\n authorizeUrl: null,\n credentials: null,\n roleAtOrganization: null,\n apiUser: 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;;;;AA6LD,SAAgB,aAAa,MAeX;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,WAAW,KAAK,aAAa;EAC7B,YAAY,KAAK,cAAc;EAC/B,WAAW,kBAAkB,KAAK,UAAU;EAC5C,aAAa,KAAK,eAAe;EAEjC,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,gBAAgB;EAChB,gBAAgB;EAChB,UAAU;EACV,cAAc;EACd,aAAa;EACb,oBAAoB;EACpB,SAAS;EACT,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-d27JGRGi.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 { Integration } from './constants';\nimport type { FrameworkConfig } from './framework-config';\nimport type { WizardReadinessResult } from './health-checks/readiness';\nimport type { SettingsConflict } from './agent/agent-interface';\nimport type { ApiUser } 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 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\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 }[];\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\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 benchmark: boolean;\n yaraReport: boolean;\n projectId?: number;\n noTelemetry: boolean;\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 // 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 skillsComplete: boolean;\n outroDismissed: 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 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 integration?: Integration;\n benchmark?: boolean;\n yaraReport?: boolean;\n projectId?: string;\n noTelemetry?: 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 benchmark: args.benchmark ?? false,\n yaraReport: args.yaraReport ?? false,\n projectId: parseProjectIdArg(args.projectId),\n noTelemetry: args.noTelemetry ?? false,\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 skillsComplete: false,\n outroDismissed: false,\n loginUrl: null,\n authorizeUrl: null,\n credentials: null,\n roleAtOrganization: null,\n apiUser: 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;;;;AA6LD,SAAgB,aAAa,MAeX;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,WAAW,KAAK,aAAa;EAC7B,YAAY,KAAK,cAAc;EAC/B,WAAW,kBAAkB,KAAK,UAAU;EAC5C,aAAa,KAAK,eAAe;EAEjC,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,gBAAgB;EAChB,gBAAgB;EAChB,UAAU;EACV,cAAc;EACd,aAAa;EACb,oBAAoB;EACpB,SAAS;EACT,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 { i as buildSession, r as RunPhase } from "./wizard-session-gsn8Z3bZ.js";
1
+ import { i as buildSession, r as RunPhase } from "./wizard-session-d27JGRGi.js";
2
2
  export { RunPhase, buildSession };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@posthog/wizard",
3
- "version": "2.16.1",
3
+ "version": "2.17.0",
4
4
  "homepage": "https://github.com/PostHog/wizard",
5
5
  "repository": "https://github.com/PostHog/wizard",
6
6
  "description": "The PostHog wizard helps you to configure your project",
@@ -1 +0,0 @@
1
- {"version":3,"file":"add-mcp-server-to-clients-BS6Rjcwh.js","names":["fs","path","path","os","path","os","fs","execSync","z","os","path","z","os","path","path","fs"],"sources":["../src/steps/add-mcp-server-to-clients/MCPClient.ts","../src/steps/add-mcp-server-to-clients/clients/cursor.ts","../src/steps/add-mcp-server-to-clients/clients/claude-code.ts","../src/steps/add-mcp-server-to-clients/clients/visual-studio-code.ts","../src/steps/add-mcp-server-to-clients/clients/zed.ts","../src/steps/add-mcp-server-to-clients/clients/codex.ts","../src/steps/add-mcp-server-to-clients/plugin-client.ts","../src/steps/add-mcp-server-to-clients/index.ts"],"sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\nimport * as jsonc from 'jsonc-parser';\nimport { getDefaultServerConfig } from './defaults';\n\nexport type MCPServerConfig = Record<string, unknown>;\n\nexport abstract class MCPClient {\n name: string;\n abstract getConfigPath(): Promise<string>;\n abstract getServerPropertyName(): string;\n abstract isServerInstalled(local?: boolean): Promise<boolean>;\n abstract addServer(\n apiKey?: string,\n selectedFeatures?: string[],\n local?: boolean,\n ): Promise<{ success: boolean }>;\n abstract removeServer(local?: boolean): Promise<{ success: boolean }>;\n abstract isClientSupported(): Promise<boolean>;\n}\n\nexport abstract class DefaultMCPClient extends MCPClient {\n name = 'Default';\n\n constructor() {\n super();\n }\n\n getServerPropertyName(): string {\n return 'mcpServers';\n }\n\n getServerConfig(\n apiKey: string | undefined,\n selectedFeatures?: string[],\n local?: boolean,\n ): MCPServerConfig {\n return getDefaultServerConfig(apiKey, selectedFeatures, local);\n }\n\n async isServerInstalled(local?: boolean): Promise<boolean> {\n try {\n const configPath = await this.getConfigPath();\n\n if (!fs.existsSync(configPath)) {\n return false;\n }\n\n const configContent = await fs.promises.readFile(configPath, 'utf8');\n const config = jsonc.parse(configContent) as Record<string, any>;\n const serverPropertyName = this.getServerPropertyName();\n const serverName = local ? 'posthog-local' : 'posthog';\n\n return (\n serverPropertyName in config && serverName in config[serverPropertyName]\n );\n } catch {\n return false;\n }\n }\n\n async addServer(\n apiKey?: string,\n selectedFeatures?: string[],\n local?: boolean,\n ): Promise<{ success: boolean }> {\n try {\n const configPath = await this.getConfigPath();\n const configDir = path.dirname(configPath);\n\n await fs.promises.mkdir(configDir, { recursive: true });\n\n const serverPropertyName = this.getServerPropertyName();\n let configContent = '';\n let existingConfig = {};\n\n if (fs.existsSync(configPath)) {\n configContent = await fs.promises.readFile(configPath, 'utf8');\n existingConfig = jsonc.parse(configContent) || {};\n }\n\n const newServerConfig = this.getServerConfig(\n apiKey,\n selectedFeatures,\n local,\n );\n const typedConfig = existingConfig as Record<string, any>;\n if (!typedConfig[serverPropertyName]) {\n typedConfig[serverPropertyName] = {};\n }\n const serverName = local ? 'posthog-local' : 'posthog';\n typedConfig[serverPropertyName][serverName] = newServerConfig;\n\n const edits = jsonc.modify(\n configContent,\n [serverPropertyName, serverName],\n newServerConfig,\n {\n formattingOptions: {\n tabSize: 2,\n insertSpaces: true,\n },\n },\n );\n\n const modifiedContent = jsonc.applyEdits(configContent, edits);\n\n await fs.promises.writeFile(configPath, modifiedContent, 'utf8');\n\n return { success: true };\n } catch {\n return { success: false };\n }\n }\n\n async removeServer(local?: boolean): Promise<{ success: boolean }> {\n try {\n const configPath = await this.getConfigPath();\n\n if (!fs.existsSync(configPath)) {\n return { success: false };\n }\n\n const configContent = await fs.promises.readFile(configPath, 'utf8');\n const config = jsonc.parse(configContent) as Record<string, any>;\n const serverPropertyName = this.getServerPropertyName();\n\n const serverName = local ? 'posthog-local' : 'posthog';\n\n if (\n serverPropertyName in config &&\n serverName in config[serverPropertyName]\n ) {\n const edits = jsonc.modify(\n configContent,\n [serverPropertyName, serverName],\n undefined,\n {\n formattingOptions: {\n tabSize: 2,\n insertSpaces: true,\n },\n },\n );\n\n const modifiedContent = jsonc.applyEdits(configContent, edits);\n\n await fs.promises.writeFile(configPath, modifiedContent, 'utf8');\n\n return { success: true };\n }\n } catch {\n //\n }\n\n return { success: false };\n }\n}\n","import {\n DefaultMCPClient,\n MCPServerConfig,\n} from '@steps/add-mcp-server-to-clients/MCPClient';\nimport * as path from 'path';\nimport * as os from 'os';\nimport {\n DefaultMCPClientConfig,\n getNativeHTTPServerConfig,\n} from '@steps/add-mcp-server-to-clients/defaults';\nimport { z } from 'zod';\n\nexport const CursorMCPConfig = DefaultMCPClientConfig;\n\nexport type CursorMCPConfig = z.infer<typeof DefaultMCPClientConfig>;\n\nexport class CursorMCPClient extends DefaultMCPClient {\n name = 'Cursor';\n\n constructor() {\n super();\n }\n\n async isClientSupported(): Promise<boolean> {\n return Promise.resolve(\n process.platform === 'darwin' || process.platform === 'win32',\n );\n }\n\n async getConfigPath(): Promise<string> {\n return Promise.resolve(path.join(os.homedir(), '.cursor', 'mcp.json'));\n }\n\n getServerConfig(\n apiKey: string | undefined,\n selectedFeatures?: string[],\n local?: boolean,\n ): MCPServerConfig {\n return getNativeHTTPServerConfig(apiKey, selectedFeatures, local);\n }\n}\n","import { DefaultMCPClient } from '@steps/add-mcp-server-to-clients/MCPClient';\nimport { DefaultMCPClientConfig } from '@steps/add-mcp-server-to-clients/defaults';\nimport {\n PluginCapable,\n PluginInstallResult,\n} from '@steps/add-mcp-server-to-clients/plugin-client';\nimport { z } from 'zod';\nimport { execSync } from 'child_process';\nimport { analytics } from '@utils/analytics';\nimport { debug } from '@utils/debug';\nimport * as os from 'os';\nimport * as path from 'path';\nimport * as fs from 'fs';\n\nexport const ClaudeCodeMCPConfig = DefaultMCPClientConfig;\n\nexport type ClaudeCodeMCPConfig = z.infer<typeof DefaultMCPClientConfig>;\n\nexport class ClaudeCodeMCPClient\n extends DefaultMCPClient\n implements PluginCapable\n{\n name = 'Claude Code';\n private claudeBinaryPath: string | null = null;\n\n constructor() {\n super();\n }\n\n private findClaudeBinary(): string | null {\n if (this.claudeBinaryPath) {\n return this.claudeBinaryPath;\n }\n\n // Common installation paths for Claude Code CLI\n const possiblePaths = [\n path.join(os.homedir(), '.claude', 'local', 'claude'),\n '/usr/local/bin/claude',\n '/opt/homebrew/bin/claude',\n ];\n\n for (const claudePath of possiblePaths) {\n if (fs.existsSync(claudePath)) {\n debug(` Found claude binary at: ${claudePath}`);\n this.claudeBinaryPath = claudePath;\n return claudePath;\n }\n }\n\n // Try PATH as fallback\n try {\n execSync('command -v claude', { stdio: 'pipe' });\n debug(' Found claude in PATH');\n this.claudeBinaryPath = 'claude';\n return 'claude';\n } catch {\n // Not in PATH\n }\n\n return null;\n }\n\n isClientSupported(): Promise<boolean> {\n try {\n debug(' Checking for Claude Code...');\n const claudeBinary = this.findClaudeBinary();\n\n if (!claudeBinary) {\n debug(' Claude Code not found. Installation paths checked:');\n debug(` - ${path.join(os.homedir(), '.claude', 'local', 'claude')}`);\n debug(` - /usr/local/bin/claude`);\n debug(` - /opt/homebrew/bin/claude`);\n debug(` - PATH`);\n return Promise.resolve(false);\n }\n\n const output = execSync(`${claudeBinary} --version`, { stdio: 'pipe' });\n const version = output.toString().trim();\n debug(` Claude Code detected: ${version}`);\n return Promise.resolve(true);\n } catch (error) {\n debug(\n ` Claude Code check failed: ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n return Promise.resolve(false);\n }\n }\n\n isServerInstalled(): Promise<boolean> {\n return this.isPluginInstalled();\n }\n\n getConfigPath(): Promise<string> {\n throw new Error('Not implemented');\n }\n\n async addServer(): Promise<{ success: boolean }> {\n const result = await this.installPlugin();\n return { success: result.success };\n }\n\n removeServer(local?: boolean): Promise<{ success: boolean }> {\n const claudeBinary = this.findClaudeBinary();\n if (!claudeBinary) {\n return Promise.resolve({ success: false });\n }\n\n const serverName = local ? 'posthog-local' : 'posthog';\n const command = `${claudeBinary} mcp remove --scope user ${serverName}`;\n\n try {\n execSync(command);\n } catch (error) {\n analytics.captureException(\n new Error(\n `Failed to remove server from Claude Code: ${\n error instanceof Error ? error.message : String(error)\n }`,\n ),\n );\n return Promise.resolve({ success: false });\n }\n\n return Promise.resolve({ success: true });\n }\n\n supportsPlugin(): boolean {\n return this.findClaudeBinary() !== null;\n }\n\n isPluginInstalled(): Promise<boolean> {\n const binary = this.findClaudeBinary();\n if (!binary) return Promise.resolve(false);\n try {\n const output = execSync(`${binary} plugin list`, {\n stdio: 'pipe',\n }).toString();\n return Promise.resolve(output.toLowerCase().includes('posthog'));\n } catch {\n return Promise.resolve(false);\n }\n }\n\n installPlugin(): Promise<PluginInstallResult> {\n const binary = this.findClaudeBinary();\n if (!binary) return Promise.resolve({ success: false });\n try {\n execSync(`${binary} plugin install posthog`, { stdio: 'pipe' });\n return Promise.resolve({ success: true });\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n if (msg.includes('already installed') || msg.includes('already exists')) {\n return Promise.resolve({ success: true, alreadyInstalled: true });\n }\n analytics.captureException(\n new Error(`Claude Code plugin install failed: ${msg}`),\n );\n return Promise.resolve({ success: false });\n }\n }\n}\n","import z from 'zod';\nimport * as path from 'path';\nimport * as os from 'os';\nimport {\n DefaultMCPClient,\n MCPServerConfig,\n} from '@steps/add-mcp-server-to-clients/MCPClient';\nimport { getNativeHTTPServerConfig } from '@steps/add-mcp-server-to-clients/defaults';\nimport { runtimeEnv } from '@env';\n\nexport const VisualStudioCodeMCPConfig = z\n .object({\n servers: z.record(\n z.string(),\n z.union([\n z.object({\n command: z.string().optional(),\n args: z.array(z.string()).optional(),\n env: z.record(z.string(), z.string()).optional(),\n }),\n z.object({\n type: z.enum(['http', 'sse']),\n url: z.string(),\n headers: z.record(z.string(), z.string()).optional(),\n }),\n ]),\n ),\n })\n .passthrough();\n\nexport type VisualStudioCodeMCPConfig = z.infer<\n typeof VisualStudioCodeMCPConfig\n>;\n\nexport class VisualStudioCodeClient extends DefaultMCPClient {\n name = 'Visual Studio Code';\n\n getServerPropertyName(): string {\n return 'servers';\n }\n\n async isClientSupported(): Promise<boolean> {\n return Promise.resolve(\n process.platform === 'darwin' ||\n process.platform === 'win32' ||\n process.platform === 'linux',\n );\n }\n\n async getConfigPath(): Promise<string> {\n const homeDir = os.homedir();\n const isWindows = process.platform === 'win32';\n const isMac = process.platform === 'darwin';\n const isLinux = process.platform === 'linux';\n\n if (isMac) {\n return Promise.resolve(\n path.join(\n homeDir,\n 'Library',\n 'Application Support',\n 'Code',\n 'User',\n 'mcp.json',\n ),\n );\n }\n\n if (isWindows) {\n return Promise.resolve(\n path.join(runtimeEnv('APPDATA') || '', 'Code', 'User', 'mcp.json'),\n );\n }\n\n if (isLinux) {\n return Promise.resolve(\n path.join(homeDir, '.config', 'Code', 'User', 'mcp.json'),\n );\n }\n\n throw new Error(`Unsupported platform: ${process.platform}`);\n }\n\n getServerConfig(\n apiKey: string | undefined,\n selectedFeatures?: string[],\n local?: boolean,\n ): MCPServerConfig {\n return {\n type: 'http',\n ...getNativeHTTPServerConfig(apiKey, selectedFeatures, local),\n };\n }\n}\n","import z from 'zod';\nimport * as path from 'path';\nimport * as os from 'os';\nimport {\n DefaultMCPClient,\n MCPServerConfig,\n} from '@steps/add-mcp-server-to-clients/MCPClient';\nimport { getNativeHTTPServerConfig } from '@steps/add-mcp-server-to-clients/defaults';\nimport { runtimeEnv } from '@env';\n\nexport const ZedMCPConfig = z\n .object({\n context_servers: z.record(\n z.string(),\n z.union([\n z.object({\n enabled: z.boolean().optional(),\n source: z.string().optional(),\n command: z.string().optional(),\n args: z.array(z.string()).optional(),\n env: z.record(z.string(), z.string()).optional(),\n }),\n z.object({\n enabled: z.boolean().optional(),\n url: z.string(),\n headers: z.record(z.string(), z.string()).optional(),\n }),\n ]),\n ),\n })\n .passthrough();\n\nexport type ZedMCPConfig = z.infer<typeof ZedMCPConfig>;\n\nexport class ZedClient extends DefaultMCPClient {\n name = 'Zed';\n\n getServerPropertyName(): string {\n return 'context_servers';\n }\n\n async isClientSupported(): Promise<boolean> {\n return Promise.resolve(\n process.platform === 'darwin' || process.platform === 'linux',\n );\n }\n\n async getConfigPath(): Promise<string> {\n const homeDir = os.homedir();\n const isMac = process.platform === 'darwin';\n const isLinux = process.platform === 'linux';\n\n if (isMac) {\n return Promise.resolve(\n path.join(homeDir, '.config', 'zed', 'settings.json'),\n );\n }\n\n if (isLinux) {\n // https://zed.dev/docs/configuring-zed#settings-files\n const xdgConfigHome = runtimeEnv('XDG_CONFIG_HOME');\n if (xdgConfigHome) {\n return Promise.resolve(\n path.join(xdgConfigHome, 'zed', 'settings.json'),\n );\n }\n return Promise.resolve(\n path.join(homeDir, '.config', 'zed', 'settings.json'),\n );\n }\n\n throw new Error(`Unsupported platform: ${process.platform}`);\n }\n\n getServerConfig(\n apiKey: string | undefined,\n selectedFeatures?: string[],\n local?: boolean,\n ): MCPServerConfig {\n return {\n enabled: true,\n ...getNativeHTTPServerConfig(apiKey, selectedFeatures, local),\n };\n }\n}\n","import { z } from 'zod';\nimport { execSync, spawnSync } from 'node:child_process';\nimport * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\n\nimport { DefaultMCPClient } from '@steps/add-mcp-server-to-clients/MCPClient';\nimport { DefaultMCPClientConfig } from '@steps/add-mcp-server-to-clients/defaults';\nimport {\n PluginCapable,\n PluginInstallResult,\n} from '@steps/add-mcp-server-to-clients/plugin-client';\n\nimport { analytics } from '@utils/analytics';\n\nexport const CodexMCPConfig = DefaultMCPClientConfig;\n\nexport type CodexMCPConfig = z.infer<typeof DefaultMCPClientConfig>;\n\nexport class CodexMCPClient extends DefaultMCPClient implements PluginCapable {\n name = 'Codex';\n private codexBinaryPath: string | null = null;\n\n constructor() {\n super();\n }\n\n private findCodexBinary(): string | null {\n if (this.codexBinaryPath) return this.codexBinaryPath;\n try {\n const resolved = execSync('command -v codex', { stdio: 'pipe' })\n .toString()\n .trim();\n if (resolved) {\n this.codexBinaryPath = resolved;\n return resolved;\n }\n } catch {\n // not in PATH\n }\n return null;\n }\n\n isClientSupported(): Promise<boolean> {\n return Promise.resolve(this.findCodexBinary() !== null);\n }\n\n getConfigPath(): Promise<string> {\n throw new Error('Not implemented');\n }\n\n isServerInstalled(): Promise<boolean> {\n return this.isPluginInstalled();\n }\n\n async addServer(): Promise<{ success: boolean }> {\n const result = await this.installPlugin();\n return { success: result.success };\n }\n\n removeServer(): Promise<{ success: boolean }> {\n const binary = this.findCodexBinary();\n if (!binary) return Promise.resolve({ success: false });\n\n const result = spawnSync(binary, ['mcp', 'remove', 'posthog'], {\n stdio: 'ignore',\n });\n\n if (result.error || result.status !== 0) {\n analytics.captureException(\n new Error('Failed to remove server from Codex CLI.'),\n );\n return Promise.resolve({ success: false });\n }\n\n return Promise.resolve({ success: true });\n }\n\n supportsPlugin(): boolean {\n return this.findCodexBinary() !== null;\n }\n\n isPluginInstalled(): Promise<boolean> {\n const configPath = path.join(os.homedir(), '.codex', 'config.toml');\n try {\n const contents = fs.readFileSync(configPath, 'utf-8');\n // Marketplace installs appear as [marketplaces.posthog] in config.toml\n return Promise.resolve(\n contents.toLowerCase().includes('[marketplaces.posthog]'),\n );\n } catch {\n return Promise.resolve(false);\n }\n }\n\n installPlugin(): Promise<PluginInstallResult> {\n const binary = this.findCodexBinary();\n if (!binary) return Promise.resolve({ success: false });\n\n const run = () =>\n spawnSync(binary, ['plugin', 'marketplace', 'add', 'PostHog/ai-plugin'], {\n encoding: 'utf-8',\n });\n\n let result = run();\n\n // Stale cache directory with no config.toml entry — clear it and retry\n if (\n result.status !== 0 &&\n (result.stderr ?? '').includes('already added from a different source')\n ) {\n const staleDir = path.join(\n os.homedir(),\n '.codex',\n '.tmp',\n 'marketplaces',\n 'posthog',\n );\n try {\n fs.rmSync(staleDir, { recursive: true, force: true });\n } catch {\n // ignore — retry anyway\n }\n result = run();\n }\n\n if (result.status !== 0) {\n analytics.captureException(\n new Error(`Codex plugin install failed: ${result.stderr ?? ''}`),\n );\n return Promise.resolve({ success: false });\n }\n\n return Promise.resolve({ success: true });\n }\n}\n\nexport default CodexMCPClient;\n","export interface PluginInstallResult {\n success: boolean;\n alreadyInstalled?: boolean;\n}\n\nexport interface PluginCapable {\n supportsPlugin(): boolean;\n isPluginInstalled(): Promise<boolean>;\n installPlugin(): Promise<PluginInstallResult>;\n}\n\nexport function isPluginCapable<T>(client: T): client is T & PluginCapable {\n return (\n typeof client === 'object' &&\n client !== null &&\n 'supportsPlugin' in client &&\n 'installPlugin' in client\n );\n}\n","import type { Integration } from '@lib/constants';\nimport type { CloudRegion } from '@utils/types';\nimport { withProgress } from '../../telemetry';\nimport { analytics } from '@utils/analytics';\nimport { getUI } from '@ui';\nimport { MCPClient } from './MCPClient';\nimport { CursorMCPClient } from './clients/cursor';\nimport { ClaudeCodeMCPClient } from './clients/claude-code';\nimport { VisualStudioCodeClient } from './clients/visual-studio-code';\nimport { ZedClient } from './clients/zed';\nimport { CodexMCPClient } from './clients/codex';\nimport { ALL_FEATURE_VALUES } from './defaults';\nimport { debug } from '@utils/debug';\nimport { isPluginCapable, PluginCapable } from './plugin-client';\n\nexport const getSupportedClients = async (): Promise<MCPClient[]> => {\n const allClients = [\n new ClaudeCodeMCPClient(),\n new CodexMCPClient(),\n new CursorMCPClient(),\n new VisualStudioCodeClient(),\n new ZedClient(),\n ];\n const supportedClients: MCPClient[] = [];\n\n debug('Checking for supported MCP clients...');\n for (const client of allClients) {\n const isSupported = await client.isClientSupported();\n debug(`${client.name}: ${isSupported ? '✓ supported' : '✗ not supported'}`);\n if (isSupported) {\n supportedClients.push(client);\n }\n }\n debug(\n `Found ${supportedClients.length} supported client(s): ${supportedClients\n .map((c) => c.name)\n .join(', ')}`,\n );\n\n return supportedClients;\n};\n\n/**\n * Add MCP server to clients. No prompts — pure orchestration.\n * Prompts are handled by McpScreen (TUI) or auto-accepted (CI).\n */\nexport const addMCPServerToClientsStep = async ({\n integration,\n local = false,\n ci = false,\n cloudRegion: _cloudRegion,\n features,\n apiKey,\n}: {\n integration?: Integration;\n local?: boolean;\n ci?: boolean;\n cloudRegion?: CloudRegion;\n features?: string[];\n apiKey?: string;\n}): Promise<string[]> => {\n const ui = getUI();\n\n // CI mode: skip MCP installation entirely\n if (ci) {\n ui.log.info('Skipping MCP installation (CI mode)');\n return [];\n }\n\n const supportedClients = await getSupportedClients();\n\n if (supportedClients.length === 0) {\n ui.log.info(\n 'No supported MCP clients detected. Skipping MCP installation.',\n );\n return [];\n }\n\n // Auto-install to all supported clients\n await withProgress('adding mcp servers', async () => {\n await addMCPServer(\n supportedClients,\n apiKey,\n features ?? [...ALL_FEATURE_VALUES],\n local,\n );\n });\n\n ui.log.success(\n `Added the MCP server to:\n ${supportedClients.map((c) => `- ${c.name}`).join('\\n ')} `,\n );\n\n analytics.wizardCapture('mcp servers added', {\n clients: supportedClients.map((c) => c.name),\n integration,\n });\n\n return supportedClients.map((c) => c.name);\n};\n\nexport const removeMCPServerFromClientsStep = async ({\n integration,\n local = false,\n}: {\n integration?: Integration;\n local?: boolean;\n}): Promise<string[]> => {\n const installedClients = await getInstalledClients(local);\n if (installedClients.length === 0) {\n analytics.wizardCapture('mcp no servers to remove', {\n integration,\n });\n return [];\n }\n\n // Auto-remove from all installed clients\n const results = await withProgress('removing mcp servers', async () => {\n await removeMCPServer(installedClients, local);\n return installedClients.map((c) => c.name);\n });\n\n analytics.wizardCapture('mcp servers removed', {\n clients: results,\n integration,\n });\n\n return results;\n};\n\nexport const getInstalledClients = async (\n local?: boolean,\n): Promise<MCPClient[]> => {\n const clients = await getSupportedClients();\n const installedClients: MCPClient[] = [];\n\n for (const client of clients) {\n if (await client.isServerInstalled(local)) {\n installedClients.push(client);\n }\n }\n\n return installedClients;\n};\n\nexport const addMCPServer = async (\n clients: MCPClient[],\n personalApiKey?: string,\n selectedFeatures?: string[],\n local?: boolean,\n): Promise<void> => {\n for (const client of clients) {\n await client.addServer(personalApiKey, selectedFeatures, local);\n }\n};\n\nexport const getSupportedPluginClients = (\n clients: MCPClient[],\n): Array<MCPClient & PluginCapable> => {\n return clients.filter(isPluginCapable).filter((c) => c.supportsPlugin());\n};\n\nexport const installPlugins = async (\n clients: Array<MCPClient & PluginCapable>,\n): Promise<string[]> => {\n const installed: string[] = [];\n for (const client of clients) {\n try {\n const result = await client.installPlugin();\n if (result.success) installed.push(client.name);\n } catch (err) {\n debug(`[installPlugins] installPlugin threw for ${client.name}: ${err}`);\n }\n }\n return installed;\n};\n\nexport const removeMCPServer = async (\n clients: MCPClient[],\n local?: boolean,\n): Promise<void> => {\n for (const client of clients) {\n await client.removeServer(local);\n }\n};\n"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- import { n as ApiError } from "./api-CGJ1iGps.js";
2
- export { ApiError };
@@ -1 +0,0 @@
1
- {"version":3,"file":"mcp-prompt-streaming-clGsVw8q.js","names":[],"sources":["../src/lib/agent/mcp-prompt-streaming.ts"],"sourcesContent":["/**\n * Streaming prompt runner for the McpSuggestedPromptsScreen.\n *\n * Calls the Claude Agent SDK's `query()` directly with just the PostHog\n * MCP server configured — no skills, no sandbox, no settings sources,\n * no wizard-tools. This is the lightweight cousin of `runAgent` in\n * `agent-interface.ts`: same SDK, much narrower surface, suitable for\n * \"user asked a question, show the answer\" interactions.\n *\n * The function is an async generator that yields `AgentChunk`s extracted\n * from the SDK's message stream. Callers (the screen) consume them via\n * `for await (...)` and render as they arrive.\n */\n\nimport type { AgentChunk } from '@ui/tui/services/mcp-suggested-prompts-services';\nimport type { Credentials } from '@lib/wizard-session';\nimport { WIZARD_USER_AGENT } from '@lib/constants';\nimport { runtimeEnv } from '@env';\nimport { logToFile } from '@utils/debug';\n\n// Cached SDK module — first call pays the dynamic-import cost; later\n// calls reuse the same module.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nlet _sdkModule: any | null = null;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nasync function loadSdk(): Promise<any> {\n if (!_sdkModule) {\n _sdkModule = await import('@anthropic-ai/claude-agent-sdk');\n }\n return _sdkModule;\n}\n\nconst MODEL = 'claude-sonnet-4-6';\n\n// Bounded turn count so a single prompt can't loop forever on the\n// user's nickel. 20 gives the agent room for non-trivial multi-step\n// chains (multi-tool reads → reason → write → verify → summarize) while\n// still capping runaway loops. Worth tuning down once we see real\n// telemetry on average turn counts per prompt.\nconst MAX_TURNS = 30;\n\nfunction resolveMcpUrl(host: string): string {\n const override = runtimeEnv('MCP_URL');\n if (override) return override;\n // Parse the actual hostname rather than substring-matching the raw\n // input. `host.includes('eu.posthog.com')` would let arbitrary URLs\n // like `https://evil.eu.posthog.com.attacker.com` or\n // `https://useu.posthog.commerce` route to the EU MCP endpoint\n // (CodeQL: incomplete-url-substring-sanitization). Parsing into a\n // hostname and checking exact match / trusted subdomain blocks both.\n const hostname = parseHostname(host);\n const isEu =\n hostname === 'eu.posthog.com' || hostname.endsWith('.eu.posthog.com');\n return isEu\n ? 'https://mcp-eu.posthog.com/mcp'\n : 'https://mcp.posthog.com/mcp';\n}\n\n/**\n * Normalize a host string into a hostname suitable for trust checks.\n * Accepts either a full URL (`https://us.posthog.com`) or a bare host\n * (`us.posthog.com`). Returns the hostname lowercased, or the trimmed\n * input lowercased if parsing fails (defensive fallback so a malformed\n * value still resolves to the safer-default US endpoint).\n */\nfunction parseHostname(raw: string): string {\n const trimmed = raw.trim().toLowerCase();\n try {\n const withScheme = trimmed.includes('://') ? trimmed : `https://${trimmed}`;\n return new URL(withScheme).hostname.toLowerCase();\n } catch {\n return trimmed;\n }\n}\n\n/**\n * Extract a short, single-line summary from an arbitrary value. Used\n * for tool-call args and tool-result bodies so the screen has something\n * compact to render.\n */\nfunction summarize(value: unknown, maxLen = 120): string {\n if (value == null) return '';\n let text: string;\n if (typeof value === 'string') text = value;\n else {\n try {\n text = JSON.stringify(value);\n } catch {\n text = String(value);\n }\n }\n text = text.replace(/\\s+/g, ' ').trim();\n if (text.length > maxLen) text = text.slice(0, maxLen - 1) + '…';\n return text;\n}\n\n/**\n * Convert one SDK message into zero or more AgentChunks. Mirrors the\n * subset of message shapes the wizard's main runAgent middleware\n * handles, but narrowed to just the kinds the screen needs to render.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction messageToChunks(message: any): AgentChunk[] {\n const chunks: AgentChunk[] = [];\n\n if (message?.type === 'assistant') {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n const content = message.message?.content;\n if (Array.isArray(content)) {\n for (const block of content) {\n if (!block || typeof block !== 'object') continue;\n const type = (block as { type?: string }).type;\n if (type === 'text') {\n const text = (block as { text?: string }).text ?? '';\n if (text) chunks.push({ kind: 'text', text });\n } else if (type === 'tool_use') {\n const name = (block as { name?: string }).name ?? 'tool';\n const input = (block as { input?: unknown }).input;\n chunks.push({\n kind: 'tool-call',\n toolName: name,\n detail: summarize(input),\n });\n }\n }\n }\n }\n\n if (message?.type === 'user') {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n const content = message.message?.content;\n if (Array.isArray(content)) {\n for (const block of content) {\n if (!block || typeof block !== 'object') continue;\n const type = (block as { type?: string }).type;\n if (type === 'tool_result') {\n const detail = summarize((block as { content?: unknown }).content);\n chunks.push({ kind: 'tool-result', toolName: 'tool', detail });\n }\n }\n }\n }\n\n if (message?.type === 'result') {\n chunks.push({ kind: 'done' });\n }\n\n return chunks;\n}\n\n/**\n * Build a system-prompt append that nudges the agent to fit its response\n * inside the current terminal window. We can't actually constrain Claude\n * — this is a soft cap that the model usually honors. The screen also\n * applies a hard truncation cap as a fallback for non-compliant runs.\n *\n * Core principle nudged at the model: TALL CONTENT IS BAD, WIDE CONTENT\n * IS GOOD. Default terminal is 120 columns × 24 rows — that's a lot of\n * horizontal space, not much vertical. Spread data across columns, never\n * stack it down rows when a horizontal layout would work.\n */\nfunction buildTerminalFitPrompt(): string {\n const cols = process.stdout.columns ?? 120;\n const rows = process.stdout.rows ?? 24;\n // Reserve rows for wizard chrome (title, status, hint, margins).\n const messageBudget = Math.max(8, rows - 10);\n const tableRowBudget = Math.min(8, Math.max(3, rows - 14));\n\n return [\n `You are responding inside a CLI window that is exactly ${cols} columns wide and ${rows} rows tall. The user CAN'T SCROLL — your entire reply must fit on screen.`,\n ``,\n `LAYOUT PRINCIPLE: tall content is the enemy, wide content is your friend. You have ${cols} columns of horizontal space; use them. Spread data across columns instead of stacking it down rows.`,\n ``,\n `Hard limits:`,\n `- Aim for 3-6 lines of prose. Maximum ${messageBudget} lines total.`,\n `- Tables: max ${tableRowBudget} rows. Prefer MULTI-COLUMN tables (5-8 columns) over narrow tables with many rows. A two-column table with a long list of rows is exactly what to AVOID — that's the tall layout. If you have many key/value pairs, transpose them: keys as column headers across the top, values as a single wide row underneath.`,\n `- Lists: if there are 6+ short items, format them inline (comma-separated) or in 2-3 columns, not as a vertical bullet list.`,\n `- For tool results, summarize the 1-3 numbers that matter. Do NOT echo raw JSON or the full payload.`,\n `- Code blocks: no language tag, no leading blank lines.`,\n `- No closing pleasantries (\"let me know if…\", \"feel free to…\"). Stop when the answer is delivered.`,\n `- No section headers unless the response actually has multiple sections.`,\n `- The last paragraph should always be one line that says \"Now go use our MCP to build something!\"`,\n ].join('\\n');\n}\n\nexport async function* runMcpPromptViaSdk(args: {\n prompt: string;\n credentials: Credentials;\n signal: AbortSignal;\n}): AsyncIterable<AgentChunk> {\n const { prompt, credentials, signal } = args;\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const { query } = await loadSdk();\n\n // Bridge external AbortSignal → SDK AbortController.\n const abortController = new AbortController();\n if (signal.aborted) abortController.abort();\n else\n signal.addEventListener('abort', () => abortController.abort(), {\n once: true,\n });\n\n const mcpUrl = resolveMcpUrl(credentials.host);\n logToFile(`[runMcpPromptViaSdk] mcpUrl=${mcpUrl} model=${MODEL}`);\n\n // The SDK expects an async generator for the prompt that stays open\n // until the result is received. For a single-turn prompt we yield one\n // user message and then await an abort (which fires when streaming\n // completes or the caller cancels).\n const createPromptStream = async function* () {\n yield {\n type: 'user' as const,\n session_id: '',\n message: { role: 'user' as const, content: prompt },\n parent_tool_use_id: null,\n };\n // Hold the stream open until abort. The SDK closes its end when it\n // sees a `result` message; we close ours via the abortController in\n // the finally block below.\n await new Promise<void>((resolve) => {\n if (abortController.signal.aborted) {\n resolve();\n return;\n }\n abortController.signal.addEventListener('abort', () => resolve(), {\n once: true,\n });\n });\n };\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call\n const response = query({\n prompt: createPromptStream(),\n options: {\n abortController,\n model: MODEL,\n cwd: process.cwd(),\n permissionMode: 'acceptEdits',\n maxTurns: MAX_TURNS,\n systemPrompt: {\n type: 'preset',\n preset: 'claude_code',\n append: buildTerminalFitPrompt(),\n },\n mcpServers: {\n 'posthog-wizard': {\n type: 'http',\n url: mcpUrl,\n headers: {\n Authorization: `Bearer ${credentials.accessToken}`,\n 'User-Agent': WIZARD_USER_AGENT,\n },\n },\n },\n // Only let the agent use MCP tools — no shell, no file I/O,\n // no Read/Edit/Write. This is a chat-with-MCP run, not a\n // wizard skill execution.\n allowedTools: ['mcp__posthog-wizard__*'],\n },\n });\n\n for await (const message of response as AsyncIterable<unknown>) {\n if (signal.aborted) return;\n for (const chunk of messageToChunks(message)) {\n yield chunk;\n if (chunk.kind === 'done') return;\n }\n }\n } catch (err) {\n const text = err instanceof Error ? err.message : String(err);\n logToFile(`[runMcpPromptViaSdk] error: ${text}`);\n yield { kind: 'error', text };\n } finally {\n // Closes the prompt stream so `query()` shuts down cleanly even if\n // we never saw a 'result' message.\n abortController.abort();\n }\n}\n"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- import { r as hasDeclaredDependency } from "./package-json-Cynjr9k4.js";
2
- export { hasDeclaredDependency };