@posthog/wizard 2.24.0 → 2.25.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 (66) hide show
  1. package/dist/{AiOptInRequiredScreen-DPn1CCeD.js → AiOptInRequiredScreen-C-D9tN6r.js} +156 -124
  2. package/dist/AiOptInRequiredScreen-C-D9tN6r.js.map +1 -0
  3. package/dist/{add-mcp-server-to-clients-BU8Owthq.js → add-mcp-server-to-clients-t0xe8gn1.js} +4 -4
  4. package/dist/{add-mcp-server-to-clients-BU8Owthq.js.map → add-mcp-server-to-clients-t0xe8gn1.js.map} +1 -1
  5. package/dist/{agent-interface-CysYcZl5.js → agent-interface-BsuUUPle.js} +403 -40
  6. package/dist/agent-interface-BsuUUPle.js.map +1 -0
  7. package/dist/{agent-runner-Br0OxBxd.js → agent-runner-L_-kJ3y3.js} +624 -17
  8. package/dist/agent-runner-L_-kJ3y3.js.map +1 -0
  9. package/dist/{analytics-BOWrR4qd.js → analytics-CDOujOSQ.js} +51 -17
  10. package/dist/analytics-CDOujOSQ.js.map +1 -0
  11. package/dist/{api-RXTR8yZo.js → api-DNS-L-1U.js} +3 -3
  12. package/dist/{api-RXTR8yZo.js.map → api-DNS-L-1U.js.map} +1 -1
  13. package/dist/bin.js +291 -75
  14. package/dist/bin.js.map +1 -1
  15. package/dist/{ci-install-BscZ60Ec.js → ci-install-_9A7tL36.js} +4 -4
  16. package/dist/{ci-install-BscZ60Ec.js.map → ci-install-_9A7tL36.js.map} +1 -1
  17. package/dist/{debug-BUdVZP84.js → debug-BwC7UkGH.js} +16 -8
  18. package/dist/debug-BwC7UkGH.js.map +1 -0
  19. package/dist/{debug-BgH07S-e.js → debug-CZQcMAJT.js} +1 -1
  20. package/dist/{environment-G0Hv6_JI.js → environment-DQPoj9sU.js} +3 -3
  21. package/dist/{environment-G0Hv6_JI.js.map → environment-DQPoj9sU.js.map} +1 -1
  22. package/dist/{interactive-fh2iyewb.js → interactive-DT5dLd7N.js} +2 -2
  23. package/dist/{interactive-fh2iyewb.js.map → interactive-DT5dLd7N.js.map} +1 -1
  24. package/dist/{mcp-prompt-streaming-DUtbxnNy.js → mcp-prompt-streaming-CBMr458Q.js} +7 -26
  25. package/dist/mcp-prompt-streaming-CBMr458Q.js.map +1 -0
  26. package/dist/{non-interactive-BfqXlY8R.js → non-interactive-csP4yGdA.js} +2 -2
  27. package/dist/{non-interactive-BfqXlY8R.js.map → non-interactive-csP4yGdA.js.map} +1 -1
  28. package/dist/{package-manager-Ca1maxU-.js → package-manager-CB4c2euf.js} +2 -2
  29. package/dist/{package-manager-Ca1maxU-.js.map → package-manager-CB4c2euf.js.map} +1 -1
  30. package/dist/{playground-4sqLVVJL.js → playground-C-lpKoKC.js} +9 -15
  31. package/dist/playground-C-lpKoKC.js.map +1 -0
  32. package/dist/{posthog-integration-Bz3HWkHn.js → posthog-integration-BL8-vC0V.js} +18 -18
  33. package/dist/{posthog-integration-Bz3HWkHn.js.map → posthog-integration-BL8-vC0V.js.map} +1 -1
  34. package/dist/{provisioning-CgwvlsIl.js → provisioning-DLOiFSM9.js} +3 -3
  35. package/dist/{provisioning-CgwvlsIl.js.map → provisioning-DLOiFSM9.js.map} +1 -1
  36. package/dist/{registry-CEnQVctL.js → registry-BbRzCV5l.js} +4 -4
  37. package/dist/{registry-CEnQVctL.js.map → registry-BbRzCV5l.js.map} +1 -1
  38. package/dist/{setup-utils-Doh69vo4.js → setup-utils-D87CyNkw.js} +8 -8
  39. package/dist/{setup-utils-Doh69vo4.js.map → setup-utils-D87CyNkw.js.map} +1 -1
  40. package/dist/smoke-test.sh +36 -1
  41. package/dist/{start-tui-CywbSvZE.js → start-tui-DnAG57vY.js} +16 -20
  42. package/dist/start-tui-DnAG57vY.js.map +1 -0
  43. package/dist/{steps-DJojDYQ-.js → steps-JaxH6u0f.js} +6 -6
  44. package/dist/{steps-DJojDYQ-.js.map → steps-JaxH6u0f.js.map} +1 -1
  45. package/dist/{task-stream-CZawuzlz.js → task-stream-BQNSp0qR.js} +4 -3
  46. package/dist/task-stream-BQNSp0qR.js.map +1 -0
  47. package/dist/{telemetry-8zMpaIuK.js → telemetry-DL28cCwY.js} +3 -3
  48. package/dist/{telemetry-8zMpaIuK.js.map → telemetry-DL28cCwY.js.map} +1 -1
  49. package/dist/{urls-BUfvQmU4.js → urls-vkJ5c0ix.js} +2 -2
  50. package/dist/{urls-BUfvQmU4.js.map → urls-vkJ5c0ix.js.map} +1 -1
  51. package/dist/{wizard-abort-Ni-mKJ58.js → wizard-abort-BRXKRL4F.js} +1 -1
  52. package/dist/{wizard-abort-BdGW4Tvi.js → wizard-abort-CLGgMAEe.js} +3 -3
  53. package/dist/{wizard-abort-BdGW4Tvi.js.map → wizard-abort-CLGgMAEe.js.map} +1 -1
  54. package/dist/{wizard-ui-YdGFRyu_.js → wizard-ui-WZ48rUgr.js} +2 -1
  55. package/dist/wizard-ui-WZ48rUgr.js.map +1 -0
  56. package/package.json +1 -1
  57. package/dist/AiOptInRequiredScreen-DPn1CCeD.js.map +0 -1
  58. package/dist/agent-interface-CysYcZl5.js.map +0 -1
  59. package/dist/agent-runner-Br0OxBxd.js.map +0 -1
  60. package/dist/analytics-BOWrR4qd.js.map +0 -1
  61. package/dist/debug-BUdVZP84.js.map +0 -1
  62. package/dist/mcp-prompt-streaming-DUtbxnNy.js.map +0 -1
  63. package/dist/playground-4sqLVVJL.js.map +0 -1
  64. package/dist/start-tui-CywbSvZE.js.map +0 -1
  65. package/dist/task-stream-CZawuzlz.js.map +0 -1
  66. package/dist/wizard-ui-YdGFRyu_.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"api-RXTR8yZo.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-DNS-L-1U.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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkBA,MAAa,gBAAgB,EAC1B,OAAO;CAEN,aAAa,EAAE,QAAQ;CACvB,MAAM,EAAE,QAAQ,CAAC,SAAS;CAC1B,IAAI,EAAE,QAAQ,CAAC,SAAS;CAGxB,OAAO,EAAE,QAAQ,CAAC,SAAS;CAC3B,YAAY,EAAE,QAAQ,CAAC,SAAS;CAChC,WAAW,EAAE,QAAQ,CAAC,SAAS;CAC/B,aAAa,EAAE,QAAQ,CAAC,SAAS;CACjC,mBAAmB,EAAE,SAAS,CAAC,SAAS;CACxC,gBAAgB,EAAE,SAAS,CAAC,SAAS;CACrC,UAAU,EAAE,SAAS,CAAC,SAAS;CAG/B,YAAY,EAAE,QAAQ,CAAC,SAAS;CAChC,cAAc,EAAE,QAAQ,CAAC,SAAS;CAClC,gBAAgB,EAAE,SAAS,CAAC,SAAS;CAKrC,sBAAsB,EAAE,QAAQ,CAAC,SAAS;CAI1C,MAAM,EACH,OAAO;EACN,IAAI,EAAE,QAAQ;EACd,MAAM,EAAE,QAAQ,CAAC,SAAS;EAC1B,cAAc,EAAE,QAAQ,CAAC,MAAM;EAC/B,WAAW,EAAE,QAAQ,CAAC,SAAS;EAC/B,YAAY,EAAE,QAAQ,CAAC,SAAS;EAChC,MAAM,EAAE,QAAQ,CAAC,SAAS;EAC1B,UAAU,EAAE,QAAQ,CAAC,SAAS;EAC/B,CAAC,CACD,aAAa;CAChB,cAAc,EACX,OAAO;EACN,IAAI,EAAE,QAAQ,CAAC,MAAM;EACrB,MAAM,EAAE,QAAQ,CAAC,SAAS;EAC1B,MAAM,EAAE,QAAQ,CAAC,SAAS;EAC1B,kBAAkB,EAAE,QAAQ,CAAC,SAAS;EACtC,aAAa,EAAE,QAAQ,CAAC,SAAS;EAClC,CAAC,CACD,aAAa;CAChB,eAAe,EAAE,MACf,EACG,OAAO;EACN,IAAI,EAAE,QAAQ,CAAC,MAAM;EACrB,MAAM,EAAE,QAAQ,CAAC,SAAS;EAC1B,kBAAkB,EAAE,QAAQ,CAAC,SAAS;EACvC,CAAC,CACD,aAAa,CACjB;CACF,CAAC,CACD,aAAa;;;;;;;;;;;;AAahB,MAAa,yBAAyB,EACnC,OAAO;CACN,OAAO,EAAE,QAAQ,CAAC,SAAS;CAC3B,UAAU,EAAE,QAAQ,CAAC,SAAS;CAC9B,YAAY,EAAE,QAAQ,CAAC,SAAS;CACjC,CAAC,CACD,aAAa;AAGyB,EAAE,OAAO,EAChD,SAAS,EAAE,MAAM,uBAAuB,EACzC,CAAC;AAKF,MAAa,mBAAmB,EAAE,OAAO;CACvC,IAAI,EAAE,QAAQ;CACd,MAAM,EAAE,QAAQ,CAAC,MAAM;CACvB,cAAc,EAAE,QAAQ,CAAC,MAAM;CAC/B,WAAW,EAAE,QAAQ;CACrB,MAAM,EAAE,QAAQ;CACjB,CAAC;AAKF,IAAa,WAAb,cAA8B,MAAM;CAClC,YACE,SACA,YACA,UACA;AACA,QAAM,QAAQ;AAHE,OAAA,aAAA;AACA,OAAA,WAAA;AAGhB,OAAK,OAAO;;;AAIhB,eAAsB,cACpB,aACA,SACkB;AAClB,KAAI;EACF,MAAM,WAAW,MAAM,MAAM,IAAI,GAAG,QAAQ,kBAAkB,EAC5D,SAAS;GACP,eAAe,UAAU;GACzB,cAAc;GACf,EACF,CAAC;AAEF,SAAO,cAAc,MAAM,SAAS,KAAK;UAClC,OAAO;EACd,MAAM,WAAW,eAAe,OAAO,kBAAkB;AACzD,YAAU,iBAAiB,UAAU;GACnC,UAAU;GACV;GACD,CAAC;AACF,QAAM;;;AA+CV,eAAsB,iBACpB,aACA,WACA,SACqB;AACrB,KAAI;EACF,MAAM,WAAW,MAAM,MAAM,IAAI,GAAG,QAAQ,gBAAgB,UAAU,IAAI,EACxE,SAAS;GACP,eAAe,UAAU;GACzB,cAAc;GACf,EACF,CAAC;AAEF,SAAO,iBAAiB,MAAM,SAAS,KAAK;UACrC,OAAO;EACd,MAAM,WAAW,eAAe,OAAO,qBAAqB;AAC5D,YAAU,iBAAiB,UAAU;GACnC,UAAU,iBAAiB,UAAU;GACrC;GACA;GACD,CAAC;AACF,QAAM;;;;AAKV,MAAM,6BAA6B,EAAE,OAAO,EAC1C,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC,aAAa,CAAC,EACzE,CAAC;;;;;;;AAQF,eAAsB,oBACpB,aACA,WACA,SACA,QACkB;CAClB,MAAM,WAAW,MAAM,MAAM,IAC3B,GAAG,QAAQ,gBAAgB,UAAU,iBACrC;EACE,SAAS;GACP,eAAe,UAAU;GACzB,cAAc;GACf;EACD;EACD,CACF;CACD,MAAM,SAAS,2BAA2B,UAAU,SAAS,KAAK;AAClE,KAAI,CAAC,OAAO,QAAS,QAAO;AAC5B,QAAO,OAAO,KAAK,QAAQ,MAAM,MAAM,EAAE,SAAS,QAAQ;;AAG5D,SAAgB,eAAe,OAAgB,WAA6B;AAC1E,KAAI,MAAM,aAAa,MAAM,EAAE;EAC7B,MAAM,aAAa;EACnB,MAAM,SAAS,WAAW,UAAU;EACpC,MAAM,SAAS,WAAW,UAAU,MAAM;EAC1C,MAAM,WAAW,WAAW,QAAQ;AAEpC,MAAI,WAAW,IACb,QAAO,IAAI,SACT,yCAAyC,aACzC,QACA,SACD;AAGH,MAAI,WAAW,IACb,QAAO,IAAI,SACT,iCAAiC,aACjC,QACA,SACD;AAGH,MAAI,WAAW,IACb,QAAO,IAAI,SACT,sCAAsC,aACtC,QACA,SACD;AAIH,SAAO,IAAI,SADK,UAAU,aAAa,aACV,QAAQ,SAAS;;AAGhD,KAAI,iBAAiB,EAAE,SACrB,QAAO,IAAI,SAAS,2CAA2C,YAAY;AAG7E,QAAO,IAAI,SACT,oCAAoC,UAAU,IAC5C,iBAAiB,QAAQ,MAAM,UAAU,kBAE5C"}
