@posthog/wizard 2.14.2 → 2.14.3

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 (69) hide show
  1. package/dist/{TextBlock-B3cm43YY.js → TextBlock-DEHERFec.js} +33 -2
  2. package/dist/TextBlock-DEHERFec.js.map +1 -0
  3. package/dist/{add-mcp-server-to-clients-BL0trzId.js → add-mcp-server-to-clients-B48J7VVO.js} +4 -4
  4. package/dist/add-mcp-server-to-clients-B48J7VVO.js.map +1 -0
  5. package/dist/{agent-interface-HBWLfIDs.js → agent-interface-cEdS_bNo.js} +5 -5
  6. package/dist/agent-interface-cEdS_bNo.js.map +1 -0
  7. package/dist/{agent-runner-PUFQDL4S.js → agent-runner-CK5r-zQF.js} +7 -7
  8. package/dist/agent-runner-CK5r-zQF.js.map +1 -0
  9. package/dist/analytics-Bw8E-yhX.js +2 -0
  10. package/dist/{analytics-D1-WXmxH.js → analytics-DaDpDus8.js} +2 -2
  11. package/dist/analytics-DaDpDus8.js.map +1 -0
  12. package/dist/bin.js +32 -55
  13. package/dist/bin.js.map +1 -1
  14. package/dist/{debug-Dmx2Q7HM.js → debug-BOogNcWX.js} +2 -2
  15. package/dist/debug-BOogNcWX.js.map +1 -0
  16. package/dist/{debug-BuBfx2GP.js → debug-B_PK52GI.js} +1 -1
  17. package/dist/{detection-CM90aZAk.js → detection-OCF8fpfp.js} +3 -3
  18. package/dist/detection-OCF8fpfp.js.map +1 -0
  19. package/dist/file-BKbKreWF.js.map +1 -1
  20. package/dist/{package-manager-D6MvXiGG.js → package-manager-CmMJAD-V.js} +2 -2
  21. package/dist/package-manager-CmMJAD-V.js.map +1 -0
  22. package/dist/posthog-BbQf_Hzq.js.map +1 -1
  23. package/dist/{posthog-integration-C4yP5ZMX.js → posthog-integration-By5930Gz.js} +11 -38
  24. package/dist/posthog-integration-By5930Gz.js.map +1 -0
  25. package/dist/{provisioning-Buru4Hui.js → provisioning-BHa8VWaa.js} +3 -3
  26. package/dist/provisioning-BHa8VWaa.js.map +1 -0
  27. package/dist/provisioning-gHqu_MXL.js +2 -0
  28. package/dist/{registry-C9-54_aB.js → registry-DpROZPnl.js} +4 -4
  29. package/dist/registry-DpROZPnl.js.map +1 -0
  30. package/dist/{setup-utils-Cra9hsR5.js → setup-utils-Mzpk1vqG.js} +6 -6
  31. package/dist/setup-utils-Mzpk1vqG.js.map +1 -0
  32. package/dist/setup-utils-ptemIB6g.js +2 -0
  33. package/dist/{slides-DtXq03Cd.js → slides-BtDXEXdn.js} +5 -5
  34. package/dist/slides-BtDXEXdn.js.map +1 -0
  35. package/dist/{start-playground-BZUi05v7.js → start-playground-zZL5y9id.js} +4 -4
  36. package/dist/start-playground-zZL5y9id.js.map +1 -0
  37. package/dist/{start-tui-BFtVjPvL.js → start-tui-Cz7RZSn_.js} +11 -11
  38. package/dist/start-tui-Cz7RZSn_.js.map +1 -0
  39. package/dist/{steps-PV5CP6fe.js → steps-C2XEzN79.js} +6 -6
  40. package/dist/steps-C2XEzN79.js.map +1 -0
  41. package/dist/task-stream-DUpUZmFQ.js.map +1 -1
  42. package/dist/{telemetry-CeitxLMv.js → telemetry-BG2bOwCp.js} +2 -2
  43. package/dist/telemetry-BG2bOwCp.js.map +1 -0
  44. package/dist/{wizard-abort-gatjLP05.js → wizard-abort-BmT-F0Vr.js} +3 -3
  45. package/dist/wizard-abort-BmT-F0Vr.js.map +1 -0
  46. package/dist/{wizard-abort-DwlDCXy5.js → wizard-abort-CYW83OG5.js} +1 -1
  47. package/dist/wizard-ui-YdGFRyu_.js.map +1 -1
  48. package/package.json +3 -1
  49. package/dist/TextBlock-B3cm43YY.js.map +0 -1
  50. package/dist/add-mcp-server-to-clients-BL0trzId.js.map +0 -1
  51. package/dist/agent-interface-HBWLfIDs.js.map +0 -1
  52. package/dist/agent-runner-PUFQDL4S.js.map +0 -1
  53. package/dist/analytics-D1-WXmxH.js.map +0 -1
  54. package/dist/analytics-DVT_xa3O.js +0 -2
  55. package/dist/debug-Dmx2Q7HM.js.map +0 -1
  56. package/dist/detection-CM90aZAk.js.map +0 -1
  57. package/dist/package-manager-D6MvXiGG.js.map +0 -1
  58. package/dist/posthog-integration-C4yP5ZMX.js.map +0 -1
  59. package/dist/provisioning-BbpTbU7J.js +0 -2
  60. package/dist/provisioning-Buru4Hui.js.map +0 -1
  61. package/dist/registry-C9-54_aB.js.map +0 -1
  62. package/dist/setup-utils-BAQfaP4a.js +0 -2
  63. package/dist/setup-utils-Cra9hsR5.js.map +0 -1
  64. package/dist/slides-DtXq03Cd.js.map +0 -1
  65. package/dist/start-playground-BZUi05v7.js.map +0 -1
  66. package/dist/start-tui-BFtVjPvL.js.map +0 -1
  67. package/dist/steps-PV5CP6fe.js.map +0 -1
  68. package/dist/telemetry-CeitxLMv.js.map +0 -1
  69. package/dist/wizard-abort-gatjLP05.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"steps-C2XEzN79.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 +1 @@
