@posthog/wizard 2.22.0 → 2.23.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 (55) hide show
  1. package/dist/{AiOptInRequiredScreen-N6L80szR.js → AiOptInRequiredScreen-BOMyYFep.js} +48 -9
  2. package/dist/AiOptInRequiredScreen-BOMyYFep.js.map +1 -0
  3. package/dist/{add-mcp-server-to-clients-DqHCkHqM.js → add-mcp-server-to-clients-BEziI3z9.js} +4 -4
  4. package/dist/{add-mcp-server-to-clients-DqHCkHqM.js.map → add-mcp-server-to-clients-BEziI3z9.js.map} +1 -1
  5. package/dist/{agent-interface-DZmVoik2.js → agent-interface-DjMPlXl0.js} +6 -5
  6. package/dist/{agent-interface-DZmVoik2.js.map → agent-interface-DjMPlXl0.js.map} +1 -1
  7. package/dist/{agent-runner-CGFUXR97.js → agent-runner-Bv-7z-pQ.js} +8 -8
  8. package/dist/{agent-runner-CGFUXR97.js.map → agent-runner-Bv-7z-pQ.js.map} +1 -1
  9. package/dist/{analytics-C_lVPZQT.js → analytics-9D4eGgmT.js} +13 -2
  10. package/dist/analytics-9D4eGgmT.js.map +1 -0
  11. package/dist/{api-QI1lO_Bz.js → api-Dwd0B-E9.js} +3 -3
  12. package/dist/{api-QI1lO_Bz.js.map → api-Dwd0B-E9.js.map} +1 -1
  13. package/dist/bin.js +31 -31
  14. package/dist/{ci-install-CXkKR4A-.js → ci-install-DGXCpvKh.js} +4 -4
  15. package/dist/{ci-install-CXkKR4A-.js.map → ci-install-DGXCpvKh.js.map} +1 -1
  16. package/dist/{debug-D8QAez2V.js → debug-CgT5MmVB.js} +133 -29
  17. package/dist/debug-CgT5MmVB.js.map +1 -0
  18. package/dist/{debug-lPpecs0J.js → debug-DayHBBST.js} +1 -1
  19. package/dist/{environment-CMmzgZkN.js → environment-CI2pTYTG.js} +3 -3
  20. package/dist/{environment-CMmzgZkN.js.map → environment-CI2pTYTG.js.map} +1 -1
  21. package/dist/{interactive-Bu8YchJG.js → interactive-D52p_opJ.js} +2 -2
  22. package/dist/{interactive-Bu8YchJG.js.map → interactive-D52p_opJ.js.map} +1 -1
  23. package/dist/{mcp-prompt-streaming-mYw2LPZZ.js → mcp-prompt-streaming-tdoy9UJ2.js} +4 -4
  24. package/dist/{mcp-prompt-streaming-mYw2LPZZ.js.map → mcp-prompt-streaming-tdoy9UJ2.js.map} +1 -1
  25. package/dist/{non-interactive-De3tJM1y.js → non-interactive-6hadW20x.js} +2 -2
  26. package/dist/{non-interactive-De3tJM1y.js.map → non-interactive-6hadW20x.js.map} +1 -1
  27. package/dist/{package-manager-BVJnbp1u.js → package-manager-BI0J5E7t.js} +2 -2
  28. package/dist/{package-manager-BVJnbp1u.js.map → package-manager-BI0J5E7t.js.map} +1 -1
  29. package/dist/{playground-wyoq1yIH.js → playground-z4A5dHPv.js} +57 -19
  30. package/dist/playground-z4A5dHPv.js.map +1 -0
  31. package/dist/{posthog-integration-mrMF-2IP.js → posthog-integration-BWbZU9Xq.js} +11 -11
  32. package/dist/{posthog-integration-mrMF-2IP.js.map → posthog-integration-BWbZU9Xq.js.map} +1 -1
  33. package/dist/{provisioning-4zipVpbq.js → provisioning-B30Be2NA.js} +3 -3
  34. package/dist/{provisioning-4zipVpbq.js.map → provisioning-B30Be2NA.js.map} +1 -1
  35. package/dist/{registry-BGUo4PlM.js → registry-CD_DplSQ.js} +4 -4
  36. package/dist/{registry-BGUo4PlM.js.map → registry-CD_DplSQ.js.map} +1 -1
  37. package/dist/{setup-utils-DmhPyWkp.js → setup-utils-Dwgkk8AQ.js} +8 -8
  38. package/dist/{setup-utils-DmhPyWkp.js.map → setup-utils-Dwgkk8AQ.js.map} +1 -1
  39. package/dist/{start-tui-DaQiY_EB.js → start-tui-SLeEzlJs.js} +47 -19
  40. package/dist/start-tui-SLeEzlJs.js.map +1 -0
  41. package/dist/{steps-CrUceWR5.js → steps-B1gzyRkC.js} +6 -6
  42. package/dist/{steps-CrUceWR5.js.map → steps-B1gzyRkC.js.map} +1 -1
  43. package/dist/{telemetry-CCVjGq7l.js → telemetry-5rkeTd2_.js} +3 -3
  44. package/dist/{telemetry-CCVjGq7l.js.map → telemetry-5rkeTd2_.js.map} +1 -1
  45. package/dist/{urls-BNFpfcN8.js → urls-Cb4SI9kf.js} +2 -2
  46. package/dist/{urls-BNFpfcN8.js.map → urls-Cb4SI9kf.js.map} +1 -1
  47. package/dist/{wizard-abort-Bp2yxYAy.js → wizard-abort-DW2-ZjiS.js} +1 -1
  48. package/dist/{wizard-abort-BmYb0bG2.js → wizard-abort-DovHQa-j.js} +3 -3
  49. package/dist/{wizard-abort-BmYb0bG2.js.map → wizard-abort-DovHQa-j.js.map} +1 -1
  50. package/package.json +2 -2
  51. package/dist/AiOptInRequiredScreen-N6L80szR.js.map +0 -1
  52. package/dist/analytics-C_lVPZQT.js.map +0 -1
  53. package/dist/debug-D8QAez2V.js.map +0 -1
  54. package/dist/playground-wyoq1yIH.js.map +0 -1
  55. package/dist/start-tui-DaQiY_EB.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"api-QI1lO_Bz.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\n/** Minimal shape of `/api/projects/:id/integrations/` — we only read `kind`. */\nconst IntegrationsResponseSchema = z.object({\n results: z.array(z.object({ kind: z.string().nullish() }).passthrough()),\n});\n\n/**\n * Check whether the project already has a Slack integration connected.\n * Requires the `integration:read` scope. Throws on failure — callers\n * (including the SlackConnectScreen poll) decide how to degrade and\n * are responsible for capturing the error exactly once.\n */\nexport async function fetchSlackConnected(\n accessToken: string,\n projectId: number,\n baseUrl: string,\n signal?: AbortSignal,\n): Promise<boolean> {\n const response = await axios.get(\n `${baseUrl}/api/projects/${projectId}/integrations/`,\n {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n 'User-Agent': WIZARD_USER_AGENT,\n },\n signal,\n },\n );\n const parsed = IntegrationsResponseSchema.safeParse(response.data);\n if (!parsed.success) return false;\n return parsed.data.results.some((i) => i.kind === 'slack');\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-Dwd0B-E9.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\n/** Minimal shape of `/api/projects/:id/integrations/` — we only read `kind`. */\nconst IntegrationsResponseSchema = z.object({\n results: z.array(z.object({ kind: z.string().nullish() }).passthrough()),\n});\n\n/**\n * Check whether the project already has a Slack integration connected.\n * Requires the `integration:read` scope. Throws on failure — callers\n * (including the SlackConnectScreen poll) decide how to degrade and\n * are responsible for capturing the error exactly once.\n */\nexport async function fetchSlackConnected(\n accessToken: string,\n projectId: number,\n baseUrl: string,\n signal?: AbortSignal,\n): Promise<boolean> {\n const response = await axios.get(\n `${baseUrl}/api/projects/${projectId}/integrations/`,\n {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n 'User-Agent': WIZARD_USER_AGENT,\n },\n signal,\n },\n );\n const parsed = IntegrationsResponseSchema.safeParse(response.data);\n if (!parsed.success) return false;\n return parsed.data.results.some((i) => i.kind === 'slack');\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,16 +1,16 @@