package/dist/bin.js CHANGED
@@ -1,16 +1,16 @@
1
1
  #!/usr/bin/env node
2
- import { $ as VERSION, P as POSTHOG_DOCS_URL, Q as getSkillsBaseUrl, 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-BUdVZP84.js";
3
- import { t as analytics } from "./analytics-BOWrR4qd.js";
4
- import { r as setEntryCommand } from "./telemetry-8zMpaIuK.js";
5
- import { n as isUsingTypeScript, t as getOrAskForProjectData } from "./setup-utils-Doh69vo4.js";
6
- import { a as getUiHostFromHost, n as getCloudUrlFromRegion } from "./urls-BUfvQmU4.js";
7
- import { o as handleApiError } from "./api-RXTR8yZo.js";
2
+ import { $ as getSkillsBaseUrl, P as POSTHOG_DOCS_URL, X as WIZARD_USER_AGENT, _ as SIGNUP_WIZARD_READINESS_CONFIG, a as getLogFilePath, et as VERSION, h as LoggingUI, m as setUI, p as getUI, r as debug, s as logToFile, v as evaluateWizardReadiness, y as getBlockingServiceKeys } from "./debug-BwC7UkGH.js";
3
+ import { t as analytics } from "./analytics-CDOujOSQ.js";
4
+ import { r as setEntryCommand } from "./telemetry-DL28cCwY.js";
5
+ import { n as isUsingTypeScript } from "./setup-utils-D87CyNkw.js";
6
+ import { a as getUiHostFromHost, n as getCloudUrlFromRegion } from "./urls-vkJ5c0ix.js";
7
+ import { o as handleApiError } from "./api-DNS-L-1U.js";
8
8
  import "./wizard-session-G3VWD6hv.js";
9
- import { r as runCleanups } from "./wizard-abort-BdGW4Tvi.js";
10
- import { n as isNonInteractiveEnvironment } from "./environment-G0Hv6_JI.js";
11
- import { _ as AUDIT_CHECKS_KEY, f as WIZARD_TOOL_NAMES, g as AUDIT_CHECKS_FILE, l as AgentSignals, m as fetchSkillMenu, s as recoverOrphanedSettingsBackups, v as AUDIT_REPORT_FILE } from "./agent-interface-CysYcZl5.js";
12
- import { i as SPINNER_MESSAGE } from "./registry-CEnQVctL.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, p as Icons, r as FUNNEL_BLOCK } from "./posthog-integration-Bz3HWkHn.js";
9
+ import { r as runCleanups } from "./wizard-abort-CLGgMAEe.js";
10
+ import { n as isNonInteractiveEnvironment } from "./environment-DQPoj9sU.js";
11
+ import { S as AUDIT_REPORT_FILE, b as AUDIT_CHECKS_FILE, c as recoverOrphanedSettingsBackups, h as fetchSkillMenu, p as WIZARD_TOOL_NAMES, u as AgentSignals, x as AUDIT_CHECKS_KEY } from "./agent-interface-BsuUUPle.js";
12
+ import { i as SPINNER_MESSAGE } from "./registry-BbRzCV5l.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, p as Icons, r as FUNNEL_BLOCK } from "./posthog-integration-BL8-vC0V.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";
@@ -18,11 +18,16 @@ import yargs from "yargs";
18
18
  import { hideBin } from "yargs/helpers";
19
19
  import fs, { existsSync, readFileSync, readdirSync, statSync } from "fs";
20
20
  import path, { join, relative } from "path";
21
+ import * as os from "node:os";
22
+ import * as path$1 from "node:path";
23
+ import { spawnSync } from "node:child_process";
24
+ import * as fs$1 from "node:fs";
21
25
  import axios from "axios";
22
26
  import { z } from "zod";
23
27
  import { Box, Text, render, useInput } from "ink";
24
28
  import { createContext, createElement, useCallback, useContext, useEffect, useRef, useState } from "react";
25
29
  import { jsx, jsxs } from "react/jsx-runtime";
30
+ import * as readline from "node:readline/promises";
26
31
  //#region src/commands/command.ts
27
32
  /** Extract the bare command word(s) from a yargs name spec, dropping positionals and aliases' arg syntax. */
28
33
  function commandKeys(name) {
@@ -184,7 +189,7 @@ function runProvision(argv) {
184
189
  }
185
190
  async function provision({ email, region, name, jsonMode }) {
186
191
  try {
187
- const { provisionNewAccount } = await import("./provisioning-CgwvlsIl.js").then((n) => n.n);
192
+ const { provisionNewAccount } = await import("./provisioning-DLOiFSM9.js").then((n) => n.n);
188
193
  if (!jsonMode) getUI().log.info(`Provisioning account for ${email} in ${region}...`);
189
194
  emitResult(await provisionNewAccount(email, name, region), jsonMode);
190
195
  process.exit(0);
@@ -249,18 +254,18 @@ const basicIntegrationCommand = {
249
254
  setEntryCommand("integrate");
250
255
  (async () => {
251
256
  if (argv.ci) {
252
- const { runCIInstall } = await import("./ci-install-BscZ60Ec.js");
257
+ const { runCIInstall } = await import("./ci-install-_9A7tL36.js");
253
258
  return runCIInstall(argv);
254
259
  }
255
260
  if (isNonInteractiveEnvironment()) {
256
- const { failNonInteractive } = await import("./non-interactive-BfqXlY8R.js");
261
+ const { failNonInteractive } = await import("./non-interactive-csP4yGdA.js");
257
262
  return failNonInteractive();
258
263
  }
259
264
  if (argv.playground) {
260
- const { runPlayground } = await import("./playground-4sqLVVJL.js");
265
+ const { runPlayground } = await import("./playground-C-lpKoKC.js");
261
266
  return runPlayground();
262
267
  }
263
- const { runInteractive } = await import("./interactive-fh2iyewb.js");
268
+ const { runInteractive } = await import("./interactive-DT5dLd7N.js");
264
269
  runInteractive(argv);
265
270
  })();
266
271
  }
@@ -2475,19 +2480,19 @@ const mcpAddConfig = {
2475
2480
  screenId: "mcp-add",
2476
2481
  isComplete: (s) => s.mcpComplete
2477
2482
  },
2478
- {
2479
- id: "mcp-suggested-prompts",
2480
- label: "Suggested prompts",
2481
- screenId: "mcp-suggested-prompts",
2482
- show: (s) => s.mcpOutcome === "installed",
2483
- isComplete: (s) => s.mcpSuggestedPromptsDismissed
2484
- },
2485
2483
  {
2486
2484
  id: "slack-connect",
2487
2485
  label: "Connect Slack",
2488
2486
  screenId: "slack-connect",
2489
2487
  show: (s) => s.mcpOutcome === "installed",
2490
2488
  isComplete: (s) => s.slackStepDismissed
2489
+ },
2490
+ {
2491
+ id: "mcp-suggested-prompts",
2492
+ label: "Suggested prompts",
2493
+ screenId: "mcp-suggested-prompts",
2494
+ show: (s) => s.mcpOutcome === "installed",
2495
+ isComplete: (s) => s.mcpSuggestedPromptsDismissed
2491
2496
  }
2492
2497
  ]
2493
2498
  };
@@ -2495,10 +2500,10 @@ const mcpAddConfig = {
2495
2500
  * `wizard mcp remove` — single-step uninstall flow.
2496
2501
  *
2497
2502
  * DO NOT append `mcp-suggested-prompts` (or any other tutorial-shaped
2498
- * step) here. A user who just removed MCP is opting OUT of the agent
2499
- * having access to PostHog; immediately pivoting into a tutorial that
2500
- * asks them to log in and try prompts is wrong on intent and confusing
2501
- * on UX. The screen also reads `session.mcpInstalledClients` for its
2503
+ * step) here. A user who just removed MCP is opting OUT of the agent having
2504
+ * access to PostHog; immediately pivoting into a tutorial that asks
2505
+ * them to log in and try prompts is wrong on intent and confusing on
2506
+ * UX. The screen also reads `session.mcpInstalledClients` for its
2502
2507
  * Choose-phase copy ("MCP is installed for X") — that array is empty
2503
2508
  * post-remove, so the copy would be a lie.
2504
2509
  *
@@ -2551,39 +2556,9 @@ const slackConnectConfig = {
2551
2556
  id: "slack-connect",
2552
2557
  label: "Connect Slack",
2553
2558
  screenId: "slack-connect",
2554
- isComplete: (s) => s.slackStepDismissed,
2555
- onInit: loginForSlackConnect
2559
+ isComplete: (s) => s.slackStepDismissed
2556
2560
  }]
2557
2561
  };