1
- {"version":3,"file":"task-stream-DUpUZmFQ.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\nimport type { WizardStore, TaskItem } from '../../ui/tui/store';\nimport { TaskStatus } from '../../ui/wizard-ui';\nimport { RunPhase } from '../wizard-session';\nimport {\n type TaskStreamDestination,\n type TaskStreamUpdate,\n type StreamTask,\n StreamTaskStatus,\n StreamEvent,\n} from './types';\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\nexport interface TaskStreamPushOptions {\n store: WizardStore;\n programId: string;\n destinations: TaskStreamDestination[];\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\n private sessionId: string | null = null;\n private created = false;\n\n constructor(opts: TaskStreamPushOptions) {\n this.store = opts.store;\n this.programId = opts.programId;\n this.destinations = opts.destinations;\n this.startedAt = new Date().toISOString();\n }\n\n /** Send a final push. */\n async dispose(): Promise<void> {\n await this.push();\n }\n\n async push(): Promise<void> {\n const { session, tasks, eventPlan } = this.store;\n const skillId = session.skillId ?? this.programId;\n\n // Lock session ID on first push so it stays stable\n if (!this.sessionId) {\n this.sessionId = `${this.programId}-${skillId}-${this.startedAt}`;\n }\n\n const payload: TaskStreamUpdate = {\n session_id: this.sessionId,\n program_id: this.programId,\n skill_id: skillId,\n started_at: this.startedAt,\n run_phase: session.runPhase,\n tasks: buildTasks(tasks),\n event_plan: eventPlan.length > 0 ? eventPlan : undefined,\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 (payload.run_phase === RunPhase.Completed) {\n event = StreamEvent.Complete;\n } else if (payload.run_phase === RunPhase.Error) {\n event = StreamEvent.Error;\n } else {\n event = StreamEvent.Update;\n }\n\n await Promise.all(\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n this.destinations.map((d) => d.send(event, payload).catch(() => {})),\n );\n }\n}\n"],"mappings":";;;;AAgBA,MAAM,aAAmD;;;;CAIxD;AAED,SAAS,WAAW,OAAiC;AACnD,QAAO,MAAM,KAAK,MAAM,OAAO;EAC7B,IAAI,OAAO,EAAE;EACb,OAAO,KAAK;EACZ,QAAQ,WAAW,KAAK,WAAA;EACzB,EAAE;;AASL,IAAa,iBAAb,MAA4B;CAC1B;CACA;CACA;CACA;CAEA,YAAmC;CACnC,UAAkB;CAElB,YAAY,MAA6B;AACvC,OAAK,QAAQ,KAAK;AAClB,OAAK,YAAY,KAAK;AACtB,OAAK,eAAe,KAAK;AACzB,OAAK,6BAAY,IAAI,MAAM,EAAC,aAAa;;;CAI3C,MAAM,UAAyB;AAC7B,QAAM,KAAK,MAAM;;CAGnB,MAAM,OAAsB;EAC1B,MAAM,EAAE,SAAS,OAAO,cAAc,KAAK;EAC3C,MAAM,UAAU,QAAQ,WAAW,KAAK;AAGxC,MAAI,CAAC,KAAK,UACR,MAAK,YAAY,GAAG,KAAK,UAAU,GAAG,QAAQ,GAAG,KAAK;EAGxD,MAAM,UAA4B;GAChC,YAAY,KAAK;GACjB,YAAY,KAAK;GACjB,UAAU;GACV,YAAY,KAAK;GACjB,WAAW,QAAQ;GACnB,OAAO,WAAW,MAAM;GACxB,YAAY,UAAU,SAAS,IAAI,YAAY,KAAA;GAC/C,4BAAW,IAAI,MAAM,EAAC,aAAa;GACpC;EAED,IAAI;AACJ,MAAI,CAAC,KAAK,SAAS;AACjB,QAAK,UAAU;AACf,WAAA;aACS,QAAQ,cAAA,YACjB,SAAA;WACS,QAAQ,cAAA,QACjB,SAAA;MAEA,SAAA;AAGF,QAAM,QAAQ,IAEZ,KAAK,aAAa,KAAK,MAAM,EAAE,KAAK,OAAO,QAAQ,CAAC,YAAY,GAAG,CAAC,CACrE"}
1
+ {"version":3,"file":"task-stream-DUpUZmFQ.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\nimport type { WizardStore, TaskItem } from '@ui/tui/store';\nimport { TaskStatus } from '@ui/wizard-ui';\nimport { RunPhase } from '@lib/wizard-session';\nimport {\n type TaskStreamDestination,\n type TaskStreamUpdate,\n type StreamTask,\n StreamTaskStatus,\n StreamEvent,\n} from './types';\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\nexport interface TaskStreamPushOptions {\n store: WizardStore;\n programId: string;\n destinations: TaskStreamDestination[];\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\n private sessionId: string | null = null;\n private created = false;\n\n constructor(opts: TaskStreamPushOptions) {\n this.store = opts.store;\n this.programId = opts.programId;\n this.destinations = opts.destinations;\n this.startedAt = new Date().toISOString();\n }\n\n /** Send a final push. */\n async dispose(): Promise<void> {\n await this.push();\n }\n\n async push(): Promise<void> {\n const { session, tasks, eventPlan } = this.store;\n const skillId = session.skillId ?? this.programId;\n\n // Lock session ID on first push so it stays stable\n if (!this.sessionId) {\n this.sessionId = `${this.programId}-${skillId}-${this.startedAt}`;\n }\n\n const payload: TaskStreamUpdate = {\n session_id: this.sessionId,\n program_id: this.programId,\n skill_id: skillId,\n started_at: this.startedAt,\n run_phase: session.runPhase,\n tasks: buildTasks(tasks),\n event_plan: eventPlan.length > 0 ? eventPlan : undefined,\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 (payload.run_phase === RunPhase.Completed) {\n event = StreamEvent.Complete;\n } else if (payload.run_phase === RunPhase.Error) {\n event = StreamEvent.Error;\n } else {\n event = StreamEvent.Update;\n }\n\n await Promise.all(\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n this.destinations.map((d) => d.send(event, payload).catch(() => {})),\n );\n }\n}\n"],"mappings":";;;;AAgBA,MAAM,aAAmD;;;;CAIxD;AAED,SAAS,WAAW,OAAiC;AACnD,QAAO,MAAM,KAAK,MAAM,OAAO;EAC7B,IAAI,OAAO,EAAE;EACb,OAAO,KAAK;EACZ,QAAQ,WAAW,KAAK,WAAA;EACzB,EAAE;;AASL,IAAa,iBAAb,MAA4B;CAC1B;CACA;CACA;CACA;CAEA,YAAmC;CACnC,UAAkB;CAElB,YAAY,MAA6B;AACvC,OAAK,QAAQ,KAAK;AAClB,OAAK,YAAY,KAAK;AACtB,OAAK,eAAe,KAAK;AACzB,OAAK,6BAAY,IAAI,MAAM,EAAC,aAAa;;;CAI3C,MAAM,UAAyB;AAC7B,QAAM,KAAK,MAAM;;CAGnB,MAAM,OAAsB;EAC1B,MAAM,EAAE,SAAS,OAAO,cAAc,KAAK;EAC3C,MAAM,UAAU,QAAQ,WAAW,KAAK;AAGxC,MAAI,CAAC,KAAK,UACR,MAAK,YAAY,GAAG,KAAK,UAAU,GAAG,QAAQ,GAAG,KAAK;EAGxD,MAAM,UAA4B;GAChC,YAAY,KAAK;GACjB,YAAY,KAAK;GACjB,UAAU;GACV,YAAY,KAAK;GACjB,WAAW,QAAQ;GACnB,OAAO,WAAW,MAAM;GACxB,YAAY,UAAU,SAAS,IAAI,YAAY,KAAA;GAC/C,4BAAW,IAAI,MAAM,EAAC,aAAa;GACpC;EAED,IAAI;AACJ,MAAI,CAAC,KAAK,SAAS;AACjB,QAAK,UAAU;AACf,WAAA;aACS,QAAQ,cAAA,YACjB,SAAA;WACS,QAAQ,cAAA,QACjB,SAAA;MAEA,SAAA;AAGF,QAAM,QAAQ,IAEZ,KAAK,aAAa,KAAK,MAAM,EAAE,KAAK,OAAO,QAAQ,CAAC,YAAY,GAAG,CAAC,CACrE"}
@@ -1,4 +1,4 @@
1
- import { n as analytics } from "./analytics-D1-WXmxH.js";
1
+ import { n as analytics } from "./analytics-DaDpDus8.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-CeitxLMv.js.map
13
+ //# sourceMappingURL=telemetry-BG2bOwCp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telemetry-BG2bOwCp.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,5 +1,5 @@
1
- import { c as getUI } from "./debug-Dmx2Q7HM.js";
2
- import { n as analytics } from "./analytics-D1-WXmxH.js";
1
+ import { c as getUI } from "./debug-BOogNcWX.js";
2
+ import { n as analytics } from "./analytics-DaDpDus8.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-gatjLP05.js.map
41
+ //# sourceMappingURL=wizard-abort-BmT-F0Vr.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wizard-abort-BmT-F0Vr.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-gatjLP05.js";
1
+ import { r as wizardAbort, t as WizardError } from "./wizard-abort-BmT-F0Vr.js";
2
2
  export { WizardError, wizardAbort };
