@posthog/wizard 2.17.0 → 2.19.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 (76) hide show
  1. package/dist/{add-mcp-server-to-clients-D4PK6ulR.js → add-mcp-server-to-clients-CjnvTVj0.js} +72 -13
  2. package/dist/add-mcp-server-to-clients-CjnvTVj0.js.map +1 -0
  3. package/dist/{agent-interface-7t5DBo2A.js → agent-interface-CQU6x4Hj.js} +112 -54
  4. package/dist/agent-interface-CQU6x4Hj.js.map +1 -0
  5. package/dist/{agent-runner-CTkKLVhp.js → agent-runner-Cj7saDkL.js} +17 -11
  6. package/dist/{agent-runner-CTkKLVhp.js.map → agent-runner-Cj7saDkL.js.map} +1 -1
  7. package/dist/{analytics-DN_Gy87F.js → analytics-Df-Xb81i.js} +26 -4
  8. package/dist/analytics-Df-Xb81i.js.map +1 -0
  9. package/dist/{api-serd0SMY.js → api-Dw6_orDE.js} +3 -3
  10. package/dist/{api-serd0SMY.js.map → api-Dw6_orDE.js.map} +1 -1
  11. package/dist/bin.js +236 -79
  12. package/dist/bin.js.map +1 -1
  13. package/dist/{ci-install-BbJ7c3WK.js → ci-install-BKAvFfK6.js} +4 -4
  14. package/dist/{ci-install-BbJ7c3WK.js.map → ci-install-BKAvFfK6.js.map} +1 -1
  15. package/dist/{debug-BI-Js0PB.js → debug-Cp_wNn8i.js} +1 -1
  16. package/dist/{debug-Bx7nvCWW.js → debug-DnMO6O8O.js} +36 -21
  17. package/dist/debug-DnMO6O8O.js.map +1 -0
  18. package/dist/{defaults-CPH6eWhN.js → defaults-BNWIWzjc.js} +34 -8
  19. package/dist/defaults-BNWIWzjc.js.map +1 -0
  20. package/dist/{env-api-key-B3gE9Un0.js → env-api-key-MlzJYAvt.js} +1 -1
  21. package/dist/{env-api-key-B3gE9Un0.js.map → env-api-key-MlzJYAvt.js.map} +1 -1
  22. package/dist/{environment-CiZVSSYt.js → environment-Ls0H9ljT.js} +3 -3
  23. package/dist/{environment-CiZVSSYt.js.map → environment-Ls0H9ljT.js.map} +1 -1
  24. package/dist/{file-utils-Dy9JncCo.js → file-utils-VAXoyXVA.js} +1 -1
  25. package/dist/{file-utils-Dy9JncCo.js.map → file-utils-VAXoyXVA.js.map} +1 -1
  26. package/dist/{interactive-BwIzklw0.js → interactive-D15byhpc.js} +2 -2
  27. package/dist/{interactive-BwIzklw0.js.map → interactive-D15byhpc.js.map} +1 -1
  28. package/dist/{mcp-prompt-streaming-8U9Qs9EV.js → mcp-prompt-streaming-DQOTQfW1.js} +4 -4
  29. package/dist/{mcp-prompt-streaming-8U9Qs9EV.js.map → mcp-prompt-streaming-DQOTQfW1.js.map} +1 -1
  30. package/dist/{non-interactive-DTaZnVq_.js → non-interactive-DcFLJtl_.js} +2 -2
  31. package/dist/{non-interactive-DTaZnVq_.js.map → non-interactive-DcFLJtl_.js.map} +1 -1
  32. package/dist/{package-manager-CKQLR20D.js → package-manager-DUPgLGpQ.js} +2 -2
  33. package/dist/{package-manager-CKQLR20D.js.map → package-manager-DUPgLGpQ.js.map} +1 -1
  34. package/dist/{playground-CR81Mwe3.js → playground-BZ0hGjbL.js} +12 -4
  35. package/dist/playground-BZ0hGjbL.js.map +1 -0
  36. package/dist/{posthog-BrLFkaji.js → posthog-Cr37rnla.js} +1 -1
  37. package/dist/{posthog-BrLFkaji.js.map → posthog-Cr37rnla.js.map} +1 -1
  38. package/dist/{posthog-integration-Bv7987YJ.js → posthog-integration-C8qhJnI3.js} +282 -13
  39. package/dist/posthog-integration-C8qhJnI3.js.map +1 -0
  40. package/dist/{provisioning-C96Kw-9D.js → provisioning-C-2ExcqY.js} +3 -3
  41. package/dist/{provisioning-C96Kw-9D.js.map → provisioning-C-2ExcqY.js.map} +1 -1
  42. package/dist/{registry-B9k73FKR.js → registry-hBUgaWFx.js} +4 -4
  43. package/dist/{registry-B9k73FKR.js.map → registry-hBUgaWFx.js.map} +1 -1
  44. package/dist/{setup-utils-Bpfsap9L.js → setup-utils-DetnhXo0.js} +65 -44
  45. package/dist/setup-utils-DetnhXo0.js.map +1 -0
  46. package/dist/{slides-DRbBgsdd.js → slides-mT2s9wM_.js} +180 -71
  47. package/dist/slides-mT2s9wM_.js.map +1 -0
  48. package/dist/{start-tui-BZ7rEf3e.js → start-tui-BfXoErKg.js} +16 -16
  49. package/dist/start-tui-BfXoErKg.js.map +1 -0
  50. package/dist/{steps-DDx35170.js → steps-SoDXSUxe.js} +6 -6
  51. package/dist/{steps-DDx35170.js.map → steps-SoDXSUxe.js.map} +1 -1
  52. package/dist/{task-stream-BI8rJg9H.js → task-stream-CZRj6auI.js} +2 -2
  53. package/dist/{task-stream-BI8rJg9H.js.map → task-stream-CZRj6auI.js.map} +1 -1
  54. package/dist/{telemetry-ByYtIfW0.js → telemetry-CPcMFxcO.js} +2 -2
  55. package/dist/{telemetry-ByYtIfW0.js.map → telemetry-CPcMFxcO.js.map} +1 -1
  56. package/dist/{urls-CTCJIxbR.js → urls-BO7doNJG.js} +2 -2
  57. package/dist/{urls-CTCJIxbR.js.map → urls-BO7doNJG.js.map} +1 -1
  58. package/dist/{wizard-abort-CY0ibdq1.js → wizard-abort-CDXufkqJ.js} +5 -3
  59. package/dist/wizard-abort-CDXufkqJ.js.map +1 -0
  60. package/dist/{wizard-abort-QdRxGQp_.js → wizard-abort-CtMY57ZE.js} +1 -1
  61. package/package.json +1 -1
  62. package/dist/TextBlock-D0Ep3zC9.js +0 -275
  63. package/dist/TextBlock-D0Ep3zC9.js.map +0 -1
  64. package/dist/add-mcp-server-to-clients-D4PK6ulR.js.map +0 -1
  65. package/dist/agent-interface-7t5DBo2A.js.map +0 -1
  66. package/dist/analytics-DN_Gy87F.js.map +0 -1
  67. package/dist/debug-Bx7nvCWW.js.map +0 -1
  68. package/dist/defaults-CPH6eWhN.js.map +0 -1
  69. package/dist/playground-CR81Mwe3.js.map +0 -1
  70. package/dist/posthog-integration-Bv7987YJ.js.map +0 -1
  71. package/dist/setup-utils-Bpfsap9L.js.map +0 -1
  72. package/dist/skill-CPqcV8zp.js +0 -29
  73. package/dist/skill-CPqcV8zp.js.map +0 -1
  74. package/dist/slides-DRbBgsdd.js.map +0 -1
  75. package/dist/start-tui-BZ7rEf3e.js.map +0 -1
  76. package/dist/wizard-abort-CY0ibdq1.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"api-serd0SMY.js","names":[],"sources":["../src/lib/api.ts"],"sourcesContent":["import axios, { AxiosError } from 'axios';\nimport { z } from 'zod';\nimport { analytics } from '@utils/analytics';\nimport { WIZARD_USER_AGENT } from './constants';\n\n/**\n * User payload from `/api/users/@me/`. Schema typed for the fields the\n * wizard actually reads + passthrough on everything else so the full\n * upstream response rides through to the session for downstream features\n * (account-aware copy, plan-gated flows, org/team metadata, etc.).\n *\n * Top-level uses `.passthrough()` so unknown fields aren't stripped;\n * the few nested objects we care about (team, organization,\n * organizations[]) do the same so their additional fields survive too.\n *\n * Keep `distinct_id` required — analytics depends on it. Everything\n * else added here is nullish so partial responses don't fail parsing.\n */\nexport const ApiUserSchema = z\n .object({\n // Identifiers\n distinct_id: z.string(),\n uuid: z.string().nullish(),\n id: z.number().nullish(),\n\n // Profile\n email: z.string().nullish(),\n first_name: z.string().nullish(),\n last_name: z.string().nullish(),\n date_joined: z.string().nullish(),\n is_email_verified: z.boolean().nullish(),\n is_2fa_enabled: z.boolean().nullish(),\n is_staff: z.boolean().nullish(),\n\n // Preferences\n theme_mode: z.string().nullish(),\n toolbar_mode: z.string().nullish(),\n hide_mcp_hints: z.boolean().nullish(),\n\n // Optional / nullable on the backend — pre-onboarding signup paths\n // return null and older accounts may not have it set. Treat as a\n // hint, never a guarantee.\n role_at_organization: z.string().nullish(),\n\n // Current team + organization (objects from the API, kept typed on\n // the fields the wizard uses; passthrough preserves the rest).\n team: z\n .object({\n id: z.number(),\n uuid: z.string().nullish(),\n organization: z.string().uuid(),\n api_token: z.string().nullish(),\n project_id: z.number().nullish(),\n name: z.string().nullish(),\n timezone: z.string().nullish(),\n })\n .passthrough(),\n organization: z\n .object({\n id: z.string().uuid(),\n name: z.string().nullish(),\n slug: z.string().nullish(),\n membership_level: z.number().nullish(),\n customer_id: z.string().nullish(),\n })\n .passthrough(),\n organizations: z.array(\n z\n .object({\n id: z.string().uuid(),\n name: z.string().nullish(),\n membership_level: z.number().nullish(),\n })\n .passthrough(),\n ),\n })\n .passthrough();\n\n/**\n * Single activity log entry the wizard cares about. The PostHog endpoint\n * returns much more — schema kept minimal so changes upstream don't break us.\n *\n * @unused — no current caller after the Phase 6 streaming-agent pivot\n * dropped activity_log polling. Deliberately retained: this is a thin,\n * well-typed wrapper around a stable PostHog endpoint, and we're likely\n * to want it again for a future feature (e.g. \"what changed in your\n * project recently\"). Re-deriving the schema is more work than letting\n * it sit dormant.\n */\nexport const ActivityLogEntrySchema = z\n .object({\n scope: z.string().nullish(),\n activity: z.string().nullish(),\n created_at: z.string().nullish(),\n })\n .passthrough();\n\n/** @unused — see ActivityLogEntrySchema. */\nexport const ActivityLogResponseSchema = z.object({\n results: z.array(ActivityLogEntrySchema),\n});\n\n/** @unused — see ActivityLogEntrySchema. */\nexport type ActivityLogEntry = z.infer<typeof ActivityLogEntrySchema>;\n\nexport const ApiProjectSchema = z.object({\n id: z.number(),\n uuid: z.string().uuid(),\n organization: z.string().uuid(),\n api_token: z.string(),\n name: z.string(),\n});\n\nexport type ApiUser = z.infer<typeof ApiUserSchema>;\nexport type ApiProject = z.infer<typeof ApiProjectSchema>;\n\nexport class ApiError extends Error {\n constructor(\n message: string,\n public readonly statusCode?: number,\n public readonly endpoint?: string,\n ) {\n super(message);\n this.name = 'ApiError';\n }\n}\n\nexport async function fetchUserData(\n accessToken: string,\n baseUrl: string,\n): Promise<ApiUser> {\n try {\n const response = await axios.get(`${baseUrl}/api/users/@me/`, {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n 'User-Agent': WIZARD_USER_AGENT,\n },\n });\n\n return ApiUserSchema.parse(response.data);\n } catch (error) {\n const apiError = handleApiError(error, 'fetch user data');\n analytics.captureException(apiError, {\n endpoint: '/api/users/@me/',\n baseUrl,\n });\n throw apiError;\n }\n}\n\n/**\n * Best-effort fetch of recent activity log entries. Returns [] on any error\n * so callers can treat absence of results as \"haven't detected anything yet\"\n * rather than a hard failure.\n *\n * @unused — no current caller after the Phase 6 streaming-agent pivot\n * dropped activity_log polling from McpSuggestedPromptsScreen.\n * Deliberately retained for future features that want a soft signal of\n * recent project changes (e.g. dashboards, audit summaries). See the\n * ActivityLogEntrySchema doc comment for the keep-vs-delete rationale.\n */\nexport async function fetchRecentActivity(\n accessToken: string,\n projectId: number,\n baseUrl: string,\n since: Date,\n): Promise<ActivityLogEntry[]> {\n try {\n const response = await axios.get(\n `${baseUrl}/api/projects/${projectId}/activity_log/`,\n {\n params: { limit: 10 },\n headers: {\n Authorization: `Bearer ${accessToken}`,\n 'User-Agent': WIZARD_USER_AGENT,\n },\n // Short timeout — best-effort probe, not a critical path.\n timeout: 4000,\n },\n );\n const parsed = ActivityLogResponseSchema.safeParse(response.data);\n if (!parsed.success) return [];\n const sinceMs = since.getTime();\n return parsed.data.results.filter((entry) => {\n if (!entry.created_at) return false;\n const t = Date.parse(entry.created_at);\n return Number.isFinite(t) && t >= sinceMs;\n });\n } catch {\n return [];\n }\n}\n\nexport async function fetchProjectData(\n accessToken: string,\n projectId: number,\n baseUrl: string,\n): Promise<ApiProject> {\n try {\n const response = await axios.get(`${baseUrl}/api/projects/${projectId}/`, {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n 'User-Agent': WIZARD_USER_AGENT,\n },\n });\n\n return ApiProjectSchema.parse(response.data);\n } catch (error) {\n const apiError = handleApiError(error, 'fetch project data');\n analytics.captureException(apiError, {\n endpoint: `/api/projects/${projectId}/`,\n baseUrl,\n projectId,\n });\n throw apiError;\n }\n}\n\nexport function handleApiError(error: unknown, operation: string): ApiError {\n if (axios.isAxiosError(error)) {\n const axiosError = error as AxiosError<{ detail?: string }>;\n const status = axiosError.response?.status;\n const detail = axiosError.response?.data?.detail;\n const endpoint = axiosError.config?.url;\n\n if (status === 401) {\n return new ApiError(\n `Authentication failed while trying to ${operation}`,\n status,\n endpoint,\n );\n }\n\n if (status === 403) {\n return new ApiError(\n `Access denied while trying to ${operation}`,\n status,\n endpoint,\n );\n }\n\n if (status === 404) {\n return new ApiError(\n `Resource not found while trying to ${operation}`,\n status,\n endpoint,\n );\n }\n\n const message = detail || `Failed to ${operation}`;\n return new ApiError(message, status, endpoint);\n }\n\n if (error instanceof z.ZodError) {\n return new ApiError(`Invalid response format while trying to ${operation}`);\n }\n\n return new ApiError(\n `Unexpected error while trying to ${operation}: ${\n error instanceof Error ? error.message : 'Unknown error'\n }`,\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"api-Dw6_orDE.js","names":[],"sources":["../src/lib/api.ts"],"sourcesContent":["import axios, { AxiosError } from 'axios';\nimport { z } from 'zod';\nimport { analytics } from '@utils/analytics';\nimport { WIZARD_USER_AGENT } from './constants';\n\n/**\n * User payload from `/api/users/@me/`. Schema typed for the fields the\n * wizard actually reads + passthrough on everything else so the full\n * upstream response rides through to the session for downstream features\n * (account-aware copy, plan-gated flows, org/team metadata, etc.).\n *\n * Top-level uses `.passthrough()` so unknown fields aren't stripped;\n * the few nested objects we care about (team, organization,\n * organizations[]) do the same so their additional fields survive too.\n *\n * Keep `distinct_id` required — analytics depends on it. Everything\n * else added here is nullish so partial responses don't fail parsing.\n */\nexport const ApiUserSchema = z\n .object({\n // Identifiers\n distinct_id: z.string(),\n uuid: z.string().nullish(),\n id: z.number().nullish(),\n\n // Profile\n email: z.string().nullish(),\n first_name: z.string().nullish(),\n last_name: z.string().nullish(),\n date_joined: z.string().nullish(),\n is_email_verified: z.boolean().nullish(),\n is_2fa_enabled: z.boolean().nullish(),\n is_staff: z.boolean().nullish(),\n\n // Preferences\n theme_mode: z.string().nullish(),\n toolbar_mode: z.string().nullish(),\n hide_mcp_hints: z.boolean().nullish(),\n\n // Optional / nullable on the backend — pre-onboarding signup paths\n // return null and older accounts may not have it set. Treat as a\n // hint, never a guarantee.\n role_at_organization: z.string().nullish(),\n\n // Current team + organization (objects from the API, kept typed on\n // the fields the wizard uses; passthrough preserves the rest).\n team: z\n .object({\n id: z.number(),\n uuid: z.string().nullish(),\n organization: z.string().uuid(),\n api_token: z.string().nullish(),\n project_id: z.number().nullish(),\n name: z.string().nullish(),\n timezone: z.string().nullish(),\n })\n .passthrough(),\n organization: z\n .object({\n id: z.string().uuid(),\n name: z.string().nullish(),\n slug: z.string().nullish(),\n membership_level: z.number().nullish(),\n customer_id: z.string().nullish(),\n })\n .passthrough(),\n organizations: z.array(\n z\n .object({\n id: z.string().uuid(),\n name: z.string().nullish(),\n membership_level: z.number().nullish(),\n })\n .passthrough(),\n ),\n })\n .passthrough();\n\n/**\n * Single activity log entry the wizard cares about. The PostHog endpoint\n * returns much more — schema kept minimal so changes upstream don't break us.\n *\n * @unused — no current caller after the Phase 6 streaming-agent pivot\n * dropped activity_log polling. Deliberately retained: this is a thin,\n * well-typed wrapper around a stable PostHog endpoint, and we're likely\n * to want it again for a future feature (e.g. \"what changed in your\n * project recently\"). Re-deriving the schema is more work than letting\n * it sit dormant.\n */\nexport const ActivityLogEntrySchema = z\n .object({\n scope: z.string().nullish(),\n activity: z.string().nullish(),\n created_at: z.string().nullish(),\n })\n .passthrough();\n\n/** @unused — see ActivityLogEntrySchema. */\nexport const ActivityLogResponseSchema = z.object({\n results: z.array(ActivityLogEntrySchema),\n});\n\n/** @unused — see ActivityLogEntrySchema. */\nexport type ActivityLogEntry = z.infer<typeof ActivityLogEntrySchema>;\n\nexport const ApiProjectSchema = z.object({\n id: z.number(),\n uuid: z.string().uuid(),\n organization: z.string().uuid(),\n api_token: z.string(),\n name: z.string(),\n});\n\nexport type ApiUser = z.infer<typeof ApiUserSchema>;\nexport type ApiProject = z.infer<typeof ApiProjectSchema>;\n\nexport class ApiError extends Error {\n constructor(\n message: string,\n public readonly statusCode?: number,\n public readonly endpoint?: string,\n ) {\n super(message);\n this.name = 'ApiError';\n }\n}\n\nexport async function fetchUserData(\n accessToken: string,\n baseUrl: string,\n): Promise<ApiUser> {\n try {\n const response = await axios.get(`${baseUrl}/api/users/@me/`, {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n 'User-Agent': WIZARD_USER_AGENT,\n },\n });\n\n return ApiUserSchema.parse(response.data);\n } catch (error) {\n const apiError = handleApiError(error, 'fetch user data');\n analytics.captureException(apiError, {\n endpoint: '/api/users/@me/',\n baseUrl,\n });\n throw apiError;\n }\n}\n\n/**\n * Best-effort fetch of recent activity log entries. Returns [] on any error\n * so callers can treat absence of results as \"haven't detected anything yet\"\n * rather than a hard failure.\n *\n * @unused — no current caller after the Phase 6 streaming-agent pivot\n * dropped activity_log polling from McpSuggestedPromptsScreen.\n * Deliberately retained for future features that want a soft signal of\n * recent project changes (e.g. dashboards, audit summaries). See the\n * ActivityLogEntrySchema doc comment for the keep-vs-delete rationale.\n */\nexport async function fetchRecentActivity(\n accessToken: string,\n projectId: number,\n baseUrl: string,\n since: Date,\n): Promise<ActivityLogEntry[]> {\n try {\n const response = await axios.get(\n `${baseUrl}/api/projects/${projectId}/activity_log/`,\n {\n params: { limit: 10 },\n headers: {\n Authorization: `Bearer ${accessToken}`,\n 'User-Agent': WIZARD_USER_AGENT,\n },\n // Short timeout — best-effort probe, not a critical path.\n timeout: 4000,\n },\n );\n const parsed = ActivityLogResponseSchema.safeParse(response.data);\n if (!parsed.success) return [];\n const sinceMs = since.getTime();\n return parsed.data.results.filter((entry) => {\n if (!entry.created_at) return false;\n const t = Date.parse(entry.created_at);\n return Number.isFinite(t) && t >= sinceMs;\n });\n } catch {\n return [];\n }\n}\n\nexport async function fetchProjectData(\n accessToken: string,\n projectId: number,\n baseUrl: string,\n): Promise<ApiProject> {\n try {\n const response = await axios.get(`${baseUrl}/api/projects/${projectId}/`, {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n 'User-Agent': WIZARD_USER_AGENT,\n },\n });\n\n return ApiProjectSchema.parse(response.data);\n } catch (error) {\n const apiError = handleApiError(error, 'fetch project data');\n analytics.captureException(apiError, {\n endpoint: `/api/projects/${projectId}/`,\n baseUrl,\n projectId,\n });\n throw apiError;\n }\n}\n\nexport function handleApiError(error: unknown, operation: string): ApiError {\n if (axios.isAxiosError(error)) {\n const axiosError = error as AxiosError<{ detail?: string }>;\n const status = axiosError.response?.status;\n const detail = axiosError.response?.data?.detail;\n const endpoint = axiosError.config?.url;\n\n if (status === 401) {\n return new ApiError(\n `Authentication failed while trying to ${operation}`,\n status,\n endpoint,\n );\n }\n\n if (status === 403) {\n return new ApiError(\n `Access denied while trying to ${operation}`,\n status,\n endpoint,\n );\n }\n\n if (status === 404) {\n return new ApiError(\n `Resource not found while trying to ${operation}`,\n status,\n endpoint,\n );\n }\n\n const message = detail || `Failed to ${operation}`;\n return new ApiError(message, status, endpoint);\n }\n\n if (error instanceof z.ZodError) {\n return new ApiError(`Invalid response format while trying to ${operation}`);\n }\n\n return new ApiError(\n `Unexpected error while trying to ${operation}: ${\n error instanceof Error ? error.message : 'Unknown error'\n }`,\n );\n}\n"],"mappings":"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"}
package/dist/bin.js CHANGED
@@ -1,17 +1,16 @@
1
1
  #!/usr/bin/env node
2
- import { J as VERSION, M as POSTHOG_DOCS_URL, W as WIZARD_USER_AGENT, X as runtimeEnv, _ as SIGNUP_WIZARD_READINESS_CONFIG, h as LoggingUI, m as setUI, p as getUI, s as logToFile, v as evaluateWizardReadiness, y as getBlockingServiceKeys } from "./debug-Bx7nvCWW.js";
3
- import { t as analytics } from "./analytics-DN_Gy87F.js";
4
- import { n as isUsingTypeScript } from "./setup-utils-Bpfsap9L.js";
5
- import { a as getUiHostFromHost, n as getCloudUrlFromRegion } from "./urls-CTCJIxbR.js";
6
- import { a as handleApiError } from "./api-serd0SMY.js";
2
+ import { J as VERSION, M as POSTHOG_DOCS_URL, W as WIZARD_USER_AGENT, _ as SIGNUP_WIZARD_READINESS_CONFIG, a as getLogFilePath, h as LoggingUI, m as setUI, p as getUI, s as logToFile, v as evaluateWizardReadiness, y as getBlockingServiceKeys } from "./debug-DnMO6O8O.js";
3
+ import { t as analytics } from "./analytics-Df-Xb81i.js";
4
+ import { n as isUsingTypeScript } from "./setup-utils-DetnhXo0.js";
5
+ import { a as getUiHostFromHost, n as getCloudUrlFromRegion } from "./urls-BO7doNJG.js";
6
+ import { a as handleApiError } from "./api-Dw6_orDE.js";
7
7
  import "./wizard-session-d27JGRGi.js";
8
- import { n as isNonInteractiveEnvironment } from "./environment-CiZVSSYt.js";
9
- import { _ as AUDIT_REPORT_FILE, d as WIZARD_TOOL_NAMES, g as AUDIT_CHECKS_KEY, h as AUDIT_CHECKS_FILE, t as AgentSignals } from "./agent-interface-7t5DBo2A.js";
10
- import { i as SPINNER_MESSAGE } from "./registry-B9k73FKR.js";
11
- import { a as PRODUCT_SUITE_BLOCK, i as LINE_CHART_BLOCK, n as posthogIntegrationConfig, o as StatusPeekTrigger, r as FUNNEL_BLOCK } from "./posthog-integration-Bv7987YJ.js";
12
- import { c as HEALTH_CHECK_STEP, o as Colors, r as isClearBlock } from "./TextBlock-D0Ep3zC9.js";
13
- import { t as IGNORED_DIRS } from "./file-utils-Dy9JncCo.js";
14
- import { n as readApiKeyFromEnv } from "./env-api-key-B3gE9Un0.js";
8
+ import { n as isNonInteractiveEnvironment } from "./environment-Ls0H9ljT.js";
9
+ import { _ as AUDIT_REPORT_FILE, c as AgentSignals, d as WIZARD_TOOL_NAMES, g as AUDIT_CHECKS_KEY, h as AUDIT_CHECKS_FILE } from "./agent-interface-CQU6x4Hj.js";
10
+ import { i as SPINNER_MESSAGE } from "./registry-hBUgaWFx.js";
11
+ import { a as PRODUCT_SUITE_BLOCK, f as Colors, i as LINE_CHART_BLOCK, l as isClearBlock, m as HEALTH_CHECK_STEP, n as posthogIntegrationConfig, o as StatusPeekTrigger, r as FUNNEL_BLOCK } from "./posthog-integration-C8qhJnI3.js";
12
+ import { t as IGNORED_DIRS } from "./file-utils-VAXoyXVA.js";
13
+ import { n as readApiKeyFromEnv } from "./env-api-key-MlzJYAvt.js";
15
14
  import { satisfies } from "semver";
16
15
  import yargs from "yargs";
17
16
  import { hideBin } from "yargs/helpers";
@@ -161,7 +160,7 @@ function runProvision(argv) {
161
160
  }
162
161
  async function provision({ email, region, name, jsonMode }) {
163
162
  try {
164
- const { provisionNewAccount } = await import("./provisioning-C96Kw-9D.js").then((n) => n.n);
163
+ const { provisionNewAccount } = await import("./provisioning-C-2ExcqY.js").then((n) => n.n);
165
164
  if (!jsonMode) getUI().log.info(`Provisioning account for ${email} in ${region}...`);
166
165
  emitResult(await provisionNewAccount(email, name, region), jsonMode);
167
166
  process.exit(0);
@@ -223,49 +222,36 @@ const basicIntegrationCommand = {
223
222
  type: "boolean",
224
223
  hidden: true
225
224
  },
226
- skill: {
227
- describe: "Run a specific context-mill skill by ID\nenv: POSTHOG_WIZARD_SKILL",
228
- type: "string"
229
- },
230
225
  name: {
231
226
  describe: "Name for account creation with --ci --signup\nenv: POSTHOG_WIZARD_NAME",
232
227
  type: "string"
233
228
  }
234
229
  },
235
230
  check: (argv) => {
236
- if (argv.playground && (argv.ci || argv.skill)) throw new Error("--playground cannot be combined with --ci or --skill.");
237
- if (typeof argv.skill === "string" && argv.skill.trim() === "") throw new Error("--skill needs a skill ID, e.g. --skill=\"foo\"");
231
+ if (argv.playground && argv.ci) throw new Error("--playground cannot be combined with --ci.");
238
232
  return true;
239
233
  },
240
234
  handler: (argv) => {
241
235
  (async () => {
242
- if (argv.ci && argv.skill) {
243
- const { runSkillMode } = await import("./skill-CPqcV8zp.js");
244
- return runSkillMode(argv);
245
- }
246
236
  if (argv.ci) {
247
- const { runCIInstall } = await import("./ci-install-BbJ7c3WK.js");
237
+ const { runCIInstall } = await import("./ci-install-BKAvFfK6.js");
248
238
  return runCIInstall(argv);
249
239
  }
250
240
  if (isNonInteractiveEnvironment()) {
251
- const { failNonInteractive } = await import("./non-interactive-DTaZnVq_.js");
241
+ const { failNonInteractive } = await import("./non-interactive-DcFLJtl_.js");
252
242
  return failNonInteractive();
253
243
  }
254
244
  if (argv.playground) {
255
- const { runPlayground } = await import("./playground-CR81Mwe3.js");
245
+ const { runPlayground } = await import("./playground-BZ0hGjbL.js");
256
246
  return runPlayground();
257
247
  }
258
- if (argv.skill) {
259
- const { runSkillMode } = await import("./skill-CPqcV8zp.js");
260
- return runSkillMode(argv);
261
- }
262
- const { runInteractive } = await import("./interactive-BwIzklw0.js");
248
+ const { runInteractive } = await import("./interactive-D15byhpc.js");
263
249
  runInteractive(argv);
264
250
  })();
265
251
  }
266
252
  };
267
253
  //#endregion
268
- //#region src/lib/programs/revenue-analytics/detect.ts
254
+ //#region src/lib/programs/shared/package-scanning.ts
269
255
  const POSTHOG_SDKS$1 = [
270
256
  "posthog-js",
271
257
  "posthog-node",
@@ -278,18 +264,6 @@ const STRIPE_SDKS = [
278
264
  "@stripe/stripe-js",
279
265
  "@stripe/react-stripe-js"
280
266
  ];
281
- /** `[ABORT] <reason>` cases the revenue analytics skill can emit. */
282
- const REVENUE_ABORT_CASES = [{
283
- match: /^could not find a posthog distinct_id$/i,
284
- message: "Could not find a PostHog distinct_id",
285
- body: "The agent could not find PostHog distinct_id usage in your codebase. Your users must be identified in PostHog before they can be tagged in Stripe. Please identify your users and try again.",
286
- docsUrl: "https://posthog.com/docs/product-analytics/identify"
287
- }, {
288
- match: /^could not find a stripe integration$/i,
289
- message: "Could not find a Stripe integration",
290
- body: "The Wizard could not find an existing Stripe customer, charge, subscription, or other Stripe operations. Please run the Revenue Analytics Wizard on a project with an existing Stripe integration.",
291
- docsUrl: "https://posthog.com/docs/revenue-analytics"
292
- }];
293
267
  /**
294
268
  * Recursively find all package.json files under installDir (max depth 3),
295
269
  * skipping common ignored directories. Returns matches with detected SDKs.
@@ -325,6 +299,26 @@ function findPackageJsons(installDir, maxDepth = 3) {
325
299
  scan(installDir, 0);
326
300
  return matches;
327
301
  }
302
+ //#endregion
303
+ //#region src/lib/programs/revenue-analytics/detect.ts
304
+ /**
305
+ * Revenue analytics prerequisite detection.
306
+ *
307
+ * Scans the project for PostHog + Stripe SDKs and writes results
308
+ * into frameworkContext for the intro screen to render.
309
+ */
310
+ /** `[ABORT] <reason>` cases the revenue analytics skill can emit. */
311
+ const REVENUE_ABORT_CASES = [{
312
+ match: /^could not find a posthog distinct_id$/i,
313
+ message: "Could not find a PostHog distinct_id",
314
+ body: "The agent could not find PostHog distinct_id usage in your codebase. Your users must be identified in PostHog before they can be tagged in Stripe. Please identify your users and try again.",
315
+ docsUrl: "https://posthog.com/docs/product-analytics/identify"
316
+ }, {
317
+ match: /^could not find a stripe integration$/i,
318
+ message: "Could not find a Stripe integration",
319
+ body: "The Wizard could not find an existing Stripe customer, charge, subscription, or other Stripe operations. Please run the Revenue Analytics Wizard on a project with an existing Stripe integration.",
320
+ docsUrl: "https://posthog.com/docs/revenue-analytics"
321
+ }];
328
322
  /**
329
323
  * Scan `session.installDir` for PostHog + Stripe SDKs. Writes detection
330
324
  * results into frameworkContext via the callback — either the detected
@@ -831,7 +825,7 @@ const EVENTS_AUDIT_SEED_CHECKS = [
831
825
  //#endregion
832
826
  //#region src/lib/programs/events-audit/index.ts
833
827
  const SETUP_REPORT_FILE = "posthog-events-audit-report.md";
834
- const DOCS_URL$1 = "https://posthog.com/docs/product-analytics/best-practices";
828
+ const DOCS_URL$2 = "https://posthog.com/docs/product-analytics/best-practices";
835
829
  const eventsAuditConfig = {
836
830
  command: "events-audit",
837
831
  description: "Audit PostHog event tracking in this project",
@@ -853,7 +847,7 @@ const eventsAuditConfig = {
853
847
  successMessage: "Events audit complete! You can view the report at ./posthog-events-audit-report.md",
854
848
  estimatedDurationMinutes: 5,
855
849
  reportFile: SETUP_REPORT_FILE,
856
- docsUrl: DOCS_URL$1,
850
+ docsUrl: DOCS_URL$2,
857
851
  errorMessage: "Events audit failed",
858
852
  additionalFeatureQueue: session.additionalFeatureQueue,
859
853
  customPrompt: (ctx) => `Audit PostHog event capture in this project. Do not modify any project files — produce a read-only report only.
@@ -871,7 +865,7 @@ Project context:
871
865
  message: "Your events audit was successful",
872
866
  reportFile: SETUP_REPORT_FILE,
873
867
  changes: [],
874
- docsUrl: DOCS_URL$1,
868
+ docsUrl: DOCS_URL$2,
875
869
  continueUrl: sess.signup && cloudUrl ? `${cloudUrl}/products?source=wizard` : void 0,
876
870
  dashboardUrl: sess.dashboardUrl ?? (cloudUrl ? `${cloudUrl}/dashboard` : void 0),
877
871
  notebookUrl: sess.notebookUrl ?? void 0
@@ -1236,6 +1230,97 @@ const posthogDoctorConfig = {
1236
1230
  disallowedTools: [WIZARD_TOOL_NAMES.wizardAsk]
1237
1231
  };
1238
1232
  //#endregion
1233
+ //#region src/lib/programs/web-analytics-doctor/detect.ts
1234
+ const WEB_ANALYTICS_ABORT_CASES = [
1235
+ {
1236
+ match: /^no web analytics events$/i,
1237
+ message: "No web analytics events",
1238
+ body: "The doctor found no $pageview events in the last 30 days, so there is nothing to audit yet. Make sure PostHog is initialized and capturing pageviews, then run the doctor again.",
1239
+ docsUrl: "https://posthog.com/docs/web-analytics/getting-started"
1240
+ },
1241
+ {
1242
+ match: /^insufficient permissions$/i,
1243
+ message: "Insufficient permissions",
1244
+ body: "The doctor could not query your project — the authenticated token is missing query access. Re-run the wizard to sign in again, or use a key with read access to your events.",
1245
+ docsUrl: "https://posthog.com/docs/web-analytics"
1246
+ },
1247
+ {
1248
+ match: /^posthog sdk not installed$/i,
1249
+ message: "PostHog SDK not installed",
1250
+ body: "The doctor could not find a PostHog SDK in this project. Install and configure PostHog first (run `npx @posthog/wizard`), then run the doctor to check your web analytics setup.",
1251
+ docsUrl: "https://posthog.com/docs/libraries/js"
1252
+ }
1253
+ ];
1254
+ function detectWebAnalyticsPrerequisites(session, setFrameworkContext) {
1255
+ const fail = (error) => setFrameworkContext("detectError", error);
1256
+ const installDir = session.installDir;
1257
+ if (!existsSync(installDir)) {
1258
+ fail({
1259
+ kind: "bad-directory",
1260
+ path: installDir,
1261
+ reason: "missing"
1262
+ });
1263
+ return;
1264
+ }
1265
+ try {
1266
+ if (!statSync(installDir).isDirectory()) {
1267
+ fail({
1268
+ kind: "bad-directory",
1269
+ path: installDir,
1270
+ reason: "not-dir"
1271
+ });
1272
+ return;
1273
+ }
1274
+ } catch {
1275
+ fail({
1276
+ kind: "bad-directory",
1277
+ path: installDir,
1278
+ reason: "unreadable"
1279
+ });
1280
+ return;
1281
+ }
1282
+ const matches = findPackageJsons(installDir);
1283
+ if (matches.length === 0) {
1284
+ fail({ kind: "no-package-json" });
1285
+ return;
1286
+ }
1287
+ const sdks = [...new Set(matches.flatMap((m) => m.posthogSdks))];
1288
+ if (sdks.length === 0) {
1289
+ fail({
1290
+ kind: "no-posthog",
1291
+ scannedCount: matches.length
1292
+ });
1293
+ return;
1294
+ }
1295
+ setFrameworkContext("detectedPosthogSdks", sdks);
1296
+ }
1297
+ //#endregion
1298
+ //#region src/lib/programs/web-analytics-doctor/steps.ts
1299
+ const WEB_ANALYTICS_DOCTOR_PROGRAM = [{
1300
+ id: "detect",
1301
+ label: "Detecting prerequisites",
1302
+ onReady: (ctx) => detectWebAnalyticsPrerequisites(ctx.session, ctx.setFrameworkContext)
1303
+ }, ...AGENT_SKILL_STEPS];
1304
+ const webAnalyticsDoctorConfig = {
1305
+ ...createSkillProgram({
1306
+ skillId: "web-analytics-doctor",
1307
+ command: "web-analytics",
1308
+ id: "web-analytics-doctor",
1309
+ description: "Audit and fix your PostHog web analytics setup",
1310
+ integrationLabel: "web-analytics-doctor",
1311
+ customPrompt: "Run the web-analytics-doctor skill to check this project's PostHog web analytics setup. Audit read-only first, then present the findings to the user with a single wizard_ask multi-select and apply only the fixes they choose — editing project code and/or PostHog project settings via the MCP — before writing the report.",
1312
+ successMessage: "Web analytics check complete! You can view the report at ./posthog-web-analytics-report.md",
1313
+ reportFile: "posthog-web-analytics-report.md",
1314
+ docsUrl: "https://posthog.com/docs/web-analytics",
1315
+ spinnerMessage: "Checking your web analytics setup...",
1316
+ estimatedDurationMinutes: 5,
1317
+ requires: ["posthog-integration"],
1318
+ abortCases: WEB_ANALYTICS_ABORT_CASES
1319
+ }),
1320
+ steps: WEB_ANALYTICS_DOCTOR_PROGRAM,
1321
+ parentCommand: "audit"
1322
+ };
1323
+ //#endregion
1239
1324
  //#region src/lib/programs/migration/steps.ts
1240
1325
  const MIGRATION_PROGRAM = [
1241
1326
  {
@@ -2627,6 +2712,7 @@ const PROGRAM_REGISTRY = [
2627
2712
  eventsAuditConfig,
2628
2713
  audit3000Config,
2629
2714
  posthogDoctorConfig,
2715
+ webAnalyticsDoctorConfig,
2630
2716
  migrationConfig,
2631
2717
  agentSkillConfig,
2632
2718
  mcpAddConfig,
@@ -2647,6 +2733,7 @@ const Program = {
2647
2733
  EventsAudit: eventsAuditConfig.id,
2648
2734
  Audit3000: audit3000Config.id,
2649
2735
  PosthogDoctor: posthogDoctorConfig.id,
2736
+ WebAnalyticsDoctor: webAnalyticsDoctorConfig.id,
2650
2737
  AgentSkill: agentSkillConfig.id,
2651
2738
  McpAdd: mcpAddConfig.id,
2652
2739
  McpRemove: mcpRemoveConfig.id,
@@ -2685,12 +2772,12 @@ const mcpAddCommand = {
2685
2772
  function runMcpAdd(argv) {
2686
2773
  const features = parseFeatures(argv.features);
2687
2774
  (async () => {
2688
- const { readApiKeyFromEnv } = await import("./env-api-key-B3gE9Un0.js").then((n) => n.t);
2775
+ const { readApiKeyFromEnv } = await import("./env-api-key-MlzJYAvt.js").then((n) => n.t);
2689
2776
  const apiKey = argv.apiKey || readApiKeyFromEnv();
2690
2777
  const debug = argv.debug;
2691
2778
  const localMcp = argv.local;
2692
2779
  try {
2693
- const { startTUI } = await import("./start-tui-BZ7rEf3e.js");
2780
+ const { startTUI } = await import("./start-tui-BfXoErKg.js");
2694
2781
  const { buildSession } = await import("./wizard-session-y304gEEI.js");
2695
2782
  const tui = startTUI(VERSION, Program.McpAdd);
2696
2783
  tui.store.session = buildSession({
@@ -2702,7 +2789,7 @@ function runMcpAdd(argv) {
2702
2789
  } catch (error) {
2703
2790
  if (!isTUIUnavailable(error)) throw error;
2704
2791
  setUI(new LoggingUI());
2705
- const { addMCPServerToClientsStep } = await import("./add-mcp-server-to-clients-D4PK6ulR.js").then((n) => n.r);
2792
+ const { addMCPServerToClientsStep } = await import("./add-mcp-server-to-clients-CjnvTVj0.js").then((n) => n.r);
2706
2793
  await addMCPServerToClientsStep({
2707
2794
  local: localMcp,
2708
2795
  features,
@@ -2741,7 +2828,7 @@ function runMcpRemove(argv) {
2741
2828
  const debug = argv.debug;
2742
2829
  const localMcp = argv.local;
2743
2830
  try {
2744
- const { startTUI } = await import("./start-tui-BZ7rEf3e.js");
2831
+ const { startTUI } = await import("./start-tui-BfXoErKg.js");
2745
2832
  const { buildSession } = await import("./wizard-session-y304gEEI.js");
2746
2833
  const tui = startTUI(VERSION, Program.McpRemove);
2747
2834
  tui.store.session = buildSession({
@@ -2750,7 +2837,7 @@ function runMcpRemove(argv) {
2750
2837
  });
2751
2838
  } catch {
2752
2839
  setUI(new LoggingUI());
2753
- const { removeMCPServerFromClientsStep } = await import("./add-mcp-server-to-clients-D4PK6ulR.js").then((n) => n.r);
2840
+ const { removeMCPServerFromClientsStep } = await import("./add-mcp-server-to-clients-CjnvTVj0.js").then((n) => n.r);
2754
2841
  await removeMCPServerFromClientsStep({ local: localMcp });
2755
2842
  }
2756
2843
  })();
@@ -2772,7 +2859,7 @@ function runMcpTutorial(argv) {
2772
2859
  const debug = argv.debug;
2773
2860
  const localMcp = argv.local;
2774
2861
  try {
2775
- const { startTUI } = await import("./start-tui-BZ7rEf3e.js");
2862
+ const { startTUI } = await import("./start-tui-BfXoErKg.js");
2776
2863
  const { buildSession } = await import("./wizard-session-y304gEEI.js");
2777
2864
  const tui = startTUI(VERSION, Program.McpTutorial);
2778
2865
  tui.store.session = buildSession({
@@ -2827,11 +2914,10 @@ function runWizard(config, options) {
2827
2914
  (async () => {
2828
2915
  try {
2829
2916
  const installDir = options.installDir || process.cwd();
2830
- const { startTUI } = await import("./start-tui-BZ7rEf3e.js");
2917
+ const { startTUI } = await import("./start-tui-BfXoErKg.js");
2831
2918
  const { buildSession, RunPhase } = await import("./wizard-session-y304gEEI.js");
2832
- const { TaskStreamPush } = await import("./task-stream-BI8rJg9H.js");
2833
- const { PostHogDestination } = await import("./posthog-BrLFkaji.js");
2834
- const { logToFile } = await import("./debug-BI-Js0PB.js");
2919
+ const { TaskStreamPush } = await import("./task-stream-CZRj6auI.js");
2920
+ const { PostHogDestination } = await import("./posthog-Cr37rnla.js");
2835
2921
  tui = startTUI(WIZARD_VERSION, config.id);
2836
2922
  const activeTui = tui;
2837
2923
  const session = buildSession({
@@ -2867,8 +2953,9 @@ function runWizard(config, options) {
2867
2953
  onSignal = () => {
2868
2954
  if (signalled || exitInProgress) return;
2869
2955
  signalled = true;
2956
+ logToFile("[run-wizard] signal received, flushing task stream");
2870
2957
  if (activeTui.store.session.runPhase === RunPhase.Running) activeTui.store.setRunPhase(RunPhase.Error);
2871
- activeStream.shutdown(2e3).finally(() => {
2958
+ activeStream.shutdown(2e3).catch((e) => logToFile("[run-wizard] task stream shutdown error on signal:", e)).finally(() => {
2872
2959
  try {
2873
2960
  activeTui.unmount();
2874
2961
  } catch {}
@@ -2882,12 +2969,13 @@ function runWizard(config, options) {
2882
2969
  await activeTui.store.getGate("health-check");
2883
2970
  const skipAgent = config.run == null;
2884
2971
  if (skipAgent) {
2885
- const { getOrAskForProjectData } = await import("./setup-utils-Bpfsap9L.js").then((n) => n.r);
2972
+ const { getOrAskForProjectData } = await import("./setup-utils-DetnhXo0.js").then((n) => n.r);
2886
2973
  const { projectApiKey, host, accessToken, projectId } = await getOrAskForProjectData({
2887
2974
  signup: session.signup,
2888
2975
  ci: session.ci,
2889
2976
  apiKey: session.apiKey,
2890
- projectId: session.projectId
2977
+ projectId: session.projectId,
2978
+ programId: config.id
2891
2979
  });
2892
2980
  activeTui.store.setCredentials({
2893
2981
  accessToken,
@@ -2896,7 +2984,7 @@ function runWizard(config, options) {
2896
2984
  projectId
2897
2985
  });
2898
2986
  } else {
2899
- const { runAgent } = await import("./agent-runner-CTkKLVhp.js");
2987
+ const { runAgent } = await import("./agent-runner-Cj7saDkL.js");
2900
2988
  await runAgent(config, activeTui.store.session);
2901
2989
  }
2902
2990
  const isDone = () => skipAgent ? activeTui.store.session.outroDismissed : activeTui.store.session.skillsComplete;
@@ -2919,7 +3007,7 @@ function runWizard(config, options) {
2919
3007
  activeTui.unmount();
2920
3008
  process.exit(0);
2921
3009
  } catch (err) {
2922
- if (runtimeEnv("DEBUG") || runtimeEnv("POSTHOG_WIZARD_DEBUG")) console.error("TUI init failed:", err);
3010
+ logToFile("[run-wizard] FATAL:", err);
2923
3011
  exitInProgress = true;
2924
3012
  if (onSignal) {
2925
3013
  process.off("SIGINT", onSignal);
@@ -2931,6 +3019,8 @@ function runWizard(config, options) {
2931
3019
  if (tui) try {
2932
3020
  tui.unmount();
2933
3021
  } catch {}
3022
+ console.error("Wizard run failed:", err);
3023
+ console.error(`Full logs: ${getLogFilePath()}`);
2934
3024
  process.exit(1);
2935
3025
  }
2936
3026
  })();
@@ -2969,10 +3059,10 @@ function runWizardCI(config, options) {
2969
3059
  (async () => {
2970
3060
  const path = await import("path");
2971
3061
  const { buildSession } = await import("./wizard-session-y304gEEI.js");
2972
- const { readEnvironment } = await import("./environment-CiZVSSYt.js").then((n) => n.t);
2973
- const { readApiKeyFromEnv } = await import("./env-api-key-B3gE9Un0.js").then((n) => n.t);
2974
- const { configureLogFileFromEnvironment, logToFile } = await import("./debug-BI-Js0PB.js");
2975
- const { wizardAbort, WizardError } = await import("./wizard-abort-QdRxGQp_.js");
3062
+ const { readEnvironment } = await import("./environment-Ls0H9ljT.js").then((n) => n.t);
3063
+ const { readApiKeyFromEnv } = await import("./env-api-key-MlzJYAvt.js").then((n) => n.t);
3064
+ const { configureLogFileFromEnvironment, logToFile } = await import("./debug-Cp_wNn8i.js");
3065
+ const { wizardAbort, WizardError } = await import("./wizard-abort-CtMY57ZE.js");
2976
3066
  configureLogFileFromEnvironment();
2977
3067
  const env = readEnvironment();
2978
3068
  const apiKey = options.apiKey ?? readApiKeyFromEnv() ?? void 0;
@@ -3020,7 +3110,7 @@ function runWizardCI(config, options) {
3020
3110
  })
3021
3111
  });
3022
3112
  }
3023
- const { runAgent } = await import("./agent-runner-CTkKLVhp.js");
3113
+ const { runAgent } = await import("./agent-runner-Cj7saDkL.js");
3024
3114
  await runAgent(config, session);
3025
3115
  } catch (error) {
3026
3116
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -3088,21 +3178,36 @@ const integrateCommand = {
3088
3178
  };
3089
3179
  //#endregion
3090
3180
  //#region src/commands/audit.ts
3181
+ const dispatchProgram = (config, argv) => {
3182
+ const extras = config.mapCliOptions?.(argv) ?? {};
3183
+ const options = {
3184
+ ...argv,
3185
+ ...extras
3186
+ };
3187
+ if (options.ci) runWizardCI(config, options);
3188
+ else runWizard(config, options);
3189
+ };
3190
+ const webAnalyticsCommand = {
3191
+ name: webAnalyticsDoctorConfig.command,
3192
+ description: webAnalyticsDoctorConfig.description,
3193
+ options: {
3194
+ ...skillProgramOptions,
3195
+ ...webAnalyticsDoctorConfig.cliOptions ?? {}
3196
+ },
3197
+ handler: (argv) => {
3198
+ dispatchProgram(webAnalyticsDoctorConfig, argv);
3199
+ }
3200
+ };
3091
3201
  const auditCommand = {
3092
3202
  name: "audit",
3093
3203
  description: auditConfig.description,
3204
+ children: [webAnalyticsCommand],
3094
3205
  options: {
3095
3206
  ...skillProgramOptions,
3096
3207
  ...auditConfig.cliOptions ?? {}
3097
3208
  },
3098
3209
  handler: (argv) => {
3099
- const extras = auditConfig.mapCliOptions?.(argv) ?? {};
3100
- const options = {
3101
- ...argv,
3102
- ...extras
3103
- };
3104
- if (options.ci) runWizardCI(auditConfig, options);
3105
- else runWizard(auditConfig, options);
3210
+ dispatchProgram(auditConfig, argv);
3106
3211
  }
3107
3212
  };
3108
3213
  //#endregion
@@ -3159,7 +3264,7 @@ async function runDoctorCI(options) {
3159
3264
  getUI().intro("Welcome to the PostHog setup wizard");
3160
3265
  getUI().log.info("Running posthog-doctor in CI mode");
3161
3266
  try {
3162
- const { getOrAskForProjectData } = await import("./setup-utils-Bpfsap9L.js").then((n) => n.r);
3267
+ const { getOrAskForProjectData } = await import("./setup-utils-DetnhXo0.js").then((n) => n.r);
3163
3268
  const { host, accessToken, projectId } = await getOrAskForProjectData({
3164
3269
  signup: false,
3165
3270
  ci: true,
@@ -3176,7 +3281,7 @@ async function runDoctorCI(options) {
3176
3281
  for (const issue of sorted) getUI().log.info(` • [${issue.severity}] ${getKindMeta(issue.kind).title}`);
3177
3282
  process.exit(1);
3178
3283
  } catch (error) {
3179
- const { ApiError } = await import("./api-serd0SMY.js").then((n) => n.n);
3284
+ const { ApiError } = await import("./api-Dw6_orDE.js").then((n) => n.n);
3180
3285
  const message = error instanceof ApiError && error.statusCode === 401 ? "Your PostHog API key is invalid or expired." : error instanceof Error ? error.message : String(error);
3181
3286
  getUI().log.error(`Doctor failed: ${message}`);
3182
3287
  process.exit(1);
@@ -3242,7 +3347,7 @@ const revenueCommand = {
3242
3347
  //#endregion
3243
3348
  //#region src/commands/upload-sourcemaps.ts
3244
3349
  const uploadSourcemapsCommand = {
3245
- name: "upload-sourcemaps",
3350
+ name: [errorTrackingUploadSourceMapsConfig.command, "upload-sourcemaps"],
3246
3351
  description: errorTrackingUploadSourceMapsConfig.description,
3247
3352
  options: {
3248
3353
  ...skillProgramOptions,
@@ -3259,14 +3364,66 @@ const uploadSourcemapsCommand = {
3259
3364
  }
3260
3365
  };
3261
3366
  //#endregion
3367
+ //#region src/commands/basic-integration/skill.ts
3368
+ /** Run an arbitrary context-mill skill by id (`wizard skill <id>`, headless with `--ci`). */
3369
+ function runSkillMode(argv) {
3370
+ const skillId = argv.skill;
3371
+ const config = createSkillProgram({
3372
+ skillId,
3373
+ command: "skill",
3374
+ id: "agent-skill",
3375
+ description: `Run skill: ${skillId}`,
3376
+ integrationLabel: skillId,
3377
+ successMessage: `${skillId} completed!`,
3378
+ reportFile: `posthog-${skillId}-report.md`,
3379
+ docsUrl: POSTHOG_DOCS_URL,
3380
+ spinnerMessage: `Running ${skillId}...`,
3381
+ estimatedDurationMinutes: 5
3382
+ });
3383
+ const options = {
3384
+ ...argv,
3385
+ skillId
3386
+ };
3387
+ if (argv.ci) runWizardCI(config, options);
3388
+ else runWizard(config, options);
3389
+ }
3390
+ //#endregion
3391
+ //#region src/commands/skill.ts
3392
+ /** Read the `<skill-name>` positional (yargs camelCases the hyphenated key). */
3393
+ function readSkillName(argv) {
3394
+ return String(argv.skillName ?? argv["skill-name"] ?? "").trim();
3395
+ }
3396
+ /**
3397
+ * `wizard skill <skill-name>` — run a single context-mill skill by id.
3398
+ *
3399
+ * Replaces the old `--skill=<id>` flag on the default command. The skill id
3400
+ * is fetched from context-mill's release at runtime (same mechanism the flag
3401
+ * used), so any published skill id works. Pass `--ci` to run headlessly.
3402
+ */
3403
+ const skillCommand = {
3404
+ name: "skill <skill-name>",
3405
+ description: "Run a specific context-mill skill by name",
3406
+ options: { ...skillProgramOptions },
3407
+ check: (argv) => {
3408
+ if (!readSkillName(argv)) throw new Error("skill needs a skill name, e.g. `wizard skill audit-events`");
3409
+ return true;
3410
+ },
3411
+ handler: (argv) => {
3412
+ runSkillMode({
3413
+ ...argv,
3414
+ skill: readSkillName(argv)
3415
+ });
3416
+ }
3417
+ };
3418
+ //#endregion
3262
3419
  //#region bin.ts
3263
3420
  const NODE_VERSION_RANGE = ">=18.17.0";
3264
3421
  if (!satisfies(process.version, NODE_VERSION_RANGE)) {
3265
3422
  console.log(`PostHog wizard requires Node.js ${NODE_VERSION_RANGE}. You are using Node.js ${process.version}. Please upgrade your Node.js version.`);
3266
3423
  process.exit(1);
3267
3424
  }
3268
- Wizard.use(basicIntegrationCommand).use(mcpCommand).use(integrateCommand).use(auditCommand).use(audit3000Command).use(doctorCommand).use(migrateCommand).use(eventsAuditCommand).use(revenueCommand).use(uploadSourcemapsCommand).init();
3425
+ Wizard.use(basicIntegrationCommand).use(mcpCommand).use(integrateCommand).use(auditCommand).use(audit3000Command).use(doctorCommand).use(migrateCommand).use(eventsAuditCommand).use(revenueCommand).use(uploadSourcemapsCommand).use(skillCommand).init();
3269
3426
  //#endregion
3270
- export { getProgramConfig as a, getContentBlocks$1 as c, createSkillProgram as d, getContentBlocks$2 as f, Program as i, getKindMeta as l, STRIPE_SDKS as m, runWizard as n, DISPLAY_NAME as o, POSTHOG_SDKS$1 as p, PROGRAM_REGISTRY as r, SOURCE_MAPS_CONTEXT_KEYS as s, runWizardCI as t, fetchHealthIssues as u };
3427
+ export { getProgramConfig as a, getContentBlocks$1 as c, getContentBlocks$2 as d, POSTHOG_SDKS$1 as f, Program as i, getKindMeta as l, runWizard as n, DISPLAY_NAME as o, STRIPE_SDKS as p, PROGRAM_REGISTRY as r, SOURCE_MAPS_CONTEXT_KEYS as s, runWizardCI as t, fetchHealthIssues as u };
3271
3428
 
3272
3429
  //# sourceMappingURL=bin.js.map