2558
- /** OAuth for the standalone flow. The screen shows the auth-wait state
2559
- * (and the login URL) until the credentials land in the store. */
2560
- function loginForSlackConnect() {
2561
- (async () => {
2562
- try {
2563
- const data = await getOrAskForProjectData({
2564
- signup: false,
2565
- ci: false,
2566
- apiKey: void 0,
2567
- projectId: void 0,
2568
- programId: "slack"
2569
- });
2570
- const ui = getUI();
2571
- ui.setCredentials({
2572
- accessToken: data.accessToken,
2573
- projectApiKey: data.projectApiKey,
2574
- host: data.host,
2575
- projectId: data.projectId
2576
- });
2577
- ui.setRoleAtOrganization(data.roleAtOrganization);
2578
- ui.setApiUser(data.user);
2579
- ui.setLoginUrl(null);
2580
- } catch (err) {
2581
- analytics.captureException(err instanceof Error ? err : new Error(String(err)), { step: "slack_connect_login" });
2582
- getUI().log.error(`Login failed. ${err instanceof Error ? err.message : String(err)}`);
2583
- process.exit(1);
2584
- }
2585
- })();
2586
- }
2587
2562
  //#endregion
2588
2563
  //#region src/lib/programs/program-registry.ts
2589
2564
  const agentSkillConfig = {
@@ -2678,7 +2653,7 @@ function runMcpAdd(argv) {
2678
2653
  const debug = argv.debug;
2679
2654
  const localMcp = argv.local;
2680
2655
  try {
2681
- const { startTUI } = await import("./start-tui-CywbSvZE.js");
2656
+ const { startTUI } = await import("./start-tui-DnAG57vY.js");
2682
2657
  const { buildSession } = await import("./wizard-session-wPJtNl4c.js");
2683
2658
  const tui = startTUI(VERSION, Program.McpAdd);
2684
2659
  tui.store.session = buildSession({
@@ -2690,7 +2665,7 @@ function runMcpAdd(argv) {
2690
2665
  } catch (error) {
2691
2666
  if (!isTUIUnavailable(error)) throw error;
2692
2667
  setUI(new LoggingUI());
2693
- const { addMCPServerToClientsStep } = await import("./add-mcp-server-to-clients-BU8Owthq.js").then((n) => n.r);
2668
+ const { addMCPServerToClientsStep } = await import("./add-mcp-server-to-clients-t0xe8gn1.js").then((n) => n.r);
2694
2669
  await addMCPServerToClientsStep({
2695
2670
  local: localMcp,
2696
2671
  features,
@@ -2729,7 +2704,7 @@ function runMcpRemove(argv) {
2729
2704
  const debug = argv.debug;
2730
2705
  const localMcp = argv.local;
2731
2706
  try {
2732
- const { startTUI } = await import("./start-tui-CywbSvZE.js");
2707
+ const { startTUI } = await import("./start-tui-DnAG57vY.js");
2733
2708
  const { buildSession } = await import("./wizard-session-wPJtNl4c.js");
2734
2709
  const tui = startTUI(VERSION, Program.McpRemove);
2735
2710
  tui.store.session = buildSession({
@@ -2738,7 +2713,7 @@ function runMcpRemove(argv) {
2738
2713
  });
2739
2714
  } catch {
2740
2715
  setUI(new LoggingUI());
2741
- const { removeMCPServerFromClientsStep } = await import("./add-mcp-server-to-clients-BU8Owthq.js").then((n) => n.r);
2716
+ const { removeMCPServerFromClientsStep } = await import("./add-mcp-server-to-clients-t0xe8gn1.js").then((n) => n.r);
2742
2717
  await removeMCPServerFromClientsStep({ local: localMcp });
2743
2718
  }
2744
2719
  })();
@@ -2760,7 +2735,7 @@ function runMcpTutorial(argv) {
2760
2735
  const debug = argv.debug;
2761
2736
  const localMcp = argv.local;
2762
2737
  try {
2763
- const { startTUI } = await import("./start-tui-CywbSvZE.js");
2738
+ const { startTUI } = await import("./start-tui-DnAG57vY.js");
2764
2739
  const { buildSession } = await import("./wizard-session-wPJtNl4c.js");
2765
2740
  const tui = startTUI(VERSION, Program.McpTutorial);
2766
2741
  tui.store.session = buildSession({
@@ -2815,9 +2790,9 @@ function runWizard(config, options) {
2815
2790
  (async () => {
2816
2791
  try {
2817
2792
  const installDir = options.installDir || process.cwd();
2818
- const { startTUI } = await import("./start-tui-CywbSvZE.js");
2793
+ const { startTUI } = await import("./start-tui-DnAG57vY.js");
2819
2794
  const { buildSession, RunPhase } = await import("./wizard-session-wPJtNl4c.js");
2820
- const { TaskStreamPush } = await import("./task-stream-CZawuzlz.js");
2795
+ const { TaskStreamPush } = await import("./task-stream-BQNSp0qR.js");
2821
2796
  const { PostHogDestination } = await import("./posthog-Cr37rnla.js");
2822
2797
  tui = startTUI(WIZARD_VERSION, config.id);
2823
2798
  const activeTui = tui;
@@ -2871,7 +2846,7 @@ function runWizard(config, options) {
2871
2846
  await activeTui.store.getGate("health-check");
2872
2847
  const skipAgent = config.run == null;
2873
2848
  if (skipAgent) {
2874
- const { getOrAskForProjectData } = await import("./setup-utils-Doh69vo4.js").then((n) => n.r);
2849
+ const { getOrAskForProjectData } = await import("./setup-utils-D87CyNkw.js").then((n) => n.r);
2875
2850
  const { projectApiKey, host, accessToken, projectId } = await getOrAskForProjectData({
2876
2851
  signup: session.signup,
2877
2852
  ci: session.ci,
@@ -2886,7 +2861,7 @@ function runWizard(config, options) {
2886
2861
  projectId
2887
2862
  });
2888
2863
  } else {
2889
- const { runAgent } = await import("./agent-runner-Br0OxBxd.js");
2864
+ const { runAgent } = await import("./agent-runner-L_-kJ3y3.js");
2890
2865
  await runAgent(config, activeTui.store.session);
2891
2866
  }
2892
2867
  const isDone = () => skipAgent ? activeTui.store.session.outroDismissed : activeTui.store.session.skillsComplete;
@@ -2963,10 +2938,10 @@ function runWizardCI(config, options) {
2963
2938
  (async () => {
2964
2939
  const path = await import("path");
2965
2940
  const { buildSession } = await import("./wizard-session-wPJtNl4c.js");
2966
- const { readEnvironment } = await import("./environment-G0Hv6_JI.js").then((n) => n.t);
2941
+ const { readEnvironment } = await import("./environment-DQPoj9sU.js").then((n) => n.t);
2967
2942
  const { readApiKeyFromEnv } = await import("./env-api-key-MlzJYAvt.js").then((n) => n.t);
2968
- const { configureLogFileFromEnvironment, logToFile } = await import("./debug-BgH07S-e.js");
2969
- const { wizardAbort, WizardError } = await import("./wizard-abort-Ni-mKJ58.js");
2943
+ const { configureLogFileFromEnvironment, logToFile } = await import("./debug-CZQcMAJT.js");
2944
+ const { wizardAbort, WizardError } = await import("./wizard-abort-BRXKRL4F.js");
2970
2945
  configureLogFileFromEnvironment();
2971
2946
  const env = readEnvironment();
2972
2947
  const apiKey = options.apiKey ?? readApiKeyFromEnv() ?? void 0;
@@ -3017,7 +2992,7 @@ function runWizardCI(config, options) {
3017
2992
  })
3018
2993
  });
3019
2994
  }
3020
- const { runAgent } = await import("./agent-runner-Br0OxBxd.js");
2995
+ const { runAgent } = await import("./agent-runner-L_-kJ3y3.js");
3021
2996
  await runAgent(config, session);
3022
2997
  } catch (error) {
3023
2998
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -3796,7 +3771,7 @@ async function runDoctorCI(options) {
3796
3771
  getUI().intro("Welcome to the PostHog setup wizard");
3797
3772
  getUI().log.info("Running posthog-doctor in CI mode");
3798
3773
  try {
3799
- const { getOrAskForProjectData } = await import("./setup-utils-Doh69vo4.js").then((n) => n.r);
3774
+ const { getOrAskForProjectData } = await import("./setup-utils-D87CyNkw.js").then((n) => n.r);
3800
3775
  const { host, accessToken, projectId } = await getOrAskForProjectData({
3801
3776
  signup: false,
3802
3777
  ci: true,
@@ -3813,7 +3788,7 @@ async function runDoctorCI(options) {
3813
3788
  for (const issue of sorted) getUI().log.info(` • [${issue.severity}] ${getKindMeta(issue.kind).title}`);
3814
3789
  process.exit(1);
3815
3790
  } catch (error) {
3816
- const { ApiError } = await import("./api-RXTR8yZo.js").then((n) => n.n);
3791
+ const { ApiError } = await import("./api-DNS-L-1U.js").then((n) => n.n);
3817
3792
  const message = error instanceof ApiError && error.statusCode === 401 ? "Your PostHog API key is invalid or expired." : error instanceof Error ? error.message : String(error);
3818
3793
  getUI().log.error(`Doctor failed: ${message}`);
3819
3794
  process.exit(1);
@@ -3876,7 +3851,7 @@ function runSlackConnect(argv) {
3876
3851
  (async () => {
3877
3852
  const debug = argv.debug;
3878
3853
  try {
3879
- const { startTUI } = await import("./start-tui-CywbSvZE.js");
3854
+ const { startTUI } = await import("./start-tui-DnAG57vY.js");
3880
3855
  const { buildSession } = await import("./wizard-session-wPJtNl4c.js");
3881
3856
  const tui = startTUI(VERSION, Program.SlackConnect);
3882
3857
  tui.store.session = buildSession({ debug });
@@ -3997,6 +3972,247 @@ const skillCommand = {
3997
3972
  }
3998
3973
  };
3999
3974
  //#endregion
3975
+ //#region src/steps/install-cli-steering/index.ts
3976
+ const dirExists = (...segments) => {
3977
+ try {
3978
+ return fs$1.existsSync(path$1.join(os.homedir(), ...segments));
3979
+ } catch {
3980
+ return false;
3981
+ }
3982
+ };
3983
+ const CLI_STEERING_TARGETS = [
3984
+ {
3985
+ id: "claude-code",
3986
+ name: "Claude Code",
3987
+ instructionsPath: () => path$1.join(os.homedir(), ".claude", "CLAUDE.md"),
3988
+ isDetected: () => dirExists(".claude")
3989
+ },
3990
+ {
3991
+ id: "codex",
3992
+ name: "Codex",
3993
+ instructionsPath: () => path$1.join(os.homedir(), ".codex", "AGENTS.md"),
3994
+ isDetected: () => dirExists(".codex")
3995
+ },
3996
+ {
3997
+ id: "gemini",
3998
+ name: "Gemini CLI",
3999
+ instructionsPath: () => path$1.join(os.homedir(), ".gemini", "GEMINI.md"),
4000
+ isDetected: () => dirExists(".gemini")
4001
+ }
4002
+ ];
4003
+ function findTarget(id) {
4004
+ return CLI_STEERING_TARGETS.find((target) => target.id === id);
4005
+ }
4006
+ function detectTargets() {
4007
+ return CLI_STEERING_TARGETS.filter((target) => target.isDetected());
4008
+ }
4009
+ const spawnOptions = {
4010
+ encoding: "utf-8",
4011
+ shell: process.platform === "win32"
4012
+ };
4013
+ /**
4014
+ * Install or update the PostHog CLI in the user's environment. `npm install
4015
+ * --global @posthog/cli@latest` covers both first-time installs and upgrades
4016
+ * for existing npm-installed CLIs.
4017
+ */
4018
+ function installOrUpdatePostHogCli() {
4019
+ const args = [
4020
+ "install",
4021
+ "--global",
4022
+ "@posthog/cli@latest"
4023
+ ];
4024
+ debug(`Running npm ${args.join(" ")}`);
4025
+ const result = spawnSync("npm", args, spawnOptions);
4026
+ if (result.error) return {
4027
+ success: false,
4028
+ error: `Failed to run npm: ${result.error.message}. Is Node.js installed?`
4029
+ };
4030
+ if (result.status !== 0) return {
4031
+ success: false,
4032
+ error: (result.stderr || result.stdout || "").trim() || `npm install --global @posthog/cli@latest exited with status ${result.status ?? "unknown"}`
4033
+ };
4034
+ return { success: true };
4035
+ }
4036
+ /**
4037
+ * Delegate the actual write to the installed `posthog-cli api agents-md
4038
+ * install`. The steering snippet lives in the CLI (its single source of truth),
4039
+ * so the command should run only after `installOrUpdatePostHogCli` refreshes
4040
+ * the CLI to the latest release.
4041
+ */
4042
+ function installSteeringSnippet(filePath) {
4043
+ const args = [
4044
+ "api",
4045
+ "agents-md",
4046
+ "install",
4047
+ "--path",
4048
+ filePath
4049
+ ];
4050
+ debug(`Running posthog-cli ${args.join(" ")}`);
4051
+ const result = spawnSync("posthog-cli", args, {
4052
+ ...spawnOptions,
4053
+ env: {
4054
+ ...process.env,
4055
+ POSTHOG_CLI_EXPERIMENTAL_API: "1"
4056
+ }
4057
+ });
4058
+ if (result.error) return {
4059
+ success: false,
4060
+ filePath,
4061
+ error: `Failed to run posthog-cli: ${result.error.message}. Make sure npm's global bin directory is on your PATH.`
4062
+ };
4063
+ if (result.status !== 0) return {
4064
+ success: false,
4065
+ filePath,
4066
+ error: (result.stderr || result.stdout || "").trim() || `posthog-cli exited with status ${result.status ?? "unknown"}`
4067
+ };
4068
+ return {
4069
+ success: true,
4070
+ filePath
4071
+ };
4072
+ }
4073
+ //#endregion
4074
+ //#region src/commands/cli/add.ts
4075
+ const cliAddCommand = {
4076
+ name: "add",
4077
+ description: "Install or update PostHog CLI and add steering instructions to your coding agent's global instructions file",
4078
+ options: {
4079
+ agent: {
4080
+ describe: "Agent to install the instructions for",
4081
+ choices: CLI_STEERING_TARGETS.map((target) => target.id),
4082
+ type: "string"
4083
+ },
4084
+ path: {
4085
+ describe: "Write to an explicit instructions file instead of a detected agent",
4086
+ type: "string"
4087
+ },
4088
+ all: {
4089
+ default: false,
4090
+ describe: "Install for every detected agent without prompting",
4091
+ type: "boolean"
4092
+ }
4093
+ },
4094
+ examples: [
4095
+ ["wizard cli add", "Detect your coding agents and pick one"],
4096
+ ["wizard cli add --agent claude-code", "Install for Claude Code (~/.claude/CLAUDE.md)"],
4097
+ ["wizard cli add --all", "Install for every detected agent"],
4098
+ ["wizard cli add --path ./AGENTS.md", "Install into a specific instructions file"]
4099
+ ],
4100
+ check: (argv) => {
4101
+ if (argv.all && (argv.agent || argv.path)) throw new Error("--all cannot be combined with --agent or --path");
4102
+ return true;
4103
+ },
4104
+ handler: (argv) => {
4105
+ runCliAdd(argv);
4106
+ }
4107
+ };
4108
+ async function runCliAdd(argv) {
4109
+ setUI(new LoggingUI());
4110
+ const ui = getUI();
4111
+ ui.intro("PostHog CLI setup");
4112
+ const files = await resolveTargetFiles(argv);
4113
+ if (files.length === 0) {
4114
+ process.exit(1);
4115
+ return;
4116
+ }
4117
+ ui.log.info("Installing or updating PostHog CLI...");
4118
+ const cliInstallResult = installOrUpdatePostHogCli();
4119
+ if (!cliInstallResult.success) {
4120
+ ui.log.error(`Failed to install or update PostHog CLI: ${cliInstallResult.error ?? ""}`);
4121
+ analytics.wizardCapture("cli steering installed", {
4122
+ files: files.length,
4123
+ failures: files.length,
4124
+ cli_install_failed: true,
4125
+ agent: typeof argv.agent === "string" ? argv.agent : void 0
4126
+ });
4127
+ process.exit(1);
4128
+ return;
4129
+ }
4130
+ ui.log.success("Installed or updated PostHog CLI.");
4131
+ let failures = 0;
4132
+ for (const file of files) {
4133
+ const result = installSteeringSnippet(file);
4134
+ if (result.success) ui.log.success(`Installed PostHog steering instructions in ${file}`);
4135
+ else {
4136
+ failures += 1;
4137
+ ui.log.error(`Failed to update ${file}: ${result.error ?? ""}`);
4138
+ }
4139
+ }
4140
+ analytics.wizardCapture("cli steering installed", {
4141
+ files: files.length,
4142
+ failures,
4143
+ agent: typeof argv.agent === "string" ? argv.agent : void 0
4144
+ });
4145
+ if (failures > 0) {
4146
+ process.exit(1);
4147
+ return;
4148
+ }
4149
+ ui.outro("Done. PostHog CLI is installed and your agent will now use `posthog-cli api` for PostHog tasks.");
4150
+ process.exit(0);
4151
+ }
4152
+ /** Resolve which instruction files to write, from flags, detection, or a prompt. */
4153
+ async function resolveTargetFiles(argv) {
4154
+ const ui = getUI();
4155
+ if (typeof argv.path === "string" && argv.path.trim()) return [path$1.resolve(argv.path.trim())];
4156
+ if (typeof argv.agent === "string") {
4157
+ const target = findTarget(argv.agent);
4158
+ if (!target) {
4159
+ ui.log.error(`Unsupported agent: ${argv.agent}`);
4160
+ return [];
4161
+ }
4162
+ return [target.instructionsPath()];
4163
+ }
4164
+ const detected = detectTargets();
4165
+ if (detected.length === 0) {
4166
+ ui.log.error("No supported coding agents detected. Pass --agent <id> or --path <file> to choose a target.");
4167
+ ui.log.info(`Supported agents: ${CLI_STEERING_TARGETS.map((t) => t.id).join(", ")}`);
4168
+ return [];
4169
+ }
4170
+ if (argv.all === true) {
4171
+ ui.log.info(`Installing for all detected agents: ${detected.map((t) => t.name).join(", ")}`);
4172
+ return detected.map((target) => target.instructionsPath());
4173
+ }
4174
+ if (detected.length === 1) {
4175
+ ui.log.info(`Detected ${detected[0].name} (${detected[0].instructionsPath()})`);
4176
+ return [detected[0].instructionsPath()];
4177
+ }
4178
+ if (!process.stdin.isTTY || !process.stdout.isTTY) {
4179
+ ui.log.info(`Installing for all detected agents: ${detected.map((t) => t.name).join(", ")}`);
4180
+ return detected.map((target) => target.instructionsPath());
4181
+ }
4182
+ return (await promptForTargets(detected)).map((target) => target.instructionsPath());
4183
+ }
4184
+ /** Minimal numbered selection — this command is intentionally not a TUI flow. */
4185
+ async function promptForTargets(detected) {
4186
+ const ui = getUI();
4187
+ ui.log.info("Which coding agent are you using?");
4188
+ detected.forEach((target, index) => {
4189
+ ui.log.info(` ${index + 1}) ${target.name} (${target.instructionsPath()})`);
4190
+ });
4191
+ ui.log.info(` ${detected.length + 1}) All of the above`);
4192
+ const rl = readline.createInterface({
4193
+ input: process.stdin,
4194
+ output: process.stdout
4195
+ });
4196
+ try {
4197
+ for (;;) {
4198
+ const answer = (await rl.question(`Select 1-${detected.length + 1}: `)).trim();
4199
+ const choice = Number(answer);
4200
+ if (Number.isInteger(choice) && choice >= 1 && choice <= detected.length) return [detected[choice - 1]];
4201
+ if (choice === detected.length + 1) return detected;
4202
+ ui.log.warn(`Enter a number between 1 and ${detected.length + 1}.`);
4203
+ }
4204
+ } finally {
4205
+ rl.close();
4206
+ }
4207
+ }
4208
+ //#endregion
4209
+ //#region src/commands/cli/index.ts
4210
+ const cliCommand = {
4211
+ name: "cli",
4212
+ description: "PostHog CLI agent integration commands",
4213
+ children: [cliAddCommand]
4214
+ };
4215
+ //#endregion
4000
4216
  //#region bin.ts
4001
4217
  const NODE_VERSION_RANGE = ">=18.17.0";
4002
4218
  if (!satisfies(process.version, NODE_VERSION_RANGE)) {
@@ -4012,7 +4228,7 @@ function resolveInstallDir() {
4012
4228
  if (inline) return inline.slice(14);
4013
4229
  return process.env.POSTHOG_WIZARD_INSTALL_DIR ?? process.cwd();
4014
4230
  }
4015
- Wizard.use(basicIntegrationCommand).use(mcpCommand).use(auditCommand).use(doctorCommand).use(migrateCommand).use(revenueCommand).use(slackCommand).use(uploadSourcemapsCommand).use(skillCommand).init();
4231
+ Wizard.use(basicIntegrationCommand).use(mcpCommand).use(cliCommand).use(auditCommand).use(doctorCommand).use(migrateCommand).use(revenueCommand).use(slackCommand).use(uploadSourcemapsCommand).use(skillCommand).init();
4016
4232
  //#endregion
4017
4233
  export { POSTHOG_SDKS$1 as _, PromptLabel as a, PROGRAM_REGISTRY as c, DISPLAY_NAME as d, SOURCE_MAPS_CONTEXT_KEYS as f, getContentBlocks$2 as g, fetchHealthIssues as h, useKeyboardHintsContext as i, Program as l, getKindMeta as m, useKeyBindings as n, runWizardCI as o, getContentBlocks$1 as p, KeyboardHintsProvider as r, runWizard as s, PickerMenu as t, getProgramConfig as u, STRIPE_SDKS as v };
4018
4234