@posthog/wizard 2.79.1 → 2.80.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 (192) hide show
  1. package/dist/{PickerMenu-dG5DQCZA.js → PickerMenu-m4CCPX4f.js} +10 -10
  2. package/dist/PickerMenu-m4CCPX4f.js.map +1 -0
  3. package/dist/{agent-BWFhuLgo.js → agent-BkBbVuNq.js} +48 -37
  4. package/dist/agent-BkBbVuNq.js.map +1 -0
  5. package/dist/agent-QGK2YzlX.js +6 -0
  6. package/dist/{agent-interface-FkbaBJwz.js → agent-interface-CzyCmp7q.js} +68 -31
  7. package/dist/agent-interface-CzyCmp7q.js.map +1 -0
  8. package/dist/{agent-prompt-loader-D0weQ-7k.js → agent-prompt-loader-4wMxlYSX.js} +5 -5
  9. package/dist/{agent-prompt-loader-D0weQ-7k.js.map → agent-prompt-loader-4wMxlYSX.js.map} +1 -1
  10. package/dist/{analytics-DXK1gc12.js → analytics-B6q5PN7a.js} +5 -5
  11. package/dist/analytics-B6q5PN7a.js.map +1 -0
  12. package/dist/analytics-BXtfK9o7.js +2 -0
  13. package/dist/{api-CrbCIQOz.js → api-C3Dc4LFl.js} +3 -3
  14. package/dist/{api-CrbCIQOz.js.map → api-C3Dc4LFl.js.map} +1 -1
  15. package/dist/api-yNjrfZs2.js +2 -0
  16. package/dist/bin.js +1 -1
  17. package/dist/{bounded-fs-vAq-T-K7.js → bounded-fs-CC_NDtoP.js} +3 -3
  18. package/dist/{bounded-fs-vAq-T-K7.js.map → bounded-fs-CC_NDtoP.js.map} +1 -1
  19. package/dist/check-screens.tsx +5 -5
  20. package/dist/{ci-install-COcV8SY2.js → ci-install-DfcAMhlu.js} +7 -7
  21. package/dist/ci-install-DfcAMhlu.js.map +1 -0
  22. package/dist/{constants-DHCBSfnx.js → constants-DO4X70po.js} +3 -3
  23. package/dist/{constants-DHCBSfnx.js.map → constants-DO4X70po.js.map} +1 -1
  24. package/dist/{debug-BuYHGr6_.js → debug-BueK5mRR.js} +1 -1
  25. package/dist/{debug-kAHwWGg7.js → debug-DyARf5TF.js} +3 -3
  26. package/dist/debug-DyARf5TF.js.map +1 -0
  27. package/dist/{defaults-a9TelDhJ.js → defaults-DpfMnH2q.js} +2 -2
  28. package/dist/defaults-DpfMnH2q.js.map +1 -0
  29. package/dist/{endpoints-BVMYm9F4.js → endpoints-D-4KxZiB.js} +3 -3
  30. package/dist/{endpoints-BVMYm9F4.js.map → endpoints-D-4KxZiB.js.map} +1 -1
  31. package/dist/env-api-key-CHGLe0iz.js +2 -0
  32. package/dist/{env-api-key-BP-NFFXt.js → env-api-key-COf0U-Au.js} +2 -2
  33. package/dist/{env-api-key-BP-NFFXt.js.map → env-api-key-COf0U-Au.js.map} +1 -1
  34. package/dist/{environment-BATlQxcQ.js → environment-DrLaSsA8.js} +4 -4
  35. package/dist/{environment-BATlQxcQ.js.map → environment-DrLaSsA8.js.map} +1 -1
  36. package/dist/environment-hBj7ngmO.js +2 -0
  37. package/dist/{file-DcRKycV8.js → file-CVA9ocIC.js} +3 -3
  38. package/dist/file-CVA9ocIC.js.map +1 -0
  39. package/dist/file-CmoKK_Pp.js +2 -0
  40. package/dist/{file-watcher-Brq2nnHV.js → file-watcher-C3Su8vXm.js} +3 -3
  41. package/dist/file-watcher-C3Su8vXm.js.map +1 -0
  42. package/dist/{gateway-C9-GlLO9.js → gateway-BmjYUSua.js} +6 -6
  43. package/dist/{gateway-C9-GlLO9.js.map → gateway-BmjYUSua.js.map} +1 -1
  44. package/dist/{headless-ui-CqI2gXlD.js → headless-ui-CUbv12Yx.js} +3 -3
  45. package/dist/headless-ui-CUbv12Yx.js.map +1 -0
  46. package/dist/host-resolution-DVSb7kXb.js +114 -0
  47. package/dist/host-resolution-DVSb7kXb.js.map +1 -0
  48. package/dist/{add-mcp-server-to-clients-DIaTRWMY.js → install-Bk5TNk27.js} +15 -14
  49. package/dist/install-Bk5TNk27.js.map +1 -0
  50. package/dist/{add-mcp-server-to-clients-artmN7mz.js → install-F4wm3RSl.js} +1 -1
  51. package/dist/interactive-C5LNvDj6.js +11 -0
  52. package/dist/interactive-C5LNvDj6.js.map +1 -0
  53. package/dist/{telemetry-B7zJdRmA.js → links-9LWZPSCq.js} +4 -13
  54. package/dist/links-9LWZPSCq.js.map +1 -0
  55. package/dist/{logging-ui-Dza4D0MK.js → logging-ui-p6XKVmTx.js} +6 -6
  56. package/dist/logging-ui-p6XKVmTx.js.map +1 -0
  57. package/dist/{main-CgKxbwMP.js → main-DKPjFHEV.js} +149 -141
  58. package/dist/main-DKPjFHEV.js.map +1 -0
  59. package/dist/{mcp-DnAyW0-w.js → mcp-Co8VRF62.js} +4 -4
  60. package/dist/{mcp-DnAyW0-w.js.map → mcp-Co8VRF62.js.map} +1 -1
  61. package/dist/mcp-install-smoke-test.ts +1 -1
  62. package/dist/{mcp-prompt-streaming-DDWQ-FCA.js → mcp-prompt-streaming-ljCVoQ9I.js} +6 -6
  63. package/dist/{mcp-prompt-streaming-DDWQ-FCA.js.map → mcp-prompt-streaming-ljCVoQ9I.js.map} +1 -1
  64. package/dist/{mint-failure-u8xQKNOn.js → mint-failure-C0HyvEwO.js} +103 -92
  65. package/dist/mint-failure-C0HyvEwO.js.map +1 -0
  66. package/dist/{models-WcwUnSKb.js → models-Dba8ITeo.js} +2 -2
  67. package/dist/{models-WcwUnSKb.js.map → models-Dba8ITeo.js.map} +1 -1
  68. package/dist/{non-interactive-DyVC1AGc.js → non-interactive-CLMJrj_7.js} +3 -3
  69. package/dist/non-interactive-CLMJrj_7.js.map +1 -0
  70. package/dist/{oauth-session-DYM2Hrl2.js → oauth-session-D-RfcVmr.js} +2 -2
  71. package/dist/{oauth-session-DYM2Hrl2.js.map → oauth-session-D-RfcVmr.js.map} +1 -1
  72. package/dist/{orchestrator-tools-DbgNBFGA.js → orchestrator-tools-CVJ1F9Ub.js} +3 -3
  73. package/dist/{orchestrator-tools-DbgNBFGA.js.map → orchestrator-tools-CVJ1F9Ub.js.map} +1 -1
  74. package/dist/package-json--ppioh2F.js +2 -0
  75. package/dist/{package-json-Atg34fa4.js → package-json-Cowya9-3.js} +1 -1
  76. package/dist/{package-json-Atg34fa4.js.map → package-json-Cowya9-3.js.map} +1 -1
  77. package/dist/{pi-8KsYsPmM.js → pi-B5YTBRDv.js} +18 -17
  78. package/dist/pi-B5YTBRDv.js.map +1 -0
  79. package/dist/{playground-BlYRBMj7.js → playground-BLsCfHmQ.js} +33 -33
  80. package/dist/playground-BLsCfHmQ.js.map +1 -0
  81. package/dist/posthog-B2E0hpZt.js +2 -0
  82. package/dist/{posthog-Bt0Aplb8.js → posthog-B42rt_1S.js} +3 -3
  83. package/dist/posthog-B42rt_1S.js.map +1 -0
  84. package/dist/project-data--L-WZyvj.js +2 -0
  85. package/dist/{setup-utils-B26Lf2yF.js → project-data-BO9IXn9y.js} +566 -947
  86. package/dist/project-data-BO9IXn9y.js.map +1 -0
  87. package/dist/provisioning-C01REIU2.js +2 -0
  88. package/dist/{provisioning-Bo2NRxFz.js → provisioning-CLhuKqXH.js} +6 -67
  89. package/dist/provisioning-CLhuKqXH.js.map +1 -0
  90. package/dist/{queue-tools-C8mXOh7e.js → queue-tools-knnPQP0e.js} +4 -4
  91. package/dist/{queue-tools-C8mXOh7e.js.map → queue-tools-knnPQP0e.js.map} +1 -1
  92. package/dist/{registry-CD5RQt38.js → registry-B3rC5U4b.js} +6 -6
  93. package/dist/{registry-CD5RQt38.js.map → registry-B3rC5U4b.js.map} +1 -1
  94. package/dist/registry-BamsM7J9.js +2 -0
  95. package/dist/run-agent-legacy-CwUmPfQF.js +2 -0
  96. package/dist/{run-agent-legacy-DOlM6DQu.js → run-agent-legacy-DWBajsMh.js} +38 -111
  97. package/dist/run-agent-legacy-DWBajsMh.js.map +1 -0
  98. package/dist/{runners-ov3EXF1n.js → runners-D1PqqpjA.js} +38 -38
  99. package/dist/runners-D1PqqpjA.js.map +1 -0
  100. package/dist/{security-C71pkwqH.js → security-BvdSFDuM.js} +5 -5
  101. package/dist/{security-C71pkwqH.js.map → security-BvdSFDuM.js.map} +1 -1
  102. package/dist/setup-utils-ChXXTi1m.js +301 -0
  103. package/dist/setup-utils-ChXXTi1m.js.map +1 -0
  104. package/dist/{start-tui-Bo2L0bar.js → start-tui-DicLfgsj.js} +92 -90
  105. package/dist/start-tui-DicLfgsj.js.map +1 -0
  106. package/dist/{steps-BPcg3_3Q.js → steps-Hc28zVc_.js} +10 -10
  107. package/dist/steps-Hc28zVc_.js.map +1 -0
  108. package/dist/store-COCO6U0P.js +5 -0
  109. package/dist/{store-BTzcvRGT.js → store-D3509G87.js} +66 -28
  110. package/dist/store-D3509G87.js.map +1 -0
  111. package/dist/{subagent-D1TrTchE.js → subagent-D_Sqak94.js} +3 -3
  112. package/dist/{subagent-D1TrTchE.js.map → subagent-D_Sqak94.js.map} +1 -1
  113. package/dist/{task-DqRlQBfs.js → task-DiTI6Sak.js} +16 -16
  114. package/dist/task-DiTI6Sak.js.map +1 -0
  115. package/dist/{wizard-ui-DVqrYaOM.js → task-status-CmrrR7zo.js} +2 -2
  116. package/dist/task-status-CmrrR7zo.js.map +1 -0
  117. package/dist/{task-stream-Bw6JaLCX.js → task-stream-BckhG_cB.js} +10 -10
  118. package/dist/task-stream-BckhG_cB.js.map +1 -0
  119. package/dist/{tasks-ChWufsdO.js → tasks-ChZ_F1YP.js} +1 -1
  120. package/dist/{tasks-ChWufsdO.js.map → tasks-ChZ_F1YP.js.map} +1 -1
  121. package/dist/telemetry-BNKsDxNS.js +13 -0
  122. package/dist/telemetry-BNKsDxNS.js.map +1 -0
  123. package/dist/{terminal-zgkEfoCL.js → terminal-PK9bCLRi.js} +123 -97
  124. package/dist/terminal-PK9bCLRi.js.map +1 -0
  125. package/dist/{tools-CkJ2y9Wt.js → tools-C8LQ8QFz.js} +8 -8
  126. package/dist/{tools-CkJ2y9Wt.js.map → tools-C8LQ8QFz.js.map} +1 -1
  127. package/dist/{ui-Q6-RvERF.js → ui-tPNpM6vj.js} +3 -3
  128. package/dist/ui-tPNpM6vj.js.map +1 -0
  129. package/dist/urls-BI4kJ4qQ.js +67 -0
  130. package/dist/urls-BI4kJ4qQ.js.map +1 -0
  131. package/dist/{version-CHhJjz_H.js → version-5_ydHkM6.js} +2 -2
  132. package/dist/{version-CHhJjz_H.js.map → version-5_ydHkM6.js.map} +1 -1
  133. package/dist/{wizard-abort-Br1qMDNa.js → wizard-abort-BVjqLyeA.js} +1 -1
  134. package/dist/{wizard-abort-BPdv07np.js → wizard-abort-DBKtfnBR.js} +18 -16
  135. package/dist/wizard-abort-DBKtfnBR.js.map +1 -0
  136. package/dist/wizard-session-B7BHnay0.js +2 -0
  137. package/dist/{wizard-session-2w4Ru-Wz.js → wizard-session-BYw6LzpS.js} +30 -28
  138. package/dist/wizard-session-BYw6LzpS.js.map +1 -0
  139. package/dist/{yara-hooks-BnxejtXK.js → yara-hooks-C3L6lBij.js} +5 -5
  140. package/dist/{yara-hooks-BnxejtXK.js.map → yara-hooks-C3L6lBij.js.map} +1 -1
  141. package/dist/yara-hooks-CF_IsoaA.js +2 -0
  142. package/package.json +2 -3
  143. package/dist/PickerMenu-dG5DQCZA.js.map +0 -1
  144. package/dist/add-mcp-server-to-clients-DIaTRWMY.js.map +0 -1
  145. package/dist/agent-BEjARD2a.js +0 -6
  146. package/dist/agent-BWFhuLgo.js.map +0 -1
  147. package/dist/agent-interface-FkbaBJwz.js.map +0 -1
  148. package/dist/analytics-DFtbRjYh.js +0 -2
  149. package/dist/analytics-DXK1gc12.js.map +0 -1
  150. package/dist/api-Cm9UtKZh.js +0 -2
  151. package/dist/ci-install-COcV8SY2.js.map +0 -1
  152. package/dist/debug-kAHwWGg7.js.map +0 -1
  153. package/dist/defaults-a9TelDhJ.js.map +0 -1
  154. package/dist/env-api-key-CaWEDj_9.js +0 -2
  155. package/dist/environment-CwD8OPYj.js +0 -2
  156. package/dist/file-C5JMsyR1.js +0 -2
  157. package/dist/file-DcRKycV8.js.map +0 -1
  158. package/dist/file-watcher-Brq2nnHV.js.map +0 -1
  159. package/dist/headless-ui-CqI2gXlD.js.map +0 -1
  160. package/dist/interactive-B_Ti_CsS.js +0 -11
  161. package/dist/interactive-B_Ti_CsS.js.map +0 -1
  162. package/dist/logging-ui-Dza4D0MK.js.map +0 -1
  163. package/dist/main-CgKxbwMP.js.map +0 -1
  164. package/dist/mint-failure-u8xQKNOn.js.map +0 -1
  165. package/dist/non-interactive-DyVC1AGc.js.map +0 -1
  166. package/dist/package-json-D8Ga03tK.js +0 -2
  167. package/dist/pi-8KsYsPmM.js.map +0 -1
  168. package/dist/playground-BlYRBMj7.js.map +0 -1
  169. package/dist/posthog-Bt0Aplb8.js.map +0 -1
  170. package/dist/posthog-CUgCEhH0.js +0 -2
  171. package/dist/provisioning-Bo2NRxFz.js.map +0 -1
  172. package/dist/provisioning-OGFGlzf7.js +0 -2
  173. package/dist/registry-C06e_x-p.js +0 -2
  174. package/dist/run-agent-legacy-ChacZImU.js +0 -2
  175. package/dist/run-agent-legacy-DOlM6DQu.js.map +0 -1
  176. package/dist/runners-ov3EXF1n.js.map +0 -1
  177. package/dist/setup-utils-B26Lf2yF.js.map +0 -1
  178. package/dist/setup-utils-CVS86NYR.js +0 -2
  179. package/dist/start-tui-Bo2L0bar.js.map +0 -1
  180. package/dist/steps-BPcg3_3Q.js.map +0 -1
  181. package/dist/store-BTzcvRGT.js.map +0 -1
  182. package/dist/store-BpqySPXm.js +0 -5
  183. package/dist/task-DqRlQBfs.js.map +0 -1
  184. package/dist/task-stream-Bw6JaLCX.js.map +0 -1
  185. package/dist/telemetry-B7zJdRmA.js.map +0 -1
  186. package/dist/terminal-zgkEfoCL.js.map +0 -1
  187. package/dist/ui-Q6-RvERF.js.map +0 -1
  188. package/dist/wizard-abort-BPdv07np.js.map +0 -1
  189. package/dist/wizard-session-2w4Ru-Wz.js.map +0 -1
  190. package/dist/wizard-session-DGaUHOF3.js +0 -2
  191. package/dist/wizard-ui-DVqrYaOM.js.map +0 -1
  192. package/dist/yara-hooks-DSuExwb4.js +0 -2