@@ -1 +1 @@
1
- {"version":3,"file":"wizard-ui-YdGFRyu_.js","names":[],"sources":["../src/ui/wizard-ui.ts"],"sourcesContent":["/**\n * WizardUI — abstraction layer for all user-facing operations.\n *\n * Business logic calls `getUI()` instead of importing the store directly.\n * Implementations: InkUI (TUI), LoggingUI (CI).\n *\n * No prompt methods — the TUI screens own all user input.\n * Session-mutating methods trigger reactive screen resolution in the TUI.\n */\n\nimport type { SettingsConflict } from '../lib/agent/agent-interface';\nimport type { WizardReadinessResult } from '../lib/health-checks/readiness.js';\nimport type {\n AskAnswers,\n OutroData,\n PendingQuestion,\n} from '../lib/wizard-session';\n\nexport enum TaskStatus {\n Pending = 'pending',\n InProgress = 'in_progress',\n Completed = 'completed',\n}\n\nexport function isTaskStatus(value: string): value is TaskStatus {\n return (Object.values(TaskStatus) as string[]).includes(value);\n}\n\nexport interface SpinnerHandle {\n start(message?: string): void;\n stop(message?: string): void;\n message(msg?: string): void;\n}\n\n/**\n * Context passed to `showAuthError` so the screen can pick the right copy.\n *\n * `hasSettingsConflict` is true when a Claude Code settings.json /\n * managed-settings file actually overrides the LLM Gateway auth — the\n * Wizard's pre-flight check missed it or it appeared after startup.\n * When false, the 401 has a different cause (bad PAT prefix, missing\n * scope, expired key, region mismatch) and we should not advise the\n * user to log out of Claude Code.\n */\nexport interface AuthErrorDetail {\n hasSettingsConflict: boolean;\n logFilePath: string;\n}\n\nexport interface WizardUI {\n // ── Lifecycle messages ────────────────────────────────────────────\n intro(message: string): void;\n /** Success outro with a plain text message. */\n outro(message: string): void;\n /**\n * Error outro. Sets structured outroData and transitions run phase so\n * the router advances to the outro screen. Use for abort/failure paths\n * that need a custom error render — do NOT build the outroData by\n * mutating session directly (nanostore holds a shallow copy).\n */\n outroError(data: OutroData): void;\n /** Resolves when the user dismisses the outro screen (presses any key).\n * Lets the abort path wait for the user to read the error before the\n * process exits. Resolves immediately in non-TUI environments. */\n waitForOutroDismissed(): Promise<void>;\n cancel(message: string): void;\n\n // ── Logging ───────────────────────────────────────────────────────\n log: {\n info(message: string): void;\n warn(message: string): void;\n error(message: string): void;\n success(message: string): void;\n step(message: string): void;\n };\n\n note(message: string): void;\n pushStatus(message: string): void;\n\n // ── Spinner ───────────────────────────────────────────────────────\n spinner(): SpinnerHandle;\n\n // ── Session state (triggers reactive screen resolution in TUI) ────\n /** Signal that the main work (agent run) has started. */\n startRun(): void;\n\n /** Store OAuth/API credentials. Resolves past AuthScreen in TUI. */\n setCredentials(credentials: {\n accessToken: string;\n projectApiKey: string;\n host: string;\n projectId: number;\n }): void;\n\n /** Show blocking service outage (pushes outage overlay in TUI). Blocks until dismissed. */\n showBlockingOutage(result: WizardReadinessResult): Promise<void>;\n\n /** Store non-blocking readiness warnings (shown as Health tab in RunScreen). */\n setReadinessWarnings(result: WizardReadinessResult): void;\n\n /** Warn that another process is blocking the OAuth port (pushes overlay in TUI). */\n showPortConflict(processInfo: {\n command: string;\n pid: string;\n port: number;\n user: string;\n }): Promise<void>;\n\n showSettingsOverride(\n conflicts: SettingsConflict[],\n backupAndFix: () => boolean,\n ): Promise<void>;\n\n /** Show auth error overlay when Anthropic API returns 401. */\n showAuthError(detail?: AuthErrorDetail): void;\n\n /**\n * Open the wizard_ask overlay and resolve with the user's answers.\n * Implementations that can't ask (CI/logging) reject so the bridge can\n * surface a clear \"not available\" error to the agent.\n */\n requestQuestion(question: PendingQuestion): Promise<AskAnswers>;\n\n // ── Display state ──────────────────────────────────────────────────\n /** Set the detected framework label (e.g., \"Django with Wagtail CMS\") */\n setDetectedFramework(label: string): void;\n\n /** Register a callback to run when the TUI transitions onto the given screen. */\n onEnterScreen(screen: string, fn: () => void): void;\n\n setLoginUrl(url: string | null): void;\n\n // ── Task tracking from SDK TaskCreate/TaskUpdate events ───────────\n // Receives the full materialised task list each call. The caller (agent\n // loop) maintains a Map<taskId, …> from incremental Task* events and\n // re-emits the snapshot here, preserving the existing store semantics.\n syncTodos(\n todos: Array<{ content: string; status: string; activeForm?: string }>,\n ): void;\n\n // ── Event plan from .posthog-events.json ────────────────────\n setEventPlan(events: Array<{ name: string; description: string }>): void;\n\n // ── Dashboard URL emitted by the agent via [DASHBOARD_URL] marker ──\n setDashboardUrl(url: string): void;\n\n // ── Generic frameworkContext setter for program file watchers ─────\n setFrameworkContext(key: string, value: unknown): void;\n}\n"],"mappings":";AAkBA,IAAY,aAAL,yBAAA,YAAA;AACL,YAAA,aAAA;AACA,YAAA,gBAAA;AACA,YAAA,eAAA;;KACD;AAED,SAAgB,aAAa,OAAoC;AAC/D,QAAQ,OAAO,OAAO,WAAW,CAAc,SAAS,MAAM"}
1
+ {"version":3,"file":"wizard-ui-YdGFRyu_.js","names":[],"sources":["../src/ui/wizard-ui.ts"],"sourcesContent":["/**\n * WizardUI — abstraction layer for all user-facing operations.\n *\n * Business logic calls `getUI()` instead of importing the store directly.\n * Implementations: InkUI (TUI), LoggingUI (CI).\n *\n * No prompt methods — the TUI screens own all user input.\n * Session-mutating methods trigger reactive screen resolution in the TUI.\n */\n\nimport type { SettingsConflict } from '@lib/agent/agent-interface';\nimport type { WizardReadinessResult } from '@lib/health-checks/readiness';\nimport type {\n AskAnswers,\n OutroData,\n PendingQuestion,\n} from '@lib/wizard-session';\n\nexport enum TaskStatus {\n Pending = 'pending',\n InProgress = 'in_progress',\n Completed = 'completed',\n}\n\nexport function isTaskStatus(value: string): value is TaskStatus {\n return (Object.values(TaskStatus) as string[]).includes(value);\n}\n\nexport interface SpinnerHandle {\n start(message?: string): void;\n stop(message?: string): void;\n message(msg?: string): void;\n}\n\n/**\n * Context passed to `showAuthError` so the screen can pick the right copy.\n *\n * `hasSettingsConflict` is true when a Claude Code settings.json /\n * managed-settings file actually overrides the LLM Gateway auth — the\n * Wizard's pre-flight check missed it or it appeared after startup.\n * When false, the 401 has a different cause (bad PAT prefix, missing\n * scope, expired key, region mismatch) and we should not advise the\n * user to log out of Claude Code.\n */\nexport interface AuthErrorDetail {\n hasSettingsConflict: boolean;\n logFilePath: string;\n}\n\nexport interface WizardUI {\n // ── Lifecycle messages ────────────────────────────────────────────\n intro(message: string): void;\n /** Success outro with a plain text message. */\n outro(message: string): void;\n /**\n * Error outro. Sets structured outroData and transitions run phase so\n * the router advances to the outro screen. Use for abort/failure paths\n * that need a custom error render — do NOT build the outroData by\n * mutating session directly (nanostore holds a shallow copy).\n */\n outroError(data: OutroData): void;\n /** Resolves when the user dismisses the outro screen (presses any key).\n * Lets the abort path wait for the user to read the error before the\n * process exits. Resolves immediately in non-TUI environments. */\n waitForOutroDismissed(): Promise<void>;\n cancel(message: string): void;\n\n // ── Logging ───────────────────────────────────────────────────────\n log: {\n info(message: string): void;\n warn(message: string): void;\n error(message: string): void;\n success(message: string): void;\n step(message: string): void;\n };\n\n note(message: string): void;\n pushStatus(message: string): void;\n\n // ── Spinner ───────────────────────────────────────────────────────\n spinner(): SpinnerHandle;\n\n // ── Session state (triggers reactive screen resolution in TUI) ────\n /** Signal that the main work (agent run) has started. */\n startRun(): void;\n\n /** Store OAuth/API credentials. Resolves past AuthScreen in TUI. */\n setCredentials(credentials: {\n accessToken: string;\n projectApiKey: string;\n host: string;\n projectId: number;\n }): void;\n\n /** Show blocking service outage (pushes outage overlay in TUI). Blocks until dismissed. */\n showBlockingOutage(result: WizardReadinessResult): Promise<void>;\n\n /** Store non-blocking readiness warnings (shown as Health tab in RunScreen). */\n setReadinessWarnings(result: WizardReadinessResult): void;\n\n /** Warn that another process is blocking the OAuth port (pushes overlay in TUI). */\n showPortConflict(processInfo: {\n command: string;\n pid: string;\n port: number;\n user: string;\n }): Promise<void>;\n\n showSettingsOverride(\n conflicts: SettingsConflict[],\n backupAndFix: () => boolean,\n ): Promise<void>;\n\n /** Show auth error overlay when Anthropic API returns 401. */\n showAuthError(detail?: AuthErrorDetail): void;\n\n /**\n * Open the wizard_ask overlay and resolve with the user's answers.\n * Implementations that can't ask (CI/logging) reject so the bridge can\n * surface a clear \"not available\" error to the agent.\n */\n requestQuestion(question: PendingQuestion): Promise<AskAnswers>;\n\n // ── Display state ──────────────────────────────────────────────────\n /** Set the detected framework label (e.g., \"Django with Wagtail CMS\") */\n setDetectedFramework(label: string): void;\n\n /** Register a callback to run when the TUI transitions onto the given screen. */\n onEnterScreen(screen: string, fn: () => void): void;\n\n setLoginUrl(url: string | null): void;\n\n // ── Task tracking from SDK TaskCreate/TaskUpdate events ───────────\n // Receives the full materialised task list each call. The caller (agent\n // loop) maintains a Map<taskId, …> from incremental Task* events and\n // re-emits the snapshot here, preserving the existing store semantics.\n syncTodos(\n todos: Array<{ content: string; status: string; activeForm?: string }>,\n ): void;\n\n // ── Event plan from .posthog-events.json ────────────────────\n setEventPlan(events: Array<{ name: string; description: string }>): void;\n\n // ── Dashboard URL emitted by the agent via [DASHBOARD_URL] marker ──\n setDashboardUrl(url: string): void;\n\n // ── Generic frameworkContext setter for program file watchers ─────\n setFrameworkContext(key: string, value: unknown): void;\n}\n"],"mappings":";AAkBA,IAAY,aAAL,yBAAA,YAAA;AACL,YAAA,aAAA;AACA,YAAA,gBAAA;AACA,YAAA,eAAA;;KACD;AAED,SAAgB,aAAa,OAAoC;AAC/D,QAAQ,OAAO,OAAO,WAAW,CAAc,SAAS,MAAM"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@posthog/wizard",
3
- "version": "2.14.2",
3
+ "version": "2.14.3",
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",
@@ -133,7 +133,9 @@
133
133
  "^@env$": "<rootDir>/src/env.ts",
134
134
  "^@lib/(.*)$": "<rootDir>/src/lib/$1",
135
135
  "^@utils/(.*)$": "<rootDir>/src/utils/$1",
136
+ "^@ui$": "<rootDir>/src/ui/index.ts",
136
137
  "^@ui/(.*)$": "<rootDir>/src/ui/$1",
138
+ "^@steps$": "<rootDir>/src/steps/index.ts",
137
139
  "^@steps/(.*)$": "<rootDir>/src/steps/$1",
138
140
  "^@frameworks/(.*)$": "<rootDir>/src/frameworks/$1",
139
141
  "^(\\.{1,2}/.*)\\.js$": "$1"
@@ -1 +0,0 @@
1
- {"version":3,"file":"TextBlock-B3cm43YY.js","names":[],"sources":["../src/ui/tui/styles.ts","../src/ui/tui/primitives/text-helpers.ts","../src/ui/tui/primitives/content-types.ts","../src/ui/tui/primitives/layout-helpers.ts","../src/ui/tui/primitives/TextBlock.tsx"],"sourcesContent":["/**\n * Shared style constants for TUI layout primitives.\n */\n\nexport enum HAlign {\n Left = 'flex-start',\n Center = 'center',\n Right = 'flex-end',\n}\n\nexport enum VAlign {\n Top = 'flex-start',\n Center = 'center',\n Bottom = 'flex-end',\n}\n\nexport const Colors = {\n primary: 'cyan',\n accent: '#DC9300',\n titleColor: '#3D2800',\n success: 'green',\n error: 'red',\n muted: 'gray',\n} as const;\n\nexport const Icons = {\n diamond: '\\u25C6',\n diamondOpen: '\\u25C7',\n check: '\\u2714',\n warning: '\\u26A0',\n squareFilled: '\\u25FC',\n squareOpen: '\\u25FB',\n triangleRight: '\\u25B6',\n triangleSmallRight: '\\u25B8',\n bullet: '\\u2022',\n} as const;\n","/**\n * Text-splitting helpers for sentence boundary detection.\n * Used by TextBlock for animation pauses at punctuation.\n */\n\n/** Split text into sentences (keeps the delimiter attached) */\nexport function splitSentences(text: string): string[] {\n const parts: string[] = [];\n const re = /[^.!?]*[.!?]+\\s*/g;\n let match: RegExpExecArray | null;\n let lastIndex = 0;\n while ((match = re.exec(text)) !== null) {\n parts.push(match[0]);\n lastIndex = re.lastIndex;\n }\n if (lastIndex < text.length) {\n parts.push(text.slice(lastIndex));\n }\n return parts;\n}\n\n/** Build a set of character indices where sentences end (for typewriter pause) */\nexport function sentenceEndChars(text: string): Set<number> {\n const ends = new Set<number>();\n const sentences = splitSentences(text);\n let pos = 0;\n for (const s of sentences) {\n pos += s.length;\n ends.add(pos - 1);\n }\n return ends;\n}\n\n/** Build a set of word indices where sentences end (for word-by-word pause) */\nexport function sentenceEndWords(text: string): Set<number> {\n const ends = new Set<number>();\n const sentences = splitSentences(text);\n let wordCount = 0;\n for (const s of sentences) {\n const words = s.trim().split(/\\s+/).filter(Boolean);\n wordCount += words.length;\n ends.add(wordCount - 1);\n }\n return ends;\n}\n","/**\n * Content block types and type guards.\n *\n * Extracted from ContentSequencer so that pure-logic modules (like\n * layout-helpers) can import them without pulling in Ink/React.\n */\n\nimport type { ReactNode } from 'react';\nimport type { TextRevealMode } from './TextBlock.js';\n\n/** Object form — string or ReactNode content with per-block overrides. */\nexport interface ContentObjectBlock {\n content: string | ReactNode;\n mode?: TextRevealMode;\n animationInterval?: number;\n sentenceInterval?: number;\n pause?: number;\n persist?: boolean;\n}\n\n/** Lines block — reveals ReactNode lines one at a time. */\nexport interface ContentLinesBlock {\n type: 'lines';\n lines: ReactNode[];\n interval?: number;\n pause?: number;\n}\n\n/** Clear block — page break that hides all prior blocks. */\nexport interface ContentClearBlock {\n type: 'clear';\n pause?: number;\n}\n\n/** A content block in the sequence. Bare strings are sugar for { content: '...' }. */\nexport type ContentBlock =\n | string\n | ContentObjectBlock\n | ContentLinesBlock\n | ContentClearBlock;\n\n/** Type guard for lines blocks. */\nexport function isLinesBlock(block: ContentBlock): block is ContentLinesBlock {\n return typeof block !== 'string' && 'type' in block && block.type === 'lines';\n}\n\n/** Type guard for clear blocks. */\nexport function isClearBlock(block: ContentBlock): block is ContentClearBlock {\n return typeof block !== 'string' && 'type' in block && block.type === 'clear';\n}\n\n/** Type guard for object blocks (text or node content). */\nexport function isObjectBlock(\n block: ContentBlock,\n): block is ContentObjectBlock {\n return typeof block !== 'string' && !('type' in block);\n}\n","/**\n * Layout helpers — pure functions for height estimation and viewport eviction.\n *\n * These are the core of the responsive content system. They estimate how many\n * terminal rows a content block will occupy and determine which blocks fit\n * within a given height budget.\n */\n\nimport type { ContentBlock } from './content-types.js';\nimport { isLinesBlock, isClearBlock, isObjectBlock } from './content-types.js';\n\n/**\n * Estimate the number of terminal rows a content block will occupy,\n * including 1 row of marginBottom.\n */\nexport function estimateBlockHeight(\n block: ContentBlock,\n availableWidth: number,\n): number {\n if (typeof block === 'string') {\n return wordWrap(block, availableWidth).length + 1; // +1 for marginBottom\n }\n\n if (isClearBlock(block)) return 0;\n\n if (isLinesBlock(block)) {\n return block.lines.length + 1;\n }\n\n if (isObjectBlock(block)) {\n if (typeof block.content === 'string') {\n return wordWrap(block.content, availableWidth).length + 1;\n }\n return 4; // conservative fixed estimate for ReactNode\n }\n\n return 1;\n}\n\n/**\n * Given all blocks, the active index, available width, and a row budget,\n * return [startIdx, endIdx] — the range of blocks to render.\n *\n * Always includes activeIdx. Walks backward to include as many completed\n * blocks as fit within maxHeight.\n */\nexport function computeVisibleRange(\n blocks: ContentBlock[],\n activeIdx: number,\n availableWidth: number,\n maxHeight: number,\n): [number, number] {\n // Reserve a 2-row buffer so resize-induced estimate drift doesn't\n // cause overflow=\"hidden\" to clip the margin between blocks.\n const budget = Math.max(4, maxHeight - 2);\n\n let totalHeight = estimateBlockHeight(blocks[activeIdx], availableWidth);\n let start = activeIdx;\n\n for (let i = activeIdx - 1; i >= 0; i--) {\n // Clear blocks act as a hard boundary — don't show anything before them\n if (isClearBlock(blocks[i])) break;\n const h = estimateBlockHeight(blocks[i], availableWidth);\n if (totalHeight + h > budget) break;\n totalHeight += h;\n start = i;\n }\n\n return [start, activeIdx];\n}\n\n/**\n * Word-wrap text at clean word boundaries. Always returns pre-wrapped text\n * joined with \\n — this avoids Ink's native wrap which can leave leading\n * spaces on continuation lines.\n *\n * Uses a 1-char safety margin so slight width estimate mismatches don't\n * cause Ink to re-wrap our already-wrapped lines.\n */\nexport function wordWrap(text: string, availableWidth: number): string[] {\n const safeWidth = Math.max(10, availableWidth - 1);\n const words = text.split(/\\s+/);\n const lines: string[] = [];\n let currentLine = '';\n\n for (const word of words) {\n if (\n currentLine.length + word.length + 1 > safeWidth &&\n currentLine.length > 0\n ) {\n lines.push(currentLine);\n currentLine = word;\n } else {\n currentLine += (currentLine.length > 0 ? ' ' : '') + word;\n }\n }\n if (currentLine.length > 0) {\n lines.push(currentLine);\n }\n\n return lines;\n}\n\n/**\n * Word-wrap text and return only the last `maxRows` lines.\n * Used for intra-block truncation when a single text block exceeds the viewport.\n * Also used for normal rendering to avoid Ink's leading-space wrap artifacts.\n */\nexport function wrapAndTruncate(\n text: string,\n availableWidth: number,\n maxRows: number,\n): string {\n const lines = wordWrap(text, availableWidth);\n\n if (lines.length <= maxRows) {\n return lines.join('\\n');\n }\n\n return lines.slice(-maxRows).join('\\n');\n}\n","/**\n * TextBlock — Animates a single string paragraph.\n *\n * Self-contained: owns its own animIdx and timer.\n * Calls onComplete() when the animation finishes.\n *\n * Five animation modes:\n * 1. Typewriter — character-by-character reveal\n * 2. Word by word — each word appears in order\n * 3. Sentence by sentence — sentences appear one at a time\n * 4. Paragraph fade — paragraph appears at full opacity immediately\n * 5. Sentence fade — paragraph dim, sentences light up in order\n */\n\nimport { Text } from 'ink';\nimport { useState, useEffect, useRef, useMemo, type ReactNode } from 'react';\nimport { Colors } from '../styles.js';\nimport {\n splitSentences,\n sentenceEndChars,\n sentenceEndWords,\n} from './text-helpers.js';\nimport { wrapAndTruncate } from './layout-helpers.js';\n\nexport enum TextRevealMode {\n Typewriter = 0,\n WordByWord = 1,\n SentenceBySentence = 2,\n ParagraphFade = 3,\n SentenceFade = 4,\n}\n\nexport const TEXT_REVEAL_MODE_LABELS = [\n 'Typewriter',\n 'Word by word',\n 'Sentence by sentence',\n 'Paragraph fade',\n 'Sentence fade',\n];\n\nexport const TEXT_REVEAL_MODE_COUNT = 5;\n\n/** Default interval per mode (ms) */\nexport const TEXT_REVEAL_MODE_DEFAULTS: Record<TextRevealMode, number> = {\n [TextRevealMode.WordByWord]: 240,\n [TextRevealMode.Typewriter]: 32,\n [TextRevealMode.SentenceBySentence]: 1800,\n [TextRevealMode.ParagraphFade]: 4800,\n [TextRevealMode.SentenceFade]: 2400,\n};\n\ninterface TextBlockProps {\n text: string;\n active: boolean;\n completed: boolean;\n onComplete: () => void;\n mode: TextRevealMode;\n bullet?: ReactNode;\n animationInterval?: number;\n sentenceInterval?: number;\n /** Max rows this block may occupy. When exceeded, top lines are truncated. */\n maxHeight?: number;\n /** Available text width in columns (for truncation wrapping). */\n availableWidth?: number;\n}\n\nexport const TextBlock = ({\n text,\n active,\n completed,\n onComplete,\n mode,\n bullet,\n animationInterval,\n sentenceInterval = 1600,\n maxHeight,\n availableWidth,\n}: TextBlockProps) => {\n const speed = animationInterval ?? TEXT_REVEAL_MODE_DEFAULTS[mode];\n\n const [animIdx, setAnimIdx] = useState(\n mode === TextRevealMode.SentenceFade ? 1 : 0,\n );\n\n // Reset synchronously during render to avoid a one-frame flash\n const resetRef = useRef(0);\n const prevMode = useRef(mode);\n if (prevMode.current !== mode) {\n prevMode.current = mode;\n resetRef.current += 1;\n setAnimIdx(mode === TextRevealMode.SentenceFade ? 1 : 0);\n }\n\n const words = text.split(/\\s+/);\n const sentences = splitSentences(text);\n\n const sentenceCharEnds = useMemo(() => sentenceEndChars(text), [text]);\n const sentenceWordEnds = useMemo(() => sentenceEndWords(text), [text]);\n\n const isDone =\n mode === TextRevealMode.Typewriter\n ? animIdx >= text.length\n : mode === TextRevealMode.ParagraphFade\n ? true\n : mode === TextRevealMode.WordByWord\n ? animIdx >= words.length\n : mode === TextRevealMode.SentenceFade ||\n mode === TextRevealMode.SentenceBySentence\n ? animIdx >= sentences.length\n : true;\n\n // Fire onComplete when done\n useEffect(() => {\n if (isDone && active) onComplete();\n }, [isDone, active, onComplete]);\n\n // Animate: single effect for all tick-based modes\n useEffect(() => {\n if (!active || mode === TextRevealMode.ParagraphFade || isDone) return;\n const token = resetRef.current;\n\n const isFirstTick = animIdx === 0;\n\n let delay = isFirstTick ? 0 : speed;\n if (\n !isFirstTick &&\n mode === TextRevealMode.Typewriter &&\n animIdx > 0 &&\n sentenceCharEnds.has(animIdx - 1)\n ) {\n delay = sentenceInterval;\n } else if (\n !isFirstTick &&\n mode === TextRevealMode.WordByWord &&\n animIdx > 0 &&\n sentenceWordEnds.has(animIdx - 1)\n ) {\n delay = sentenceInterval;\n }\n\n const timer = setTimeout(() => {\n if (token !== resetRef.current) return;\n setAnimIdx((c) => c + 1);\n }, delay);\n return () => clearTimeout(timer);\n }, [\n active,\n mode,\n animIdx,\n isDone,\n speed,\n sentenceInterval,\n sentenceCharEnds,\n sentenceWordEnds,\n ]);\n\n // Pre-wrap text ourselves to avoid Ink's native wrap leaving leading spaces\n // on continuation lines. When maxHeight is set, also truncates to last N rows.\n const wrap = (visibleText: string): string => {\n if (availableWidth == null) return visibleText;\n if (maxHeight == null) {\n return wrapAndTruncate(visibleText, availableWidth, Infinity);\n }\n return wrapAndTruncate(visibleText, availableWidth, maxHeight);\n };\n\n // Completed: dimmed text\n if (completed) {\n return (\n <Text dimColor>\n {bullet}\n {wrap(text)}\n </Text>\n );\n }\n\n // Active: mode-specific rendering\n if (mode === TextRevealMode.Typewriter) {\n const revealed = text.slice(0, animIdx);\n const atSentenceEnd = /[.!?]\\s*$/.test(revealed);\n const display = atSentenceEnd ? revealed.trimEnd() : revealed;\n return (\n <Text>\n {bullet}\n {wrap(display)}\n <Text color={Colors.muted}>{'\\u258C'}</Text>\n </Text>\n );\n }\n\n if (mode === TextRevealMode.WordByWord) {\n const visible = words.slice(0, animIdx).join(' ');\n return (\n <Text>\n {bullet}\n {wrap(visible)}\n </Text>\n );\n }\n\n if (mode === TextRevealMode.ParagraphFade) {\n return (\n <Text>\n {bullet}\n {wrap(text)}\n </Text>\n );\n }\n\n if (mode === TextRevealMode.SentenceBySentence) {\n const visible = sentences.slice(0, animIdx).join('');\n return (\n <Text>\n {bullet}\n {wrap(visible)}\n </Text>\n );\n }\n\n // SentenceFade\n return (\n <Text>\n {bullet}\n {sentences.map((s, si) => (\n <Text key={si} dimColor={si >= animIdx}>\n {s}\n </Text>\n ))}\n </Text>\n );\n};\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"add-mcp-server-to-clients-BL0trzId.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 { DefaultMCPClient, MCPServerConfig } from '../MCPClient';\nimport * as path from 'path';\nimport * as os from 'os';\nimport { DefaultMCPClientConfig, getNativeHTTPServerConfig } from '../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 '../MCPClient';\nimport { DefaultMCPClientConfig } from '../defaults';\nimport { PluginCapable, PluginInstallResult } from '../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 { DefaultMCPClient, MCPServerConfig } from '../MCPClient';\nimport { getNativeHTTPServerConfig } from '../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 { DefaultMCPClient, MCPServerConfig } from '../MCPClient';\nimport { getNativeHTTPServerConfig } from '../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 '../MCPClient';\nimport { DefaultMCPClientConfig } from '../defaults';\nimport { PluginCapable, PluginInstallResult } from '../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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"}