1
1
  #!/usr/bin/env node
2
- import { $ as VERSION, P as POSTHOG_DOCS_URL, Y 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-D8QAez2V.js";
3
- import { t as analytics } from "./analytics-C_lVPZQT.js";
4
- import { r as setEntryCommand } from "./telemetry-CCVjGq7l.js";
5
- import { n as isUsingTypeScript, t as getOrAskForProjectData } from "./setup-utils-DmhPyWkp.js";
6
- import { a as getUiHostFromHost, n as getCloudUrlFromRegion } from "./urls-BNFpfcN8.js";
7
- import { o as handleApiError } from "./api-QI1lO_Bz.js";
2
+ import { $ as VERSION, P as POSTHOG_DOCS_URL, Y 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-CgT5MmVB.js";
3
+ import { t as analytics } from "./analytics-9D4eGgmT.js";
4
+ import { r as setEntryCommand } from "./telemetry-5rkeTd2_.js";
5
+ import { n as isUsingTypeScript, t as getOrAskForProjectData } from "./setup-utils-Dwgkk8AQ.js";
6
+ import { a as getUiHostFromHost, n as getCloudUrlFromRegion } from "./urls-Cb4SI9kf.js";
7
+ import { o as handleApiError } from "./api-Dwd0B-E9.js";
8
8
  import "./wizard-session-G3VWD6hv.js";
9
- import { r as runCleanups } from "./wizard-abort-BmYb0bG2.js";
10
- import { n as isNonInteractiveEnvironment } from "./environment-CMmzgZkN.js";
11
- import { _ as AUDIT_CHECKS_KEY, f as WIZARD_TOOL_NAMES, g as AUDIT_CHECKS_FILE, l as AgentSignals, s as recoverOrphanedSettingsBackups, v as AUDIT_REPORT_FILE } from "./agent-interface-DZmVoik2.js";
12
- import { i as SPINNER_MESSAGE } from "./registry-BGUo4PlM.js";
13
- 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-mrMF-2IP.js";
9
+ import { r as runCleanups } from "./wizard-abort-DovHQa-j.js";
10
+ import { n as isNonInteractiveEnvironment } from "./environment-CI2pTYTG.js";
11
+ import { _ as AUDIT_CHECKS_KEY, f as WIZARD_TOOL_NAMES, g as AUDIT_CHECKS_FILE, l as AgentSignals, s as recoverOrphanedSettingsBackups, v as AUDIT_REPORT_FILE } from "./agent-interface-DjMPlXl0.js";
12
+ import { i as SPINNER_MESSAGE } from "./registry-CD_DplSQ.js";
13
+ 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-BWbZU9Xq.js";
14
14
  import { t as IGNORED_DIRS } from "./file-utils-VAXoyXVA.js";
15
15
  import { n as readApiKeyFromEnv } from "./env-api-key-MlzJYAvt.js";
16
16
  import { satisfies } from "semver";
@@ -166,7 +166,7 @@ function runProvision(argv) {
166
166
  }
167
167
  async function provision({ email, region, name, jsonMode }) {
168
168
  try {
169
- const { provisionNewAccount } = await import("./provisioning-4zipVpbq.js").then((n) => n.n);
169
+ const { provisionNewAccount } = await import("./provisioning-B30Be2NA.js").then((n) => n.n);
170
170
  if (!jsonMode) getUI().log.info(`Provisioning account for ${email} in ${region}...`);
171
171
  emitResult(await provisionNewAccount(email, name, region), jsonMode);
172
172
  process.exit(0);
@@ -241,18 +241,18 @@ const basicIntegrationCommand = {
241
241
  setEntryCommand("integrate");
242
242
  (async () => {
243
243
  if (argv.ci) {
244
- const { runCIInstall } = await import("./ci-install-CXkKR4A-.js");
244
+ const { runCIInstall } = await import("./ci-install-DGXCpvKh.js");
245
245
  return runCIInstall(argv);
246
246
  }
247
247
  if (isNonInteractiveEnvironment()) {
248
- const { failNonInteractive } = await import("./non-interactive-De3tJM1y.js");
248
+ const { failNonInteractive } = await import("./non-interactive-6hadW20x.js");
249
249
  return failNonInteractive();
250
250
  }
251
251
  if (argv.playground) {
252
- const { runPlayground } = await import("./playground-wyoq1yIH.js");
252
+ const { runPlayground } = await import("./playground-z4A5dHPv.js");
253
253
  return runPlayground();
254
254
  }
255
- const { runInteractive } = await import("./interactive-Bu8YchJG.js");
255
+ const { runInteractive } = await import("./interactive-D52p_opJ.js");
256
256
  runInteractive(argv);
257
257
  })();
258
258
  }
@@ -2873,7 +2873,7 @@ function runMcpAdd(argv) {
2873
2873
  const debug = argv.debug;
2874
2874
  const localMcp = argv.local;
2875
2875
  try {
2876
- const { startTUI } = await import("./start-tui-DaQiY_EB.js");
2876
+ const { startTUI } = await import("./start-tui-SLeEzlJs.js");
2877
2877
  const { buildSession } = await import("./wizard-session-wPJtNl4c.js");
2878
2878
  const tui = startTUI(VERSION, Program.McpAdd);
2879
2879
  tui.store.session = buildSession({
@@ -2885,7 +2885,7 @@ function runMcpAdd(argv) {
2885
2885
  } catch (error) {
2886
2886
  if (!isTUIUnavailable(error)) throw error;
2887
2887
  setUI(new LoggingUI());
2888
- const { addMCPServerToClientsStep } = await import("./add-mcp-server-to-clients-DqHCkHqM.js").then((n) => n.r);
2888
+ const { addMCPServerToClientsStep } = await import("./add-mcp-server-to-clients-BEziI3z9.js").then((n) => n.r);
2889
2889
  await addMCPServerToClientsStep({
2890
2890
  local: localMcp,
2891
2891
  features,
@@ -2924,7 +2924,7 @@ function runMcpRemove(argv) {
2924
2924
  const debug = argv.debug;
2925
2925
  const localMcp = argv.local;
2926
2926
  try {
2927
- const { startTUI } = await import("./start-tui-DaQiY_EB.js");
2927
+ const { startTUI } = await import("./start-tui-SLeEzlJs.js");
2928
2928
  const { buildSession } = await import("./wizard-session-wPJtNl4c.js");
2929
2929
  const tui = startTUI(VERSION, Program.McpRemove);
2930
2930
  tui.store.session = buildSession({
@@ -2933,7 +2933,7 @@ function runMcpRemove(argv) {
2933
2933
  });
2934
2934
  } catch {
2935
2935
  setUI(new LoggingUI());
2936
- const { removeMCPServerFromClientsStep } = await import("./add-mcp-server-to-clients-DqHCkHqM.js").then((n) => n.r);
2936
+ const { removeMCPServerFromClientsStep } = await import("./add-mcp-server-to-clients-BEziI3z9.js").then((n) => n.r);
2937
2937
  await removeMCPServerFromClientsStep({ local: localMcp });
2938
2938
  }
2939
2939
  })();
@@ -2955,7 +2955,7 @@ function runMcpTutorial(argv) {
2955
2955
  const debug = argv.debug;
2956
2956
  const localMcp = argv.local;
2957
2957
  try {
2958
- const { startTUI } = await import("./start-tui-DaQiY_EB.js");
2958
+ const { startTUI } = await import("./start-tui-SLeEzlJs.js");
2959
2959
  const { buildSession } = await import("./wizard-session-wPJtNl4c.js");
2960
2960
  const tui = startTUI(VERSION, Program.McpTutorial);
2961
2961
  tui.store.session = buildSession({
@@ -3010,7 +3010,7 @@ function runWizard(config, options) {
3010
3010
  (async () => {
3011
3011
  try {
3012
3012
  const installDir = options.installDir || process.cwd();
3013
- const { startTUI } = await import("./start-tui-DaQiY_EB.js");
3013
+ const { startTUI } = await import("./start-tui-SLeEzlJs.js");
3014
3014
  const { buildSession, RunPhase } = await import("./wizard-session-wPJtNl4c.js");
3015
3015
  const { TaskStreamPush } = await import("./task-stream-CZawuzlz.js");
3016
3016
  const { PostHogDestination } = await import("./posthog-Cr37rnla.js");
@@ -3066,7 +3066,7 @@ function runWizard(config, options) {
3066
3066
  await activeTui.store.getGate("health-check");
3067
3067
  const skipAgent = config.run == null;
3068
3068
  if (skipAgent) {
3069
- const { getOrAskForProjectData } = await import("./setup-utils-DmhPyWkp.js").then((n) => n.r);
3069
+ const { getOrAskForProjectData } = await import("./setup-utils-Dwgkk8AQ.js").then((n) => n.r);
3070
3070
  const { projectApiKey, host, accessToken, projectId } = await getOrAskForProjectData({
3071
3071
  signup: session.signup,
3072
3072
  ci: session.ci,
@@ -3081,7 +3081,7 @@ function runWizard(config, options) {
3081
3081
  projectId
3082
3082
  });
3083
3083
  } else {
3084
- const { runAgent } = await import("./agent-runner-CGFUXR97.js");
3084
+ const { runAgent } = await import("./agent-runner-Bv-7z-pQ.js");
3085
3085
  await runAgent(config, activeTui.store.session);
3086
3086
  }
3087
3087
  const isDone = () => skipAgent ? activeTui.store.session.outroDismissed : activeTui.store.session.skillsComplete;
@@ -3158,10 +3158,10 @@ function runWizardCI(config, options) {
3158
3158
  (async () => {
3159
3159
  const path = await import("path");
3160
3160
  const { buildSession } = await import("./wizard-session-wPJtNl4c.js");
3161
- const { readEnvironment } = await import("./environment-CMmzgZkN.js").then((n) => n.t);
3161
+ const { readEnvironment } = await import("./environment-CI2pTYTG.js").then((n) => n.t);
3162
3162
  const { readApiKeyFromEnv } = await import("./env-api-key-MlzJYAvt.js").then((n) => n.t);
3163
- const { configureLogFileFromEnvironment, logToFile } = await import("./debug-lPpecs0J.js");
3164
- const { wizardAbort, WizardError } = await import("./wizard-abort-Bp2yxYAy.js");
3163
+ const { configureLogFileFromEnvironment, logToFile } = await import("./debug-DayHBBST.js");
3164
+ const { wizardAbort, WizardError } = await import("./wizard-abort-DW2-ZjiS.js");
3165
3165
  configureLogFileFromEnvironment();
3166
3166
  const env = readEnvironment();
3167
3167
  const apiKey = options.apiKey ?? readApiKeyFromEnv() ?? void 0;
@@ -3212,7 +3212,7 @@ function runWizardCI(config, options) {
3212
3212
  })
3213
3213
  });
3214
3214
  }
3215
- const { runAgent } = await import("./agent-runner-CGFUXR97.js");
3215
+ const { runAgent } = await import("./agent-runner-Bv-7z-pQ.js");
3216
3216
  await runAgent(config, session);
3217
3217
  } catch (error) {
3218
3218
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -3366,7 +3366,7 @@ async function runDoctorCI(options) {
3366
3366
  getUI().intro("Welcome to the PostHog setup wizard");
3367
3367
  getUI().log.info("Running posthog-doctor in CI mode");
3368
3368
  try {
3369
- const { getOrAskForProjectData } = await import("./setup-utils-DmhPyWkp.js").then((n) => n.r);
3369
+ const { getOrAskForProjectData } = await import("./setup-utils-Dwgkk8AQ.js").then((n) => n.r);
3370
3370
  const { host, accessToken, projectId } = await getOrAskForProjectData({
3371
3371
  signup: false,
3372
3372
  ci: true,
@@ -3383,7 +3383,7 @@ async function runDoctorCI(options) {
3383
3383
  for (const issue of sorted) getUI().log.info(` • [${issue.severity}] ${getKindMeta(issue.kind).title}`);
3384
3384
  process.exit(1);
3385
3385
  } catch (error) {
3386
- const { ApiError } = await import("./api-QI1lO_Bz.js").then((n) => n.n);
3386
+ const { ApiError } = await import("./api-Dwd0B-E9.js").then((n) => n.n);
3387
3387
  const message = error instanceof ApiError && error.statusCode === 401 ? "Your PostHog API key is invalid or expired." : error instanceof Error ? error.message : String(error);
3388
3388
  getUI().log.error(`Doctor failed: ${message}`);
3389
3389
  process.exit(1);
@@ -3462,7 +3462,7 @@ function runSlackConnect(argv) {
3462
3462
  (async () => {
3463
3463
  const debug = argv.debug;
3464
3464
  try {
3465
- const { startTUI } = await import("./start-tui-DaQiY_EB.js");
3465
+ const { startTUI } = await import("./start-tui-SLeEzlJs.js");
3466
3466
  const { buildSession } = await import("./wizard-session-wPJtNl4c.js");
3467
3467
  const tui = startTUI(VERSION, Program.SlackConnect);
3468
3468
  tui.store.session = buildSession({ debug });
@@ -1,6 +1,6 @@
1
- import { h as LoggingUI, m as setUI, p as getUI } from "./debug-D8QAez2V.js";
2
- import { t as provisionNewAccount } from "./provisioning-4zipVpbq.js";
3
- import { n as posthogIntegrationConfig } from "./posthog-integration-mrMF-2IP.js";
1
+ import { h as LoggingUI, m as setUI, p as getUI } from "./debug-CgT5MmVB.js";
2
+ import { t as provisionNewAccount } from "./provisioning-B30Be2NA.js";
3
+ import { n as posthogIntegrationConfig } from "./posthog-integration-BWbZU9Xq.js";
4
4
  import { t as runWizardCI } from "./bin.js";
5
5
  //#region src/commands/basic-integration/ci-install.ts
6
6
  /** CI-mode entry point: validate signup flags, optionally provision an account, then install. */
@@ -70,4 +70,4 @@ async function provisionForSignup(options) {
70
70
  //#endregion
71
71
  export { runCIInstall };
72
72
 
73
- //# sourceMappingURL=ci-install-CXkKR4A-.js.map
73
+ //# sourceMappingURL=ci-install-DGXCpvKh.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ci-install-CXkKR4A-.js","names":[],"sources":["../src/commands/basic-integration/ci-install.ts"],"sourcesContent":["import type { Arguments } from 'yargs';\nimport { getUI, setUI } from '@ui';\nimport { LoggingUI } from '@ui/logging-ui';\nimport { runWizardCI } from '@lib/runners';\nimport { provisionNewAccount } from '@utils/provisioning';\nimport { posthogIntegrationConfig } from '@lib/programs/posthog-integration/index';\n\ntype Options = Arguments & {\n region?: string;\n installDir?: string;\n apiKey?: string;\n signup?: boolean;\n email?: string;\n name?: string;\n projectId?: string;\n};\n\n/** CI-mode entry point: validate signup flags, optionally provision an account, then install. */\nexport function runCIInstall(argv: Arguments): void {\n const options = { ...argv } as Options;\n\n // Base CI validation (region/install-dir/api-key) is owned by runWizardCI.\n // runCIInstall only layers the signup branch on top.\n if (!options.apiKey && !options.signup) {\n return failCI(\n 'CI mode requires --api-key (personal API key phx_xxx). ' +\n 'To create a new account instead, use --signup --email you@example.com.',\n );\n }\n if (!options.apiKey && options.signup && !options.email) {\n return failCI('CI --signup requires --email to create a new account.');\n }\n warnOnUnexpectedKeyPrefix(options.apiKey);\n\n void (async () => {\n if (!options.apiKey && options.signup) {\n // Fail before the irreversible provisioning step rather than after it.\n if (!options.installDir) {\n return failCI(\n 'CI mode requires --install-dir (directory to install in)',\n );\n }\n const provisioned = await provisionForSignup(options);\n options.apiKey = provisioned.personalApiKey;\n if (options.projectId == null) options.projectId = provisioned.projectId;\n }\n runWizardCI(posthogIntegrationConfig, options);\n })().catch(() => {\n process.exit(1);\n });\n}\n\nfunction failCI(message: string): void {\n setUI(new LoggingUI());\n getUI().intro('PostHog Wizard');\n getUI().log.error(message);\n process.exit(1);\n}\n\n/** `phx_` is the personal-API-key prefix the LLM Gateway expects. */\nfunction warnOnUnexpectedKeyPrefix(apiKey: string | undefined): void {\n if (!apiKey || apiKey.startsWith('phx_')) return;\n setUI(new LoggingUI());\n getUI().intro('PostHog Wizard');\n const prefix = apiKey.slice(0, 4);\n const hint =\n prefix === 'pha_'\n ? ' (pha_ is an OAuth access token — CI mode expects a personal API key)'\n : prefix === 'phc_'\n ? ' (phc_ is a project/client key — CI mode expects a personal API key)'\n : '';\n getUI().log.warn(\n `--api-key does not start with \"phx_\"${hint}. Continuing anyway, but the LLM Gateway may reject it with a 401.`,\n );\n}\n\n/**\n * Provision a new account and return its credentials. Throws on any failure\n * (after logging a user-facing message); the caller's `.catch` turns that\n * into a non-zero exit. The return type carries no failure sentinel.\n */\nasync function provisionForSignup(\n options: Options,\n): Promise<{ personalApiKey: string; projectId: string }> {\n setUI(new LoggingUI());\n getUI().intro('PostHog Wizard');\n const signupRegion = ((options.region as string) || 'us').toUpperCase() as\n | 'US'\n | 'EU';\n getUI().log.info(\n `Provisioning new PostHog account for ${String(\n options.email,\n )} in ${signupRegion}...`,\n );\n\n let result;\n try {\n result = await provisionNewAccount(\n options.email as string,\n options.name ?? '',\n signupRegion,\n );\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n getUI().log.error(`Provisioning failed: ${msg}`);\n throw error;\n }\n\n if (!result.personalApiKey) {\n getUI().log.error(\n 'Provisioning succeeded but no personal API key was returned — cannot continue install.',\n );\n throw new Error('provisioning returned no personal API key');\n }\n\n getUI().log.success('Account ready.');\n getUI().log.info(` Project API Key: ${result.projectApiKey}`);\n getUI().log.info(` Personal API Key: ${result.personalApiKey}`);\n getUI().log.info(` Host: ${result.host}`);\n return {\n personalApiKey: result.personalApiKey,\n projectId: result.projectId,\n };\n}\n"],"mappings":";;;;;;AAkBA,SAAgB,aAAa,MAAuB;CAClD,MAAM,UAAU,EAAE,GAAG,MAAM;AAI3B,KAAI,CAAC,QAAQ,UAAU,CAAC,QAAQ,OAC9B,QAAO,OACL,gIAED;AAEH,KAAI,CAAC,QAAQ,UAAU,QAAQ,UAAU,CAAC,QAAQ,MAChD,QAAO,OAAO,wDAAwD;AAExE,2BAA0B,QAAQ,OAAO;AAEzC,EAAM,YAAY;AAChB,MAAI,CAAC,QAAQ,UAAU,QAAQ,QAAQ;AAErC,OAAI,CAAC,QAAQ,WACX,QAAO,OACL,2DACD;GAEH,MAAM,cAAc,MAAM,mBAAmB,QAAQ;AACrD,WAAQ,SAAS,YAAY;AAC7B,OAAI,QAAQ,aAAa,KAAM,SAAQ,YAAY,YAAY;;AAEjE,cAAY,0BAA0B,QAAQ;KAC5C,CAAC,YAAY;AACf,UAAQ,KAAK,EAAE;GACf;;AAGJ,SAAS,OAAO,SAAuB;AACrC,OAAM,IAAI,WAAW,CAAC;AACtB,QAAO,CAAC,MAAM,iBAAiB;AAC/B,QAAO,CAAC,IAAI,MAAM,QAAQ;AAC1B,SAAQ,KAAK,EAAE;;;AAIjB,SAAS,0BAA0B,QAAkC;AACnE,KAAI,CAAC,UAAU,OAAO,WAAW,OAAO,CAAE;AAC1C,OAAM,IAAI,WAAW,CAAC;AACtB,QAAO,CAAC,MAAM,iBAAiB;CAC/B,MAAM,SAAS,OAAO,MAAM,GAAG,EAAE;CACjC,MAAM,OACJ,WAAW,SACP,0EACA,WAAW,SACX,yEACA;AACN,QAAO,CAAC,IAAI,KACV,uCAAuC,KAAK,oEAC7C;;;;;;;AAQH,eAAe,mBACb,SACwD;AACxD,OAAM,IAAI,WAAW,CAAC;AACtB,QAAO,CAAC,MAAM,iBAAiB;CAC/B,MAAM,gBAAiB,QAAQ,UAAqB,MAAM,aAAa;AAGvE,QAAO,CAAC,IAAI,KACV,wCAAwC,OACtC,QAAQ,MACT,CAAC,MAAM,aAAa,KACtB;CAED,IAAI;AACJ,KAAI;AACF,WAAS,MAAM,oBACb,QAAQ,OACR,QAAQ,QAAQ,IAChB,aACD;UACM,OAAO;EACd,MAAM,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;AAClE,SAAO,CAAC,IAAI,MAAM,wBAAwB,MAAM;AAChD,QAAM;;AAGR,KAAI,CAAC,OAAO,gBAAgB;AAC1B,SAAO,CAAC,IAAI,MACV,yFACD;AACD,QAAM,IAAI,MAAM,4CAA4C;;AAG9D,QAAO,CAAC,IAAI,QAAQ,iBAAiB;AACrC,QAAO,CAAC,IAAI,KAAK,uBAAuB,OAAO,gBAAgB;AAC/D,QAAO,CAAC,IAAI,KAAK,uBAAuB,OAAO,iBAAiB;AAChE,QAAO,CAAC,IAAI,KAAK,uBAAuB,OAAO,OAAO;AACtD,QAAO;EACL,gBAAgB,OAAO;EACvB,WAAW,OAAO;EACnB"}
1
+ {"version":3,"file":"ci-install-DGXCpvKh.js","names":[],"sources":["../src/commands/basic-integration/ci-install.ts"],"sourcesContent":["import type { Arguments } from 'yargs';\nimport { getUI, setUI } from '@ui';\nimport { LoggingUI } from '@ui/logging-ui';\nimport { runWizardCI } from '@lib/runners';\nimport { provisionNewAccount } from '@utils/provisioning';\nimport { posthogIntegrationConfig } from '@lib/programs/posthog-integration/index';\n\ntype Options = Arguments & {\n region?: string;\n installDir?: string;\n apiKey?: string;\n signup?: boolean;\n email?: string;\n name?: string;\n projectId?: string;\n};\n\n/** CI-mode entry point: validate signup flags, optionally provision an account, then install. */\nexport function runCIInstall(argv: Arguments): void {\n const options = { ...argv } as Options;\n\n // Base CI validation (region/install-dir/api-key) is owned by runWizardCI.\n // runCIInstall only layers the signup branch on top.\n if (!options.apiKey && !options.signup) {\n return failCI(\n 'CI mode requires --api-key (personal API key phx_xxx). ' +\n 'To create a new account instead, use --signup --email you@example.com.',\n );\n }\n if (!options.apiKey && options.signup && !options.email) {\n return failCI('CI --signup requires --email to create a new account.');\n }\n warnOnUnexpectedKeyPrefix(options.apiKey);\n\n void (async () => {\n if (!options.apiKey && options.signup) {\n // Fail before the irreversible provisioning step rather than after it.\n if (!options.installDir) {\n return failCI(\n 'CI mode requires --install-dir (directory to install in)',\n );\n }\n const provisioned = await provisionForSignup(options);\n options.apiKey = provisioned.personalApiKey;\n if (options.projectId == null) options.projectId = provisioned.projectId;\n }\n runWizardCI(posthogIntegrationConfig, options);\n })().catch(() => {\n process.exit(1);\n });\n}\n\nfunction failCI(message: string): void {\n setUI(new LoggingUI());\n getUI().intro('PostHog Wizard');\n getUI().log.error(message);\n process.exit(1);\n}\n\n/** `phx_` is the personal-API-key prefix the LLM Gateway expects. */\nfunction warnOnUnexpectedKeyPrefix(apiKey: string | undefined): void {\n if (!apiKey || apiKey.startsWith('phx_')) return;\n setUI(new LoggingUI());\n getUI().intro('PostHog Wizard');\n const prefix = apiKey.slice(0, 4);\n const hint =\n prefix === 'pha_'\n ? ' (pha_ is an OAuth access token — CI mode expects a personal API key)'\n : prefix === 'phc_'\n ? ' (phc_ is a project/client key — CI mode expects a personal API key)'\n : '';\n getUI().log.warn(\n `--api-key does not start with \"phx_\"${hint}. Continuing anyway, but the LLM Gateway may reject it with a 401.`,\n );\n}\n\n/**\n * Provision a new account and return its credentials. Throws on any failure\n * (after logging a user-facing message); the caller's `.catch` turns that\n * into a non-zero exit. The return type carries no failure sentinel.\n */\nasync function provisionForSignup(\n options: Options,\n): Promise<{ personalApiKey: string; projectId: string }> {\n setUI(new LoggingUI());\n getUI().intro('PostHog Wizard');\n const signupRegion = ((options.region as string) || 'us').toUpperCase() as\n | 'US'\n | 'EU';\n getUI().log.info(\n `Provisioning new PostHog account for ${String(\n options.email,\n )} in ${signupRegion}...`,\n );\n\n let result;\n try {\n result = await provisionNewAccount(\n options.email as string,\n options.name ?? '',\n signupRegion,\n );\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n getUI().log.error(`Provisioning failed: ${msg}`);\n throw error;\n }\n\n if (!result.personalApiKey) {\n getUI().log.error(\n 'Provisioning succeeded but no personal API key was returned — cannot continue install.',\n );\n throw new Error('provisioning returned no personal API key');\n }\n\n getUI().log.success('Account ready.');\n getUI().log.info(` Project API Key: ${result.projectApiKey}`);\n getUI().log.info(` Personal API Key: ${result.personalApiKey}`);\n getUI().log.info(` Host: ${result.host}`);\n return {\n personalApiKey: result.personalApiKey,\n projectId: result.projectId,\n };\n}\n"],"mappings":";;;;;;AAkBA,SAAgB,aAAa,MAAuB;CAClD,MAAM,UAAU,EAAE,GAAG,MAAM;AAI3B,KAAI,CAAC,QAAQ,UAAU,CAAC,QAAQ,OAC9B,QAAO,OACL,gIAED;AAEH,KAAI,CAAC,QAAQ,UAAU,QAAQ,UAAU,CAAC,QAAQ,MAChD,QAAO,OAAO,wDAAwD;AAExE,2BAA0B,QAAQ,OAAO;AAEzC,EAAM,YAAY;AAChB,MAAI,CAAC,QAAQ,UAAU,QAAQ,QAAQ;AAErC,OAAI,CAAC,QAAQ,WACX,QAAO,OACL,2DACD;GAEH,MAAM,cAAc,MAAM,mBAAmB,QAAQ;AACrD,WAAQ,SAAS,YAAY;AAC7B,OAAI,QAAQ,aAAa,KAAM,SAAQ,YAAY,YAAY;;AAEjE,cAAY,0BAA0B,QAAQ;KAC5C,CAAC,YAAY;AACf,UAAQ,KAAK,EAAE;GACf;;AAGJ,SAAS,OAAO,SAAuB;AACrC,OAAM,IAAI,WAAW,CAAC;AACtB,QAAO,CAAC,MAAM,iBAAiB;AAC/B,QAAO,CAAC,IAAI,MAAM,QAAQ;AAC1B,SAAQ,KAAK,EAAE;;;AAIjB,SAAS,0BAA0B,QAAkC;AACnE,KAAI,CAAC,UAAU,OAAO,WAAW,OAAO,CAAE;AAC1C,OAAM,IAAI,WAAW,CAAC;AACtB,QAAO,CAAC,MAAM,iBAAiB;CAC/B,MAAM,SAAS,OAAO,MAAM,GAAG,EAAE;CACjC,MAAM,OACJ,WAAW,SACP,0EACA,WAAW,SACX,yEACA;AACN,QAAO,CAAC,IAAI,KACV,uCAAuC,KAAK,oEAC7C;;;;;;;AAQH,eAAe,mBACb,SACwD;AACxD,OAAM,IAAI,WAAW,CAAC;AACtB,QAAO,CAAC,MAAM,iBAAiB;CAC/B,MAAM,gBAAiB,QAAQ,UAAqB,MAAM,aAAa;AAGvE,QAAO,CAAC,IAAI,KACV,wCAAwC,OACtC,QAAQ,MACT,CAAC,MAAM,aAAa,KACtB;CAED,IAAI;AACJ,KAAI;AACF,WAAS,MAAM,oBACb,QAAQ,OACR,QAAQ,QAAQ,IAChB,aACD;UACM,OAAO;EACd,MAAM,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;AAClE,SAAO,CAAC,IAAI,MAAM,wBAAwB,MAAM;AAChD,QAAM;;AAGR,KAAI,CAAC,OAAO,gBAAgB;AAC1B,SAAO,CAAC,IAAI,MACV,yFACD;AACD,QAAM,IAAI,MAAM,4CAA4C;;AAG9D,QAAO,CAAC,IAAI,QAAQ,iBAAiB;AACrC,QAAO,CAAC,IAAI,KAAK,uBAAuB,OAAO,gBAAgB;AAC/D,QAAO,CAAC,IAAI,KAAK,uBAAuB,OAAO,iBAAiB;AAChE,QAAO,CAAC,IAAI,KAAK,uBAAuB,OAAO,OAAO;AACtD,QAAO;EACL,gBAAgB,OAAO;EACvB,WAAW,OAAO;EACnB"}
@@ -28,7 +28,7 @@ function runtimeEnv(key) {
28
28
  }
29
29
  //#endregion
30
30
  //#region src/lib/version.ts
31
- const VERSION = "2.22.0";
31
+ const VERSION = "2.23.0";
32
32
  //#endregion
33
33
  //#region src/lib/constants.ts
34
34
  /**
@@ -286,9 +286,23 @@ function mapComponentStatus(status) {
286
286
  default: return "degraded";
287
287
  }
288
288
  }
289
- function errResult(error) {
289
+ /**
290
+ * Build an error result for fetch failures. The kind matters for
291
+ * downstream reconciliation:
292
+ *
293
+ * - 'http' (incident.io returned a bad status code) → `Down`. We
294
+ * reached the status page but it told us something is wrong on
295
+ * its side. We have a definitive response.
296
+ * - 'network' (timeout, DNS failure, TCP/TLS failure) → `NoConnection`.
297
+ * We never reached the status page. Treating this as `Degraded`
298
+ * (the previous behavior) silently flipped the reconciliation in
299
+ * `readiness.ts` from "soft" to "confirmed outage" whenever the
300
+ * user's own network was flaky — exactly the false positive this
301
+ * module is meant to help diagnose.
302
+ */
303
+ function errResult(error, kind) {
290
304
  return {
291
- status: "degraded",
305
+ status: kind === "http" ? "down" : "no-connection",
292
306
  error
293
307
  };
294
308
  }
@@ -300,7 +314,7 @@ async function fetchPosthogStatus(timeoutMs = 5e3) {
300
314
  const res = await fetch(POSTHOG_STATUS_URL, { signal: controller.signal });
301
315
  clearTimeout(tid);
302
316
  if (!res.ok) {
303
- const err = errResult(`HTTP ${res.status}`);
317
+ const err = errResult(`HTTP ${res.status}`, "http");
304
318
  return {
305
319
  overall: err,
306
320
  components: err
@@ -333,13 +347,13 @@ async function fetchPosthogStatus(timeoutMs = 5e3) {
333
347
  };
334
348
  } catch (e) {
335
349
  if (e instanceof Error && e.name === "AbortError") {
336
- const err = errResult("Request timed out");
350
+ const err = errResult("Request timed out", "network");
337
351
  return {
338
352
  overall: err,
339
353
  components: err
340
354
  };
341
355
  }
342
- const err = errResult(e instanceof Error ? e.message : "Unknown error");
356
+ const err = errResult(e instanceof Error ? e.message : "Unknown error", "network");
343
357
  return {
344
358
  overall: err,
345
359
  components: err
@@ -355,33 +369,73 @@ const checkPosthogOverallHealth = async () => (await getPosthogHealth()).overall
355
369
  const checkPosthogComponentHealth = async () => (await getPosthogHealth()).components;
356
370
  //#endregion
357
371
  //#region src/lib/health-checks/endpoints.ts
372
+ function noConnectionResult(error, attempts) {
373
+ return {
374
+ status: "no-connection",
375
+ error,
376
+ rawIndicator: attempts > 1 ? `attempts=${attempts}` : void 0
377
+ };
378
+ }
358
379
  function downResult(error) {
359
380
  return {
360
381
  status: "down",
361
382
  error
362
383
  };
363
384
  }
385
+ const RETRY_BACKOFFS_MS = [500, 2e3];
386
+ async function attemptFetch(url, timeoutMs, redirect) {
387
+ const controller = new AbortController();
388
+ const tid = setTimeout(() => controller.abort(), timeoutMs);
389
+ try {
390
+ const res = await fetch(url, {
391
+ signal: controller.signal,
392
+ redirect
393
+ });
394
+ clearTimeout(tid);
395
+ return {
396
+ kind: "response",
397
+ res
398
+ };
399
+ } catch (e) {
400
+ clearTimeout(tid);
401
+ const err = e instanceof Error ? e : /* @__PURE__ */ new Error("Unknown error");
402
+ return {
403
+ kind: "error",
404
+ error: err,
405
+ timedOut: err.name === "AbortError"
406
+ };
407
+ }
408
+ }
364
409
  async function fetchEndpointHealth(url, timeoutMs = 5e3, isExpectedStatus = (s) => s === 200, redirect = "follow") {
365
- const result = await (async () => {
366
- try {
367
- const controller = new AbortController();
368
- const tid = setTimeout(() => controller.abort(), timeoutMs);
369
- const res = await fetch(url, {
370
- signal: controller.signal,
371
- redirect
372
- });
373
- clearTimeout(tid);
374
- if (isExpectedStatus(res.status)) return {
375
- status: "healthy",
376
- rawIndicator: `HTTP ${res.status}`
377
- };
378
- return downResult(`HTTP ${res.status}`);
379
- } catch (e) {
380
- if (e instanceof Error && e.name === "AbortError") return downResult(`Request timed out after ${timeoutMs}ms`);
381
- return downResult(e instanceof Error ? e.message : "Unknown error");
410
+ let lastHttpStatus = null;
411
+ let lastError = "Unknown error";
412
+ let attempts = 0;
413
+ for (let i = 0; i <= RETRY_BACKOFFS_MS.length; i++) {
414
+ if (i > 0) {
415
+ const wait = RETRY_BACKOFFS_MS[i - 1];
416
+ logToFile(`[health-checks] retry ${i}/${RETRY_BACKOFFS_MS.length} for ${url} in ${wait}ms (last: ${lastError})`);
417
+ await new Promise((r) => setTimeout(r, wait));
418
+ }
419
+ attempts++;
420
+ const outcome = await attemptFetch(url, timeoutMs, redirect);
421
+ if (outcome.kind === "response") {
422
+ const res = outcome.res;
423
+ if (isExpectedStatus(res.status)) {
424
+ const result = {
425
+ status: "healthy",
426
+ rawIndicator: attempts > 1 ? `HTTP ${res.status} (attempts=${attempts})` : `HTTP ${res.status}`
427
+ };
428
+ logToFile(`[health-checks] GET ${url} -> ${result.status} (${result.rawIndicator})`);
429
+ return result;
430
+ }
431
+ lastHttpStatus = res.status;
432
+ lastError = `HTTP ${res.status}`;
433
+ continue;
382
434
  }
383
- })();
384
- logToFile(`[health-checks] GET ${url} -> ${result.status}${result.rawIndicator ? ` (${result.rawIndicator})` : ""}${result.error ? ` (${result.error})` : ""}`);
435
+ lastError = outcome.timedOut ? `Request timed out after ${timeoutMs}ms` : outcome.error.message;
436
+ }
437
+ const result = lastHttpStatus !== null ? downResult(`HTTP ${lastHttpStatus} (attempts=${attempts})`) : noConnectionResult(lastError, attempts);
438
+ logToFile(`[health-checks] GET ${url} -> ${result.status} (attempts=${attempts}, ${result.error})`);
385
439
  return result;
386
440
  }
387
441
  const checkLlmGatewayHealth = () => fetchEndpointHealth("https://gateway.us.posthog.com/_liveness");
@@ -437,7 +491,7 @@ async function checkAllExternalServices() {
437
491
  checkMcpHealth(),
438
492
  checkGithubReleasesHealth()
439
493
  ]);
440
- return {
494
+ return reconcilePosthogReachability({
441
495
  anthropic,
442
496
  posthogOverall,
443
497
  posthogComponents,
@@ -449,6 +503,51 @@ async function checkAllExternalServices() {
449
503
  llmGateway,
450
504
  mcp,
451
505
  githubReleases
506
+ });
507
+ }
508
+ /**
509
+ * When a PostHog-owned endpoint probe returns `NoConnection`, decide
510
+ * whether it's a real outage or a likely-local issue by checking the
511
+ * official status page (`posthogstatus.com`):
512
+ *
513
+ * - Status page says PostHog is `Down` / `Degraded` → upgrade
514
+ * llmGateway / mcp to `Down`. The status page corroborates.
515
+ * - Status page is `Healthy` → keep `NoConnection`. The status page
516
+ * contradicts; this is probably the user's network.
517
+ * - Status page is also `NoConnection` → keep `NoConnection`. User
518
+ * can't reach two independent PostHog properties; almost
519
+ * certainly their network. (This case relies on incidentio.ts
520
+ * correctly emitting `NoConnection` for fetch failures rather
521
+ * than the previous `Degraded`, which used to silently flip the
522
+ * reconciliation into a false positive.)
523
+ *
524
+ * Why `Degraded` corroborates: a `Degraded` reading here only fires
525
+ * when incident.io's API parsed successfully and reported a real
526
+ * `partial_outage` or `degraded_performance` for some component. That's
527
+ * PostHog acknowledging an issue, even if narrower than a full outage.
528
+ * If our gateway probe is also failing, those two signals together
529
+ * justify pointing at PostHog rather than the user.
530
+ *
531
+ * A narrower variant — only corroborate when the affected component is
532
+ * gateway-related (LLM, US/EU Cloud, app) — would be more precise. We
533
+ * have the data in `posthogComponents` but don't use it here. If the
534
+ * analytics show false positives concentrated in this case, it's a
535
+ * cheap follow-up.
536
+ *
537
+ * Mutates a copy of `health` and returns it.
538
+ */
539
+ function reconcilePosthogReachability(health) {
540
+ const posthogStatus = health.posthogOverall.status;
541
+ if (!(posthogStatus === "down" || posthogStatus === "degraded")) return health;
542
+ const upgrade = (r) => r.status === "no-connection" ? {
543
+ ...r,
544
+ status: "down",
545
+ error: r.error ? `${r.error} (corroborated by status page)` : "corroborated by status page"
546
+ } : r;
547
+ return {
548
+ ...health,
549
+ llmGateway: upgrade(health.llmGateway),
550
+ mcp: upgrade(health.mcp)
452
551
  };
453
552
  }
454
553
  function describeResult(label, h) {
@@ -465,7 +564,7 @@ function describeComponents(label, h) {
465
564
  const suffix = affected.length > MAX_COMPONENT_NAMES ? `, +${affected.length - MAX_COMPONENT_NAMES} more` : "";
466
565
  return `${label} components impacted: ${shown.join(", ")}${suffix}`;
467
566
  }
468
- const READINESS_TIMEOUT_MS = 1e4;
567
+ const READINESS_TIMEOUT_MS = 2e4;
469
568
  async function evaluateWizardReadiness(config = DEFAULT_WIZARD_READINESS_CONFIG) {
470
569
  try {
471
570
  const health = await Promise.race([checkAllExternalServices(), new Promise((resolve) => setTimeout(() => resolve(allUnknown("Health check timed out")), READINESS_TIMEOUT_MS))]);
@@ -515,12 +614,17 @@ const COMPONENT_KEYS = [
515
614
  ];
516
615
  /**
517
616
  * Get the keys of services that would block a wizard run per the given config.
617
+ *
618
+ * `NoConnection` blocks the same services as `Down` — the wizard genuinely
619
+ * can't continue if it can't reach the gateway. The screen shows softer
620
+ * framing in that case (HealthCheckScreen) so we don't falsely accuse
621
+ * PostHog of an outage when the user's network is the likely cause.
518
622
  */
519
623
  function getBlockingServiceKeys(health, config = DEFAULT_WIZARD_READINESS_CONFIG) {
520
624
  return Object.keys(health).filter((key) => {
521
625
  if (COMPONENT_KEYS.includes(key)) return false;
522
626
  const result = health[key];
523
- if (config.downBlocksRun.includes(key) && result.status === "down") return true;
627
+ if (config.downBlocksRun.includes(key) && (result.status === "down" || result.status === "no-connection")) return true;
524
628
  if ((config.degradedBlocksRun ?? []).includes(key) && result.status !== "healthy") return true;
525
629
  return false;
526
630
  });
@@ -765,4 +869,4 @@ function enableDebugLogs() {
765
869
  //#endregion
766
870
  export { VERSION as $, OAUTH_PORTS as A, POSTHOG_PROXY_CLIENT_ID as B, CONTEXT_MILL_RELEASES_URL as C, DUMMY_PROJECT_API_KEY as D, DETECTION_TIMEOUT_MS as E, POSTHOG_FLAG_HEADER_PREFIX as F, WIZARD_OAUTH_SCOPES as G, POSTHOG_US_CLIENT_ID as H, POSTHOG_OAUTH_URL as I, WIZARD_TOOLS_MENU_FLAG_KEY as J, WIZARD_PROVISIONING_SCOPES as K, POSTHOG_ORG_AI_SETTINGS_URL as L, POSTHOG_APP_URL as M, POSTHOG_DEV_CLIENT_ID as N, ISSUES_URL as O, POSTHOG_DOCS_URL as P, getSkillsBaseUrl as Q, POSTHOG_PRIVACY_URL as R, ANALYTICS_TEAM_TAG as S, DEFAULT_HOST_URL as T, REMOTE_SKILLS_BASE_URL as U, POSTHOG_TERMS_URL as V, WIZARD_INTERACTION_EVENT_NAME as W, WIZARD_VARIANTS as X, WIZARD_USER_AGENT as Y, WIZARD_VARIANT_FLAG_KEY as Z, SIGNUP_WIZARD_READINESS_CONFIG as _, getLogFilePath as a, ANALYTICS_HOST_URL as b, WIZARD_BENCHMARK_FILE as c, relativeToInstallDir as d, NODE_ENV as et, skillTmpPath as f, SERVICE_LABELS as g, LoggingUI as h, enableDebugLogs as i, OAUTH_TIMEOUT_MS as j, Integration as k, WIZARD_LOG_FILE as l, setUI as m, configureLogFileFromEnvironment as n, initLogFile as o, getUI as p, WIZARD_REMARK_EVENT_NAME as q, debug as r, logToFile as s, configureLogFile as t, runtimeEnv as tt, WIZARD_YARA_REPORT_FILE as u, evaluateWizardReadiness as v, CONTEXT_MILL_URL as w, ANALYTICS_POSTHOG_PUBLIC_PROJECT_WRITE_KEY as x, getBlockingServiceKeys as y, POSTHOG_PROPERTY_HEADER_PREFIX as z };
767
871
 
768
- //# sourceMappingURL=debug-D8QAez2V.js.map
872
+ //# sourceMappingURL=debug-CgT5MmVB.js.map