@@ -1 +0,0 @@
1
- {"version":3,"file":"provisioning-Bo2NRxFz.js","names":[],"sources":["../src/shared/utils/urls.ts","../src/shared/utils/provisioning.ts"],"sourcesContent":["import axios from 'axios';\nimport { IS_DEV, WIZARD_USER_AGENT } from '@shared/constants';\nimport type { CloudRegion } from './types';\n\n/**\n * Resolve a pinned PostHog base URL from an optional override. When present, it\n * becomes the single source of truth for every PostHog origin — the\n * API/ingestion host, the cloud/app URL, and the OAuth server — bypassing\n * region resolution entirely.\n *\n * The override lives on the session (`session.baseUrl`, set by `--base-url`) and\n * is threaded in by callers, so there is no hidden module-level state. A `--base-url`\n * value wins; otherwise a dev/test build implies `localhost:8010`; otherwise the\n * result is `undefined`, meaning region-based resolution applies.\n *\n * This is the runtime equivalent of the `IS_DEV` localhost routing: `IS_DEV` is a\n * build-time constant that tsdown compiles out of production builds, so it can't\n * point a shipped wizard at a local stack — `--base-url` can. Both feed this one\n * resolver so every URL helper only asks the question once.\n */\nexport const resolveBaseUrl = (override?: string): string | undefined => {\n return override?.trim() || (IS_DEV ? 'http://localhost:8010' : undefined);\n};\n\nexport const getUiHostFromHost = (host: string) => {\n if (host.includes('us.i.posthog.com')) {\n return 'https://us.posthog.com';\n }\n\n if (host.includes('eu.i.posthog.com')) {\n return 'https://eu.posthog.com';\n }\n\n return host;\n};\n\nexport const getHost = (region: CloudRegion, baseUrl?: string) => {\n const override = resolveBaseUrl(baseUrl);\n if (override) {\n return override;\n }\n\n if (region === 'eu') {\n return 'https://eu.i.posthog.com';\n }\n\n return 'https://us.i.posthog.com';\n};\n\nexport const getCloudUrl = (region: CloudRegion, baseUrl?: string) => {\n const override = resolveBaseUrl(baseUrl);\n if (override) {\n return override;\n }\n\n if (region === 'eu') {\n return 'https://eu.posthog.com';\n }\n\n return 'https://us.posthog.com';\n};\n\nexport async function detectRegion(\n accessToken: string,\n baseUrl?: string,\n): Promise<CloudRegion> {\n // With a pinned base URL there is only one instance to talk to — skip the\n // us/eu probe and default the region label to 'us'. (Covers IS_DEV too, via\n // resolveBaseUrl.) The URLs themselves come from the override, not this label.\n if (resolveBaseUrl(baseUrl)) {\n return 'us';\n }\n\n const headers = {\n Authorization: `Bearer ${accessToken}`,\n 'User-Agent': WIZARD_USER_AGENT,\n };\n\n const [usResult, euResult] = await Promise.allSettled([\n axios.get('https://us.posthog.com/api/users/@me/', { headers }),\n axios.get('https://eu.posthog.com/api/users/@me/', { headers }),\n ]);\n\n if (usResult.status === 'fulfilled') return 'us';\n if (euResult.status === 'fulfilled') return 'eu';\n\n throw new Error(\n 'Could not determine cloud region from access token. Please check your PostHog account.',\n );\n}\n\n/** Region-agnostic prod OAuth server. Resolves to the right region server-side. */\nconst PROD_OAUTH_URL = 'https://oauth.posthog.com';\n\n/**\n * OAuth server URL. Follows the base-URL override (and thus IS_DEV → localhost),\n * otherwise the region-agnostic prod OAuth host.\n */\nexport const getOAuthUrl = (baseUrl?: string): string =>\n resolveBaseUrl(baseUrl) ?? PROD_OAUTH_URL;\n\n/**\n * One-click integration install/authorize deep-link. Opening it in the user's\n * logged-in browser runs the install directly — no settings-page hunting. The\n * one link covers fresh install, link-existing, and re-auth.\n */\nexport const getIntegrationAuthorizeUrl = (\n appHost: string,\n projectId: number,\n kind: string,\n): string =>\n `${appHost.replace(\n /\\/$/,\n '',\n )}/api/environments/${projectId}/integrations/authorize?kind=${kind}`;\n","/**\n * Provisioning API client for creating new PostHog accounts.\n *\n * Uses the agentic provisioning API with PKCE auth:\n * 1. POST /account_requests - create account, get auth code\n * 2. POST /oauth/token - exchange code for tokens (with PKCE)\n * 3. POST /resources - provision project, get API key\n */\n\nimport * as crypto from 'node:crypto';\nimport axios from 'axios';\nimport { z } from 'zod';\nimport {\n POSTHOG_DEV_CLIENT_ID,\n POSTHOG_EU_CLIENT_ID,\n POSTHOG_US_CLIENT_ID,\n WIZARD_PROVISIONING_SCOPES,\n WIZARD_USER_AGENT,\n} from '@shared/constants';\nimport { resolveBaseUrl } from './urls';\nimport { logToFile } from './debug';\nimport { analytics } from './analytics';\nimport type { HostResolution } from '@shared/host-resolution';\n\nconst API_VERSION = '0.1d';\n\n/**\n * Provisioning host. Follows a `--base-url` override (and IS_DEV → localhost),\n * else the prod provisioning host for the target region. Unlike the login OAuth\n * flow (which goes through the region-agnostic `oauth.posthog.com` proxy), the\n * provisioning API is region-specific: an EU account must be created against\n * `eu.posthog.com`, and the subsequent token-exchange / resources calls stay on\n * the same host (they carry the account's bearer token).\n */\nconst getProvisioningBaseUrl = (\n region: 'US' | 'EU',\n baseUrl?: string,\n): string => {\n const override = resolveBaseUrl(baseUrl);\n if (override) return override;\n return region === 'EU' ? 'https://eu.posthog.com' : 'https://us.posthog.com';\n};\n\n/**\n * OAuth client ID for provisioning. A pinned base URL means a dev-seeded stack\n * that registers the dev client; prod uses the client registered for the target\n * region (the wizard OAuth app is registered separately per region).\n *\n * TODO: same assumption as `getOAuthClientId` in oauth.ts — a pinned base URL is\n * treated as a dev-seeded instance. Make configurable if we ever point\n * `--base-url` at a non-dev instance with its own OAuth app.\n */\nconst getProvisioningClientId = (\n region: 'US' | 'EU',\n baseUrl?: string,\n): string => {\n if (resolveBaseUrl(baseUrl)) return POSTHOG_DEV_CLIENT_ID;\n return region === 'EU' ? POSTHOG_EU_CLIENT_ID : POSTHOG_US_CLIENT_ID;\n};\n\nfunction generateCodeVerifier(): string {\n return crypto.randomBytes(32).toString('base64url');\n}\n\nfunction generateCodeChallenge(verifier: string): string {\n return crypto.createHash('sha256').update(verifier).digest('base64url');\n}\n\n// --- Response schemas ---\n//\n// These schemas validate only the fields the wizard actually reads. The rule is load\n// bearing, not stylistic: the wizard ships to npm and old versions keep running against\n// a provisioning API that moves independently, so a field we require but never consume\n// is a crash we cannot fix in the field. `service_id` was exactly that — required here,\n// read nowhere, and every signup broke the day the API stopped echoing it. Zod strips\n// unknown keys, so fields the API adds are tolerated for free; the only way to break is\n// to demand something back.\n\nconst AccountRequestResponseSchema = z.object({\n id: z.string(),\n type: z.enum(['oauth', 'requires_auth', 'error']),\n oauth: z\n .object({\n code: z.string(),\n })\n .optional(),\n error: z\n .object({\n code: z.string(),\n message: z.string(),\n })\n .optional(),\n});\n\nconst TokenResponseSchema = z.object({\n token_type: z.string(),\n access_token: z.string(),\n refresh_token: z.string(),\n expires_in: z.number(),\n account: z\n .object({\n id: z.string(),\n })\n .optional(),\n});\n\nconst AccessConfigurationSchema = z.object({\n api_key: z.string(),\n host: z.string(),\n personal_api_key: z.string().optional(),\n});\n\nconst ResourceResponseSchema = z.object({\n status: z.string(),\n id: z.string(),\n complete: z\n .object({\n access_configuration: AccessConfigurationSchema,\n })\n .optional(),\n});\n\n/**\n * Teams the account can reach, from the token exchange. Parsed separately from\n * `TokenResponseSchema` and as loosely as possible: it is only used to recover from a\n * response we already failed to read, so it must never become a new way to fail.\n */\nconst AvailableTeamsSchema = z.array(\n z.object({ id: z.union([z.number(), z.string()]) }),\n);\n\n/**\n * Thrown when the provisioning API completed the work but the wizard could not read the\n * project back out of the response. The account, organization and project exist — callers\n * must not tell the user their account wasn't created.\n */\nexport class ProvisionedAccountUnreadableError extends Error {\n readonly accountCreated = true;\n\n constructor(message: string) {\n super(message);\n this.name = 'ProvisionedAccountUnreadableError';\n }\n}\n\n/** The field paths Zod rejected — never the values, which carry tokens and API keys. */\nfunction issuePaths(error: z.ZodError): string[] {\n return error.issues.map((issue) => issue.path.join('.') || '(root)');\n}\n\n/**\n * Report a response the wizard couldn't read. Silently degrading on a shape mismatch\n * turns the next contract change into a week of guesswork, so the rejected paths go to\n * the debug log and to error tracking before anything else happens.\n */\nfunction reportUnreadableResponse(step: string, error: z.ZodError): Error {\n const paths = issuePaths(error);\n const reported = new Error(\n `Unexpected ${step} response from the provisioning API (missing or invalid: ${paths.join(\n ', ',\n )})`,\n );\n\n logToFile(\n `[provisioning] unexpected ${step} response shape: ${paths.join(', ')}`,\n );\n analytics.captureException(reported, {\n step: `provisioning_${step}`,\n issue_paths: paths,\n });\n\n return reported;\n}\n\nfunction parseOrThrow<T extends z.ZodTypeAny>(\n schema: T,\n data: unknown,\n step: string,\n): z.infer<T> {\n const parsed = schema.safeParse(data);\n if (!parsed.success) {\n throw reportUnreadableResponse(step, parsed.error);\n }\n return parsed.data;\n}\n\ntype ResourceRead =\n | {\n ok: true;\n projectId: string;\n access: z.infer<typeof AccessConfigurationSchema>;\n }\n | { ok: false; reason: 'unreadable' | 'incomplete' };\n\nfunction readResource(data: unknown, step: string): ResourceRead {\n const parsed = ResourceResponseSchema.safeParse(data);\n if (!parsed.success) {\n reportUnreadableResponse(step, parsed.error);\n return { ok: false, reason: 'unreadable' };\n }\n\n if (parsed.data.status !== 'complete' || !parsed.data.complete) {\n logToFile(`[provisioning] ${step} returned status=${parsed.data.status}`);\n return { ok: false, reason: 'incomplete' };\n }\n\n return {\n ok: true,\n projectId: parsed.data.id,\n access: parsed.data.complete.access_configuration,\n };\n}\n\n/**\n * Recover the project after an unreadable `POST /resources` response.\n *\n * By the time that call returns 2xx the account, organization and project exist, so\n * aborting would abandon a provisioned account and leave the user with an orphaned\n * project. `GET /resources/:id` returns the same access configuration, so read it back\n * instead. Best-effort by design: any failure returns null and the caller reports the\n * original drift. The detail endpoint never mints a personal API key, so a recovered\n * result has none — `personalApiKey` is optional for every consumer.\n */\nasync function readBackResource(\n provisioningBaseUrl: string,\n accessToken: string,\n tokenPayload: unknown,\n): Promise<ResourceRead | null> {\n const teams = AvailableTeamsSchema.safeParse(\n (tokenPayload as { account?: { available_teams?: unknown } } | undefined)\n ?.account?.available_teams,\n );\n\n // A freshly provisioned account owns exactly one team. With any other count we can't\n // tell which team the create call made, and guessing would capture into the wrong one.\n if (!teams.success || teams.data.length !== 1) {\n logToFile(\n '[provisioning] no unambiguous team to read the resource back from',\n );\n return null;\n }\n\n const resourceId = String(teams.data[0].id);\n\n try {\n const res = await axios.get(\n `${provisioningBaseUrl}/api/agentic/provisioning/resources/${resourceId}`,\n {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n 'API-Version': API_VERSION,\n 'User-Agent': WIZARD_USER_AGENT,\n },\n timeout: 30_000,\n },\n );\n\n logToFile(\n `[provisioning] read resource ${resourceId} back after unreadable create`,\n );\n return readResource(res.data, 'resource_readback');\n } catch {\n logToFile(`[provisioning] read-back of resource ${resourceId} failed`);\n return null;\n }\n}\n\nexport interface ProvisioningResult {\n accessToken: string;\n refreshToken: string;\n /** Epoch ms when `accessToken` expires. */\n expiresAt: number;\n /** OAuth client the grant was minted under — refreshes must present the same one. */\n oauthClientId: string;\n projectApiKey: string;\n host: string;\n personalApiKey?: string;\n projectId: string;\n accountId: string;\n}\n\n/**\n * Create a new PostHog account and provision a project via the provisioning API.\n *\n * This is the \"no browser\" signup path: the wizard collects the email,\n * calls the provisioning API to create the account, and gets back\n * credentials without opening a browser.\n */\nexport async function provisionNewAccount(\n email: string,\n name: string,\n region: 'US' | 'EU' = 'US',\n opts?: {\n orgName?: string;\n projectName?: string;\n baseUrl?: string;\n /** Scope list to request; defaults to `WIZARD_PROVISIONING_SCOPES`. */\n scopes?: readonly string[];\n },\n): Promise<ProvisioningResult> {\n const codeVerifier = generateCodeVerifier();\n const codeChallenge = generateCodeChallenge(codeVerifier);\n const provisioningBaseUrl = getProvisioningBaseUrl(region, opts?.baseUrl);\n const oauthClientId = getProvisioningClientId(region, opts?.baseUrl);\n\n logToFile('[provisioning] starting account creation');\n\n // Step 1: Create account\n const accountRes = await axios.post(\n `${provisioningBaseUrl}/api/agentic/provisioning/account_requests`,\n {\n id: crypto.randomUUID(),\n email,\n name,\n client_id: oauthClientId,\n code_challenge: codeChallenge,\n code_challenge_method: 'S256',\n scopes: opts?.scopes ?? WIZARD_PROVISIONING_SCOPES,\n configuration: {\n region,\n ...(opts?.orgName ? { organization_name: opts.orgName } : {}),\n },\n },\n {\n headers: {\n 'Content-Type': 'application/json',\n 'API-Version': API_VERSION,\n 'User-Agent': WIZARD_USER_AGENT,\n },\n timeout: 30_000,\n },\n );\n\n const accountData = parseOrThrow(\n AccountRequestResponseSchema,\n accountRes.data,\n 'account_requests',\n );\n\n if (accountData.type === 'error') {\n const msg = accountData.error?.message ?? 'Account creation failed';\n analytics.captureException(new Error(msg), {\n step: 'provisioning_account_request',\n error_code: accountData.error?.code,\n });\n throw new Error(msg);\n }\n\n if (accountData.type === 'requires_auth') {\n throw new Error(\n 'This email is already associated with a PostHog account. Please use the login flow instead.',\n );\n }\n\n const code = accountData.oauth?.code;\n if (!code) {\n throw new Error('No authorization code received from account creation');\n }\n\n logToFile('[provisioning] account created, exchanging code for tokens');\n\n // Step 2: Exchange code for tokens\n const tokenRes = await axios.post(\n `${provisioningBaseUrl}/api/agentic/oauth/token`,\n new URLSearchParams({\n grant_type: 'authorization_code',\n code,\n code_verifier: codeVerifier,\n }).toString(),\n {\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded',\n 'API-Version': API_VERSION,\n 'User-Agent': WIZARD_USER_AGENT,\n },\n timeout: 30_000,\n },\n );\n\n const tokenData = parseOrThrow(\n TokenResponseSchema,\n tokenRes.data,\n 'oauth_token',\n );\n\n logToFile('[provisioning] tokens received, provisioning resources');\n\n // Step 3: Provision resources\n const resourceRes = await axios.post(\n `${provisioningBaseUrl}/api/agentic/provisioning/resources`,\n {\n ...(opts?.projectName\n ? { configuration: { project_name: opts.projectName } }\n : {}),\n },\n {\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${tokenData.access_token}`,\n 'API-Version': API_VERSION,\n 'User-Agent': WIZARD_USER_AGENT,\n },\n timeout: 30_000,\n },\n );\n\n // `/resources` is synchronous: it answers `status: \"complete\"` or an error envelope.\n // So an unreadable body means the contract moved, not that provisioning is still\n // running — and the project already exists either way, which is why this recovers\n // instead of aborting.\n let resource = readResource(resourceRes.data, 'resources');\n\n if (!resource.ok && resource.reason === 'unreadable') {\n resource =\n (await readBackResource(\n provisioningBaseUrl,\n tokenData.access_token,\n tokenRes.data,\n )) ?? resource;\n }\n\n if (!resource.ok) {\n if (resource.reason === 'incomplete') {\n throw new Error('Resource provisioning did not complete');\n }\n throw new ProvisionedAccountUnreadableError(\n 'Your PostHog project was created, but the provisioning API returned a response the wizard could not read',\n );\n }\n\n logToFile('[provisioning] resources provisioned successfully');\n\n return {\n accessToken: tokenData.access_token,\n refreshToken: tokenData.refresh_token,\n expiresAt: Date.now() + tokenData.expires_in * 1000,\n oauthClientId,\n projectApiKey: resource.access.api_key,\n host: resource.access.host,\n personalApiKey: resource.access.personal_api_key,\n projectId: resource.projectId,\n accountId: tokenData.account?.id ?? '',\n };\n}\n\n/**\n * Request a one-time deep link URL that logs the user into PostHog\n * and redirects to their project dashboard — or, when `opts.path` is\n * given, to any safe in-app relative path (e.g. the Signals inbox).\n */\nexport async function requestDeepLink(\n accessToken: string,\n host: HostResolution,\n opts?: { purpose?: string; path?: string },\n): Promise<string | null> {\n try {\n const baseUrl = host.appHost;\n\n const res = await axios.post(\n `${baseUrl}/api/agentic/provisioning/deep_links`,\n {\n purpose: opts?.purpose ?? 'dashboard',\n ...(opts?.path ? { path: opts.path } : {}),\n },\n {\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${accessToken}`,\n 'API-Version': API_VERSION,\n 'User-Agent': WIZARD_USER_AGENT,\n },\n timeout: 10_000,\n },\n );\n\n const url = res.data?.url;\n if (typeof url === 'string') {\n logToFile(`[provisioning] deep link created: ${url}`);\n return url;\n }\n return null;\n } catch {\n logToFile('[provisioning] deep link request failed, skipping');\n return null;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAoBA,MAAa,kBAAkB,aAA0C;AACvE,QAAO,UAAU,MAAM,IAAwC,KAAA;;AAGjE,MAAa,qBAAqB,SAAiB;AACjD,KAAI,KAAK,SAAS,mBAAmB,CACnC,QAAO;AAGT,KAAI,KAAK,SAAS,mBAAmB,CACnC,QAAO;AAGT,QAAO;;AAGT,MAAa,WAAW,QAAqB,YAAqB;CAChE,MAAM,WAAW,eAAe,QAAQ;AACxC,KAAI,SACF,QAAO;AAGT,KAAI,WAAW,KACb,QAAO;AAGT,QAAO;;AAGT,MAAa,eAAe,QAAqB,YAAqB;CACpE,MAAM,WAAW,eAAe,QAAQ;AACxC,KAAI,SACF,QAAO;AAGT,KAAI,WAAW,KACb,QAAO;AAGT,QAAO;;AAGT,eAAsB,aACpB,aACA,SACsB;AAItB,KAAI,eAAe,QAAQ,CACzB,QAAO;CAGT,MAAM,UAAU;EACd,eAAe,UAAU;EACzB,cAAc;EACf;CAED,MAAM,CAAC,UAAU,YAAY,MAAM,QAAQ,WAAW,CACpD,MAAM,IAAI,yCAAyC,EAAE,SAAS,CAAC,EAC/D,MAAM,IAAI,yCAAyC,EAAE,SAAS,CAAC,CAChE,CAAC;AAEF,KAAI,SAAS,WAAW,YAAa,QAAO;AAC5C,KAAI,SAAS,WAAW,YAAa,QAAO;AAE5C,OAAM,IAAI,MACR,yFACD;;;AAIH,MAAM,iBAAiB;;;;;AAMvB,MAAa,eAAe,YAC1B,eAAe,QAAQ,IAAI;;;;;;AAO7B,MAAa,8BACX,SACA,WACA,SAEA,GAAG,QAAQ,QACT,OACA,GACD,CAAC,oBAAoB,UAAU,+BAA+B;;;;;;;;;;;AC1FjE,MAAM,cAAc;;;;;;;;;AAUpB,MAAM,0BACJ,QACA,YACW;CACX,MAAM,WAAW,eAAe,QAAQ;AACxC,KAAI,SAAU,QAAO;AACrB,QAAO,WAAW,OAAO,2BAA2B;;;;;;;;;;;AAYtD,MAAM,2BACJ,QACA,YACW;AACX,KAAI,eAAe,QAAQ,CAAE,QAAO;AACpC,QAAO,WAAW,OAAO,uBAAuB;;AAGlD,SAAS,uBAA+B;AACtC,QAAO,OAAO,YAAY,GAAG,CAAC,SAAS,YAAY;;AAGrD,SAAS,sBAAsB,UAA0B;AACvD,QAAO,OAAO,WAAW,SAAS,CAAC,OAAO,SAAS,CAAC,OAAO,YAAY;;AAazE,MAAM,+BAA+B,EAAE,OAAO;CAC5C,IAAI,EAAE,QAAQ;CACd,MAAM,EAAE,KAAK;EAAC;EAAS;EAAiB;EAAQ,CAAC;CACjD,OAAO,EACJ,OAAO,EACN,MAAM,EAAE,QAAQ,EACjB,CAAC,CACD,UAAU;CACb,OAAO,EACJ,OAAO;EACN,MAAM,EAAE,QAAQ;EAChB,SAAS,EAAE,QAAQ;EACpB,CAAC,CACD,UAAU;CACd,CAAC;AAEF,MAAM,sBAAsB,EAAE,OAAO;CACnC,YAAY,EAAE,QAAQ;CACtB,cAAc,EAAE,QAAQ;CACxB,eAAe,EAAE,QAAQ;CACzB,YAAY,EAAE,QAAQ;CACtB,SAAS,EACN,OAAO,EACN,IAAI,EAAE,QAAQ,EACf,CAAC,CACD,UAAU;CACd,CAAC;AAEF,MAAM,4BAA4B,EAAE,OAAO;CACzC,SAAS,EAAE,QAAQ;CACnB,MAAM,EAAE,QAAQ;CAChB,kBAAkB,EAAE,QAAQ,CAAC,UAAU;CACxC,CAAC;AAEF,MAAM,yBAAyB,EAAE,OAAO;CACtC,QAAQ,EAAE,QAAQ;CAClB,IAAI,EAAE,QAAQ;CACd,UAAU,EACP,OAAO,EACN,sBAAsB,2BACvB,CAAC,CACD,UAAU;CACd,CAAC;;;;;;AAOF,MAAM,uBAAuB,EAAE,MAC7B,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,QAAQ,EAAE,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,CACpD;;;;;;AAOD,IAAa,oCAAb,cAAuD,MAAM;CAC3D,iBAA0B;CAE1B,YAAY,SAAiB;AAC3B,QAAM,QAAQ;AACd,OAAK,OAAO;;;;AAKhB,SAAS,WAAW,OAA6B;AAC/C,QAAO,MAAM,OAAO,KAAK,UAAU,MAAM,KAAK,KAAK,IAAI,IAAI,SAAS;;;;;;;AAQtE,SAAS,yBAAyB,MAAc,OAA0B;CACxE,MAAM,QAAQ,WAAW,MAAM;CAC/B,MAAM,2BAAW,IAAI,MACnB,cAAc,KAAK,2DAA2D,MAAM,KAClF,KACD,CAAC,GACH;AAED,WACE,6BAA6B,KAAK,mBAAmB,MAAM,KAAK,KAAK,GACtE;AACD,WAAU,iBAAiB,UAAU;EACnC,MAAM,gBAAgB;EACtB,aAAa;EACd,CAAC;AAEF,QAAO;;AAGT,SAAS,aACP,QACA,MACA,MACY;CACZ,MAAM,SAAS,OAAO,UAAU,KAAK;AACrC,KAAI,CAAC,OAAO,QACV,OAAM,yBAAyB,MAAM,OAAO,MAAM;AAEpD,QAAO,OAAO;;AAWhB,SAAS,aAAa,MAAe,MAA4B;CAC/D,MAAM,SAAS,uBAAuB,UAAU,KAAK;AACrD,KAAI,CAAC,OAAO,SAAS;AACnB,2BAAyB,MAAM,OAAO,MAAM;AAC5C,SAAO;GAAE,IAAI;GAAO,QAAQ;GAAc;;AAG5C,KAAI,OAAO,KAAK,WAAW,cAAc,CAAC,OAAO,KAAK,UAAU;AAC9D,YAAU,kBAAkB,KAAK,mBAAmB,OAAO,KAAK,SAAS;AACzE,SAAO;GAAE,IAAI;GAAO,QAAQ;GAAc;;AAG5C,QAAO;EACL,IAAI;EACJ,WAAW,OAAO,KAAK;EACvB,QAAQ,OAAO,KAAK,SAAS;EAC9B;;;;;;;;;;;;AAaH,eAAe,iBACb,qBACA,aACA,cAC8B;CAC9B,MAAM,QAAQ,qBAAqB,UAChC,cACG,SAAS,gBACd;AAID,KAAI,CAAC,MAAM,WAAW,MAAM,KAAK,WAAW,GAAG;AAC7C,YACE,oEACD;AACD,SAAO;;CAGT,MAAM,aAAa,OAAO,MAAM,KAAK,GAAG,GAAG;AAE3C,KAAI;EACF,MAAM,MAAM,MAAM,MAAM,IACtB,GAAG,oBAAoB,sCAAsC,cAC7D;GACE,SAAS;IACP,eAAe,UAAU;IACzB,eAAe;IACf,cAAc;IACf;GACD,SAAS;GACV,CACF;AAED,YACE,gCAAgC,WAAW,+BAC5C;AACD,SAAO,aAAa,IAAI,MAAM,oBAAoB;SAC5C;AACN,YAAU,wCAAwC,WAAW,SAAS;AACtE,SAAO;;;;;;;;;;AAyBX,eAAsB,oBACpB,OACA,MACA,SAAsB,MACtB,MAO6B;CAC7B,MAAM,eAAe,sBAAsB;CAC3C,MAAM,gBAAgB,sBAAsB,aAAa;CACzD,MAAM,sBAAsB,uBAAuB,QAAQ,MAAM,QAAQ;CACzE,MAAM,gBAAgB,wBAAwB,QAAQ,MAAM,QAAQ;AAEpE,WAAU,2CAA2C;CA4BrD,MAAM,cAAc,aAClB,+BA1BiB,MAAM,MAAM,KAC7B,GAAG,oBAAoB,6CACvB;EACE,IAAI,OAAO,YAAY;EACvB;EACA;EACA,WAAW;EACX,gBAAgB;EAChB,uBAAuB;EACvB,QAAQ,MAAM,UAAU;EACxB,eAAe;GACb;GACA,GAAI,MAAM,UAAU,EAAE,mBAAmB,KAAK,SAAS,GAAG,EAAE;GAC7D;EACF,EACD;EACE,SAAS;GACP,gBAAgB;GAChB,eAAe;GACf,cAAc;GACf;EACD,SAAS;EACV,CACF,EAIY,MACX,mBACD;AAED,KAAI,YAAY,SAAS,SAAS;EAChC,MAAM,MAAM,YAAY,OAAO,WAAW;AAC1C,YAAU,iBAAiB,IAAI,MAAM,IAAI,EAAE;GACzC,MAAM;GACN,YAAY,YAAY,OAAO;GAChC,CAAC;AACF,QAAM,IAAI,MAAM,IAAI;;AAGtB,KAAI,YAAY,SAAS,gBACvB,OAAM,IAAI,MACR,8FACD;CAGH,MAAM,OAAO,YAAY,OAAO;AAChC,KAAI,CAAC,KACH,OAAM,IAAI,MAAM,uDAAuD;AAGzE,WAAU,6DAA6D;CAGvE,MAAM,WAAW,MAAM,MAAM,KAC3B,GAAG,oBAAoB,2BACvB,IAAI,gBAAgB;EAClB,YAAY;EACZ;EACA,eAAe;EAChB,CAAC,CAAC,UAAU,EACb;EACE,SAAS;GACP,gBAAgB;GAChB,eAAe;GACf,cAAc;GACf;EACD,SAAS;EACV,CACF;CAED,MAAM,YAAY,aAChB,qBACA,SAAS,MACT,cACD;AAED,WAAU,yDAAyD;CAyBnE,IAAI,WAAW,cAtBK,MAAM,MAAM,KAC9B,GAAG,oBAAoB,sCACvB,EACE,GAAI,MAAM,cACN,EAAE,eAAe,EAAE,cAAc,KAAK,aAAa,EAAE,GACrD,EAAE,EACP,EACD;EACE,SAAS;GACP,gBAAgB;GAChB,eAAe,UAAU,UAAU;GACnC,eAAe;GACf,cAAc;GACf;EACD,SAAS;EACV,CACF,EAMuC,MAAM,YAAY;AAE1D,KAAI,CAAC,SAAS,MAAM,SAAS,WAAW,aACtC,YACG,MAAM,iBACL,qBACA,UAAU,cACV,SAAS,KACV,IAAK;AAGV,KAAI,CAAC,SAAS,IAAI;AAChB,MAAI,SAAS,WAAW,aACtB,OAAM,IAAI,MAAM,yCAAyC;AAE3D,QAAM,IAAI,kCACR,2GACD;;AAGH,WAAU,oDAAoD;AAE9D,QAAO;EACL,aAAa,UAAU;EACvB,cAAc,UAAU;EACxB,WAAW,KAAK,KAAK,GAAG,UAAU,aAAa;EAC/C;EACA,eAAe,SAAS,OAAO;EAC/B,MAAM,SAAS,OAAO;EACtB,gBAAgB,SAAS,OAAO;EAChC,WAAW,SAAS;EACpB,WAAW,UAAU,SAAS,MAAM;EACrC;;;;;;;AAQH,eAAsB,gBACpB,aACA,MACA,MACwB;AACxB,KAAI;EACF,MAAM,UAAU,KAAK;EAmBrB,MAAM,OAjBM,MAAM,MAAM,KACtB,GAAG,QAAQ,uCACX;GACE,SAAS,MAAM,WAAW;GAC1B,GAAI,MAAM,OAAO,EAAE,MAAM,KAAK,MAAM,GAAG,EAAE;GAC1C,EACD;GACE,SAAS;IACP,gBAAgB;IAChB,eAAe,UAAU;IACzB,eAAe;IACf,cAAc;IACf;GACD,SAAS;GACV,CACF,EAEe,MAAM;AACtB,MAAI,OAAO,QAAQ,UAAU;AAC3B,aAAU,qCAAqC,MAAM;AACrD,UAAO;;AAET,SAAO;SACD;AACN,YAAU,oDAAoD;AAC9D,SAAO"}
@@ -1,2 +0,0 @@
1
- import { n as provisionNewAccount } from "./provisioning-Bo2NRxFz.js";
2
- export { provisionNewAccount };
@@ -1,2 +0,0 @@
1
- import { t as FRAMEWORK_REGISTRY } from "./registry-CD5RQt38.js";
2
- export { FRAMEWORK_REGISTRY };
@@ -1,2 +0,0 @@
1
- import { t as runProgramAgent } from "./run-agent-legacy-DOlM6DQu.js";
2
- export { runProgramAgent };
@@ -1 +0,0 @@
1
- {"version":3,"file":"run-agent-legacy-DOlM6DQu.js","names":[],"sources":["../src/programs/credentials.ts","../src/programs/warehouse-sources/registry.ts","../src/programs/posthog-integration/ai-sdk-stamp.ts","../src/programs/program-store.ts","../src/programs/run-program.ts","../src/ui/agent-progress.ts","../src/programs/program-step.ts","../src/programs/authenticate.ts","../src/programs/audit/types.ts","../src/programs/audit/ledger-watcher.ts","../src/programs/detection/features.ts","../src/programs/warehouse-sources/detect.ts","../src/programs/warehouse-source/detect.ts","../src/programs/run-agent-legacy.ts"],"sourcesContent":["/** Resolved credentials runProgram passes to one agent run, and the grant that rotates them. */\n\nimport type { ApiProject, ApiUser, Credentials } from '@shared/api';\nimport { WIZARD_OAUTH_SCOPES } from '@shared/constants';\nimport { markGrantRevoked } from '@shared/auth-session-state';\nimport { missingOAuthScopes, refreshAccessToken } from '@utils/oauth';\nimport { OAuthError } from '@utils/oauth-errors';\nimport { analytics } from '@utils/analytics';\nimport { logToFile } from '@utils/debug';\n\nexport type ResolvedProgramCredentials = {\n posthog: Credentials; // token, project API key, project ID and host\n project: ApiProject | null; // the project, when known\n apiUser: ApiUser | null; // the user, when known\n};\n\n/** The caller authenticates once per scope; the signal aborts with the invocation. */\nexport type CredentialsProvider = {\n resolve(\n programId: string,\n context: { signal: AbortSignal },\n ): Promise<ResolvedProgramCredentials>;\n};\n\n/**\n * Grants the token endpoint refuses permanently. A dead grant means the login\n * is gone, not that the network blipped, so only these mark the session.\n */\nconst DEAD_GRANT_CODES = new Set(['invalid_grant', 'invalid_client']);\n\n// One refresh-token grant. A failure returns the same credentials: the old token may still have minutes of life.\nexport async function rotateCredentials(\n credentials: Credentials,\n baseUrl: string | undefined,\n): Promise<Credentials> {\n if (!credentials.refreshToken) return credentials;\n try {\n const token = await refreshAccessToken(\n credentials.refreshToken,\n baseUrl,\n credentials.oauthClientId,\n );\n return {\n ...credentials,\n accessToken: token.access_token,\n missingScopes: missingOAuthScopes(\n [...WIZARD_OAUTH_SCOPES, ...(credentials.missingScopes ?? [])],\n token.scope,\n ),\n // Rotation: keep the returned refresh token or the old one stops working.\n refreshToken: token.refresh_token ?? credentials.refreshToken,\n expiresAt: Date.now() + token.expires_in * 1000,\n };\n } catch (error) {\n // A dead grant is recorded but not thrown. If a 401 does follow, the auth-error screen can name the cause.\n if (error instanceof OAuthError && DEAD_GRANT_CODES.has(error.code)) {\n markGrantRevoked();\n analytics.wizardCapture('auth session expired', { reason: error.code });\n }\n logToFile(\n '[oauth] token refresh failed, continuing with the existing token:',\n error instanceof Error ? error.message : error,\n );\n return credentials;\n }\n}\n","/**\n * Registry of data warehouse source detectors.\n *\n * Each entry maps a codebase footprint to a PostHog source `kind`. The `kind`\n * strings are validated against the MCP `external-data-sources-wizard` tool —\n * keep them in sync with PostHog's released source types.\n *\n * `in-cli` sources are created from the terminal (databases + API-key SaaS).\n * `deep-link` sources have no safe terminal credential path (OAuth) but a\n * codebase footprint worth nudging the user about — we open the app instead.\n */\n\nimport type { SourceDetector } from './types.js';\n\nconst CORE_SOURCE_DETECTORS: SourceDetector[] = [\n {\n kind: 'Postgres',\n label: 'PostgreSQL',\n mode: 'in-cli',\n signals: {\n npm: ['pg', 'postgres', 'postgres.js', 'knex', 'sequelize'],\n python: ['psycopg', 'psycopg2', 'psycopg2-binary', 'asyncpg'],\n ruby: ['pg'],\n envKeys: [\n // NOTE: DATABASE_URL is ambiguous — MySQL/SQLite projects (Prisma,\n // Rails) use it too. We only read key NAMES, not the scheme, so this\n // is a deliberate precision/recall tradeoff biased toward the most\n // common convention (DATABASE_URL → Postgres).\n /^DATABASE_URL$/,\n /^POSTGRES_/,\n /^PG(HOST|DATABASE|USER|PORT)$/,\n ],\n },\n // Neon and Supabase are hosted Postgres, and a project on either still\n // names its connection with the generic signals above. Two sources over\n // one database import the same tables twice.\n supersededBy: ['Neon', 'Supabase'],\n },\n {\n kind: 'MySQL',\n label: 'MySQL',\n mode: 'in-cli',\n signals: {\n npm: ['mysql', 'mysql2'],\n python: ['pymysql', 'mysqlclient', 'mysql-connector-python'],\n ruby: ['mysql2'],\n envKeys: [/^MYSQL_/],\n },\n },\n {\n kind: 'MongoDB',\n label: 'MongoDB',\n mode: 'in-cli',\n signals: {\n npm: ['mongodb', 'mongoose'],\n python: ['pymongo', 'motor'],\n ruby: ['mongo', 'mongoid'],\n // Matches both MONGO_* and MONGODB_* prefixes (e.g. MONGO_HOST,\n // MONGODB_URI) in one pattern.\n envKeys: [/^MONGO(DB)?_/],\n },\n },\n {\n kind: 'Snowflake',\n label: 'Snowflake',\n mode: 'in-cli',\n signals: {\n npm: ['snowflake-sdk'],\n python: ['snowflake-connector-python', 'snowflake-sqlalchemy'],\n envKeys: [/^SNOWFLAKE_/],\n },\n },\n {\n // BigQuery authenticates with a Google Cloud service-account JSON key\n // file, like Firebase above — the source's only required credential field\n // is a file upload, and the terminal prompt collects single-line text, so\n // there is no in-cli path that can accept it. Deep-link to the app's\n // new-source form instead of dead-ending on an unpasteable credential.\n kind: 'BigQuery',\n label: 'BigQuery',\n mode: 'deep-link',\n signals: {\n npm: ['@google-cloud/bigquery'],\n python: ['google-cloud-bigquery'],\n envKeys: [/^BIGQUERY_/],\n },\n },\n {\n kind: 'Redshift',\n label: 'Redshift',\n mode: 'in-cli',\n signals: {\n npm: ['node-redshift'],\n python: ['redshift-connector'],\n envKeys: [/^REDSHIFT_/],\n },\n },\n {\n kind: 'MSSQL',\n label: 'SQL Server',\n mode: 'in-cli',\n signals: {\n npm: ['mssql', 'tedious'],\n python: ['pyodbc', 'pymssql'],\n envKeys: [/^MSSQL_/],\n },\n },\n {\n kind: 'Supabase',\n label: 'Supabase',\n mode: 'in-cli',\n signals: {\n npm: ['@supabase/supabase-js'],\n python: ['supabase'],\n envKeys: [/^SUPABASE_/],\n },\n },\n {\n kind: 'ClickHouse',\n label: 'ClickHouse',\n mode: 'in-cli',\n signals: {\n npm: ['@clickhouse/client'],\n python: ['clickhouse-connect', 'clickhouse-driver'],\n envKeys: [/^CLICKHOUSE_/],\n },\n },\n {\n kind: 'Convex',\n label: 'Convex',\n mode: 'in-cli',\n signals: {\n npm: ['convex'],\n python: ['convex'],\n envKeys: [/^CONVEX_/, /^NEXT_PUBLIC_CONVEX_URL$/],\n },\n },\n {\n // Firebase authenticates with a service-account JSON key file, not a\n // pasteable string. The terminal credential prompt only collects\n // single-line text, so there is no safe in-cli path: the file upload lives\n // in the app's new-source form. Deep-link there instead of dead-ending on a\n // credential the CLI cannot accept.\n kind: 'Firebase',\n label: 'Firebase',\n mode: 'deep-link',\n signals: {\n // NOTE: the `firebase` client SDK also covers auth-only projects, which\n // have no Firestore data to import. We accept the false positives — the\n // package is a strong signal for the common case.\n npm: ['firebase-admin', 'firebase'],\n python: ['firebase-admin'],\n envKeys: [/^FIREBASE_/, /^NEXT_PUBLIC_FIREBASE_/],\n },\n },\n {\n kind: 'Neon',\n label: 'Neon',\n mode: 'in-cli',\n signals: {\n npm: ['@neondatabase/serverless'],\n envKeys: [/^NEON_/],\n },\n },\n {\n kind: 'PlanetScaleMySQL',\n label: 'PlanetScale MySQL',\n mode: 'in-cli',\n signals: {\n npm: ['@planetscale/database'],\n envKeys: [/^PLANETSCALE_/],\n },\n },\n {\n kind: 'DynamoDB',\n label: 'DynamoDB',\n mode: 'in-cli',\n signals: {\n npm: ['@aws-sdk/client-dynamodb', '@aws-sdk/lib-dynamodb'],\n python: ['pynamodb'],\n },\n },\n {\n kind: 'Motherduck',\n label: 'MotherDuck',\n mode: 'in-cli',\n signals: {\n npm: ['@motherduck/wasm-client'],\n envKeys: [/^MOTHERDUCK_/],\n },\n },\n {\n kind: 'Databricks',\n label: 'Databricks',\n mode: 'in-cli',\n signals: {\n npm: ['@databricks/sql'],\n python: ['databricks-sql-connector', 'databricks-sdk'],\n envKeys: [/^DATABRICKS_/],\n },\n },\n {\n kind: 'Singlestore',\n label: 'SingleStore',\n mode: 'in-cli',\n signals: {\n python: ['singlestoredb'],\n envKeys: [/^SINGLESTORE_/],\n },\n },\n {\n kind: 'Stripe',\n label: 'Stripe',\n mode: 'in-cli',\n signals: {\n npm: ['stripe', '@stripe/stripe-js', '@stripe/react-stripe-js'],\n python: ['stripe'],\n ruby: ['stripe'],\n envKeys: [/^STRIPE_(SECRET|API)_KEY$/],\n },\n },\n {\n kind: 'Clerk',\n label: 'Clerk',\n mode: 'in-cli',\n signals: {\n npm: [\n '@clerk/nextjs',\n '@clerk/clerk-react',\n '@clerk/backend',\n '@clerk/express',\n '@clerk/fastify',\n '@clerk/remix',\n ],\n envKeys: [/^CLERK_SECRET_KEY$/, /^NEXT_PUBLIC_CLERK_/],\n },\n },\n {\n kind: 'Resend',\n label: 'Resend',\n mode: 'in-cli',\n signals: {\n npm: ['resend'],\n python: ['resend'],\n envKeys: [/^RESEND_API_KEY$/],\n },\n },\n {\n kind: 'Shopify',\n label: 'Shopify',\n mode: 'in-cli',\n signals: {\n npm: ['@shopify/shopify-api', 'shopify-api-node'],\n python: ['shopifyapi'],\n envKeys: [/^SHOPIFY_/],\n },\n },\n {\n kind: 'Klaviyo',\n label: 'Klaviyo',\n mode: 'in-cli',\n signals: {\n npm: ['klaviyo-api'],\n python: ['klaviyo-api'],\n envKeys: [/^KLAVIYO_/],\n },\n },\n {\n kind: 'Chargebee',\n label: 'Chargebee',\n mode: 'in-cli',\n signals: {\n npm: ['chargebee'],\n python: ['chargebee'],\n envKeys: [/^CHARGEBEE_/],\n },\n },\n {\n kind: 'Paddle',\n label: 'Paddle',\n mode: 'in-cli',\n signals: {\n npm: ['@paddle/paddle-node-sdk', '@paddle/paddle-js'],\n envKeys: [/^PADDLE_/],\n },\n },\n {\n kind: 'Polar',\n label: 'Polar',\n mode: 'in-cli',\n signals: {\n npm: ['@polar-sh/sdk', '@polar-sh/nextjs'],\n envKeys: [/^POLAR_/],\n },\n },\n {\n kind: 'Mailchimp',\n label: 'Mailchimp',\n mode: 'in-cli',\n signals: {\n npm: ['@mailchimp/mailchimp_marketing'],\n python: ['mailchimp-marketing'],\n envKeys: [/^MAILCHIMP_/],\n },\n },\n {\n kind: 'CustomerIO',\n label: 'Customer.io',\n mode: 'in-cli',\n signals: {\n npm: ['customerio-node'],\n python: ['customerio'],\n envKeys: [/^CUSTOMER_?IO_/],\n },\n },\n {\n kind: 'Typeform',\n label: 'Typeform',\n mode: 'in-cli',\n signals: {\n npm: ['@typeform/api-client'],\n envKeys: [/^TYPEFORM_/],\n },\n },\n {\n kind: 'Sentry',\n label: 'Sentry',\n mode: 'in-cli',\n signals: {\n npm: [\n '@sentry/node',\n '@sentry/browser',\n '@sentry/react',\n '@sentry/nextjs',\n ],\n python: ['sentry-sdk'],\n ruby: ['sentry-ruby'],\n },\n },\n {\n kind: 'Plaid',\n label: 'Plaid',\n mode: 'in-cli',\n signals: {\n npm: ['plaid'],\n python: ['plaid-python', 'plaid'],\n ruby: ['plaid'],\n envKeys: [/^PLAID_/],\n },\n },\n {\n kind: 'Braintree',\n label: 'Braintree',\n mode: 'in-cli',\n signals: {\n npm: ['braintree'],\n python: ['braintree'],\n ruby: ['braintree'],\n envKeys: [/^BRAINTREE_/],\n },\n },\n {\n kind: 'Square',\n label: 'Square',\n mode: 'in-cli',\n signals: {\n npm: ['square'],\n python: ['squareup'],\n ruby: ['square'],\n envKeys: [/^SQUARE_/],\n },\n },\n {\n kind: 'GoCardless',\n label: 'GoCardless',\n mode: 'in-cli',\n signals: {\n npm: ['gocardless-nodejs'],\n python: ['gocardless-pro'],\n ruby: ['gocardless_pro'],\n envKeys: [/^GOCARDLESS_/],\n },\n },\n {\n kind: 'Mollie',\n label: 'Mollie',\n mode: 'in-cli',\n signals: {\n npm: ['@mollie/api-client'],\n python: ['mollie-api-python'],\n envKeys: [/^MOLLIE_/],\n },\n },\n {\n kind: 'CheckoutCom',\n label: 'Checkout.com',\n mode: 'in-cli',\n signals: {\n npm: ['checkout-sdk-node'],\n python: ['checkout-sdk'],\n // Checkout.com's own convention is the CKO_ prefix.\n envKeys: [/^CKO_/, /^CHECKOUT_COM_/],\n },\n },\n {\n kind: 'Recurly',\n label: 'Recurly',\n mode: 'in-cli',\n signals: {\n npm: ['recurly'],\n python: ['recurly'],\n ruby: ['recurly'],\n envKeys: [/^RECURLY_/],\n },\n },\n {\n kind: 'RevenueCat',\n label: 'RevenueCat',\n mode: 'in-cli',\n signals: {\n npm: [\n '@revenuecat/purchases-js',\n 'react-native-purchases',\n '@revenuecat/purchases-capacitor',\n ],\n envKeys: [/^REVENUE_?CAT_/],\n },\n },\n {\n kind: 'Twilio',\n label: 'Twilio',\n mode: 'in-cli',\n signals: {\n npm: ['twilio'],\n python: ['twilio'],\n ruby: ['twilio-ruby'],\n envKeys: [/^TWILIO_/],\n },\n },\n {\n kind: 'SendGrid',\n label: 'SendGrid',\n mode: 'in-cli',\n signals: {\n npm: ['@sendgrid/mail', '@sendgrid/client'],\n python: ['sendgrid'],\n ruby: ['sendgrid-ruby'],\n envKeys: [/^SENDGRID_/],\n },\n },\n {\n kind: 'Mailgun',\n label: 'Mailgun',\n mode: 'in-cli',\n signals: {\n npm: ['mailgun.js', 'mailgun-js'],\n python: ['mailgun'],\n ruby: ['mailgun-ruby'],\n envKeys: [/^MAILGUN_/],\n },\n },\n {\n kind: 'Postmark',\n label: 'Postmark',\n mode: 'in-cli',\n signals: {\n npm: ['postmark'],\n python: ['postmarker'],\n ruby: ['postmark'],\n envKeys: [/^POSTMARK_/],\n },\n },\n {\n kind: 'Brevo',\n label: 'Brevo',\n mode: 'in-cli',\n signals: {\n npm: ['@getbrevo/brevo', 'sib-api-v3-sdk'],\n python: ['sib-api-v3-sdk'],\n envKeys: [/^BREVO_/],\n },\n },\n {\n kind: 'MailerLite',\n label: 'MailerLite',\n mode: 'in-cli',\n signals: {\n npm: ['@mailerlite/mailerlite-nodejs'],\n python: ['mailerlite'],\n envKeys: [/^MAILERLITE_/],\n },\n },\n {\n kind: 'Mailjet',\n label: 'Mailjet',\n mode: 'in-cli',\n signals: {\n npm: ['node-mailjet'],\n python: ['mailjet-rest'],\n // Mailjet's documented env convention is MJ_APIKEY_PUBLIC / *_PRIVATE.\n envKeys: [/^MAILJET_/, /^MJ_APIKEY_/],\n },\n },\n {\n kind: 'LaunchDarkly',\n label: 'LaunchDarkly',\n mode: 'in-cli',\n signals: {\n npm: [\n 'launchdarkly-node-server-sdk',\n '@launchdarkly/node-server-sdk',\n 'launchdarkly-js-client-sdk',\n 'launchdarkly-react-client-sdk',\n ],\n python: ['launchdarkly-server-sdk'],\n ruby: ['launchdarkly-server-sdk'],\n envKeys: [/^LAUNCHDARKLY_/, /^LD_SDK_KEY$/],\n },\n },\n {\n kind: 'Optimizely',\n label: 'Optimizely',\n mode: 'in-cli',\n signals: {\n npm: ['@optimizely/optimizely-sdk'],\n python: ['optimizely-sdk'],\n envKeys: [/^OPTIMIZELY_/],\n },\n },\n {\n kind: 'Braze',\n label: 'Braze',\n mode: 'in-cli',\n signals: {\n npm: ['@braze/web-sdk', '@braze/react-native-sdk'],\n python: ['braze-client'],\n envKeys: [/^BRAZE_/],\n },\n },\n {\n kind: 'Rollbar',\n label: 'Rollbar',\n mode: 'in-cli',\n signals: {\n npm: ['rollbar'],\n python: ['rollbar', 'pyrollbar'],\n ruby: ['rollbar'],\n envKeys: [/^ROLLBAR_/],\n },\n },\n {\n kind: 'Okta',\n label: 'Okta',\n mode: 'in-cli',\n signals: {\n npm: ['@okta/okta-sdk-nodejs', '@okta/okta-auth-js', '@okta/okta-react'],\n python: ['okta'],\n envKeys: [/^OKTA_/],\n },\n },\n {\n kind: 'WorkOS',\n label: 'WorkOS',\n mode: 'in-cli',\n signals: {\n npm: ['@workos-inc/node'],\n python: ['workos'],\n envKeys: [/^WORKOS_/],\n },\n },\n {\n kind: 'Notion',\n label: 'Notion',\n mode: 'in-cli',\n signals: {\n npm: ['@notionhq/client'],\n python: ['notion-client'],\n envKeys: [/^NOTION_/],\n },\n },\n {\n kind: 'FullStory',\n label: 'FullStory',\n mode: 'in-cli',\n signals: {\n npm: ['@fullstory/browser', '@fullstory/react-native'],\n envKeys: [/^FULLSTORY_/],\n },\n },\n {\n kind: 'Amplitude',\n label: 'Amplitude',\n mode: 'in-cli',\n signals: {\n npm: [\n '@amplitude/analytics-browser',\n '@amplitude/analytics-node',\n '@amplitude/analytics-react-native',\n 'amplitude-js',\n ],\n python: ['amplitude-analytics'],\n envKeys: [/^AMPLITUDE_/],\n },\n },\n {\n kind: 'Mixpanel',\n label: 'Mixpanel',\n mode: 'in-cli',\n signals: {\n npm: ['mixpanel', 'mixpanel-browser'],\n python: ['mixpanel'],\n ruby: ['mixpanel-ruby'],\n envKeys: [/^MIXPANEL_/],\n },\n },\n {\n kind: 'Pendo',\n label: 'Pendo',\n mode: 'in-cli',\n signals: {\n npm: ['@pendo/agent'],\n envKeys: [/^PENDO_/],\n },\n },\n {\n kind: 'Salesforce',\n label: 'Salesforce',\n mode: 'deep-link',\n signals: {\n npm: ['jsforce'],\n python: ['simple-salesforce'],\n envKeys: [/^SALESFORCE_/],\n },\n },\n {\n kind: 'Hubspot',\n label: 'HubSpot',\n mode: 'deep-link',\n signals: {\n npm: ['@hubspot/api-client'],\n python: ['hubspot-api-client'],\n envKeys: [/^HUBSPOT_/],\n },\n },\n {\n kind: 'Zendesk',\n label: 'Zendesk',\n mode: 'deep-link',\n signals: {\n npm: ['node-zendesk'],\n python: ['zenpy'],\n envKeys: [/^ZENDESK_/],\n },\n },\n {\n kind: 'Intercom',\n label: 'Intercom',\n mode: 'deep-link',\n signals: {\n npm: ['intercom-client', '@intercom/messenger-js-sdk'],\n python: ['python-intercom'],\n envKeys: [/^INTERCOM_/],\n },\n },\n {\n kind: 'Linear',\n label: 'Linear',\n mode: 'deep-link',\n signals: {\n npm: ['@linear/sdk'],\n envKeys: [/^LINEAR_API_KEY$/],\n },\n },\n {\n // OAuth-only in PostHog (Slack app integration), so deep-link.\n kind: 'Slack',\n label: 'Slack',\n mode: 'deep-link',\n signals: {\n npm: ['@slack/web-api', '@slack/bolt'],\n python: ['slack-sdk', 'slack-bolt'],\n envKeys: [/^SLACK_(BOT|APP|SIGNING|CLIENT)_/],\n },\n },\n {\n // 'Github' (not 'GitHub') — matches the ExternalDataSourceType value.\n // Default auth is the GitHub App integration (OAuth), so deep-link.\n kind: 'Github',\n label: 'GitHub',\n mode: 'deep-link',\n signals: {\n npm: ['@octokit/rest', '@octokit/core', '@octokit/graphql', 'octokit'],\n python: ['pygithub'],\n ruby: ['octokit'],\n },\n },\n];\n\n// ============================================================\n// Additional released source types (see PostHog data-warehouse\n// source catalog). Detected by SDK package or .env key convention.\n// ============================================================\n// ---- LLM / AI ----\nconst LLM_SOURCE_DETECTORS: SourceDetector[] = [\n {\n kind: 'OpenAI',\n label: 'OpenAI',\n mode: 'in-cli',\n signals: {\n npm: ['openai'],\n python: ['openai'],\n envKeys: [/^OPENAI_/],\n },\n },\n {\n kind: 'Anthropic',\n label: 'Anthropic',\n mode: 'in-cli',\n signals: {\n npm: ['@anthropic-ai/sdk'],\n python: ['anthropic'],\n envKeys: [/^ANTHROPIC_/],\n },\n },\n {\n kind: 'Cohere',\n label: 'Cohere',\n mode: 'in-cli',\n signals: {\n npm: ['cohere-ai'],\n python: ['cohere'],\n envKeys: [/^COHERE_/],\n },\n },\n {\n kind: 'MistralAI',\n label: 'Mistral AI',\n mode: 'in-cli',\n signals: {\n npm: ['@mistralai/mistralai'],\n python: ['mistralai'],\n envKeys: [/^MISTRAL_/],\n },\n },\n {\n kind: 'Groq',\n label: 'Groq',\n mode: 'in-cli',\n signals: {\n npm: ['groq-sdk'],\n python: ['groq'],\n envKeys: [/^GROQ_/],\n },\n },\n {\n kind: 'TogetherAI',\n label: 'Together AI',\n mode: 'in-cli',\n signals: {\n npm: ['together-ai'],\n python: ['together'],\n envKeys: [/^TOGETHER_/],\n },\n },\n {\n kind: 'FireworksAI',\n label: 'Fireworks AI',\n mode: 'in-cli',\n signals: {\n python: ['fireworks-ai'],\n envKeys: [/^FIREWORKS_/],\n },\n },\n {\n kind: 'Replicate',\n label: 'Replicate',\n mode: 'in-cli',\n signals: {\n npm: ['replicate'],\n python: ['replicate'],\n envKeys: [/^REPLICATE_/],\n },\n },\n {\n kind: 'HuggingFace',\n label: 'Hugging Face',\n mode: 'in-cli',\n signals: {\n npm: ['@huggingface/inference'],\n python: ['huggingface-hub'],\n envKeys: [/^HUGGINGFACE_/, /^HF_TOKEN$/],\n },\n },\n {\n kind: 'ElevenLabs',\n label: 'ElevenLabs',\n mode: 'in-cli',\n signals: {\n npm: ['@elevenlabs/elevenlabs-js', 'elevenlabs'],\n python: ['elevenlabs'],\n envKeys: [/^ELEVENLABS_/, /^ELEVEN_LABS_/],\n },\n },\n {\n kind: 'Deepgram',\n label: 'Deepgram',\n mode: 'in-cli',\n signals: {\n npm: ['@deepgram/sdk'],\n python: ['deepgram-sdk'],\n envKeys: [/^DEEPGRAM_/],\n },\n },\n {\n kind: 'AssemblyAI',\n label: 'AssemblyAI',\n mode: 'in-cli',\n signals: {\n npm: ['assemblyai'],\n python: ['assemblyai'],\n envKeys: [/^ASSEMBLYAI_/],\n },\n },\n {\n kind: 'Langfuse',\n label: 'Langfuse',\n mode: 'in-cli',\n signals: {\n npm: ['langfuse'],\n python: ['langfuse'],\n envKeys: [/^LANGFUSE_/],\n },\n },\n {\n kind: 'LangSmith',\n label: 'LangSmith',\n mode: 'in-cli',\n signals: {\n npm: ['langsmith'],\n python: ['langsmith'],\n envKeys: [/^LANGSMITH_/, /^LANGCHAIN_API_KEY$/],\n },\n },\n {\n kind: 'Firecrawl',\n label: 'Firecrawl',\n mode: 'in-cli',\n signals: {\n npm: ['@mendable/firecrawl-js'],\n python: ['firecrawl-py'],\n envKeys: [/^FIRECRAWL_/],\n },\n },\n {\n kind: 'Mem0',\n label: 'Mem0',\n mode: 'in-cli',\n signals: {\n npm: ['mem0ai'],\n python: ['mem0ai'],\n envKeys: [/^MEM0_/],\n },\n },\n {\n kind: 'Vellum',\n label: 'Vellum',\n mode: 'in-cli',\n signals: {\n npm: ['vellum-ai'],\n python: ['vellum-ai'],\n envKeys: [/^VELLUM_/],\n },\n },\n {\n kind: 'Helicone',\n label: 'Helicone',\n mode: 'in-cli',\n signals: {\n npm: ['@helicone/helpers'],\n envKeys: [/^HELICONE_/],\n },\n },\n {\n kind: 'OpenRouter',\n label: 'OpenRouter',\n mode: 'in-cli',\n signals: {\n npm: ['@openrouter/ai-sdk-provider'],\n envKeys: [/^OPENROUTER_/],\n },\n },\n {\n kind: 'Browserbase',\n label: 'Browserbase',\n mode: 'in-cli',\n signals: {\n npm: ['@browserbasehq/sdk', '@browserbasehq/stagehand'],\n python: ['browserbase'],\n envKeys: [/^BROWSERBASE_/],\n },\n },\n {\n kind: 'E2B',\n label: 'E2B',\n mode: 'in-cli',\n signals: {\n npm: ['e2b', '@e2b/code-interpreter'],\n python: ['e2b', 'e2b-code-interpreter'],\n envKeys: [/^E2B_/],\n },\n },\n {\n kind: 'WeightsAndBiases',\n label: 'Weights & Biases',\n mode: 'in-cli',\n signals: {\n python: ['wandb'],\n envKeys: [/^WANDB_/],\n },\n },\n {\n kind: 'LlamaCloud',\n label: 'LlamaCloud',\n mode: 'in-cli',\n signals: {\n npm: ['llama-cloud-services'],\n python: ['llama-cloud-services'],\n envKeys: [/^LLAMA_CLOUD_/],\n },\n },\n {\n kind: 'Zep',\n label: 'Zep',\n mode: 'in-cli',\n signals: {\n npm: ['@getzep/zep-cloud'],\n python: ['zep-cloud'],\n envKeys: [/^ZEP_API_KEY$/],\n },\n },\n];\n\nconst OTHER_SOURCE_DETECTORS: SourceDetector[] = [\n // ---- Payments / billing ----\n {\n kind: 'Paystack',\n label: 'Paystack',\n mode: 'in-cli',\n signals: {\n python: ['paystackapi'],\n envKeys: [/^PAYSTACK_/],\n },\n },\n {\n kind: 'Orb',\n label: 'Orb',\n mode: 'in-cli',\n signals: {\n npm: ['orb-billing'],\n python: ['orb-billing'],\n envKeys: [/^ORB_/],\n },\n },\n {\n kind: 'Lago',\n label: 'Lago',\n mode: 'in-cli',\n signals: {\n npm: ['lago-javascript-client'],\n python: ['lago-python-client'],\n envKeys: [/^LAGO_/],\n },\n },\n {\n kind: 'Zuora',\n label: 'Zuora',\n mode: 'in-cli',\n signals: {\n envKeys: [/^ZUORA_/],\n },\n },\n {\n kind: 'Stigg',\n label: 'Stigg',\n mode: 'in-cli',\n signals: {\n npm: ['@stigg/node-server-sdk'],\n envKeys: [/^STIGG_/],\n },\n },\n {\n kind: 'Ramp',\n label: 'Ramp',\n mode: 'in-cli',\n signals: {\n envKeys: [/^RAMP_/],\n },\n },\n {\n kind: 'Brex',\n label: 'Brex',\n mode: 'in-cli',\n signals: {\n envKeys: [/^BREX_/],\n },\n },\n {\n kind: 'Tremendous',\n label: 'Tremendous',\n mode: 'in-cli',\n signals: {\n envKeys: [/^TREMENDOUS_/],\n },\n },\n {\n kind: 'Maxio',\n label: 'Maxio',\n mode: 'in-cli',\n signals: {\n envKeys: [/^MAXIO_/],\n },\n },\n {\n kind: 'Chargify',\n label: 'Chargify',\n mode: 'in-cli',\n signals: {\n envKeys: [/^CHARGIFY_/],\n },\n },\n {\n kind: 'Invoiced',\n label: 'Invoiced',\n mode: 'in-cli',\n signals: {\n npm: ['invoiced'],\n python: ['invoiced'],\n envKeys: [/^INVOICED_/],\n },\n },\n {\n kind: 'LemonSqueezy',\n label: 'Lemon Squeezy',\n mode: 'in-cli',\n signals: {\n npm: ['@lemonsqueezy/lemonsqueezy.js'],\n envKeys: [/^LEMONSQUEEZY_/, /^LEMON_SQUEEZY_/],\n },\n },\n {\n kind: 'Razorpay',\n label: 'Razorpay',\n mode: 'in-cli',\n signals: {\n npm: ['razorpay'],\n python: ['razorpay'],\n ruby: ['razorpay'],\n envKeys: [/^RAZORPAY_/],\n },\n },\n {\n kind: 'Adyen',\n label: 'Adyen',\n mode: 'in-cli',\n signals: {\n npm: ['@adyen/api-library'],\n python: ['adyen'],\n envKeys: [/^ADYEN_/],\n },\n },\n {\n kind: 'ChartMogul',\n label: 'ChartMogul',\n mode: 'in-cli',\n signals: {\n npm: ['chartmogul-node'],\n python: ['chartmogul'],\n envKeys: [/^CHARTMOGUL_/],\n },\n },\n {\n kind: 'Airwallex',\n label: 'Airwallex',\n mode: 'in-cli',\n signals: {\n npm: ['airwallex-payment-elements'],\n envKeys: [/^AIRWALLEX_/],\n },\n },\n {\n kind: 'Flutterwave',\n label: 'Flutterwave',\n mode: 'in-cli',\n signals: {\n npm: ['flutterwave-node-v3'],\n python: ['flutterwave'],\n envKeys: [/^FLUTTERWAVE_/, /^FLW_(PUBLIC|SECRET)_KEY$/],\n },\n },\n {\n kind: 'DodoPayments',\n label: 'Dodo Payments',\n mode: 'in-cli',\n signals: {\n npm: ['dodopayments'],\n python: ['dodopayments'],\n envKeys: [/^DODO_PAYMENTS_/],\n },\n },\n {\n kind: 'Whop',\n label: 'Whop',\n mode: 'in-cli',\n signals: {\n npm: ['@whop/api', '@whop-apps/sdk'],\n envKeys: [/^WHOP_/],\n },\n },\n // ---- Email / marketing ----\n {\n kind: 'SparkPost',\n label: 'SparkPost',\n mode: 'in-cli',\n signals: {\n npm: ['sparkpost'],\n python: ['sparkpost'],\n envKeys: [/^SPARKPOST_/],\n },\n },\n {\n kind: 'MailerSend',\n label: 'MailerSend',\n mode: 'in-cli',\n signals: {\n npm: ['mailersend'],\n python: ['mailersend'],\n envKeys: [/^MAILERSEND_/],\n },\n },\n {\n kind: 'Iterable',\n label: 'Iterable',\n mode: 'in-cli',\n signals: {\n envKeys: [/^ITERABLE_/],\n },\n },\n {\n kind: 'ConvertKit',\n label: 'ConvertKit',\n mode: 'in-cli',\n signals: {\n envKeys: [/^CONVERTKIT_/],\n },\n },\n {\n kind: 'Drip',\n label: 'Drip',\n mode: 'in-cli',\n signals: {\n npm: ['drip-nodejs'],\n envKeys: [/^DRIP_/],\n },\n },\n {\n kind: 'Omnisend',\n label: 'Omnisend',\n mode: 'in-cli',\n signals: {\n envKeys: [/^OMNISEND_/],\n },\n },\n {\n kind: 'EmailOctopus',\n label: 'EmailOctopus',\n mode: 'in-cli',\n signals: {\n envKeys: [/^EMAILOCTOPUS_/, /^EMAIL_OCTOPUS_/],\n },\n },\n {\n kind: 'Elasticemail',\n label: 'Elastic Email',\n mode: 'in-cli',\n signals: {\n envKeys: [/^ELASTICEMAIL_/, /^ELASTIC_EMAIL_/],\n },\n },\n {\n kind: 'CampaignMonitor',\n label: 'Campaign Monitor',\n mode: 'in-cli',\n signals: {\n npm: ['createsend-node'],\n envKeys: [/^CAMPAIGN_MONITOR_/, /^CREATESEND_/],\n },\n },\n {\n kind: 'Lemlist',\n label: 'Lemlist',\n mode: 'in-cli',\n signals: {\n envKeys: [/^LEMLIST_/],\n },\n },\n {\n kind: 'Loops',\n label: 'Loops',\n mode: 'in-cli',\n signals: {\n npm: ['loops'],\n envKeys: [/^LOOPS_/],\n },\n },\n {\n kind: 'Knock',\n label: 'Knock',\n mode: 'in-cli',\n signals: {\n npm: ['@knocklabs/node', '@knocklabs/client'],\n python: ['knockapi'],\n envKeys: [/^KNOCK_/],\n },\n },\n {\n kind: 'AwsSes',\n label: 'Amazon SES',\n mode: 'in-cli',\n signals: {\n npm: ['@aws-sdk/client-ses', '@aws-sdk/client-sesv2'],\n // A bare /^AWS_/ would fire on every AWS project, so we match only\n // the SES-specific prefix.\n envKeys: [/^AWS_SES_/],\n },\n },\n {\n kind: 'Beehiiv',\n label: 'beehiiv',\n mode: 'in-cli',\n signals: {\n envKeys: [/^BEEHIIV_/],\n },\n },\n {\n kind: 'Mailtrap',\n label: 'Mailtrap',\n mode: 'in-cli',\n signals: {\n npm: ['mailtrap'],\n python: ['mailtrap'],\n envKeys: [/^MAILTRAP_/],\n },\n },\n {\n kind: 'Plunk',\n label: 'Plunk',\n mode: 'in-cli',\n signals: {\n npm: ['@plunk/node'],\n envKeys: [/^PLUNK_/],\n },\n },\n {\n kind: 'Ortto',\n label: 'Ortto',\n mode: 'in-cli',\n signals: {\n envKeys: [/^ORTTO_/],\n },\n },\n {\n kind: 'Postscript',\n label: 'Postscript',\n mode: 'in-cli',\n signals: {\n envKeys: [/^POSTSCRIPT_/],\n },\n },\n {\n kind: 'Marketo',\n label: 'Marketo',\n mode: 'in-cli',\n signals: {\n python: ['marketorestpython'],\n envKeys: [/^MARKETO_/],\n },\n },\n {\n kind: 'Lob',\n label: 'Lob',\n mode: 'in-cli',\n signals: {\n npm: ['lob'],\n python: ['lob'],\n envKeys: [/^LOB_API_KEY$/],\n },\n },\n // ---- Product analytics / CDP ----\n {\n kind: 'Segment',\n label: 'Segment',\n mode: 'in-cli',\n signals: {\n npm: ['@segment/analytics-node', 'analytics-node'],\n python: ['segment-analytics-python', 'analytics-python'],\n envKeys: [/^SEGMENT_/],\n },\n },\n {\n kind: 'Snowplow',\n label: 'Snowplow Analytics',\n mode: 'in-cli',\n signals: {\n npm: ['@snowplow/node-tracker'],\n python: ['snowplow-tracker'],\n envKeys: [/^SNOWPLOW_/],\n },\n },\n {\n kind: 'Matomo',\n label: 'Matomo',\n mode: 'in-cli',\n signals: {\n npm: ['matomo-tracker'],\n envKeys: [/^MATOMO_/],\n },\n },\n {\n kind: 'Plausible',\n label: 'Plausible',\n mode: 'in-cli',\n signals: {\n npm: ['plausible-tracker'],\n envKeys: [/^PLAUSIBLE_/],\n },\n },\n // ---- Feature flags / experimentation ----\n {\n kind: 'ConfigCat',\n label: 'ConfigCat',\n mode: 'in-cli',\n signals: {\n npm: ['configcat-node', 'configcat-js'],\n python: ['configcat-client'],\n envKeys: [/^CONFIGCAT_/],\n },\n },\n {\n kind: 'Flagsmith',\n label: 'Flagsmith',\n mode: 'in-cli',\n signals: {\n npm: ['flagsmith-nodejs', 'flagsmith'],\n python: ['flagsmith'],\n envKeys: [/^FLAGSMITH_/],\n },\n },\n {\n kind: 'Unleash',\n label: 'Unleash',\n mode: 'in-cli',\n signals: {\n npm: ['unleash-client'],\n python: ['unleashclient'],\n envKeys: [/^UNLEASH_/],\n },\n },\n {\n kind: 'SplitIo',\n label: 'Split.io',\n mode: 'in-cli',\n signals: {\n npm: ['@splitsoftware/splitio'],\n python: ['splitio-client'],\n envKeys: [/^SPLITIO_/, /^SPLIT_IO_/],\n },\n },\n // ---- Auth / secrets ----\n {\n kind: 'Stytch',\n label: 'Stytch',\n mode: 'in-cli',\n signals: {\n npm: ['stytch'],\n python: ['stytch'],\n envKeys: [/^STYTCH_/],\n },\n },\n {\n kind: 'Doppler',\n label: 'Doppler',\n mode: 'in-cli',\n signals: {\n npm: ['@dopplerhq/node-sdk'],\n envKeys: [/^DOPPLER_/],\n },\n },\n {\n kind: 'Infisical',\n label: 'Infisical',\n mode: 'in-cli',\n signals: {\n npm: ['@infisical/sdk'],\n python: ['infisicalsdk'],\n envKeys: [/^INFISICAL_/],\n },\n },\n {\n kind: 'OnePassword',\n label: '1Password',\n mode: 'in-cli',\n signals: {\n npm: ['@1password/sdk'],\n python: ['onepassword-sdk'],\n envKeys: [/^ONEPASSWORD_/, /^OP_SERVICE_ACCOUNT_TOKEN$/],\n },\n },\n {\n kind: 'Persona',\n label: 'Persona',\n mode: 'in-cli',\n signals: {\n envKeys: [/^PERSONA_/],\n },\n },\n // ---- Comms / webhooks / voice ----\n {\n kind: 'Svix',\n label: 'Svix',\n mode: 'in-cli',\n signals: {\n npm: ['svix'],\n python: ['svix'],\n envKeys: [/^SVIX_/],\n },\n },\n {\n kind: 'Mux',\n label: 'Mux',\n mode: 'in-cli',\n signals: {\n npm: ['@mux/mux-node'],\n python: ['mux-python'],\n envKeys: [/^MUX_/],\n },\n },\n {\n kind: 'Vapi',\n label: 'Vapi',\n mode: 'in-cli',\n signals: {\n npm: ['@vapi-ai/server-sdk'],\n python: ['vapi-server-sdk'],\n envKeys: [/^VAPI_/],\n },\n },\n {\n kind: 'Aircall',\n label: 'Aircall',\n mode: 'in-cli',\n signals: {\n envKeys: [/^AIRCALL_/],\n },\n },\n {\n kind: 'JustCall',\n label: 'JustCall',\n mode: 'in-cli',\n signals: {\n envKeys: [/^JUSTCALL_/],\n },\n },\n {\n kind: 'Telnyx',\n label: 'Telnyx',\n mode: 'in-cli',\n signals: {\n npm: ['telnyx'],\n python: ['telnyx'],\n envKeys: [/^TELNYX_/],\n },\n },\n {\n kind: 'Plivo',\n label: 'Plivo',\n mode: 'in-cli',\n signals: {\n npm: ['plivo'],\n python: ['plivo'],\n envKeys: [/^PLIVO_/],\n },\n },\n {\n kind: 'Courier',\n label: 'Courier',\n mode: 'in-cli',\n signals: {\n npm: ['@trycourier/courier'],\n python: ['trycourier'],\n // COURIER_ is a generic shipping word, so we match the exact key.\n envKeys: [/^COURIER_AUTH_TOKEN$/],\n },\n },\n // ---- E-commerce / logistics ----\n {\n kind: 'WooCommerce',\n label: 'WooCommerce',\n mode: 'in-cli',\n signals: {\n npm: ['@woocommerce/woocommerce-rest-api'],\n python: ['woocommerce'],\n envKeys: [/^WOOCOMMERCE_/],\n },\n },\n {\n kind: 'Recharge',\n label: 'Recharge',\n mode: 'in-cli',\n signals: {\n envKeys: [/^RECHARGE_/],\n },\n },\n {\n kind: 'Commercetools',\n label: 'commercetools',\n mode: 'in-cli',\n signals: {\n npm: ['@commercetools/platform-sdk'],\n python: ['commercetools'],\n envKeys: [/^CTP_/, /^COMMERCETOOLS_/],\n },\n },\n {\n kind: 'Webflow',\n label: 'Webflow',\n mode: 'in-cli',\n signals: {\n npm: ['webflow-api'],\n envKeys: [/^WEBFLOW_/],\n },\n },\n {\n kind: 'Easypost',\n label: 'EasyPost',\n mode: 'in-cli',\n signals: {\n npm: ['@easypost/api'],\n python: ['easypost'],\n envKeys: [/^EASYPOST_/],\n },\n },\n {\n kind: 'Shippo',\n label: 'Shippo',\n mode: 'in-cli',\n signals: {\n npm: ['shippo'],\n python: ['shippo'],\n envKeys: [/^SHIPPO_/],\n },\n },\n {\n kind: 'ShipStation',\n label: 'ShipStation',\n mode: 'in-cli',\n signals: {\n envKeys: [/^SHIPSTATION_/],\n },\n },\n {\n kind: 'Squarespace',\n label: 'Squarespace',\n mode: 'in-cli',\n signals: {\n envKeys: [/^SQUARESPACE_/],\n },\n },\n {\n kind: 'Printify',\n label: 'Printify',\n mode: 'in-cli',\n signals: {\n envKeys: [/^PRINTIFY_/],\n },\n },\n {\n kind: 'BigCommerce',\n label: 'BigCommerce',\n mode: 'in-cli',\n signals: {\n npm: ['node-bigcommerce'],\n envKeys: [/^BIGCOMMERCE_/],\n },\n },\n // ---- Support / helpdesk ----\n {\n kind: 'Freshdesk',\n label: 'Freshdesk',\n mode: 'in-cli',\n signals: {\n python: ['python-freshdesk'],\n envKeys: [/^FRESHDESK_/],\n },\n },\n {\n kind: 'Front',\n label: 'Front',\n mode: 'in-cli',\n signals: {\n envKeys: [/^FRONTAPP_/, /^FRONT_API_/],\n },\n },\n {\n kind: 'Gorgias',\n label: 'Gorgias',\n mode: 'in-cli',\n signals: {\n envKeys: [/^GORGIAS_/],\n },\n },\n {\n kind: 'Chatwoot',\n label: 'Chatwoot',\n mode: 'in-cli',\n signals: {\n envKeys: [/^CHATWOOT_/],\n },\n },\n {\n kind: 'Kustomer',\n label: 'Kustomer',\n mode: 'in-cli',\n signals: {\n envKeys: [/^KUSTOMER_/],\n },\n },\n {\n kind: 'Plain',\n label: 'Plain',\n mode: 'in-cli',\n signals: {\n npm: ['@team-plain/typescript-sdk'],\n envKeys: [/^PLAIN_/],\n },\n },\n {\n kind: 'Canny',\n label: 'Canny',\n mode: 'in-cli',\n signals: {\n envKeys: [/^CANNY_/],\n },\n },\n {\n kind: 'Pylon',\n label: 'Pylon',\n mode: 'in-cli',\n signals: {\n envKeys: [/^PYLON_/],\n },\n },\n // ---- Dev / infra / observability ----\n {\n kind: 'GitLab',\n label: 'GitLab',\n mode: 'in-cli',\n signals: {\n npm: ['@gitbeaker/rest'],\n python: ['python-gitlab'],\n ruby: ['gitlab'],\n envKeys: [/^GITLAB_/],\n },\n },\n {\n kind: 'Bitbucket',\n label: 'Atlassian Bitbucket Cloud',\n mode: 'in-cli',\n signals: {\n npm: ['bitbucket'],\n envKeys: [/^BITBUCKET_/],\n },\n },\n {\n kind: 'Gitea',\n label: 'Gitea',\n mode: 'in-cli',\n signals: {\n npm: ['gitea-js'],\n envKeys: [/^GITEA_/],\n },\n },\n {\n kind: 'Datadog',\n label: 'Datadog',\n mode: 'in-cli',\n signals: {\n npm: ['@datadog/datadog-api-client', 'dd-trace'],\n python: ['datadog', 'datadog-api-client'],\n ruby: ['dogapi'],\n envKeys: [/^DATADOG_/, /^DD_API_KEY$/, /^DD_APP_KEY$/],\n },\n },\n {\n kind: 'NewRelic',\n label: 'New Relic',\n mode: 'in-cli',\n signals: {\n npm: ['newrelic'],\n python: ['newrelic'],\n ruby: ['newrelic_rpm'],\n envKeys: [/^NEW_RELIC_/, /^NEWRELIC_/],\n },\n },\n {\n kind: 'Cloudflare',\n label: 'Cloudflare',\n mode: 'in-cli',\n signals: {\n npm: ['cloudflare'],\n python: ['cloudflare'],\n envKeys: [/^CLOUDFLARE_/, /^CF_API_TOKEN$/],\n },\n },\n {\n kind: 'Elasticsearch',\n label: 'Elasticsearch',\n mode: 'in-cli',\n signals: {\n npm: ['@elastic/elasticsearch'],\n python: ['elasticsearch'],\n ruby: ['elasticsearch'],\n envKeys: [/^ELASTICSEARCH_/],\n },\n },\n {\n kind: 'Snyk',\n label: 'Snyk',\n mode: 'in-cli',\n signals: {\n npm: ['snyk'],\n python: ['pysnyk'],\n envKeys: [/^SNYK_/],\n },\n },\n {\n kind: 'PagerDuty',\n label: 'PagerDuty',\n mode: 'in-cli',\n signals: {\n npm: ['@pagerduty/pdjs'],\n python: ['pdpyras'],\n envKeys: [/^PAGERDUTY_/, /^PD_API_KEY$/],\n },\n },\n {\n kind: 'Opsgenie',\n label: 'Opsgenie',\n mode: 'in-cli',\n signals: {\n envKeys: [/^OPSGENIE_/],\n },\n },\n {\n kind: 'IncidentIo',\n label: 'incident.io',\n mode: 'in-cli',\n signals: {\n envKeys: [/^INCIDENT_IO_/, /^INCIDENTIO_/],\n },\n },\n {\n kind: 'Bugsnag',\n label: 'Bugsnag',\n mode: 'in-cli',\n signals: {\n npm: ['@bugsnag/js'],\n python: ['bugsnag'],\n ruby: ['bugsnag'],\n envKeys: [/^BUGSNAG_/],\n },\n },\n {\n kind: 'Honeybadger',\n label: 'Honeybadger',\n mode: 'in-cli',\n signals: {\n npm: ['@honeybadger-io/js'],\n python: ['honeybadger'],\n ruby: ['honeybadger'],\n envKeys: [/^HONEYBADGER_/],\n },\n },\n {\n kind: 'Raygun',\n label: 'Raygun',\n mode: 'in-cli',\n signals: {\n npm: ['raygun'],\n python: ['raygun4py'],\n ruby: ['raygun4ruby'],\n envKeys: [/^RAYGUN_/],\n },\n },\n {\n kind: 'CircleCI',\n label: 'CircleCI',\n mode: 'in-cli',\n signals: {\n envKeys: [/^CIRCLECI_/, /^CIRCLE_TOKEN$/],\n },\n },\n {\n kind: 'Upstash',\n label: 'Upstash',\n mode: 'in-cli',\n signals: {\n npm: ['@upstash/redis'],\n python: ['upstash-redis'],\n envKeys: [/^UPSTASH_/],\n },\n },\n {\n kind: 'Vercel',\n label: 'Vercel',\n mode: 'in-cli',\n signals: {\n npm: ['@vercel/sdk'],\n envKeys: [/^VERCEL_API_TOKEN$/],\n },\n },\n {\n kind: 'Algolia',\n label: 'Algolia',\n mode: 'in-cli',\n signals: {\n npm: ['algoliasearch'],\n python: ['algoliasearch'],\n ruby: ['algolia'],\n envKeys: [/^ALGOLIA_/],\n },\n },\n {\n kind: 'Inngest',\n label: 'Inngest',\n mode: 'in-cli',\n signals: {\n npm: ['inngest'],\n python: ['inngest'],\n envKeys: [/^INNGEST_/],\n },\n },\n {\n kind: 'TriggerDev',\n label: 'Trigger.dev',\n mode: 'in-cli',\n signals: {\n npm: ['@trigger.dev/sdk'],\n // TRIGGER_ alone is a common app-domain prefix, so we match only the\n // three keys Trigger.dev actually documents.\n envKeys: [/^TRIGGER_(SECRET_KEY|API_KEY|PROJECT_ID)$/],\n },\n },\n {\n kind: 'Ably',\n label: 'Ably',\n mode: 'in-cli',\n signals: {\n npm: ['ably'],\n python: ['ably'],\n envKeys: [/^ABLY_/],\n },\n },\n {\n kind: 'Netlify',\n label: 'Netlify',\n mode: 'in-cli',\n signals: {\n npm: ['@netlify/functions'],\n envKeys: [/^NETLIFY_/],\n },\n },\n {\n kind: 'Railway',\n label: 'Railway',\n mode: 'in-cli',\n signals: {\n envKeys: [/^RAILWAY_/],\n },\n },\n {\n kind: 'Render',\n label: 'Render',\n mode: 'in-cli',\n signals: {\n // RENDER_ is a generic word in front-end code — exact key only.\n envKeys: [/^RENDER_API_KEY$/],\n },\n },\n {\n kind: 'FlyIo',\n label: 'Fly.io',\n mode: 'in-cli',\n signals: {\n // `fly.toml` is not one of the manifests we read, so env keys are the\n // only signal available.\n envKeys: [/^FLY_API_TOKEN$/, /^FLY_APP_NAME$/],\n },\n },\n {\n kind: 'Heroku',\n label: 'Heroku',\n mode: 'in-cli',\n signals: {\n envKeys: [/^HEROKU_/],\n },\n },\n {\n kind: 'DigitalOcean',\n label: 'DigitalOcean',\n mode: 'in-cli',\n signals: {\n // DO_ is too short to be safe, so we match the full product name.\n envKeys: [/^DIGITALOCEAN_/],\n },\n },\n {\n kind: 'Grafana',\n label: 'Grafana',\n mode: 'in-cli',\n signals: {\n python: ['grafana-client'],\n envKeys: [/^GRAFANA_/],\n },\n },\n {\n kind: 'BetterStack',\n label: 'Better Stack',\n mode: 'in-cli',\n signals: {\n // Logtail is Better Stack's log product — same account, same source.\n npm: ['@logtail/node', '@logtail/js'],\n envKeys: [/^BETTERSTACK_/, /^BETTER_STACK_/, /^LOGTAIL_/],\n },\n },\n {\n kind: 'Honeycomb',\n label: 'Honeycomb',\n mode: 'in-cli',\n signals: {\n npm: ['@honeycombio/opentelemetry-node', 'honeycomb-beeline'],\n python: ['honeycomb-beeline', 'libhoney'],\n envKeys: [/^HONEYCOMB_/],\n },\n },\n {\n kind: 'Descope',\n label: 'Descope',\n mode: 'in-cli',\n signals: {\n npm: ['@descope/node-sdk', '@descope/nextjs-sdk', '@descope/react-sdk'],\n python: ['descope'],\n envKeys: [/^DESCOPE_/],\n },\n },\n {\n kind: 'FusionAuth',\n label: 'FusionAuth',\n mode: 'in-cli',\n signals: {\n npm: ['@fusionauth/typescript-client'],\n python: ['fusionauth-client'],\n envKeys: [/^FUSIONAUTH_/, /^FUSION_AUTH_/],\n },\n },\n {\n kind: 'Hookdeck',\n label: 'Hookdeck',\n mode: 'in-cli',\n signals: {\n npm: ['@hookdeck/sdk'],\n envKeys: [/^HOOKDECK_/],\n },\n },\n {\n kind: 'N8n',\n label: 'n8n',\n mode: 'in-cli',\n signals: {\n npm: ['n8n'],\n envKeys: [/^N8N_/],\n },\n },\n {\n kind: 'Dbt',\n label: 'dbt',\n mode: 'in-cli',\n signals: {\n // NOTE: these signals prove the project uses dbt, not that it uses dbt\n // Cloud — the source needs dbt Cloud credentials. Local-only dbt users\n // are a known false positive.\n python: [\n 'dbt-core',\n 'dbt-snowflake',\n 'dbt-postgres',\n 'dbt-bigquery',\n 'dbt-redshift',\n 'dbt-databricks',\n ],\n envKeys: [/^DBT_/],\n },\n },\n {\n kind: 'Fastly',\n label: 'Fastly',\n mode: 'in-cli',\n signals: {\n npm: ['fastly'],\n python: ['fastly'],\n envKeys: [/^FASTLY_/],\n },\n },\n {\n kind: 'Bunny',\n label: 'Bunny.net',\n mode: 'in-cli',\n signals: {\n envKeys: [/^BUNNY_/],\n },\n },\n {\n kind: 'Codecov',\n label: 'Codecov',\n mode: 'in-cli',\n signals: {\n npm: ['codecov'],\n envKeys: [/^CODECOV_/],\n },\n },\n {\n kind: 'Sourcegraph',\n label: 'Sourcegraph',\n mode: 'in-cli',\n signals: {\n envKeys: [/^SOURCEGRAPH_/, /^SRC_ACCESS_TOKEN$/],\n },\n },\n {\n kind: 'TemporalIO',\n label: 'Temporal.io',\n mode: 'in-cli',\n signals: {\n // NOTE: these signals also match a self-hosted Temporal cluster, but the\n // source wants Temporal Cloud mTLS certificates.\n npm: ['@temporalio/client', '@temporalio/worker'],\n python: ['temporalio'],\n envKeys: [/^TEMPORAL_/],\n },\n },\n {\n kind: 'Hatchet',\n label: 'Hatchet',\n mode: 'in-cli',\n signals: {\n npm: ['@hatchet-dev/typescript-sdk'],\n python: ['hatchet-sdk'],\n envKeys: [/^HATCHET_/],\n },\n },\n // ---- CRM / sales ----\n {\n kind: 'Pipedrive',\n label: 'Pipedrive',\n mode: 'in-cli',\n signals: {\n npm: ['pipedrive'],\n envKeys: [/^PIPEDRIVE_/],\n },\n },\n {\n kind: 'Close',\n label: 'Close',\n mode: 'in-cli',\n signals: {\n python: ['closeio'],\n envKeys: [/^CLOSE_API_KEY$/],\n },\n },\n {\n kind: 'Copper',\n label: 'Copper',\n mode: 'in-cli',\n signals: {\n envKeys: [/^COPPER_/],\n },\n },\n {\n kind: 'Insightly',\n label: 'Insightly',\n mode: 'in-cli',\n signals: {\n envKeys: [/^INSIGHTLY_/],\n },\n },\n {\n kind: 'Salesflare',\n label: 'Salesflare',\n mode: 'in-cli',\n signals: {\n envKeys: [/^SALESFLARE_/],\n },\n },\n {\n kind: 'SalesLoft',\n label: 'Salesloft',\n mode: 'in-cli',\n signals: {\n envKeys: [/^SALESLOFT_/],\n },\n },\n {\n kind: 'Attio',\n label: 'Attio',\n mode: 'in-cli',\n signals: {\n npm: ['attio'],\n envKeys: [/^ATTIO_/],\n },\n },\n {\n kind: 'ActiveCampaign',\n label: 'ActiveCampaign',\n mode: 'in-cli',\n signals: {\n envKeys: [/^ACTIVECAMPAIGN_/, /^ACTIVE_CAMPAIGN_/],\n },\n },\n {\n kind: 'Vitally',\n label: 'Vitally',\n mode: 'in-cli',\n signals: {\n envKeys: [/^VITALLY_/],\n },\n },\n {\n kind: 'Docusign',\n label: 'DocuSign',\n mode: 'in-cli',\n signals: {\n npm: ['docusign-esign'],\n python: ['docusign-esign'],\n envKeys: [/^DOCUSIGN_/],\n },\n },\n {\n kind: 'PandaDoc',\n label: 'PandaDoc',\n mode: 'in-cli',\n signals: {\n envKeys: [/^PANDADOC_/],\n },\n },\n {\n kind: 'Gong',\n label: 'Gong',\n mode: 'in-cli',\n signals: {\n envKeys: [/^GONG_/],\n },\n },\n // ---- PM / productivity ----\n {\n kind: 'Asana',\n label: 'Asana',\n mode: 'in-cli',\n signals: {\n npm: ['asana'],\n python: ['asana'],\n envKeys: [/^ASANA_/],\n },\n },\n {\n kind: 'Trello',\n label: 'Trello',\n mode: 'in-cli',\n signals: {\n npm: ['trello'],\n envKeys: [/^TRELLO_/],\n },\n },\n {\n kind: 'Todoist',\n label: 'Todoist',\n mode: 'in-cli',\n signals: {\n npm: ['@doist/todoist-api-typescript'],\n python: ['todoist-api-python'],\n envKeys: [/^TODOIST_/],\n },\n },\n {\n kind: 'Monday',\n label: 'monday.com',\n mode: 'in-cli',\n signals: {\n npm: ['@mondaydotcomorg/api'],\n envKeys: [/^MONDAY_/],\n },\n },\n {\n kind: 'ClickUp',\n label: 'ClickUp',\n mode: 'in-cli',\n signals: {\n envKeys: [/^CLICKUP_/],\n },\n },\n {\n kind: 'Height',\n label: 'Height',\n mode: 'in-cli',\n signals: {\n envKeys: [/^HEIGHT_API_KEY$/],\n },\n },\n {\n kind: 'Shortcut',\n label: 'Shortcut',\n mode: 'in-cli',\n signals: {\n npm: ['@shortcut/client'],\n envKeys: [/^SHORTCUT_/],\n },\n },\n {\n kind: 'Jira',\n label: 'Jira',\n mode: 'in-cli',\n signals: {\n npm: ['jira-client'],\n python: ['jira', 'atlassian-python-api'],\n envKeys: [/^JIRA_/],\n },\n },\n {\n kind: 'Confluence',\n label: 'Confluence',\n mode: 'in-cli',\n signals: {\n envKeys: [/^CONFLUENCE_/],\n },\n },\n {\n kind: 'Airtable',\n label: 'Airtable',\n mode: 'in-cli',\n signals: {\n npm: ['airtable'],\n python: ['pyairtable'],\n envKeys: [/^AIRTABLE_/],\n },\n },\n {\n kind: 'Smartsheet',\n label: 'Smartsheet',\n mode: 'in-cli',\n signals: {\n npm: ['smartsheet'],\n python: ['smartsheet-python-sdk'],\n envKeys: [/^SMARTSHEET_/],\n },\n },\n {\n kind: 'Coda',\n label: 'Coda',\n mode: 'in-cli',\n signals: {\n envKeys: [/^CODA_API_/],\n },\n },\n {\n kind: 'Productboard',\n label: 'Productboard',\n mode: 'in-cli',\n signals: {\n envKeys: [/^PRODUCTBOARD_/],\n },\n },\n {\n kind: 'GoogleSheets',\n label: 'Google Sheets',\n mode: 'in-cli',\n signals: {\n npm: ['google-spreadsheet'],\n python: ['gspread'],\n envKeys: [/^GOOGLE_SHEETS_/],\n },\n },\n {\n kind: 'Formbricks',\n label: 'Formbricks',\n mode: 'in-cli',\n signals: {\n npm: ['@formbricks/js'],\n envKeys: [/^FORMBRICKS_/],\n },\n },\n {\n kind: 'Tally',\n label: 'Tally',\n mode: 'in-cli',\n signals: {\n // Tally is also an accounting product, so we match the exact key.\n envKeys: [/^TALLY_API_KEY$/],\n },\n },\n {\n kind: 'Jotform',\n label: 'Jotform',\n mode: 'in-cli',\n signals: {\n python: ['jotform'],\n envKeys: [/^JOTFORM_/],\n },\n },\n {\n kind: 'GitBook',\n label: 'GitBook',\n mode: 'in-cli',\n signals: {\n npm: ['@gitbook/api'],\n envKeys: [/^GITBOOK_/],\n },\n },\n {\n kind: 'Wordpress',\n label: 'WordPress',\n mode: 'in-cli',\n signals: {\n // NOTE: recall is low here. Most WordPress projects are PHP, and\n // `composer.json` is not one of the manifests we read.\n npm: ['wpapi'],\n envKeys: [/^WORDPRESS_/],\n },\n },\n {\n kind: 'Clockify',\n label: 'Clockify',\n mode: 'in-cli',\n signals: {\n envKeys: [/^CLOCKIFY_/],\n },\n },\n // ---- Scheduling / events ----\n {\n kind: 'Calendly',\n label: 'Calendly',\n mode: 'in-cli',\n signals: {\n envKeys: [/^CALENDLY_/],\n },\n },\n {\n kind: 'CalCom',\n label: 'Cal.com',\n mode: 'in-cli',\n signals: {\n envKeys: [/^CALCOM_/, /^CAL_API_KEY$/],\n },\n },\n {\n kind: 'Eventbrite',\n label: 'Eventbrite',\n mode: 'in-cli',\n signals: {\n python: ['eventbrite'],\n envKeys: [/^EVENTBRITE_/],\n },\n },\n // ---- HR / people ----\n {\n kind: 'BambooHR',\n label: 'BambooHR',\n mode: 'in-cli',\n signals: {\n python: ['pybamboohr'],\n envKeys: [/^BAMBOOHR_/, /^BAMBOO_HR_/],\n },\n },\n {\n kind: 'Personio',\n label: 'Personio',\n mode: 'in-cli',\n signals: {\n envKeys: [/^PERSONIO_/],\n },\n },\n {\n kind: 'Rippling',\n label: 'Rippling',\n mode: 'in-cli',\n signals: {\n envKeys: [/^RIPPLING_/],\n },\n },\n {\n kind: 'Greenhouse',\n label: 'Greenhouse',\n mode: 'in-cli',\n signals: {\n envKeys: [/^GREENHOUSE_/],\n },\n },\n {\n kind: 'Ashby',\n label: 'Ashby',\n mode: 'in-cli',\n signals: {\n envKeys: [/^ASHBY_/],\n },\n },\n {\n kind: 'Workable',\n label: 'Workable',\n mode: 'in-cli',\n signals: {\n envKeys: [/^WORKABLE_/],\n },\n },\n // ---- Ads / marketing analytics (OAuth-first -> deep-link) ----\n {\n kind: 'GoogleAds',\n label: 'Google Ads',\n mode: 'deep-link',\n signals: {\n npm: ['google-ads-api'],\n python: ['google-ads'],\n envKeys: [/^GOOGLE_ADS_/],\n },\n },\n {\n kind: 'MetaAds',\n label: 'Meta Ads',\n mode: 'deep-link',\n signals: {\n npm: ['facebook-nodejs-business-sdk'],\n python: ['facebook-business'],\n envKeys: [/^META_ADS_/, /^FACEBOOK_ADS_/],\n },\n },\n {\n kind: 'LinkedinAds',\n label: 'LinkedIn Ads',\n mode: 'deep-link',\n signals: {\n envKeys: [/^LINKEDIN_ADS_/],\n },\n },\n {\n kind: 'TikTokAds',\n label: 'TikTok Ads',\n mode: 'deep-link',\n signals: {\n envKeys: [/^TIKTOK_ADS_/],\n },\n },\n {\n kind: 'RedditAds',\n label: 'Reddit Ads',\n mode: 'deep-link',\n signals: {\n envKeys: [/^REDDIT_ADS_/],\n },\n },\n {\n kind: 'PinterestAds',\n label: 'Pinterest Ads',\n mode: 'deep-link',\n signals: {\n envKeys: [/^PINTEREST_ADS_/],\n },\n },\n {\n kind: 'BingAds',\n label: 'Bing Ads',\n mode: 'deep-link',\n signals: {\n python: ['bingads'],\n envKeys: [/^BING_ADS_/, /^MICROSOFT_ADS_/],\n },\n },\n {\n kind: 'AmazonAds',\n label: 'Amazon Ads',\n mode: 'deep-link',\n signals: {\n envKeys: [/^AMAZON_ADS_/],\n },\n },\n {\n kind: 'GoogleAnalytics',\n label: 'Google Analytics',\n mode: 'deep-link',\n signals: {\n npm: ['react-ga4'],\n python: ['google-analytics-data'],\n envKeys: [/^GOOGLE_ANALYTICS_/, /^GA4_/],\n },\n },\n {\n kind: 'GoogleSearchConsole',\n label: 'Google Search Console',\n mode: 'deep-link',\n signals: {\n envKeys: [/^SEARCH_CONSOLE_/, /^GSC_/],\n },\n },\n {\n kind: 'AppsFlyer',\n label: 'AppsFlyer',\n mode: 'in-cli',\n signals: {\n npm: ['react-native-appsflyer'],\n envKeys: [/^APPSFLYER_/],\n },\n },\n {\n kind: 'Dub',\n label: 'Dub',\n mode: 'in-cli',\n signals: {\n npm: ['dub'],\n python: ['dub'],\n envKeys: [/^DUB_API_KEY$/],\n },\n },\n];\n\nexport const SOURCE_DETECTORS: SourceDetector[] = [\n ...CORE_SOURCE_DETECTORS,\n ...LLM_SOURCE_DETECTORS,\n ...OTHER_SOURCE_DETECTORS,\n];\n\n/** Kinds from the LLM / AI section above — the only ones that may set `wizard_ai_sdk_detected`. */\nexport const AI_SOURCE_KINDS: ReadonlySet<string> = new Set(\n LLM_SOURCE_DETECTORS.map((detector) => detector.kind),\n);\n","/** The AI SDK org stamp. Session-free, so runProgram can load it without the session. */\n\nimport type { ApiUser } from '@shared/api';\nimport { DiscoveredFeature } from '@shared/discovered-feature';\nimport { analytics } from '@utils/analytics';\nimport { AI_SOURCE_KINDS } from '@programs/warehouse-sources/registry';\nimport type { DetectedSource } from '@programs/warehouse-sources/types';\n\n/** What the org stamp reads, with no session. */\nexport type AiSdkStampEvidence = {\n apiUser: Pick<ApiUser, 'organization'> | null;\n discoveredFeatures: readonly DiscoveredFeature[];\n warehouseSources: readonly DetectedSource[];\n /** Scan consent was granted, so local detection results may be reported. */\n mayReportScanResults: boolean;\n};\n\nfunction hasAiSdkEvidence(evidence: AiSdkStampEvidence): boolean {\n return (\n evidence.warehouseSources.some((s) => AI_SOURCE_KINDS.has(s.kind)) ||\n evidence.discoveredFeatures.includes(DiscoveredFeature.LLM)\n );\n}\n\n/**\n * Boolean only, on the org, never the list of kinds or any non-AI tool: a\n * decline must not leak even the shape of what local detection saw.\n */\nexport function stampAiSdkDetected(evidence: AiSdkStampEvidence): void {\n if (!evidence.mayReportScanResults) return;\n const organizationId = evidence.apiUser?.organization?.id;\n if (!organizationId) return;\n if (!hasAiSdkEvidence(evidence)) return;\n\n analytics.groupIdentify('organization', organizationId, {\n wizard_ai_sdk_detected: true,\n });\n}\n","import type { AgentProgress, ResolvedBinding, RunResult } from '@agent/types';\nimport type { ApiProject, ApiUser, Credentials } from '@shared/api';\n\n/** One agent run's progress event, attributed to its run. */\nexport type ProgramRunProgress = {\n kind: 'run'; // one agent event\n runId: string; // the run it came from\n event: AgentProgress; // status, tasks, links, completion and more\n};\n\n/** A copy of the invocation's data, sent after each write. */\nexport type ProgramDataProgress = {\n kind: 'program'; // the program's data changed\n data: ProgramInvocationData; // a copy of it after the change\n};\n\nexport type ProgramProgress = ProgramRunProgress | ProgramDataProgress;\n\n/** What a diagnostic is about: one run's progress event, or a data snapshot. */\ntype DiagnosticSource =\n | { runId: string; eventKind: AgentProgress['kind'] }\n | { eventKind: 'data' };\n\n/** An observer failure or a late event, kept instead of breaking the run. */\nexport type ProgramDiagnostic = DiagnosticSource & { message: string };\n\n/** Data owned by one program invocation, independent of its progress feed. */\nexport type ProgramInvocationData = {\n credentials: Credentials | null; // the login; holds tokens, don't log it\n apiProject: ApiProject | null; // the login's project\n apiUser: ApiUser | null; // the login's user\n detection: { frameworkContext: Record<string, unknown> }; // always {} here\n binding: ResolvedBinding | null; // the route; null until it resolves\n aiSdkStampReported: boolean; // true once the AI SDK stamp was considered\n};\n\n/** An agent run's final result. */\nexport type SettledProgramRun = {\n runId: string; // the run's label\n result: RunResult; // what runAgent returned\n};\n\nexport type AgentProgressAdapter = {\n onProgress(event: AgentProgress): void;\n finish(result: RunResult): void;\n};\n\ntype RunEntry = {\n runId: string;\n result?: RunResult;\n};\n\nconst MAX_DIAGNOSTICS = 10;\n\nexport class ProgramStore {\n private readonly runs: RunEntry[] = [];\n private readonly diagnostics: ProgramDiagnostic[] = [];\n private readonly data: ProgramInvocationData;\n private readonly onData?: (progress: ProgramDataProgress) => void;\n\n constructor(\n options: {\n aiSdkStampReported?: boolean;\n onData?: (progress: ProgramDataProgress) => void;\n } = {},\n ) {\n this.onData = options.onData;\n this.data = {\n credentials: null,\n apiProject: null,\n apiUser: null,\n detection: { frameworkContext: {} },\n binding: null,\n aiSdkStampReported: options.aiSdkStampReported ?? false,\n };\n }\n\n readData(): ProgramInvocationData {\n return structuredClone(this.data);\n }\n\n setAuthenticated(\n auth: Pick<ProgramInvocationData, 'credentials' | 'apiProject' | 'apiUser'>,\n ): void {\n Object.assign(this.data, structuredClone(auth));\n this.emitData();\n }\n\n setFrameworkContext(key: string, value: unknown): void {\n this.data.detection.frameworkContext[key] = structuredClone(value);\n this.emitData();\n }\n\n setBinding(binding: ResolvedBinding): void {\n this.data.binding = structuredClone(binding);\n this.emitData();\n }\n\n setAiSdkStampReported(): void {\n if (this.data.aiSdkStampReported) return;\n this.data.aiSdkStampReported = true;\n this.emitData();\n }\n\n beginRun(\n runId: string,\n observer?: (progress: ProgramRunProgress) => void,\n ): AgentProgressAdapter {\n const run: RunEntry = { runId };\n this.runs.push(run);\n\n return {\n onProgress: (event) => {\n const source = { runId: run.runId, eventKind: event.kind };\n if (run.result) {\n this.recordDiagnostic(source, 'progress after finish');\n return;\n }\n if (!observer) return;\n this.deliver(source, () =>\n observer({ kind: 'run', runId, event: structuredClone(event) }),\n );\n },\n finish: (result) => {\n run.result = result;\n },\n };\n }\n\n settledRuns(): SettledProgramRun[] {\n return this.runs.flatMap(({ runId, result }) =>\n result ? [{ runId, result }] : [],\n );\n }\n\n readDiagnostics(): ProgramDiagnostic[] {\n return this.diagnostics.map((diagnostic) => ({ ...diagnostic }));\n }\n\n private emitData(): void {\n const onData = this.onData;\n if (!onData) return;\n this.deliver({ eventKind: 'data' }, () =>\n onData({ kind: 'program', data: this.readData() }),\n );\n }\n\n /** Never waits for an observer; a throw or a rejection becomes a diagnostic. */\n private deliver(source: DiagnosticSource, send: () => unknown): void {\n try {\n const delivery = send();\n if (\n delivery &&\n typeof (delivery as PromiseLike<unknown>).then === 'function'\n ) {\n void Promise.resolve(delivery).catch((error: unknown) => {\n this.recordDiagnostic(source, error);\n });\n }\n } catch (error) {\n this.recordDiagnostic(source, error);\n }\n }\n\n private recordDiagnostic(source: DiagnosticSource, error: unknown): void {\n this.diagnostics.push({\n ...source,\n message: error instanceof Error ? error.message : String(error),\n });\n if (this.diagnostics.length > MAX_DIAGNOSTICS) this.diagnostics.shift();\n }\n}\n","/** A caller-owned program invocation. No TUI store or session is required. */\nimport path from 'path';\nimport { randomUUID } from 'crypto';\nimport { buildRunTags, resolveBinding, runAgent, RunOutcome } from '@agent';\nimport type {\n AgentInteraction,\n AgentRunDefinition,\n ProgramBinding,\n RunConfig,\n RunHooks,\n RunInput,\n RunResult,\n SwitchboardCtx,\n} from '@agent/types';\nimport {\n getSkillsBaseUrl,\n Sequence,\n WIZARD_ORCHESTRATOR_FLAG_KEY,\n WIZARD_SELF_DRIVING_USE_PI_HARNESS_FLAG_KEY,\n type Harness,\n type Integration,\n} from '@shared/constants';\nimport { ErrorCodes } from '@shared/errors';\nimport type { DiscoveredFeature } from '@shared/discovered-feature';\nimport { analytics, groupsFromUser } from '@utils/analytics';\nimport { logToFile } from '@utils/debug';\nimport type { DetectedSource } from './warehouse-sources/types';\nimport { configureOAuthSession, oauthCredentials } from '@shared/oauth-session';\nimport {\n rotateCredentials,\n type CredentialsProvider,\n type ResolvedProgramCredentials,\n} from './credentials';\nimport { stampAiSdkDetected } from './posthog-integration/ai-sdk-stamp';\nimport {\n ProgramStore,\n type ProgramDiagnostic,\n type ProgramInvocationData,\n type ProgramProgress,\n type SettledProgramRun,\n} from './program-store';\n\n/** Launch-time routing choices, such as the CLI's --harness, --sequence and --model. */\nexport type ProgramOverrides = {\n harness?: Harness; // --harness\n sequence?: Sequence; // --sequence\n model?: string; // --model\n};\n\n/** Feature flags and their payloads from one evaluation. */\nexport type WizardFlagSnapshot = {\n flags: Record<string, string>; // flag key to variant\n payloads: Record<string, unknown>; // flag key to payload\n};\n\n/** Program-level settings the caller reads from the program's `ProgramConfig`. */\nexport type ProgramSettings = {\n requiresAi?: boolean; // false skips the AI-processing approval\n agentFlow?: string; // context-mill flow; defaults to the program ID\n allowedTools?: RunConfig['allowedTools']; // added to the base tools\n disallowedTools?: RunConfig['disallowedTools']; // removed from the base tools\n excludedTaskTypes?: RunConfig['excludedTaskTypes']; // task types to skip for these flags\n postAuthGates?: readonly string[]; // steps settled after login, before the agent\n};\n\n/** Copied when runProgram receives it; credentials, run, program, hooks and seedTasks stay by reference. */\nexport interface ProgramInput {\n installDir: string; // the project the agent works in\n run: AgentRunDefinition; // built from the program's ProgramConfig\n program?: ProgramSettings; // from the same ProgramConfig\n credentials?: ResolvedProgramCredentials; // a login you hold; else options.credentials\n runId?: string; // labels progress and the outcome; generated when absent\n overrides?: ProgramOverrides; // launch overrides; dev and test builds only\n composed?: boolean; // true for a sub-run inside another program\n skillId?: string; // labels the run; defaults to run.skillId, then integrationLabel\n integration?: Integration | null; // the detected framework\n frameworkDocsUrl?: string; // the framework's docs page\n flags?: Partial<RunInput['flags']>; // run flags such as ci and signup\n host?: RunInput['host']; // where PostHog is\n wizardFlags?: Record<string, string>; // a flag snapshot; else options.featureFlags\n wizardFlagPayloads?: Record<string, unknown>; // payloads for wizardFlags\n seedTasks?: RunConfig['seedTasks']; // tasks queued before the planner runs\n hooks?: RunHooks; // the program's completion hooks\n warehouseSources?: readonly DetectedSource[]; // AI SDK stamp evidence\n mayReportScanResults?: boolean; // consent to send the AI SDK stamp\n discoveredFeatures?: readonly DiscoveredFeature[]; // AI SDK stamp evidence\n aiSdkStampReported?: boolean; // true skips the AI SDK stamp\n}\n\nexport interface ProgramOptions {\n credentials?: CredentialsProvider; // resolves the login when input has none\n interaction?: AgentInteraction; // answers the agent's questions and notices\n onProgress?: (progress: ProgramProgress) => void; // run events and data snapshots\n awaitAiApproval?: (context: {\n programId: string;\n signal: AbortSignal;\n }) => Promise<boolean>; // asks for AI-processing approval; false aborts\n awaitPostAuthGates?: (context: {\n programId: string;\n gates: readonly string[];\n signal: AbortSignal;\n }) => Promise<void>; // waits while the caller settles the gates\n featureFlags?: () => Promise<WizardFlagSnapshot>; // loads flags when input has none\n signal?: AbortSignal; // cancels the run\n}\n\nexport interface ProgramRunOutcome {\n programId: string; // the program that ran\n outcome: RunOutcome; // success, aborted, failed or crashed\n data: ProgramInvocationData; // the final login and route\n settledRuns: SettledProgramRun[]; // the agent run's result, once it ran\n diagnostics: ProgramDiagnostic[]; // observer failures and late events\n artifacts: { reportFile?: string }; // where the agent writes its report\n failure?: RunResult['failure']; // code and message on any non-success\n}\n\n/** Handed to the caller's capabilities when it supplied no signal. */\nconst NEVER_ABORTED = new AbortController().signal;\n\nconst DEFAULT_FLAGS: RunInput['flags'] = {\n ci: false,\n signup: false,\n debug: false,\n e2eAsk: false,\n localMcp: false,\n captureAio: false,\n benchmark: false,\n yaraReport: false,\n};\n\n/** Fields that carry functions or class instances; everything else is data. */\nconst KEPT_BY_REFERENCE = [\n 'credentials',\n 'run',\n 'program',\n 'hooks',\n 'seedTasks',\n] as const satisfies readonly (keyof ProgramInput)[];\n\n/** Copy the caller's input, so a later caller write cannot reach the run or its hooks. */\nfunction snapshotProgramInput(input: ProgramInput): ProgramInput {\n const data: Partial<ProgramInput> = { ...input };\n for (const key of KEPT_BY_REFERENCE) delete data[key];\n return { ...input, ...structuredClone(data) };\n}\n\n/** Run an existing program from explicit inputs, with invocation-owned state. */\nexport async function runProgram(\n programId: string,\n callerInput: ProgramInput,\n options: ProgramOptions = {},\n): Promise<ProgramRunOutcome> {\n const input = snapshotProgramInput(callerInput);\n const store = new ProgramStore({\n aiSdkStampReported: input.aiSdkStampReported,\n onData: options.onProgress,\n });\n const { installDir, run } = input;\n const program = input.program ?? {};\n const artifacts: ProgramRunOutcome['artifacts'] = {};\n const runId = input.runId ?? randomUUID();\n const signal = options.signal ?? NEVER_ABORTED;\n\n const settle = (\n outcome: RunOutcome,\n failure?: RunResult['failure'],\n ): ProgramRunOutcome => ({\n programId,\n outcome,\n data: store.readData(),\n settledRuns: store.settledRuns(),\n diagnostics: store.readDiagnostics(),\n artifacts,\n ...(failure && { failure }),\n });\n const fail = (message: string) =>\n settle(RunOutcome.Failed, { code: ErrorCodes.InternalUnhandled, message });\n const abort = (message: string) =>\n settle(RunOutcome.Aborted, { code: ErrorCodes.AgentAbort, message });\n const cancelled = () => abort('Run cancelled by the caller.');\n\n if (signal.aborted) return cancelled();\n\n analytics.wizardCapture('agent started', {\n integration: run.integrationLabel,\n program_id: programId,\n skill_id: run.skillId ?? null,\n });\n\n /** Await a caller capability; a caller abort during the wait wins over its answer. */\n const park = async <T>(work: Promise<T>): Promise<T> => {\n const value = await work;\n signal.throwIfAborted();\n return value;\n };\n\n let credentials = input.credentials;\n const flags = { ...DEFAULT_FLAGS, ...input.flags };\n let flagSnapshot: WizardFlagSnapshot = {\n flags: { ...input.wizardFlags },\n payloads: { ...input.wizardFlagPayloads },\n };\n // Everything before the agent starts: a rejection fails the run, unless the caller aborted.\n try {\n if (!credentials && options.credentials) {\n credentials = await park(\n options.credentials.resolve(programId, { signal }),\n );\n }\n if (!credentials)\n return fail(`Credentials are required to run ${programId}.`);\n store.setAuthenticated({\n credentials: credentials.posthog,\n apiProject: credentials.project,\n apiUser: credentials.apiUser,\n });\n // Identify before flags are evaluated, so flags can target the user.\n if (credentials.apiUser) analytics.identifyUser(credentials.apiUser);\n analytics.setGroups(\n groupsFromUser(credentials.apiUser, credentials.posthog.host.apiHost),\n );\n if (!store.readData().aiSdkStampReported) {\n store.setAiSdkStampReported();\n stampAiSdkDetected({\n apiUser: credentials.apiUser,\n discoveredFeatures: input.discoveredFeatures ?? [],\n warehouseSources: input.warehouseSources ?? [],\n mayReportScanResults: input.mayReportScanResults ?? false,\n });\n }\n\n if (\n program.requiresAi !== false &&\n !flags.ci &&\n !flags.signup &&\n credentials.apiUser?.organization?.is_ai_data_processing_approved !== true\n ) {\n if (!options.awaitAiApproval) {\n return fail(\n 'AI processing approval is required before this program can run.',\n );\n }\n const approved = await park(\n options.awaitAiApproval({ programId, signal }),\n );\n if (!approved) return abort('AI processing approval declined.');\n }\n\n const gates = program.postAuthGates ?? [];\n if (gates.length > 0 && options.awaitPostAuthGates) {\n await park(options.awaitPostAuthGates({ programId, gates, signal }));\n }\n\n if (!input.wizardFlags && options.featureFlags) {\n flagSnapshot = await park(options.featureFlags());\n }\n\n // Freshness is measured after every park above, right before the agent mints.\n // Every rotation of this login, before or during the run, lands in data.\n const login = credentials;\n configureOAuthSession(login.posthog, {\n rotate: (held) => rotateCredentials(held, input.host?.baseUrl),\n onRefreshed: (refreshed) =>\n store.setAuthenticated({\n credentials: refreshed,\n apiProject: login.project,\n apiUser: login.apiUser,\n }),\n });\n // Not parked: a rotation spends the old refresh token, so the new one is kept before a cancel returns.\n const posthog = (await oauthCredentials()) ?? login.posthog;\n credentials = { ...login, posthog };\n signal.throwIfAborted();\n } catch (error) {\n if (signal.aborted) return cancelled();\n return fail(error instanceof Error ? error.message : String(error));\n }\n const wizardFlags = { ...flagSnapshot.flags };\n const wizardFlagPayloads = { ...flagSnapshot.payloads };\n\n // Resolve which sequence and harness run the program (CLI → PostHog flag →\n // per-program binding → default) and tag both axes onto analytics.\n const switchboard: SwitchboardCtx = {\n program: programId,\n composed: input.composed ?? false,\n flags: wizardFlags,\n flagPayloads: wizardFlagPayloads,\n cliHarness: input.overrides?.harness,\n cliSequence: input.overrides?.sequence,\n cliModel: input.overrides?.model,\n };\n const binding = resolveBinding(switchboard);\n analytics.setTag('sequence', binding.sequence);\n analytics.setTag('harness', binding.harness);\n captureSwitchboardDecision(switchboard, binding);\n store.setBinding(binding);\n\n const wizardMetadata = {\n ...buildRunTags({\n programId,\n integration: run.integrationLabel,\n runId: analytics.runId,\n build: analytics.build,\n skillId: run.skillId,\n }),\n SEQUENCE: binding.sequence,\n HARNESS: binding.harness,\n };\n artifacts.reportFile = path.resolve(installDir, run.reportFile);\n const adapter = store.beginRun(runId, options.onProgress);\n\n const result = await runAgent(\n {\n programId,\n run,\n composed: input.composed ?? false,\n binding,\n switchboard,\n skillsBaseUrl: getSkillsBaseUrl(),\n wizardFlags,\n wizardFlagPayloads,\n wizardMetadata,\n allowedTools: program.allowedTools,\n disallowedTools: program.disallowedTools,\n agentFlow: program.agentFlow,\n excludedTaskTypes: program.excludedTaskTypes,\n seedTasks: input.seedTasks,\n hooks: input.hooks,\n },\n {\n installDir,\n credentials: credentials.posthog,\n project: credentials.project,\n apiUser: credentials.apiUser,\n skillId: input.skillId ?? run.skillId ?? run.integrationLabel,\n integration: input.integration,\n frameworkDocsUrl: input.frameworkDocsUrl,\n flags,\n host: { ...input.host },\n },\n {\n interaction: options.interaction,\n onProgress: (event) => adapter.onProgress(event),\n signal: options.signal,\n },\n );\n adapter.finish(result);\n return settle(\n result.outcome,\n result.outcome === RunOutcome.Success ? undefined : result.failure,\n );\n}\n\n/**\n * One event + one log line per run: what entered the switchboard, which\n * precedence rung decided each axis, and the final pick.\n */\nfunction captureSwitchboardDecision(\n ctx: SwitchboardCtx,\n binding: ProgramBinding,\n): void {\n const trace = ctx.trace ?? {};\n // Unpinned orchestrator runs choose a model per task from the context-mill agent prompts; the orchestrator logs that map once the prompts load.\n const perTaskModel =\n binding.sequence === Sequence.orchestrator && trace.model === 'binding';\n const model = perTaskModel ? 'chosen-per-task' : binding.model;\n const modelSource = perTaskModel ? 'agent-prompts' : trace.model;\n analytics.wizardCapture('switchboard resolved', {\n program: ctx.program,\n flag_self_driving_use_pi_harness:\n ctx.flags[WIZARD_SELF_DRIVING_USE_PI_HARNESS_FLAG_KEY],\n flag_self_driving_pi_payload: JSON.stringify(\n ctx.flagPayloads?.[WIZARD_SELF_DRIVING_USE_PI_HARNESS_FLAG_KEY] ?? null,\n ),\n flag_orchestrator: ctx.flags[WIZARD_ORCHESTRATOR_FLAG_KEY],\n cli_harness: ctx.cliHarness,\n cli_sequence: ctx.cliSequence,\n cli_model: ctx.cliModel,\n harness_source: trace.harness,\n model_source: modelSource,\n sequence_source: trace.sequence,\n harness: binding.harness,\n model,\n thinking_level: binding.thinkingLevel,\n sequence: binding.sequence,\n });\n logToFile(\n `[switchboard] decision: program=${ctx.program}` +\n ` in(orchestrator=${ctx.flags[WIZARD_ORCHESTRATOR_FLAG_KEY] ?? '-'},` +\n ` cli=${ctx.cliHarness ?? '-'}/${ctx.cliSequence ?? '-'}/${\n ctx.cliModel ?? '-'\n })` +\n ` → harness=${binding.harness} (${trace.harness ?? '?'})` +\n ` model=${model} (${modelSource ?? '?'})` +\n ` sequence=${binding.sequence} (${trace.sequence ?? '?'})`,\n );\n}\n","import type { WizardUI, SpinnerHandle } from './wizard-ui';\nimport type { AgentInteraction, AgentProgress } from '@agent/types';\nimport { logToFile } from '@utils/debug';\n\n// ── Progress → WizardUI, one call per event ───────────────────────────\n\n/**\n * The inverse of the agent's former `getUI()` calls: one event, one\n * `WizardUI` method, synchronous, in emission order. Because each case maps\n * back to exactly the call the agent used to make, the frame and flow goldens\n * hold without regeneration.\n */\nexport function createUiReducer(ui: WizardUI): (event: AgentProgress) => void {\n let spinner: SpinnerHandle | undefined;\n return (event) => {\n switch (event.kind) {\n case 'lifecycle':\n if (event.phase === 'started') ui.startRun();\n else ui.outro(event.message);\n break;\n case 'spinner': {\n const handle = (spinner ??= ui.spinner());\n handle[event.action](event.message);\n break;\n }\n case 'log':\n ui.log[event.level](event.message);\n break;\n case 'status':\n ui.pushStatus(event.message);\n break;\n case 'tasks':\n ui.syncTodos(event.tasks);\n break;\n case 'stage':\n ui.setStage(event.stage);\n break;\n case 'url':\n if (event.which === 'dashboard') ui.setDashboardUrl(event.url);\n else ui.setNotebookUrl(event.url);\n break;\n case 'usage':\n ui.addTokenUsage(event.delta);\n break;\n case 'finalCost':\n ui.setFinalTokenCostUsd(event.usd);\n break;\n case 'authError':\n ui.showAuthError(event.detail);\n break;\n case 'handoff':\n ui.setHandoffText(event.text);\n break;\n case 'completion':\n ui.setOutroData(event.outro);\n break;\n case 'activity':\n // Step lines belong to the caller that asked for them, not the run UI.\n break;\n default: {\n const unhandled: never = event;\n throw new Error(\n `Unhandled agent progress: ${JSON.stringify(unhandled)}`,\n );\n }\n }\n };\n}\n\n/** The agent's questions, answered wherever `getUI()` answers them today. */\nexport function uiInteraction(ui: WizardUI): AgentInteraction {\n return {\n ask: (question, { signal }) =>\n dismissOnAbort(ui.requestQuestion(question), signal, () =>\n ui.cancelPendingQuestion(),\n ),\n taskNotice: (notice, { signal }) =>\n dismissOnAbort(ui.showTaskNotice(notice), signal, () =>\n ui.cancelTaskNotice(),\n ),\n };\n}\n\n/**\n * Dismiss one open request on abort; a settled one leaves the UI alone. A\n * throw inside an abort listener reaches no caller: Node rethrows it as an\n * uncaught exception, so a broken overlay is logged here instead.\n */\nfunction dismissOnAbort<T>(\n open: Promise<T>,\n signal: AbortSignal,\n dismiss: () => void,\n): Promise<T> {\n const onAbort = () => {\n try {\n dismiss();\n } catch (error) {\n logToFile('[agent-progress] dismissing an aborted request failed', error);\n }\n };\n // An abort listener added to an already aborted signal never fires.\n if (signal.aborted) onAbort();\n else signal.addEventListener('abort', onAbort, { once: true });\n return open.finally(() => signal.removeEventListener('abort', onAbort));\n}\n","import type {\n WizardSession,\n DiscoveredFeature,\n TaskNotice,\n} from '@lib/wizard-session';\nimport type { WizardReadinessResult } from '@shared/health-checks/readiness';\nimport type { ProgramRun } from '@programs/program-run';\nimport type { Integration } from '@shared/constants';\nimport type { FrameworkConfig } from '@programs/framework-config';\nimport type { ContentBlock } from '@ui/tui/primitives/index';\nimport type { WizardStore } from '@ui/tui/store';\nimport type { Tip } from '@ui/tui/components/TipsCard';\n// Type-only — erased at compile time, so no runtime cycle with the\n// registry that imports `ProgramConfig` back from this module.\nimport type { ProgramId } from './program-registry.js';\nimport type { CiRunnerContext, RunnerContext } from './runner-context.js';\n\n/**\n * A program step is the primary unit of the wizard's execution model.\n *\n * It can own:\n * - a screen in the TUI (optional — some steps are headless)\n * - agent work via a program reference (optional — some steps are UI-only)\n * - completion and visibility predicates\n *\n * The PostHog integration program is one ordered list of steps.\n * Other programs (e.g. revenue analytics) register a different step list.\n */\n/**\n * Context passed to onInit callbacks — fires when the TUI starts\n * rendering, before bin.ts has assigned the real session.\n */\nexport interface StoreInitContext {\n readonly session: WizardSession;\n readonly setReadinessResult: (result: WizardReadinessResult | null) => void;\n readonly setFrameworkContext: (key: string, value: unknown) => void;\n readonly emitChange: () => void;\n}\n\n/**\n * Context passed to onReady callbacks — fires after bin.ts has assigned\n * the real session, so reading `session.installDir` returns the target\n * project. Use for async pre-program work like prerequisite detection.\n */\nexport interface ProgramReadyContext {\n readonly session: WizardSession;\n readonly setFrameworkContext: (key: string, value: unknown) => void;\n\n // Detection-specific methods — used by core-integration's detect step\n readonly setFrameworkConfig: (\n integration: Integration,\n config: FrameworkConfig,\n ) => void;\n readonly setDetectedFramework: (label: string) => void;\n readonly setSkillId: (skillId: string | null) => void;\n readonly setUnsupportedVersion: (info: {\n current: string;\n minimum: string;\n docsUrl: string;\n }) => void;\n readonly addDiscoveredFeature: (feature: DiscoveredFeature) => void;\n readonly setDetectionComplete: () => void;\n readonly setPosthogSdkDetected: (detected: boolean) => void;\n}\n\nexport interface ProgramStep {\n /** Unique identifier for this step */\n id: string;\n\n /** Human-readable label for progress display */\n label: string;\n\n /**\n * TUI screen this step owns, if any.\n * Matches the ScreenId enum values (e.g. 'intro', 'run', 'outro').\n */\n screenId?: string;\n\n /**\n * For a run step (`screenId: 'run'`): runs this step's own agent. A program\n * exports a self-contained run step and another imports it into its step list\n * — e.g. posthog-integration exports a run step that runs its agent, and\n * self-driving imports it before its own run step. Omit to run the host\n * program's own agent (`config.run`).\n */\n run?: (session: WizardSession) => Promise<void>;\n\n /**\n * For a run step: prepare a derived session before its agent runs — e.g.\n * gather framework context for the chosen project. The session it receives is\n * the run's own, so writes don't leak into later runs.\n */\n onRunPrep?: (session: WizardSession) => Promise<void>;\n\n /**\n * For a run step: the working directory its agent runs in, resolved from the\n * session (e.g. self-driving's integration runs in the picked monorepo\n * sub-app, not the repo root). The runner scopes a derived session to this\n * dir for that run only. Defaults to `session.installDir`.\n */\n targetDir?: (session: WizardSession) => string;\n\n /**\n * Whether this step should be visible in the current program.\n * If omitted, the step is always visible.\n */\n show?: (session: WizardSession) => boolean;\n\n /**\n * Exit condition for the screen. Router advances when true.\n * Defaults to `gate` if unset.\n */\n isComplete?: (session: WizardSession) => boolean;\n\n /**\n * Define a gate if your screen needs to await user interactions.\n * bin.ts can `await store.getGate(stepId)` to pause until the\n * predicate becomes true.\n */\n gate?: (session: WizardSession) => boolean;\n\n /**\n * Called once when the TUI starts rendering, with the default\n * session. Use for session-independent fire-and-forget work that\n * should start as early as possible (e.g. health check kicked off\n * while the user is still reading the intro screen). Never fires for\n * a store that isn't rendering screens (tests, playground).\n */\n onInit?: (ctx: StoreInitContext) => void;\n\n /**\n * Called once after bin.ts has assigned the real session to the store,\n * before any gate is awaited. Awaited in sequence with other steps'\n * onReady callbacks. Use for session-dependent pre-program work like\n * scanning the installDir for prerequisites. May be sync or async.\n */\n onReady?: (ctx: ProgramReadyContext) => void | Promise<void>;\n\n /**\n * Report this step's analytics under a different program than its host, for\n * steps shared across programs (the MCP tutorial is all of `mcp-tutorial`\n * and the last step of `mcp-add`). Attribution only — scopes, bindings, and\n * sequences still follow the host. Matched by `screenId`, so headless steps\n * are unaffected.\n */\n reportsAsProgramId?: ProgramId;\n}\n\n/**\n * Declares a program's place in the wizard CLI surface.\n *\n * Mirrors the `cli:` block in context-mill skill configs so wizard-native\n * programs and skill-backed programs share one vocabulary. Field names\n * match `ProgramConfig.command` / `parentCommand` above, so contributors\n * only learn one set of words.\n *\n * - `role: 'command'` — appears as a normal wizard command.\n * - `role: 'skill'` — reachable only via `wizard skill <id>`.\n * - `role: 'internal'` — hidden everywhere, only reachable via the\n * `--skill=<id>` dev escape hatch.\n *\n * Mapping table — declaration on the left, registered command on the right:\n *\n * { role: 'command', → wizard revenue-analytics\n * command: 'revenue-analytics' }\n *\n * { role: 'command', → wizard audit feature-flags\n * parentCommand: 'audit',\n * command: 'feature-flags' }\n *\n * { role: 'skill' } → wizard skill <id>\n *\n * `cli` only configures the command shape — the verbs the user types.\n * Flags and positional args (e.g. `--since=30d`) are configured on\n * `cliOptions`, not here.\n *\n * Naming rule: commands use the full PostHog product name with hyphens\n * (`revenue-analytics`, `feature-flags`, `session-replay`), not\n * abbreviations like `revenue` or `flags`.\n */\nexport interface ProgramCliSurface {\n /** Where the program appears in the wizard CLI surface. */\n role: 'command' | 'skill' | 'internal';\n /**\n * The user-typed word that registers this program (e.g. `'feature-flags'`\n * in `wizard audit feature-flags`, or `'revenue-analytics'` in\n * `wizard revenue-analytics`). Required when `role` is `'command'`.\n */\n command?: string;\n /**\n * The command this program nests under (e.g. `'audit'` for\n * `wizard audit feature-flags`). Omit for flat / standalone commands.\n */\n parentCommand?: string;\n}\n\n/**\n * Uniform configuration for a wizard program.\n *\n * Each program directory exports one of these. The system uses it\n * for CLI registration, sequence/step wiring, and skill bootstrap.\n */\nexport interface ProgramConfig {\n /** CLI command name (e.g. 'revenue-analytics'). Omit for the default program. */\n command?: string;\n /**\n * Parent CLI command to nest this program under. When set, the program is\n * registered as `<parentCommand> <command>` instead of as a top-level\n * command. The parent must itself be a registered subcommand program. Omit\n * for top-level programs.\n */\n parentCommand?: string;\n /** CLI description shown in --help */\n description: string;\n /** Unique program id — matches the Program enum value */\n id: string;\n /**\n * Content-mill flow the orchestrator loads its agent prompts + step-skills\n * from (`agents/<flow>/` and `skills/<flow>/`). Defaults to `id`; set it when\n * the content-mill flow name diverges from the program id.\n */\n agentFlow?: string;\n /**\n * Whether this program's agent run requires third-party AI services.\n *\n * When true (the default), the wizard checks\n * `apiUser.organization.is_ai_data_processing_approved` after auth and\n * renders `AiOptInRequiredScreen` if the org has not opted in. Matches\n * Max's strict reading: only literal `true` proceeds.\n *\n * Opt out (set to `false`) for programs that don't run the agent —\n * doctor, mcp install/remove/tutorial, source-map upload. The safe\n * default is `true` so future programs gate by declaration.\n */\n requiresAi?: boolean;\n /**\n * Context-mill skill ID this program installs and runs. When present,\n * bin.ts seeds `session.skillId` with this value before the TUI renders\n * so intro screens can resolve skill metadata without waiting for the\n * agent run.\n */\n skillId?: string;\n /** The ordered step list */\n steps: ProgramStep[];\n /** Agent run config. Static object or async function for dynamic config. */\n run?:\n | ProgramRun\n | ((session: WizardSession, runner: RunnerContext) => Promise<ProgramRun>);\n /**\n * CI-mode pre-run strategy. When set, runWizardCI awaits this after building\n * the ci:true session and before the agent runs, instead of walking step\n * onReady hooks. Use for headless prerequisite work (e.g. framework\n * detection) that the TUI performs via step onReady callbacks.\n */\n ciPreRun?: (session: WizardSession, runner: CiRunnerContext) => Promise<void>;\n /**\n * Tasks the orchestrator queues itself, before the planner runs, from what\n * the wizard detected. Their types are marked `runnerSeeded: true` in the\n * agent prompt, so the planner never sees them: whether such a task runs is\n * decided here, in code, not by a model that could invent it or forget it.\n * Return an empty list to queue none.\n */\n seedTasks?: (session: WizardSession) => Array<{\n type: string;\n label?: string;\n inputs?: Record<string, unknown>;\n /**\n * Shown before the run starts, letting the user decline the task. The\n * program owns the words — the runner and the modal only carry them. A\n * task without one is queued silently.\n */\n notice?: TaskNotice;\n }>;\n /**\n * Task types this run excludes, decided from the run's wizard flags. An\n * excluded type does not exist for the run: the planner cannot enqueue it\n * and no agent boots for it. The program owns the flag→type mapping; the\n * runner only applies it.\n */\n excludedTaskTypes?: (flags: Record<string, string>) => readonly string[];\n /** Prerequisites: other program ids that must have run first */\n requires?: string[];\n /**\n * Path (relative to installDir) of the report file the program writes.\n * Mirrors `run.reportFile` but lifted to the top level so UI screens can\n * read it synchronously without resolving a deferred `run` function.\n */\n reportFile?: string;\n /**\n * Agent-authored event-plan artifact to mirror into the wizard session.\n * Relative to `session.installDir`. Programs that do not produce an event\n * plan leave this unset, so generic runner machinery does not inspect a\n * stale or unrelated `.posthog-events.json` file.\n */\n eventPlanFile?: string;\n /** Audit ledger to mirror into the session and delete at run end, relative to `installDir`. */\n auditLedgerFile?: string;\n /**\n * Channel the task stream publishes this run under, when it differs from the\n * program id. A family leaf runs on the generic skill program, so without\n * this every `wizard audit <leaf>` would report as `agent-skill`.\n */\n streamWorkflowId?: string;\n /**\n * LearnCard deck rendered in the shared `RunScreen` while the agent\n * runs. Lives at `<program>/content/index.tsx` by convention.\n * Programs that ship a custom RunScreen variant (audit) or skip the\n * run step (posthog-doctor) leave this unset.\n */\n getContentBlocks?: (store?: WizardStore) => ContentBlock[];\n /**\n * Tips shown in the run screen's right pane (the `Tips` sidebar) once\n * the LearnCard finishes. Lets a program supply its own explainer copy\n * (e.g. self-driving explaining what signal sources and scouts are)\n * instead of the generic onboarding deck. Unset → `RunScreen` falls back\n * to `DEFAULT_TIPS`, so every other program is unaffected. Lives at\n * `<program>/content/tips.ts` by convention.\n */\n getTips?: (store?: WizardStore) => Tip[];\n /**\n * Subcommand-specific CLI options. Spread into yargs `.options(...)` when the\n * program's subcommand is registered. Program-specific knowledge stays in\n * the program config, not in bin.ts. Typed as `unknown` to avoid pulling a\n * yargs dependency into this module.\n */\n cliOptions?: Record<string, unknown>;\n /**\n * Translate parsed CLI argv into extra options the runner consumes. Runs\n * after yargs validation, before runWizard/runWizardCI. Use this when a flag\n * needs to derive another field (e.g. `--product=statsig` → `skillId:\n * 'migrate-statsig'`).\n */\n mapCliOptions?: (argv: Record<string, unknown>) => Record<string, unknown>;\n /**\n * Extra tool names added on top of BASE_ALLOWED_TOOLS for this program's\n * agent run. Use for tools that only this program needs.\n */\n allowedTools?: readonly string[];\n /**\n * Tool names removed from BASE_ALLOWED_TOOLS for this program's agent\n * run. Use to forbid a base tool — e.g. `['Agent']` to block subagent\n * dispatch in a program whose steps are explicitly single-agent.\n */\n disallowedTools?: readonly string[];\n /**\n * Declares this program's place in the wizard CLI surface. See\n * `ProgramCliSurface` for semantics.\n */\n cli?: ProgramCliSurface;\n}\n\n/**\n * Project program steps into the narrower Screen shape the router consumes.\n *\n * Two things happen here:\n * 1. Headless steps (no `screenId`) are filtered out. The router walks\n * visible screens; gate-only steps like `detect` are store concerns.\n * 2. The step is narrowed to just { id, show, isComplete } — the\n * router has no business touching gate, onInit, or label.\n *\n * This intentional separation keeps the router focused on one question:\n * \"Which screen should be rendered right now?\"\n */\n/**\n * The gated steps the agent runner awaits after `auth` and before `run`, in\n * step order. Empty when a program has no auth step or runs before it.\n */\nexport function postAuthGateSteps(steps: ProgramStep[]): ProgramStep[] {\n const authIndex = steps.findIndex((s) => s.screenId === 'auth');\n const runIndex = steps.findIndex((s) => s.screenId === 'run');\n if (authIndex === -1 || runIndex <= authIndex) return [];\n return steps.slice(authIndex + 1, runIndex).filter((s) => s.gate);\n}\n\nexport function createProgramSequence(steps: ProgramStep[]): Array<{\n id: string;\n show?: (session: WizardSession) => boolean;\n isComplete?: (session: WizardSession) => boolean;\n}> {\n const entries = steps\n .filter((step) => step.screenId != null)\n .map((step) => ({\n id: step.screenId!,\n show: step.show,\n // `isComplete` defaults to `gate` — for most steps they're the same\n // predicate (e.g. intro: setupConfirmed unblocks bin.ts AND finishes\n // the screen). Only override when the two conditions diverge.\n isComplete: step.isComplete ?? step.gate,\n }));\n\n // Every program ends with the exit screen.\n entries.push({ id: 'exit', show: undefined, isComplete: undefined });\n\n return entries;\n}\n","/**\n * Authenticate the wizard — once per invocation.\n *\n * Idempotent: when `session.credentials` is already set, this is a no-op. So a\n * second agent run in the same invocation (e.g. self-driving runs the\n * integration program as a phase, then the Self-driving run) reuses the first\n * login instead of launching another OAuth — a second OAuth re-prompts and\n * fails with a 400 (the first authorization code is already spent). The first\n * call stores the full result on the session so any later bootstrap reads it\n * back rather than fetching again.\n */\n\nimport type { WizardSession } from '@lib/wizard-session';\nimport type { ProgramId } from '@programs/program-registry';\nimport { getOrAskForProjectData } from '@utils/setup-utils';\nimport { analytics, groupsFromUser } from '@utils/analytics';\nimport { getUI } from '@ui';\nimport { logToFile } from '@utils/debug';\n\nexport async function authenticate(\n session: WizardSession,\n programId: ProgramId,\n): Promise<void> {\n if (session.credentials) return;\n\n logToFile('[agent-runner] starting OAuth');\n const {\n projectApiKey,\n host,\n accessToken,\n refreshToken,\n expiresAt,\n oauthClientId,\n projectId,\n roleAtOrganization,\n user,\n project,\n missingScopes,\n } = await getOrAskForProjectData({\n signup: session.signup,\n ci: session.ci,\n apiKey: session.apiKey,\n projectId: session.projectId,\n email: session.email,\n region: session.region,\n baseUrl: session.baseUrl,\n localMcp: session.localMcp,\n programId,\n });\n\n session.credentials = {\n accessToken,\n refreshToken,\n expiresAt,\n oauthClientId,\n projectApiKey,\n host,\n projectId,\n missingScopes,\n };\n session.apiProject = project;\n session.roleAtOrganization = roleAtOrganization;\n session.apiUser = user;\n\n getUI().setCredentials(session.credentials);\n getUI().setRoleAtOrganization(roleAtOrganization);\n getUI().setApiUser(user);\n\n // Identify the user (email, name) before flags are evaluated, so flags can\n // target the individual user and not just $app_name.\n if (user) analytics.identifyUser(user);\n analytics.setGroups(groupsFromUser(user, host.apiHost));\n}\n","import type { WizardSession } from '@lib/wizard-session';\nimport {\n AUDIT_CHECKS_FILE,\n AUDIT_REPORT_FILE,\n coerceAuditChecks,\n type AuditCheck,\n type AuditStatus,\n} from '@shared/audit-ledger';\n\n// The ledger contract lives in `@lib/audit-ledger`; re-exported so the audit\n// views and the ledger watcher keep their import path.\nexport { AUDIT_CHECKS_FILE, AUDIT_REPORT_FILE, coerceAuditChecks };\nexport type { AuditCheck, AuditStatus };\n\nexport interface AuditSeverityStyle {\n glyph: string;\n color: string;\n}\n\n/** Single source of truth for status glyph + color across audit views. */\nexport const AUDIT_SEVERITY_STYLE: Record<AuditStatus, AuditSeverityStyle> = {\n pending: { glyph: '◌', color: 'gray' },\n pass: { glyph: '✔', color: 'green' },\n error: { glyph: '✘', color: 'red' },\n warning: { glyph: '⚠', color: 'yellow' },\n suggestion: { glyph: '•', color: 'cyan' },\n};\n\nexport const AUDIT_CHECKS_KEY = 'auditChecks';\n\nexport function getAuditChecks(session: WizardSession): AuditCheck[] {\n const raw = session.frameworkContext[AUDIT_CHECKS_KEY];\n return Array.isArray(raw) ? (raw as AuditCheck[]) : [];\n}\n","/**\n * Mirrors the agent's `.posthog-audit-checks.json` into the session, so the TUI\n * screens and the task stream read one value. `runProgramAgent` owns the\n * lifecycle and removes the file at run end, so every path gets it — including\n * the e2e host, which builds no task stream.\n */\n\nimport fs from 'fs';\nimport path from 'path';\nimport { getUI } from '@ui';\nimport {\n startFileWatcher,\n type FileWatcherHandle,\n type FileWatcherOptions,\n} from '@lib/file-watcher';\nimport { logToFile } from '@utils/debug';\nimport { AUDIT_CHECKS_KEY, coerceAuditChecks } from './types.js';\n\nconst MAX_LEDGER_FILE_BYTES = 256 * 1024;\n\nexport function startAuditLedgerWatcher(\n installDir: string,\n file: string,\n options: FileWatcherOptions = {},\n): FileWatcherHandle {\n const target = path.join(installDir, file);\n logToFile(`[audit-ledger] watching ${target}`);\n\n return startFileWatcher(\n target,\n (parsed) =>\n getUI().setFrameworkContext(AUDIT_CHECKS_KEY, coerceAuditChecks(parsed)),\n {\n // A ledger an earlier run left behind stays ignored until this run writes.\n ignoreInitialFile: true,\n maxFileSizeBytes: MAX_LEDGER_FILE_BYTES,\n ...options,\n },\n );\n}\n\n/** The program declared the ledger, so it removes it, agent `rm` step or not. */\nexport function removeAuditLedger(installDir: string, file: string): void {\n const target = path.join(installDir, file);\n try {\n fs.rmSync(target, { force: true });\n } catch (error) {\n logToFile(`[audit-ledger] could not remove ${target}: ${String(error)}`);\n }\n}\n","/**\n * Feature discovery — scan project dependencies for known SDK patterns\n * that indicate additional PostHog programs are relevant.\n *\n * Pure function: takes an install dir, returns a set of discovered features.\n * No store mutations, no UI calls.\n */\n\nimport { join } from 'path';\nimport { readProjectFile } from '@utils/bounded-fs';\nimport { DiscoveredFeature } from '@lib/wizard-session';\n\nconst STRIPE_PACKAGES = new Set(['stripe', '@stripe/stripe-js']);\n\nconst LLM_PACKAGES = new Set([\n 'openai',\n '@anthropic-ai/sdk',\n 'ai',\n '@ai-sdk/openai',\n 'langchain',\n '@langchain/openai',\n '@langchain/langgraph',\n '@google/generative-ai',\n '@google/genai',\n '@instructor-ai/instructor',\n '@mastra/core',\n 'portkey-ai',\n]);\n\n// PyPI normalizes `_` to `-` and is case-insensitive; compare via normalizePyName.\nconst PYTHON_LLM_PACKAGES = new Set([\n 'openai',\n 'anthropic',\n 'langchain',\n 'langchain-openai',\n 'langchain-anthropic',\n 'langchain-google-genai',\n 'langgraph',\n 'litellm',\n 'llama-index',\n 'pydantic-ai',\n 'crewai',\n 'instructor',\n 'dspy-ai',\n 'mistralai',\n 'cohere',\n 'google-generativeai',\n 'google-genai',\n 'portkey-ai',\n]);\n\nexport function discoverFeatures(installDir: string): DiscoveredFeature[] {\n const features: DiscoveredFeature[] = [];\n discoverNodeFeatures(installDir, features);\n discoverPythonFeatures(installDir, features);\n return features;\n}\n\nfunction discoverNodeFeatures(\n installDir: string,\n features: DiscoveredFeature[],\n): void {\n const packageJsonText = safeRead(installDir, 'package.json');\n if (!packageJsonText) return;\n\n let packageJson: {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n };\n try {\n packageJson = JSON.parse(packageJsonText);\n } catch {\n return;\n }\n\n const depNames = Object.keys({\n ...packageJson.dependencies,\n ...packageJson.devDependencies,\n });\n\n if (depNames.some((depName) => STRIPE_PACKAGES.has(depName))) {\n features.push(DiscoveredFeature.Stripe);\n }\n if (depNames.some((depName) => LLM_PACKAGES.has(depName))) {\n features.push(DiscoveredFeature.LLM);\n }\n}\n\nfunction discoverPythonFeatures(\n installDir: string,\n features: DiscoveredFeature[],\n): void {\n if (features.includes(DiscoveredFeature.LLM)) return;\n\n const depNames: string[] = [];\n\n const requirementsTxt = safeRead(installDir, 'requirements.txt');\n if (requirementsTxt) depNames.push(...parseRequirementsTxt(requirementsTxt));\n\n const pyprojectToml = safeRead(installDir, 'pyproject.toml');\n if (pyprojectToml) depNames.push(...parsePyprojectToml(pyprojectToml));\n\n const pipfile = safeRead(installDir, 'Pipfile');\n if (pipfile) depNames.push(...parsePipfile(pipfile));\n\n if (depNames.some((depName) => PYTHON_LLM_PACKAGES.has(depName))) {\n features.push(DiscoveredFeature.LLM);\n }\n}\n\n// Manifests over MAX_PROJECT_FILE_BYTES are skipped, not parsed.\nfunction safeRead(installDir: string, file: string): string | null {\n return readProjectFile(join(installDir, file));\n}\n\nfunction normalizePyName(name: string): string {\n return name.toLowerCase().replace(/_/g, '-');\n}\n\nexport function parseRequirementsTxt(content: string): string[] {\n return content\n .split('\\n')\n .map((line) => line.trim())\n .filter((line) => line && !line.startsWith('#') && !line.startsWith('-'))\n .map((line) => line.replace(/\\[[^\\]]*\\]/, ''))\n .map((line) => line.split(/[<>=!~;\\s]/)[0])\n .filter(Boolean)\n .map(normalizePyName);\n}\n\n// Pragmatic, not a full TOML parser — only the dep shapes we care about.\nexport function parsePyprojectToml(content: string): string[] {\n const depNames: string[] = [];\n\n for (const arrayMatch of content.matchAll(\n /dependencies\\s*=\\s*\\[([^\\]]*)\\]/g,\n )) {\n const arrayBody = arrayMatch[1];\n for (const quotedMatch of arrayBody.matchAll(/[\"']([^\"']+)[\"']/g)) {\n const depSpec = quotedMatch[1];\n const name = depSpec.replace(/\\[[^\\]]*\\]/, '').split(/[<>=!~;\\s]/)[0];\n if (name) depNames.push(normalizePyName(name));\n }\n }\n\n const poetrySectionRe =\n /\\[tool\\.poetry\\.(?:dev-dependencies|dependencies|group\\.[^.\\]]+\\.dependencies)\\]([\\s\\S]*?)(?=\\n\\[|$)/g;\n for (const sectionMatch of content.matchAll(poetrySectionRe)) {\n const sectionBody = sectionMatch[1];\n depNames.push(...extractTomlSectionKeys(sectionBody, { skip: ['python'] }));\n }\n\n return depNames;\n}\n\nexport function parsePipfile(content: string): string[] {\n const depNames: string[] = [];\n const sectionRe = /\\[(packages|dev-packages)\\]([\\s\\S]*?)(?=\\n\\[|$)/g;\n for (const sectionMatch of content.matchAll(sectionRe)) {\n const sectionBody = sectionMatch[2];\n depNames.push(...extractTomlSectionKeys(sectionBody));\n }\n return depNames;\n}\n\nfunction extractTomlSectionKeys(\n sectionBody: string,\n opts: { skip?: string[] } = {},\n): string[] {\n const skipNames = new Set(opts.skip ?? []);\n const depNames: string[] = [];\n for (const line of sectionBody.split('\\n')) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) continue;\n const equalsIndex = trimmed.indexOf('=');\n if (equalsIndex <= 0) continue;\n const name = trimmed.slice(0, equalsIndex).trim();\n if (!/^[a-zA-Z0-9._-]+$/.test(name)) continue;\n if (skipNames.has(name.toLowerCase())) continue;\n depNames.push(normalizePyName(name));\n }\n return depNames;\n}\n","/**\n * Data warehouse source detection.\n *\n * Scans a project for codebase signals (npm/python/ruby deps, `.env` key\n * names) and matches them against the `SOURCE_DETECTORS` registry. Pure\n * function: no store mutations, no UI calls. Reads files locally — only the\n * wizard process does this; the agent never sees secret values.\n *\n * Note we only read `.env` KEY NAMES, never values.\n */\n\nimport { analytics } from '@utils/analytics';\nimport { walkProjectFiles, safeReadFile } from '@utils/bounded-fs';\nimport {\n ENV_SCAN_MAX_DEPTH,\n MAX_ENV_KEY_SET,\n isEnvFileName,\n parseEnvKeyNames,\n toPromptSafeRelativePath,\n} from '@utils/env-scan';\nimport type { PackageJson } from '@utils/package-json';\nimport {\n parseRequirementsTxt,\n parsePyprojectToml,\n parsePipfile,\n} from '@programs/detection/features';\nimport { SOURCE_DETECTORS } from './registry.js';\nimport type { DetectedSource, SourceDetector } from './types.js';\n\ninterface ProjectSignals {\n npm: Set<string>;\n python: Set<string>;\n ruby: Set<string>;\n /**\n * Key NAME → the project-relative `.env*` file that first defined it. The\n * path is sanitised on the way in, so nothing here can reach a prompt raw.\n */\n envKeys: Map<string, string>;\n}\n\n// Shared with `check_env_keys` so the tool scans exactly what the detector\n// scanned — see `@utils/env-scan`.\nconst MAX_DEPTH = ENV_SCAN_MAX_DEPTH;\n\n// Each signal Set retains at most this many entries.\nconst MAX_SIGNAL_SET = MAX_ENV_KEY_SET;\n\nfunction addCapped(set: Set<string>, value: string): void {\n if (set.size < MAX_SIGNAL_SET) set.add(value);\n}\n\n/**\n * Detect which warehouse sources the project at `installDir` appears to use.\n * Returns one `DetectedSource` per matched registry entry (kinds are unique,\n * so the result is naturally deduped), minus the entries a more specific\n * match supersedes.\n */\nexport function detectWarehouseSources(installDir: string): DetectedSource[] {\n // No directory guard here: walkProjectFiles is best-effort and yields no\n // signals for a missing/unreadable dir (→ []). The program-level detect\n // step is responsible for surfacing a structured `bad-directory` error.\n const signals = collectSignals(installDir);\n\n const matched: { detector: SourceDetector; signal: string }[] = [];\n for (const detector of SOURCE_DETECTORS) {\n const signal = matchDetector(detector, signals);\n if (signal) matched.push({ detector, signal });\n }\n\n const kinds = new Set(matched.map((m) => m.detector.kind));\n return matched\n .filter(({ detector }) => !isSuperseded(detector, kinds))\n .map(({ detector, signal }) => ({\n kind: detector.kind,\n label: detector.label,\n mode: detector.mode,\n matchedSignal: signal,\n }));\n}\n\n/**\n * Whether a more specific match covers this detector's data. Every consumer\n * treats a detected kind as a source to create, so a project whose Postgres\n * lives on Neon or Supabase would otherwise be offered both and end up with\n * the same tables imported twice.\n */\nfunction isSuperseded(\n detector: SourceDetector,\n detectedKinds: ReadonlySet<string>,\n): boolean {\n return (detector.supersededBy ?? []).some((kind) => detectedKinds.has(kind));\n}\n\n/** Returns a human-readable description of the first matching signal, or null. */\nfunction matchDetector(\n detector: SourceDetector,\n signals: ProjectSignals,\n): string | null {\n const { npm, python, ruby, envKeys } = detector.signals;\n\n const npmHit = npm?.find((dep) => signals.npm.has(dep));\n if (npmHit) return `found \\`${npmHit}\\` in package.json`;\n\n const pyHit = python?.find((dep) => signals.python.has(dep));\n if (pyHit) return `found \\`${pyHit}\\` in Python dependencies`;\n\n const rubyHit = ruby?.find((gem) => signals.ruby.has(gem));\n if (rubyHit) return `found \\`${rubyHit}\\` in Gemfile`;\n\n if (envKeys) {\n // Name the file that actually matched. The agent acts on this string, so\n // pointing it at `.env` when the key lives in `apps/api/.env.local` sends\n // it to look in the wrong place and conclude the credential is absent.\n //\n // Both interpolated parts are repository-derived, so both are quoted as\n // code and both are constrained. `parseEnvKeyNames` limits the key to\n // `[A-Za-z_][A-Za-z0-9_]*`. The path is the unconstrained part: the\n // repository names its own directories, so it arrives already sanitised\n // from `toPromptSafeRelativePath` and cannot break out of the code span.\n for (const [key, file] of signals.envKeys) {\n if (envKeys.some((re) => re.test(key))) {\n return `found \\`${key}\\` in \\`${file}\\``;\n }\n }\n }\n\n return null;\n}\n\nfunction collectSignals(installDir: string): ProjectSignals {\n const signals: ProjectSignals = {\n npm: new Set(),\n python: new Set(),\n ruby: new Set(),\n envKeys: new Map(),\n };\n\n walkProjectFiles(\n installDir,\n (name, fullPath) => ingestFile(installDir, name, fullPath, signals),\n MAX_DEPTH,\n );\n\n return signals;\n}\n\n/**\n * Route a file to the right parser BY NAME, reading its contents only when the\n * name matches one of the ~6 manifests we care about. Checking the name first\n * avoids slurping every file in the tree (lockfiles, binaries, assets) into\n * memory just to discard it.\n */\nfunction ingestFile(\n installDir: string,\n name: string,\n fullPath: string,\n signals: ProjectSignals,\n): void {\n const ingest = ingestorFor(name);\n if (!ingest) return;\n\n const content = safeReadFile(fullPath);\n if (content === null) return;\n\n ingest(content, signals, toPromptSafeRelativePath(installDir, fullPath));\n}\n\ntype Ingestor = (\n content: string,\n signals: ProjectSignals,\n relativePath: string,\n) => void;\n\n/** Pick the parser for a manifest filename, or null if it's not one we read. */\nfunction ingestorFor(name: string): Ingestor | null {\n if (name === 'package.json') return addNpmDeps;\n if (name === 'requirements.txt')\n return (c, s) =>\n parseRequirementsTxt(c).forEach((d) => addCapped(s.python, d));\n if (name === 'pyproject.toml')\n return (c, s) =>\n parsePyprojectToml(c).forEach((d) => addCapped(s.python, d));\n if (name === 'Pipfile')\n return (c, s) => parsePipfile(c).forEach((d) => addCapped(s.python, d));\n if (name === 'Gemfile')\n return (c, s) => parseGemfile(c).forEach((g) => addCapped(s.ruby, g));\n if (isEnvFileName(name))\n return (c, s, relativePath) => addEnvKeys(c, s, relativePath);\n return null;\n}\n\n/**\n * Record each key NAME against the file that defined it. The first file wins,\n * so the reported signal stays stable when several `.env*` files repeat a key.\n * Values are never read.\n */\nfunction addEnvKeys(\n content: string,\n signals: ProjectSignals,\n relativePath: string,\n): void {\n for (const key of parseEnvKeyNames(content)) {\n if (signals.envKeys.has(key)) continue;\n if (signals.envKeys.size >= MAX_SIGNAL_SET) return;\n signals.envKeys.set(key, relativePath);\n }\n}\n\nfunction addNpmDeps(content: string, signals: ProjectSignals): void {\n try {\n const pkg = JSON.parse(content) as PackageJson;\n for (const dep of Object.keys({\n ...pkg.dependencies,\n ...pkg.devDependencies,\n })) {\n addCapped(signals.npm, dep);\n }\n } catch (error) {\n // Malformed package.json — skip it, but record that we hit it.\n analytics.captureException(\n error instanceof Error ? error : new Error(String(error)),\n { step: 'detectWarehouseSources.parsePackageJson' },\n );\n }\n}\n\n/** Extract gem names from `gem 'name'` declarations. */\nexport function parseGemfile(content: string): string[] {\n const gems: string[] = [];\n for (const match of content.matchAll(/^\\s*gem\\s+['\"]([^'\"]+)['\"]/gm)) {\n gems.push(match[1]);\n }\n return gems;\n}\n\n/**\n * Extract KEY NAMES from a dotenv file. Values are intentionally discarded.\n * Re-exported from `@utils/env-scan`, which `check_env_keys` shares, so the\n * detector and the tool cannot disagree about what counts as a key.\n */\nexport { parseEnvKeyNames as parseEnvKeys } from '@utils/env-scan';\n","/**\n * Warehouse-source program detection step.\n *\n * Thin adapter over `detectWarehouseSources` that writes results into\n * frameworkContext for the intro screen, plus the `[ABORT]` cases the\n * data-warehouse-source-setup skill can emit.\n */\n\nimport { existsSync, statSync } from 'fs';\nimport { analytics } from '@utils/analytics';\nimport type { WizardSession } from '@lib/wizard-session';\nimport type { AbortCase } from '@agent/types';\nimport { detectWarehouseSources } from '@programs/warehouse-sources/detect';\nimport type { DetectedSource } from '@programs/warehouse-sources/types';\n\n/** Structured detection errors rendered by the intro screen. */\nexport type WarehouseDetectError =\n | {\n kind: 'bad-directory';\n path: string;\n reason: 'missing' | 'not-dir' | 'unreadable';\n }\n | { kind: 'no-sources' };\n\n/** frameworkContext key holding the detected sources (set on success). */\nexport const DETECTED_WAREHOUSE_SOURCES_KEY = 'detectedWarehouseSources';\n\n/**\n * Read the detected sources out of frameworkContext. Single accessor shared by\n * the intro screen and the prompt builder so the key + cast live in one place.\n */\nexport function getDetectedWarehouseSources(\n session: WizardSession,\n): DetectedSource[] {\n return (\n (session.frameworkContext[DETECTED_WAREHOUSE_SOURCES_KEY] as\n | DetectedSource[]\n | undefined) ?? []\n );\n}\n\n/** `[ABORT] <reason>` cases the skill can emit. */\nexport const WAREHOUSE_ABORT_CASES: AbortCase[] = [\n {\n // Skill emits: [ABORT] No data source detected\n // Tolerant of plural (\"sources\") and a trailing period.\n match: /^no data sources? detected\\.?$/i,\n message: 'No data source detected',\n body:\n 'The agent could not confirm a data warehouse source to connect. ' +\n 'Run this command from a project that uses a supported source ' +\n '(a database, Stripe, etc.).',\n docsUrl: 'https://posthog.com/docs/data-warehouse',\n },\n {\n // Skill emits: [ABORT] Source creation failed\n match: /^source creation failed\\.?$/i,\n message: 'Source creation failed',\n body:\n 'PostHog could not create the data warehouse source with the ' +\n 'credentials provided. Double-check the connection details and try ' +\n 'again, or set the source up directly in the PostHog app.',\n docsUrl: 'https://posthog.com/docs/data-warehouse',\n },\n];\n\n/**\n * Scan `session.installDir` for warehouse-source signals. Writes the detected\n * sources (or a `detectError`) into frameworkContext for the intro screen.\n */\nexport function detectWarehousePrerequisites(\n session: WizardSession,\n setFrameworkContext: (key: string, value: unknown) => void,\n): void {\n const fail = (error: WarehouseDetectError) =>\n setFrameworkContext('detectError', error);\n\n const installDir = session.installDir;\n\n if (!existsSync(installDir)) {\n fail({ kind: 'bad-directory', path: installDir, reason: 'missing' });\n return;\n }\n try {\n if (!statSync(installDir).isDirectory()) {\n fail({ kind: 'bad-directory', path: installDir, reason: 'not-dir' });\n return;\n }\n } catch (error) {\n analytics.captureException(\n error instanceof Error ? error : new Error(String(error)),\n { step: 'detectWarehousePrerequisites.stat', path: installDir },\n );\n fail({ kind: 'bad-directory', path: installDir, reason: 'unreadable' });\n return;\n }\n\n const sources = detectWarehouseSources(installDir);\n\n if (sources.length === 0) {\n fail({ kind: 'no-sources' });\n return;\n }\n\n // Tag every subsequent event (agent started/completed, setup wizard\n // finished, …) with what was detected — without this the analytics can't\n // say which source types a run attempted, only that a run happened.\n analytics.setTag(\n 'warehouse_source_kinds',\n sources.map((s) => s.kind).join(','),\n );\n analytics.setTag(\n 'warehouse_source_modes',\n sources.map((s) => `${s.kind}:${s.mode}`).join(','),\n );\n analytics.setTag('warehouse_source_count', sources.length);\n\n setFrameworkContext(DETECTED_WAREHOUSE_SOURCES_KEY, sources);\n}\n","/**\n * The session-driven agent runner every existing caller uses.\n *\n * `runProgramAgent(programConfig, session)` runs the gates the TUI owns\n * (health, settings), then calls `runProgram` as its caller, backed by the\n * session and `getUI()`: credentials come from `authenticate`, the AI\n * opt-in and post-auth gates park on the UI, every progress event maps back\n * onto `getUI()`, and the invocation's data projects back onto the session.\n * It applies the result — `wizardAbort` with the outcome's terminal status for\n * a decided failure, the terminal analytics event for a finished top-level run.\n *\n * This is the only file that knows about `getUI()`, the session and\n * `wizardAbort` on the agent's behalf.\n *\n * ⚠️ Temporary adapter. It is removed later in the refactor.\n */\n\nimport { mayReportScanResults, type WizardSession } from '@lib/wizard-session';\nimport { analytics } from '@utils/analytics';\nimport { getUI, type WizardUI } from '@ui';\nimport { createUiReducer, uiInteraction } from '@ui/agent-progress';\nimport { flushScanReport, RunOutcome, TASK_OUTCOMES_KEY } from '@agent';\nimport type { ProgramRun } from './program-run';\nimport type { RunnerContext } from './runner-context';\nimport {\n backupAndFixClaudeSettings,\n checkAllSettingsConflicts,\n classifySettingsConflicts,\n restoreClaudeSettings,\n} from '@shared/claude-settings';\nimport {\n evaluateWizardReadiness,\n WizardReadiness,\n SIGNUP_WIZARD_READINESS_CONFIG,\n getBlockingServiceKeys,\n SERVICE_LABELS,\n} from '@shared/health-checks/readiness';\nimport { enableDebugLogs, logToFile, initLogFile } from '@utils/debug';\nimport { registerCleanup, wizardAbort } from '@utils/wizard-abort';\nimport { ErrorCodes } from '@shared/errors';\nimport { isNonInteractiveEnvironment } from '@utils/environment';\nimport { Sequence, type Integration } from '@shared/constants';\nimport { FRAMEWORK_REGISTRY } from '@programs/frameworks/registry';\nimport { postAuthGateSteps, type ProgramConfig } from './program-step';\nimport { authenticate } from './authenticate';\nimport {\n removeAuditLedger,\n startAuditLedgerWatcher,\n} from './audit/ledger-watcher';\nimport { getDetectedWarehouseSources } from './warehouse-source/detect';\nimport { runProgram, type WizardFlagSnapshot } from './run-program';\nimport type { ProgramInvocationData } from './program-store';\n\n/**\n * Resolve a ProgramConfig's agent run definition and execute the pipeline.\n * Entry point for the runners and for composed run steps.\n */\nexport async function runProgramAgent(\n programConfig: ProgramConfig,\n session: WizardSession,\n options: { composed?: boolean } = {},\n): Promise<void> {\n if (!programConfig.run) {\n throw new Error(`Program \"${programConfig.id}\" has no run configuration.`);\n }\n\n // Before `run()` resolves: an audit seeds the ledger from inside its recipe,\n // and a watcher started later would ignore that write as pre-existing.\n const ledgerFile = programConfig.auditLedgerFile;\n const ledger = ledgerFile\n ? startAuditLedgerWatcher(session.installDir, ledgerFile)\n : null;\n const releaseLedger = () => {\n // Read a last write the watch debounce hasn't picked up before stopping.\n ledger?.refresh();\n ledger?.stop();\n if (ledgerFile) removeAuditLedger(session.installDir, ledgerFile);\n };\n if (ledger) registerCleanup(releaseLedger);\n\n try {\n const runDef =\n typeof programConfig.run === 'function'\n ? await programConfig.run(session, uiRunnerContext())\n : programConfig.run;\n\n await runSessionProgram(\n session,\n runDef,\n programConfig,\n options.composed ?? false,\n );\n } finally {\n releaseLedger();\n }\n}\n\n/** The runner context each program effect reaches `getUI()` through, read at call time. */\nfunction uiRunnerContext(): RunnerContext {\n return {\n getFrameworkContext: (key) => getUI().getFrameworkContext(key),\n setFrameworkContext: (key, value) =>\n getUI().setFrameworkContext(key, value),\n log: { warn: (message) => getUI().log.warn(message) },\n };\n}\n\n/** Gates → runProgram on the session's behalf → apply result. */\nasync function runSessionProgram(\n session: WizardSession,\n run: ProgramRun,\n programConfig: ProgramConfig,\n composed: boolean,\n): Promise<void> {\n // 1. Init logging + debug\n initLogFile();\n session.skillId = run.skillId ?? run.integrationLabel;\n logToFile(\n `[agent-runner] START ${run.integrationLabel} build=${analytics.build}` +\n `${session.ci ? ' (non-interactive)' : ''}`,\n );\n if (session.debug) {\n enableDebugLogs();\n }\n\n // 2. Health check (guarded — skip if TUI already ran it). Only\n // programs that declare a health-check screen get pre-flight checks;\n // for everything else the checks never fire and never block.\n await runHealthGate(session, programConfig);\n\n // 3. Settings conflicts\n await runSettingsGate(session);\n\n const ui = getUI();\n const reduceUi = createUiReducer(ui);\n const projectData = projectProgramData(ui, session);\n\n // runProgram turns a throwing capability into a failed run; the CLI roots expect the throw.\n let capabilityFailure: { error: unknown } | undefined;\n const keepFailure = <T>(work: Promise<T>): Promise<T> =>\n work.catch((error: unknown) => {\n capabilityFailure ??= { error };\n throw error;\n });\n\n const framework = session.integration ?? session.skillId ?? undefined;\n const result = await runProgram(\n programConfig.id,\n {\n installDir: session.installDir,\n run,\n composed,\n overrides: {\n harness: session.harness,\n sequence: session.sequence,\n model: session.model,\n },\n skillId: session.skillId ?? undefined,\n integration: session.integration,\n frameworkDocsUrl: framework\n ? FRAMEWORK_REGISTRY[framework as Integration]?.metadata.docsUrl\n : undefined,\n flags: {\n ci: session.ci,\n signup: session.signup,\n debug: session.debug,\n e2eAsk: session.e2eAsk,\n localMcp: session.localMcp,\n captureAio: session.captureAio,\n benchmark: session.benchmark,\n yaraReport: session.yaraReport,\n },\n host: {\n baseUrl: session.baseUrl,\n region: session.region,\n email: session.email,\n projectId: session.projectId,\n apiKey: session.apiKey,\n },\n seedTasks: programConfig.seedTasks\n ? () => programConfig.seedTasks!(session)\n : undefined,\n hooks: {\n postRun: run.postRun\n ? (creds) => run.postRun!(session, creds)\n : undefined,\n buildOutroData: run.buildOutroData\n ? (creds) => run.buildOutroData!(session, creds) ?? undefined\n : undefined,\n buildOutroNextSteps: run.buildOutroNextSteps\n ? (creds, completed) =>\n run.buildOutroNextSteps!(session, creds, completed)\n : undefined,\n recordTaskOutcomes: (outcomes) => {\n session.frameworkContext[TASK_OUTCOMES_KEY] = outcomes;\n },\n },\n program: {\n requiresAi: programConfig.requiresAi,\n agentFlow: programConfig.agentFlow,\n allowedTools: programConfig.allowedTools,\n disallowedTools: programConfig.disallowedTools,\n excludedTaskTypes: programConfig.excludedTaskTypes,\n postAuthGates: postAuthGateSteps(programConfig.steps).map(\n (step) => step.id,\n ),\n },\n aiSdkStampReported: session.aiSdkStampReported,\n discoveredFeatures: session.discoveredFeatures,\n warehouseSources: getDetectedWarehouseSources(session),\n mayReportScanResults: mayReportScanResults(session),\n },\n {\n credentials: {\n // Idempotent within a run: a second agent run in the same invocation\n // (self-driving's integration phase) reuses the first login.\n resolve: () =>\n keepFailure(\n authenticate(session, programConfig.id).then(() => ({\n posthog: session.credentials!,\n project: session.apiProject,\n apiUser: session.apiUser,\n })),\n ),\n },\n // The actual AI opt-in gate: it parks while AiOptInRequiredScreen is up,\n // before the skill install and agent start, so no source leaves the machine.\n awaitAiApproval: async () => {\n logToFile('[agent-runner] checking AI opt-in gate');\n await ui.waitForAiOptIn();\n logToFile('[agent-runner] AI opt-in gate cleared');\n return true;\n },\n // Each step the user settles between auth and run, such as the source-maps\n // project picker, which writes its choice to frameworkContext for the prompt.\n awaitPostAuthGates: async ({ gates }) => {\n for (const gate of gates) {\n logToFile(`[agent-runner] awaiting post-auth gate: ${gate}`);\n await ui.waitForGate(gate);\n logToFile(`[agent-runner] post-auth gate cleared: ${gate}`);\n }\n },\n featureFlags: () => keepFailure(loadWizardFlags()),\n onProgress: (progress) => {\n if (progress.kind === 'run') reduceUi(progress.event);\n else projectData(progress.data);\n },\n interaction: uiInteraction(ui),\n },\n );\n // runProgram keeps a throwing progress handler or a late event as a diagnostic, so log it.\n for (const diagnostic of result.diagnostics) {\n const runLabel = 'runId' in diagnostic ? ` run=${diagnostic.runId}` : '';\n logToFile(\n `[agent-runner] progress diagnostic (${diagnostic.eventKind}${runLabel}): ${diagnostic.message}`,\n );\n }\n if (capabilityFailure) throw capabilityFailure.error;\n\n // The adapter owns process exits, terminal analytics and rethrowing crashes.\n if (result.outcome === RunOutcome.Crashed) {\n throw result.failure?.error;\n }\n if (result.outcome !== RunOutcome.Success) {\n if (result.failure?.authErrorDetail) {\n ui.showAuthError(result.failure.authErrorDetail);\n }\n // The terminal status follows how the run ended, not whether an Error came back.\n await wizardAbort({\n ...result.failure,\n status: result.outcome === RunOutcome.Aborted ? 'cancelled' : 'error',\n });\n } else if (!composed) {\n // A composed sub-run leaves the terminal event to its parent program's run.\n // The run already succeeded: a failed flush is logged, never the outcome.\n try {\n await analytics.shutdown('success');\n } catch (error) {\n logToFile('[agent-runner] analytics shutdown failed:', error);\n }\n }\n}\n\n/** Mirror the invocation's data onto the session and the UI the TUI reads. */\nfunction projectProgramData(\n ui: WizardUI,\n session: WizardSession,\n): (data: ProgramInvocationData) => void {\n let bindingSeen = false;\n return (data) => {\n const current = session.credentials;\n if (\n current &&\n data.credentials &&\n data.credentials.accessToken !== current.accessToken\n ) {\n // A refresh replaces only the token fields; the login keeps its host.\n session.credentials = {\n ...current,\n accessToken: data.credentials.accessToken,\n refreshToken: data.credentials.refreshToken,\n expiresAt: data.credentials.expiresAt,\n };\n ui.setAccessToken(session.credentials);\n }\n if (data.aiSdkStampReported) session.aiSdkStampReported = true;\n if (!data.binding || bindingSeen) return;\n bindingSeen = true;\n\n // Cleanup coverage for the abort/cancel path: `wizardAbort` runs the\n // registered cleanups, and the agent's own `finally` covers completion.\n // flushScanReport is idempotent, so the overlap is a harmless no-op.\n registerCleanup(() => {\n const report = flushScanReport({ yaraReport: session.yaraReport });\n if (report) ui.log.info(report);\n });\n\n // Linear settings restoration fires on entry to the outro screen, so it\n // is registered before the run can reach that screen. The abort path\n // still restores through the cleanup `backupAndFixClaudeSettings`\n // registered.\n if (data.binding.sequence === Sequence.linear) {\n ui.onEnterScreen('outro', () =>\n restoreClaudeSettings(session.installDir),\n );\n }\n };\n}\n\nconst loadWizardFlags = async (): Promise<WizardFlagSnapshot> => ({\n flags: await analytics.getAllFlagsForWizard(),\n payloads: analytics.getWizardFlagPayloads(),\n});\n\n// ── Gates ─────────────────────────────────────────────────────────────\n\nasync function runHealthGate(\n session: WizardSession,\n programConfig: ProgramConfig,\n): Promise<void> {\n const hasHealthCheckScreen = programConfig.steps.some(\n (s) => s.screenId === 'health-check',\n );\n if (session.readinessResult) {\n logToFile(\n `[agent-runner] readiness pre-computed by TUI: decision=${session.readinessResult.decision}` +\n `${\n session.outageDismissed ? ' (outage dismissed by user)' : ''\n } — skipping re-check`,\n );\n }\n if (!hasHealthCheckScreen || session.readinessResult) return;\n\n logToFile('[agent-runner] evaluating wizard readiness');\n const readinessConfig = session.signup\n ? SIGNUP_WIZARD_READINESS_CONFIG\n : undefined;\n const readiness = await evaluateWizardReadiness(readinessConfig);\n logToFile(`[agent-runner] readiness=${readiness.decision}`);\n if (readiness.decision === WizardReadiness.No) {\n const blockingKeys = getBlockingServiceKeys(\n readiness.health,\n readinessConfig,\n );\n const blockingLabels = blockingKeys.map(\n (k) => `${SERVICE_LABELS[k]} (${readiness.health[k].status})`,\n );\n logToFile(`[agent-runner] blocked by: ${blockingLabels.join(', ')}`);\n\n await getUI().showBlockingOutage(readiness);\n\n // The TUI lets the user continue past an outage; non-interactive runs\n // (CI) do the same automatically — the degraded services are reported\n // above, but we proceed rather than aborting on a transient upstream blip.\n if (!isNonInteractiveEnvironment()) {\n await wizardAbort({\n code: ErrorCodes.EnvServiceOutage,\n message:\n 'Cannot start — external services are down:\\n' +\n blockingLabels.map((l) => ` - ${l}`).join('\\n') +\n '\\n\\nPlease try again later.',\n });\n }\n } else if (readiness.decision === WizardReadiness.YesWithWarnings) {\n getUI().setReadinessWarnings(readiness);\n }\n}\n\nasync function runSettingsGate(session: WizardSession): Promise<void> {\n const settingsConflicts = checkAllSettingsConflicts(session.installDir);\n logToFile(\n `[agent-runner] settings conflicts: ${\n settingsConflicts.length > 0\n ? settingsConflicts\n .map((c) => `${c.source}(${c.keys.join(',')})`)\n .join('; ')\n : 'none'\n }`,\n );\n if (settingsConflicts.length === 0) return;\n\n for (const conflict of settingsConflicts) {\n const level = conflict.source === 'managed' ? 'org' : conflict.source;\n analytics.wizardCapture('settings conflict detected', {\n level,\n keys: conflict.keys,\n });\n }\n\n const { autoFix, failClosed, warnOnly } =\n classifySettingsConflicts(settingsConflicts);\n\n // User-global and project-local files are already neutralized — the agent\n // runs with settingSources:['project'], so the SDK never reads them. Record\n // it and move on; don't make the user act on a setting that can't bite.\n for (const conflict of warnOnly) {\n logToFile(\n `[agent-runner] settings conflict in ${conflict.source} (${conflict.path}) ` +\n `neutralized by settingSources:['project'] — not blocking`,\n );\n analytics.wizardCapture('settings conflict neutralized', {\n level: conflict.source,\n keys: conflict.keys,\n });\n }\n\n // Writable project settings.json — the SDK *does* read it, but we can back\n // it up and remove it (restored at outro). Neutralize without prompting.\n let unfixable = failClosed;\n if (autoFix.length > 0) {\n const fixed = backupAndFixClaudeSettings(session.installDir);\n if (fixed) {\n logToFile('[agent-runner] auto-neutralized writable settings conflict');\n analytics.wizardCapture('settings conflict auto-neutralized', {\n keys: autoFix.flatMap((c) => c.keys),\n });\n } else {\n // Couldn't remove it — don't run into the redirect; fail closed instead.\n logToFile(\n '[agent-runner] could not back up writable settings conflict — failing closed',\n );\n unfixable = [...failClosed, ...autoFix];\n }\n }\n\n // What we cannot neutralize (org-managed, always read by the SDK; or a\n // writable file we failed to back up) must be fixed by the user. Fail\n // closed: the screen names the file + keys and exits.\n if (unfixable.length > 0) {\n if (isNonInteractiveEnvironment()) {\n await wizardAbort({\n code: ErrorCodes.SettingsUnfixableConflict,\n message:\n 'Cannot start — a Claude settings file redirects the agent away ' +\n 'from the PostHog gateway and cannot be neutralized automatically:\\n' +\n unfixable\n .map((c) => ` - ${c.source} (${c.path}): ${c.keys.join(', ')}`)\n .join('\\n') +\n '\\n\\nRemove the conflicting keys and re-run the wizard.',\n });\n }\n await getUI().showSettingsOverride(unfixable, () =>\n backupAndFixClaudeSettings(session.installDir),\n );\n logToFile('[agent-runner] settings override resolved');\n }\n}\n"],"mappings":"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"}