@posthog/wizard 2.69.0 → 2.70.1
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.
- package/dist/{add-mcp-server-to-clients-Cl2HBuxp.js → add-mcp-server-to-clients-BCnjUqnW.js} +4 -4
- package/dist/{add-mcp-server-to-clients-Cl2HBuxp.js.map → add-mcp-server-to-clients-BCnjUqnW.js.map} +1 -1
- package/dist/{agent-interface-CI89BrWE.js → agent-interface-Lu7tnLr0.js} +8 -8
- package/dist/{agent-interface-CI89BrWE.js.map → agent-interface-Lu7tnLr0.js.map} +1 -1
- package/dist/{agent-prompt-loader-Dc1g5Oub.js → agent-prompt-loader-y5GxgEkc.js} +5 -5
- package/dist/{agent-prompt-loader-Dc1g5Oub.js.map → agent-prompt-loader-y5GxgEkc.js.map} +1 -1
- package/dist/{agent-runner-D5dhuE4z.js → agent-runner-vKtpgqVI.js} +21 -16
- package/dist/agent-runner-vKtpgqVI.js.map +1 -0
- package/dist/analytics-D-bMEYjD.js +2 -0
- package/dist/{analytics-D90QbLf5.js → analytics-DTyJClPr.js} +13 -3
- package/dist/analytics-DTyJClPr.js.map +1 -0
- package/dist/{api-BHhrT6wb.js → api-j-OfJ8Dz.js} +3 -3
- package/dist/{api-BHhrT6wb.js.map → api-j-OfJ8Dz.js.map} +1 -1
- package/dist/bin.js +61 -56
- package/dist/bin.js.map +1 -1
- package/dist/{bounded-fs-BhlVkP1r.js → bounded-fs-BWX25ixc.js} +3 -3
- package/dist/{bounded-fs-BhlVkP1r.js.map → bounded-fs-BWX25ixc.js.map} +1 -1
- package/dist/{ci-install-94wC3a4K.js → ci-install-zNWgp1TL.js} +4 -4
- package/dist/{ci-install-94wC3a4K.js.map → ci-install-zNWgp1TL.js.map} +1 -1
- package/dist/{debug-CifTS9lQ.js → debug-BM0fZaGl.js} +3 -3
- package/dist/{debug-CifTS9lQ.js.map → debug-BM0fZaGl.js.map} +1 -1
- package/dist/{debug-DtixqVEY.js → debug-xr2Pq5VA.js} +1 -1
- package/dist/{env-api-key-CwhtZrik.js → env-api-key-DlxCZWU0.js} +2 -2
- package/dist/{env-api-key-CwhtZrik.js.map → env-api-key-DlxCZWU0.js.map} +1 -1
- package/dist/{environment-DhacWZf7.js → environment-o-bTOuzK.js} +4 -4
- package/dist/{environment-DhacWZf7.js.map → environment-o-bTOuzK.js.map} +1 -1
- package/dist/{file-watcher-L28OpUV2.js → file-watcher-D7G4f5sP.js} +2 -2
- package/dist/{file-watcher-L28OpUV2.js.map → file-watcher-D7G4f5sP.js.map} +1 -1
- package/dist/{headless-ui-DNcOVJxU.js → headless-ui-C46DctKG.js} +2 -2
- package/dist/{headless-ui-DNcOVJxU.js.map → headless-ui-C46DctKG.js.map} +1 -1
- package/dist/{interactive-DlNrV77o.js → interactive-B5zy3Gxk.js} +2 -2
- package/dist/{interactive-DlNrV77o.js.map → interactive-B5zy3Gxk.js.map} +1 -1
- package/dist/{mcp-CJEem9qs.js → mcp-lJRwE-YW.js} +2 -2
- package/dist/{mcp-CJEem9qs.js.map → mcp-lJRwE-YW.js.map} +1 -1
- package/dist/{mcp-prompt-streaming-DER7MG3q.js → mcp-prompt-streaming-Dsos09hT.js} +4 -4
- package/dist/{mcp-prompt-streaming-DER7MG3q.js.map → mcp-prompt-streaming-Dsos09hT.js.map} +1 -1
- package/dist/{non-interactive-CbvniKHm.js → non-interactive-qcCCtiYQ.js} +2 -2
- package/dist/{non-interactive-CbvniKHm.js.map → non-interactive-qcCCtiYQ.js.map} +1 -1
- package/dist/{orchestrator-tools-Czf3Wo_y.js → orchestrator-tools-ezFTbAIp.js} +3 -3
- package/dist/{orchestrator-tools-Czf3Wo_y.js.map → orchestrator-tools-ezFTbAIp.js.map} +1 -1
- package/dist/{package-json-GEU2VZlS.js → package-json-xt3eeyBI.js} +1 -1
- package/dist/{package-json-GEU2VZlS.js.map → package-json-xt3eeyBI.js.map} +1 -1
- package/dist/{package-manager-CNNlFA2q.js → package-manager-CGfN9UhH.js} +2 -2
- package/dist/{package-manager-CNNlFA2q.js.map → package-manager-CGfN9UhH.js.map} +1 -1
- package/dist/{pi-kpN-bO9z.js → pi-DzQLHIcQ.js} +11 -11
- package/dist/{pi-kpN-bO9z.js.map → pi-DzQLHIcQ.js.map} +1 -1
- package/dist/{playground-ZYaQmfBa.js → playground-DLN31BPV.js} +7 -7
- package/dist/{playground-ZYaQmfBa.js.map → playground-DLN31BPV.js.map} +1 -1
- package/dist/{posthog-D1zHPgYJ.js → posthog-Dxr8XK4x.js} +2 -2
- package/dist/{posthog-D1zHPgYJ.js.map → posthog-Dxr8XK4x.js.map} +1 -1
- package/dist/{posthog-integration-DdeIUkYw.js → posthog-integration-MDfRO911.js} +93 -29
- package/dist/posthog-integration-MDfRO911.js.map +1 -0
- package/dist/{provisioning-e3roaLgp.js → provisioning-Di5GNV9k.js} +3 -3
- package/dist/{provisioning-e3roaLgp.js.map → provisioning-Di5GNV9k.js.map} +1 -1
- package/dist/{queue-tools-zrqCiy6q.js → queue-tools-KosDptd6.js} +3 -3
- package/dist/{queue-tools-zrqCiy6q.js.map → queue-tools-KosDptd6.js.map} +1 -1
- package/dist/{registry-C1t8v5tE.js → registry-BBdaIFWq.js} +6 -6
- package/dist/{registry-C1t8v5tE.js.map → registry-BBdaIFWq.js.map} +1 -1
- package/dist/{security-CIfhIscL.js → security-BwOvjMaq.js} +5 -5
- package/dist/{security-CIfhIscL.js.map → security-BwOvjMaq.js.map} +1 -1
- package/dist/{setup-utils-B_06xag2.js → setup-utils-Bo3WZt3a.js} +9 -9
- package/dist/{setup-utils-B_06xag2.js.map → setup-utils-Bo3WZt3a.js.map} +1 -1
- package/dist/{start-tui-BafJXVNT.js → start-tui-B1LrB7k1.js} +288 -133
- package/dist/start-tui-B1LrB7k1.js.map +1 -0
- package/dist/{steps-DR-Yo_IT.js → steps-BMrQJpQh.js} +7 -7
- package/dist/{steps-DR-Yo_IT.js.map → steps-BMrQJpQh.js.map} +1 -1
- package/dist/{store-DSUCWMRO.js → store-DhNTBWQR.js} +40 -6
- package/dist/store-DhNTBWQR.js.map +1 -0
- package/dist/{subagent-DjZM3G7y.js → subagent-q6M-mBHo.js} +2 -2
- package/dist/{subagent-DjZM3G7y.js.map → subagent-q6M-mBHo.js.map} +1 -1
- package/dist/{task-Czzz3tzt.js → task-CgAOxod7.js} +12 -12
- package/dist/{task-Czzz3tzt.js.map → task-CgAOxod7.js.map} +1 -1
- package/dist/{task-stream-uxG6wJfj.js → task-stream-rxR1IsdJ.js} +5 -5
- package/dist/{task-stream-uxG6wJfj.js.map → task-stream-rxR1IsdJ.js.map} +1 -1
- package/dist/{tasks-CVmG8qFw.js → tasks-lzvWF__k.js} +2 -2
- package/dist/{tasks-CVmG8qFw.js.map → tasks-lzvWF__k.js.map} +1 -1
- package/dist/{telemetry-B1VEXHpL.js → telemetry-CickTk_7.js} +3 -3
- package/dist/{telemetry-B1VEXHpL.js.map → telemetry-CickTk_7.js.map} +1 -1
- package/dist/{terminal-Czuo0x8i.js → terminal-BjUFxn_x.js} +12 -12
- package/dist/{terminal-Czuo0x8i.js.map → terminal-BjUFxn_x.js.map} +1 -1
- package/dist/{tools-DOZg9n3A.js → tools-MKXGXFSk.js} +6 -6
- package/dist/{tools-DOZg9n3A.js.map → tools-MKXGXFSk.js.map} +1 -1
- package/dist/{wizard-abort-BZOeapsf.js → wizard-abort-CW_C2EXr.js} +1 -1
- package/dist/{wizard-abort-CFMdj6sZ.js → wizard-abort-CooWEh9N.js} +4 -4
- package/dist/{wizard-abort-CFMdj6sZ.js.map → wizard-abort-CooWEh9N.js.map} +1 -1
- package/dist/{wizard-session-C_7r3-rO.js → wizard-session-Bki7dQhv.js} +12 -2
- package/dist/wizard-session-Bki7dQhv.js.map +1 -0
- package/dist/{wizard-session-D1KQqUml.js → wizard-session-gbYCXdBf.js} +1 -1
- package/dist/{yara-hooks-CmQT-oBy.js → yara-hooks-BpngckdZ.js} +4 -4
- package/dist/{yara-hooks-CmQT-oBy.js.map → yara-hooks-BpngckdZ.js.map} +1 -1
- package/dist/yara-hooks-C-qG6EJt.js +2 -0
- package/package.json +1 -1
- package/dist/agent-runner-D5dhuE4z.js.map +0 -1
- package/dist/analytics-D90QbLf5.js.map +0 -1
- package/dist/analytics-Dmf_Jm3K.js +0 -2
- package/dist/posthog-integration-DdeIUkYw.js.map +0 -1
- package/dist/start-tui-BafJXVNT.js.map +0 -1
- package/dist/store-DSUCWMRO.js.map +0 -1
- package/dist/wizard-session-C_7r3-rO.js.map +0 -1
- package/dist/yara-hooks-BhNAWw7W.js +0 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"posthog-integration-MDfRO911.js","names":["executeAgent"],"sources":["../src/lib/detection/framework.ts","../src/lib/detection/features.ts","../src/lib/detection/context.ts","../src/lib/detection/agentic.ts","../src/lib/detection/project-scope.ts","../src/lib/warehouse-sources/registry.ts","../src/lib/warehouse-sources/detect.ts","../src/lib/programs/warehouse-source/detect.ts","../src/lib/programs/shared/health-check-step.ts","../src/lib/programs/posthog-integration/detect.ts","../src/lib/programs/posthog-integration/steps.ts","../src/ui/tui/styles.ts","../src/ui/tui/primitives/text-helpers.ts","../src/ui/tui/primitives/content-types.ts","../src/ui/tui/primitives/layout-helpers.ts","../src/ui/tui/primitives/TextBlock.tsx","../src/ui/tui/components/StatusPeekTrigger.tsx","../src/lib/programs/posthog-integration/content/data-flow.tsx","../src/lib/programs/posthog-integration/content/product-suite.tsx","../src/lib/programs/posthog-integration/content/line-chart.tsx","../src/lib/programs/posthog-integration/content/funnel.tsx","../src/lib/programs/posthog-integration/content/index.tsx","../src/lib/programs/posthog-integration/handoff.ts","../src/lib/programs/posthog-integration/index.ts"],"sourcesContent":["/**\n * Framework detection — identify which PostHog-supported framework\n * is present in the project directory.\n *\n * Pure function: takes an install dir, returns the detected integration\n * (or undefined). No store mutations, no UI calls.\n */\n\nimport { Integration, DETECTION_TIMEOUT_MS } from '@lib/constants';\nimport { FRAMEWORK_REGISTRY } from '@lib/registry';\n\n/**\n * Loop through all registered frameworks and return the first one\n * whose `detect()` predicate matches the given directory.\n * Returns undefined if no framework is detected or detection times out.\n */\nexport async function detectFramework(\n installDir: string,\n): Promise<Integration | undefined> {\n for (const integration of Object.values(Integration)) {\n const config = FRAMEWORK_REGISTRY[integration];\n try {\n const detected = await Promise.race([\n config.detection.detect({ installDir }),\n new Promise<false>((resolve) =>\n setTimeout(() => resolve(false), DETECTION_TIMEOUT_MS),\n ),\n ]);\n if (detected) {\n return integration;\n }\n } catch {\n // Skip frameworks whose detection throws\n }\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 * Framework context gathering — run gatherContext and version checks\n * for a detected framework.\n *\n * Pure functions: take a framework config and options, return results.\n * No store mutations, no UI calls.\n */\n\nimport * as semver from 'semver';\nimport { DETECTION_TIMEOUT_MS } from '@lib/constants';\nimport type { FrameworkConfig } from '@lib/framework-config';\nimport type { WizardRunOptions } from '@utils/types';\n\n/**\n * Run a framework's `gatherContext()` to collect variant-specific\n * metadata (e.g., router type for Next.js, Expo vs bare for React Native).\n *\n * Returns the gathered context, or an empty object on failure/timeout.\n */\nexport async function gatherFrameworkContext(\n config: FrameworkConfig,\n options: WizardRunOptions,\n): Promise<Record<string, unknown>> {\n if (!config.metadata.gatherContext) return {};\n\n try {\n return await Promise.race([\n config.metadata.gatherContext(options),\n new Promise<Record<string, never>>((resolve) =>\n setTimeout(() => resolve({}), DETECTION_TIMEOUT_MS),\n ),\n ]);\n } catch {\n return {};\n }\n}\n\nexport interface VersionCheckResult {\n /** Whether the installed version is supported */\n supported:\n | true\n | {\n current: string;\n minimum: string;\n docsUrl: string;\n };\n}\n\n/**\n * Check whether the installed framework version meets the minimum requirement.\n *\n * Returns `{ supported: true }` if the version is fine (or no check is needed).\n * Returns the version details if unsupported.\n */\nexport async function checkFrameworkVersion(\n config: FrameworkConfig,\n options: WizardRunOptions,\n): Promise<VersionCheckResult> {\n if (\n !config.detection.minimumVersion ||\n !config.detection.getInstalledVersion\n ) {\n return { supported: true };\n }\n\n const version = await config.detection.getInstalledVersion(options);\n if (!version) return { supported: true };\n\n const coerced = semver.coerce(version);\n if (coerced && semver.lt(coerced, config.detection.minimumVersion)) {\n return {\n supported: {\n current: version,\n minimum: config.detection.minimumVersion,\n docsUrl:\n config.metadata.unsupportedVersionDocsUrl ?? config.metadata.docsUrl,\n },\n };\n }\n\n return { supported: true };\n}\n","/**\n * Agentic project detection.\n *\n * A reusable detection tool that drives a Haiku agent over the repo: it finds\n * project roots, resolves monorepo/workspace markers, reads package manifests,\n * classifies each project against a caller-supplied set of targets, and reports\n * which projects already have a PostHog SDK installed.\n *\n * Product-knowledge-free by design — the caller passes the targets to classify\n * into (e.g. source-map skill variants) and maps the result back. Sits next to\n * the other detection tools (framework, features, package-manager) so it's\n * discoverable. Runs AFTER auth: it uses the same agent loop every program\n * uses, which needs credentials.\n */\n\nimport {\n initializeAgent,\n runAgent as executeAgent,\n buildRunTags,\n AgentSignals,\n} from '@lib/agent/agent-interface';\nimport { isAbsolute, resolve, sep } from 'path';\nimport { detectNodePackageManagers } from './package-manager.js';\nimport { CallType, getSkillsBaseUrl, HAIKU_MODEL } from '@lib/constants';\nimport { analytics } from '@utils/analytics';\nimport type { WizardSession } from '@lib/wizard-session';\nimport type { WizardRunOptions } from '@utils/types';\nimport type { SpinnerHandle } from '@ui';\n\n/** A category the agent classifies each project into (id the agent returns). */\nexport type DetectTarget = { id: string; name: string };\n\n/** One project the agent found in the repo. */\nexport type AgenticProject = {\n /** Path relative to the working directory (\".\" for the repo root). */\n path: string;\n /** Human-readable framework the agent detected (e.g. \"Next.js\"). */\n framework: string;\n /** A target id when the project matches one of the supplied targets, else null. */\n targetId: string | null;\n /** Whether a PostHog SDK is already installed in this project. */\n hasPostHog: boolean;\n /** True on the one project picked as the main user-facing app; only present when the scan set `recommend`. */\n recommended?: boolean;\n};\n\nexport type AgenticDetectionReport = {\n repoType: 'monorepo' | 'single';\n projects: AgenticProject[];\n};\n\n/** Streaming progress callback — one short activity line per agent step. */\nexport type DetectEvent = (line: string) => void;\n\n/**\n * Every project-manifest / workspace-marker filename the wizard's frameworks\n * are identified by. One brace-expansion Glob over all of these locates every\n * project root in the repo in a single call, regardless of language.\n *\n * Counterpart: POSTHOG_MANIFESTS in @lib/programs/self-driving/detect (SDK\n * grep); keep the two in sync.\n */\nexport const PROJECT_MANIFESTS: readonly string[] = [\n // JS/TS + workspace markers\n 'package.json',\n 'pnpm-workspace.yaml',\n 'turbo.json',\n 'nx.json',\n 'lerna.json',\n // Python\n 'requirements.txt',\n 'pyproject.toml',\n 'setup.py',\n 'Pipfile',\n 'manage.py',\n // Ruby / PHP\n 'Gemfile',\n 'composer.json',\n // Java\n 'pom.xml',\n // Rust\n 'Cargo.toml',\n // Elixir\n 'mix.exs',\n // Go\n 'go.mod',\n // .NET: no framework targets yet, but found so\n // an existing PostHog SDK is reported (feeds self-driving's \"continue\" path).\n '*.csproj',\n // Mobile / native\n 'Package.swift',\n 'Podfile',\n 'project.yml',\n 'project.pbxproj',\n 'pubspec.yaml',\n 'build.gradle',\n 'build.gradle.kts',\n 'settings.gradle',\n 'settings.gradle.kts',\n // Gradle version catalog (holds dependency coordinates).\n 'gradle/libs.versions.toml',\n];\n\n/** The single brace-expansion glob covering every supported manifest. */\nexport function manifestGlob(): string {\n return `**/{${PROJECT_MANIFESTS.join(',')}}`;\n}\n\nexport type AgenticDetectOptions = {\n /**\n * Categories to classify each project into. Order matters: list targets by\n * priority, most specific first. When a project could match more than one,\n * the agent keeps the earliest — so the caller encodes precedence purely\n * through ordering (e.g. a bundler target before a generic framework target).\n */\n targets: readonly DetectTarget[];\n /** The program this scan bills to. Required, not optional: the scan drives a\n * real agent through the gateway, and a caller that forgets leaves that\n * spend unattributed. */\n programId: string;\n /** One short clause describing what the scan is for (frames the prompt). */\n purpose?: string;\n /** Ask the agent to label exactly one project `recommended` (the main client app). Off by default. */\n recommend?: boolean;\n /**\n * Target ids whose technologies co-occur in one manifest (e.g. the JS\n * family). Among these, the enumeration's priority winner overrides the\n * model's pick; elsewhere a valid pick always wins — see coerceAgenticReport.\n */\n rerankIds?: readonly string[];\n /** Streaming activity callback for the UI. */\n onEvent?: DetectEvent;\n};\n\nfunction buildPrompt(\n cwd: string,\n targets: readonly DetectTarget[],\n purpose: string,\n recommend: boolean,\n): string {\n const targetList = targets.map((t) => `- ${t.id} → ${t.name}`).join('\\n');\n // matchingTargets precedes targetId: the model enumerates before it picks.\n const projectShape = `{\"path\":string,\"framework\":string,\"matchingTargets\":string[],\"targetId\":string|null,\"hasPostHog\":boolean,\"evidence\":string${\n recommend ? ',\"recommended\":boolean' : ''\n }}`;\n return [\n `You are scanning a code repository to ${purpose}. Be fast and mechanical — do not over-explore. Keep any reasoning to one short sentence, then run the tool calls and output the JSON.`,\n '',\n `Working directory: ${cwd}`,\n '',\n 'A \"project\" is a directory containing one or more of the manifest files below. Find projects by their manifests, NOT by walking directories — never report a directory that has no manifest.',\n '',\n 'Do exactly this:',\n `1. Run Glob ONCE with this pattern to find every project manifest in the repo in a single call: \"${manifestGlob()}\". Discard any result whose path contains node_modules/, dist/, build/, .next/, out/, coverage/, vendor/, .venv/, site-packages/, target/, Pods/, Carthage/, or DerivedData/. Group the remaining results by directory — each directory is one project. Three exceptions to \"directory = project\": a project.pbxproj lives inside a \"<Name>.xcodeproj/\" wrapper, so the project root is the PARENT of that .xcodeproj directory; a project.yml at a directory root is an XcodeGen-generated Xcode app rooted at that directory; a gradle/libs.versions.toml is a version catalog belonging to the gradle project rooted at the PARENT of that gradle/ directory (read it alongside the build.gradle when deciding hasPostHog), never its own project.`,\n '2. Decide repoType: \"monorepo\" if the root package.json has a \"workspaces\" field OR a pnpm-workspace.yaml / turbo.json / nx.json / lerna.json was found at the root, else \"single\".',\n `3. For EACH project directory, ONE AT A TIME: Read its manifest(s) ONCE, decide the fields below, then IMMEDIATELY — before reading any other project — write that project's verdict as one JSON line of shape ${projectShape}. Never write a verdict from memory of an earlier Read; the manifest you just read is the only source. Decide from its dependency lists:`,\n ' - the human-readable framework name (e.g. \"Next.js\", \"Django\", \"Rails\"),',\n ' - matchingTargets: EVERY target id from the list below whose technology appears in THIS manifest, in the priority order of the list. An id belongs here only if you can point at the dependency or setting in the manifest you just read — never carry one over from another project,',\n ' - targetId: the FIRST entry of matchingTargets (the list is ordered by priority, most specific first). null when matchingTargets is empty,',\n ` - hasPostHog: true if any dependency is a PostHog SDK. This includes: a name containing \"posthog\" in any ecosystem (e.g. posthog-js, posthog-node, @posthog/*, posthog for pip/gem/hex, a com.posthog:* gradle/maven coordinate, a PostHog NuGet PackageReference); an SPM package named \"PostHog\" or a repositoryURL of github.com/PostHog/posthog-ios (in Package.swift or a .pbxproj); or a \"pod 'PostHog'\" line in a Podfile. Else false.`,\n ' - evidence: the manifest fact that decided targetId, with the file it came from (e.g. \"rollup in devDependencies of backend/package.json\"). When targetId is null, name the closest fact you saw. One short clause, quoted from the manifest you just read.',\n ' Do NOT read any file other than these manifests.',\n ...(recommend\n ? [\n '4. Pick exactly ONE project as recommended — the main user-facing client application. Prefer a frontend web app or a mobile app over backend servers/APIs, libraries, CLIs, tooling, and example/demo/docs apps. If several client apps exist, pick the primary production app; if no client app exists, pick the primary application project.',\n ]\n : []),\n '',\n 'Target ids (id → name), in priority order — most specific first; if several match a project, keep the one listed earliest:',\n targetList,\n '',\n 'Output requirements:',\n '- After the last verdict line, respond with ONLY a single JSON object assembling the verdict lines you wrote, copied VERBATIM — same path, framework, targetId and evidence per project. No prose, no markdown code fences.',\n `- Shape: {\"repoType\":\"monorepo\"|\"single\",\"projects\":[${projectShape}]}`,\n '- \"path\" is the project directory relative to the working directory; use \".\" for the repo root.',\n '- \"targetId\" MUST be exactly one of the target ids above when it matches; if several match, use the one listed earliest; otherwise null.',\n '- Include projects whose stack matches no target too (targetId: null).',\n ...(recommend\n ? [\n '- Exactly one project has \"recommended\": true; every other project has \"recommended\": false.',\n ]\n : []),\n `- If there are no manifests at all, respond with exactly: ${AgentSignals.ABORT} detection failed`,\n ].join('\\n');\n}\n\n/**\n * Build the detection report from the agent's output, or null when it holds\n * no verdicts. Exported for testing.\n *\n * The verdict lines are far more reliable than the model's final assembly\n * (prose, pretty-printing, per-object fences), so every parseable line\n * contributes: objects with a `path` merge by path (last wins), and a\n * one-line assembly's `projects` merge the same way. `repoType` is\n * approximated from the count — it only feeds telemetry and display.\n */\nexport function deriveReportJson(text: string): unknown | null {\n const byPath = new Map<string, Record<string, unknown>>();\n for (const line of text.split('\\n')) {\n const start = line.indexOf('{');\n const end = line.lastIndexOf('}');\n if (start === -1 || end <= start) continue;\n let parsed: unknown;\n try {\n parsed = JSON.parse(line.slice(start, end + 1));\n } catch {\n continue; // not JSON — prose, shape echoes, pretty-printed fragments\n }\n const obj = (parsed ?? {}) as Record<string, unknown>;\n const candidates = Array.isArray(obj.projects) ? obj.projects : [obj];\n for (const candidate of candidates) {\n const p = (candidate ?? {}) as Record<string, unknown>;\n if (typeof p.path === 'string') byPath.set(p.path, p);\n }\n }\n if (byPath.size === 0) return null;\n const projects = [...byPath.values()];\n return { repoType: projects.length > 1 ? 'monorepo' : 'single', projects };\n}\n\n/**\n * Clamp an agent-reported project path to a safe repo-relative dir. The path\n * is LLM output: absolute paths or `..` segments could steer later phases\n * (e.g. integrate-run's targetDir) outside the repo, so they clamp to '.'.\n */\nfunction coercePath(raw: unknown): string {\n if (typeof raw !== 'string' || raw.length === 0) return '.';\n if (isAbsolute(raw) || raw.split(/[\\\\/]/).includes('..')) return '.';\n return raw;\n}\n\n/** Resolve an agent-reported path to an absolute dir clamped to the root — the caller-side counterpart of coercePath. */\nexport function resolveProjectDir(installDir: string, rel: unknown): string {\n if (typeof rel !== 'string' || rel === '.') return installDir;\n const root = resolve(installDir);\n const dir = resolve(root, rel);\n return dir === root || dir.startsWith(root + sep) ? dir : root;\n}\n\n/**\n * Validate the agent's raw JSON into a report, clamping each targetId to the\n * supplied set and each path to a repo-relative dir. Exported for testing.\n * `recommended` is stripped unless requested; at most one (the first) survives.\n */\nexport function coerceAgenticReport(\n parsed: unknown,\n validTargetIds: readonly string[],\n options?: { recommend?: boolean; rerankIds?: readonly string[] },\n): AgenticDetectionReport {\n const recommend = options?.recommend === true;\n const rerankIds = options?.rerankIds ?? [];\n const obj = (parsed ?? {}) as Record<string, unknown>;\n const repoType = obj.repoType === 'monorepo' ? 'monorepo' : 'single';\n const rawProjects = Array.isArray(obj.projects) ? obj.projects : [];\n let recommendedSeen = false;\n const projects: AgenticProject[] = rawProjects.map((raw) => {\n const p = (raw ?? {}) as Record<string, unknown>;\n // Trust the model's pick; an invalid one falls back to the enumeration's\n // highest-priority member (validTargetIds IS the priority order). The\n // winner overrides a valid pick only when both sit in rerankIds — stacks\n // that co-occur in one manifest, where a misordered enumeration is the\n // common miss. Elsewhere enumerations are padded across exclusive stacks\n // (a Flutter app listing react-native) and must not beat a correct pick.\n const pick =\n typeof p.targetId === 'string' && validTargetIds.includes(p.targetId)\n ? p.targetId\n : null;\n const enumerated = Array.isArray(p.matchingTargets)\n ? validTargetIds.find((id) =>\n (p.matchingTargets as unknown[]).includes(id),\n ) ?? null\n : null;\n const targetId =\n pick === null\n ? enumerated\n : enumerated !== null &&\n rerankIds.includes(enumerated) &&\n rerankIds.includes(pick)\n ? enumerated\n : pick;\n const recommended = recommend && !recommendedSeen && p.recommended === true;\n recommendedSeen ||= recommended;\n return {\n path: coercePath(p.path),\n framework: typeof p.framework === 'string' ? p.framework : 'Unknown',\n targetId,\n hasPostHog: p.hasPostHog === true,\n ...(recommend ? { recommended } : {}),\n };\n });\n return { repoType, projects };\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction formatToolUse(block: any): string {\n const name = typeof block?.name === 'string' ? block.name : 'tool';\n const input = (block?.input ?? {}) as Record<string, unknown>;\n const detail =\n (input.file_path as string) ||\n (input.pattern as string) ||\n (input.path as string) ||\n '';\n return detail ? `${name} ${detail}` : name;\n}\n\nfunction sessionToWizardOptions(session: WizardSession): WizardRunOptions {\n return {\n installDir: session.installDir,\n ci: session.ci,\n debug: session.debug,\n benchmark: session.benchmark,\n yaraReport: session.yaraReport,\n signup: session.signup,\n apiKey: session.apiKey,\n projectId: session.projectId,\n };\n}\n\nconst NOOP_SPINNER: SpinnerHandle = {\n start: () => undefined,\n stop: () => undefined,\n message: () => undefined,\n};\n\n/**\n * Drive the wizard's agent loop on HAIKU_MODEL to scan the repo and return a\n * structured detection report. Reuses the same setup every program uses, so\n * MCP, tools, and credentials are wired identically.\n */\nexport async function detectProjectsWithAgent(\n session: WizardSession,\n options: AgenticDetectOptions,\n): Promise<AgenticDetectionReport> {\n if (!session.credentials) {\n throw new Error('Detection requires authenticated credentials.');\n }\n const {\n targets,\n programId,\n purpose = 'set up a PostHog integration',\n recommend = false,\n rerankIds,\n onEvent,\n } = options;\n const { accessToken, host } = session.credentials;\n const cwd = session.installDir;\n const runOptions = sessionToWizardOptions(session);\n\n // Built here rather than inherited: this scan runs before\n // `bootstrapProgram`, so there's no `boot.wizardMetadata` yet.\n const wizardMetadata = {\n ...buildRunTags({\n programId,\n integration: 'agentic-detect',\n runId: analytics.runId,\n build: analytics.build,\n }),\n call_type: CallType.detection,\n };\n\n const agent = await initializeAgent(\n {\n workingDirectory: cwd,\n posthogMcpUrl: host.mcpUrl,\n posthogApiKey: accessToken,\n host,\n detectPackageManager: detectNodePackageManagers,\n skillsBaseUrl: getSkillsBaseUrl(),\n programId,\n integrationLabel: 'agentic-detect',\n wizardMetadata,\n allowedTools: ['Read', 'Grep', 'Glob'],\n modelOverride: HAIKU_MODEL,\n },\n runOptions,\n );\n\n // Keeps only the transcript tail — the report JSON is the last output.\n const MAX_TRANSCRIPT_CHARS = 256 * 1024;\n const collected: string[] = [];\n let collectedChars = 0;\n const collect = (text: string): void => {\n collected.push(text);\n collectedChars += text.length;\n while (collectedChars > MAX_TRANSCRIPT_CHARS && collected.length > 1) {\n collectedChars -= collected.shift()!.length;\n }\n };\n let resultText = '';\n\n const middleware = {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n onMessage: (message: any): void => {\n if (message?.type === 'assistant') {\n for (const block of message.message?.content ?? []) {\n if (block?.type === 'text' && typeof block.text === 'string') {\n collect(block.text);\n const line = block.text.trim();\n if (line && onEvent) {\n onEvent(line.length > 100 ? `${line.slice(0, 100)}…` : line);\n }\n } else if (block?.type === 'tool_use') {\n onEvent?.(formatToolUse(block));\n }\n }\n } else if (\n message?.type === 'result' &&\n typeof message.result === 'string'\n ) {\n resultText = message.result;\n }\n },\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n finalize: (_resultMessage: any, _durationMs: number): unknown => undefined,\n };\n\n const result = await executeAgent(\n agent,\n buildPrompt(cwd, targets, purpose, recommend),\n runOptions,\n NOOP_SPINNER,\n {\n spinnerMessage: 'Scanning the repo...',\n successMessage: 'Detection complete',\n errorMessage: 'Detection failed',\n requestRemark: false,\n },\n middleware,\n );\n\n if (result.error) {\n throw new Error(result.message || `Agent error: ${result.error}`);\n }\n\n // Transcript first, final message last — its verdicts win path conflicts.\n const output = `${collected.join('\\n')}\\n${resultText}`;\n const derived = deriveReportJson(output);\n if (derived === null) {\n // The prompt tells the agent to emit `[ABORT] detection failed` when the\n // repo has no recognizable project manifests. Surface that (and any other\n // non-JSON terminal output that carries the abort signal) as an empty\n // report so the screen renders a friendly \"nothing to instrument\" state\n // instead of a cryptic \"Agent did not return a JSON object\" error.\n if (output.includes(AgentSignals.ABORT)) {\n return { repoType: 'single', projects: [] };\n }\n throw new Error('Agent did not return a JSON object');\n }\n return coerceAgenticReport(\n derived,\n targets.map((t) => t.id),\n { recommend, rerankIds },\n );\n}\n","/** Non-interactive project scoping — scan the repo agentically and pick which project the run integrates. */\n\nimport {\n detectProjectsWithAgent,\n resolveProjectDir,\n type AgenticDetectionReport,\n type AgenticProject,\n type DetectEvent,\n type DetectTarget,\n} from './agentic.js';\nimport { authenticate } from '@lib/agent/runner/shared/authenticate';\nimport { FRAMEWORK_REGISTRY } from '@lib/registry';\nimport {\n AGENTIC_DETECTION_TIMEOUT_MS,\n WIZARD_BASIC_INTEGRATION_AGENTIC_DETECTION_FLAG_KEY,\n} from '@lib/constants';\nimport type { WizardSession } from '@lib/wizard-session';\nimport { getUI } from '@ui/index';\nimport { analytics } from '@utils/analytics';\nimport { logToFile } from '@utils/debug';\n\n/** Integration framework targets for the agentic detector (id → display name). */\nconst INTEGRATION_TARGETS: DetectTarget[] = Object.entries(\n FRAMEWORK_REGISTRY,\n).map(([id, config]) => ({ id, name: config.metadata.name }));\n\n/** Run the agentic detector for the wizard's integration frameworks — the single home of targets + purpose. */\nexport async function detectIntegrationProjects(\n session: WizardSession,\n options: {\n /** Program the scan bills to. Required so no caller can go unattributed. */\n programId: string;\n recommend?: boolean;\n onEvent?: DetectEvent;\n },\n): Promise<AgenticDetectionReport> {\n // Spread first so the targets and purpose this function owns always win.\n return detectProjectsWithAgent(session, {\n ...options,\n targets: INTEGRATION_TARGETS,\n purpose: 'set up a PostHog SDK integration',\n });\n}\n\n/** Pick the recommended-if-supported project (even with PostHog — the main app wins), else the first supported PostHog-free one. */\nexport function chooseIntegrationProject(\n projects: AgenticProject[],\n): AgenticProject | undefined {\n return (\n projects.find((p) => p.recommended === true && p.targetId != null) ??\n projects.find((p) => p.targetId != null && !p.hasPostHog)\n );\n}\n\n/** Every run fires exactly one `wizard: agentic detection` event with one of these outcomes — no untracked exits. */\nexport type AgenticDetectionOutcome =\n | 'flag-off'\n | 'error'\n | 'timeout'\n | 'no-project'\n | 'recommended'\n | 'first-instrumentable';\n\n/** Sentinel for a scan that outran AGENTIC_DETECTION_TIMEOUT_MS. */\nconst TIMED_OUT = Symbol('timed-out');\n\nfunction captureOutcome(\n outcome: AgenticDetectionOutcome,\n properties: Record<string, unknown> = {},\n): void {\n analytics.wizardCapture('agentic detection', { outcome, ...properties });\n}\n\n/** Flag-gated non-interactive monorepo phase: scan, auto-choose the recommended project, re-point session.installDir; every failure leaves the session untouched. */\nexport async function scopeInstallDirToProject(\n session: WizardSession,\n): Promise<void> {\n // Idempotent early auth: the detector needs credentials and the flag must evaluate as the logged-in user.\n await authenticate(session, 'posthog-integration');\n const flags = await analytics.getAllFlagsForWizard();\n if (flags[WIZARD_BASIC_INTEGRATION_AGENTIC_DETECTION_FLAG_KEY] !== 'true') {\n // A failed flag fetch surfaces as an empty map, so flag-off also covers \"flags unavailable\".\n captureOutcome('flag-off');\n return;\n }\n\n getUI().log.info('Scanning the repo for projects...');\n const startedAt = Date.now();\n let report: AgenticDetectionReport | typeof TIMED_OUT;\n try {\n report = await Promise.race([\n detectIntegrationProjects(session, {\n // Literal, like the `authenticate` call above: importing the program\n // registry here would cycle.\n programId: 'posthog-integration',\n recommend: true,\n onEvent: (line) => logToFile('[agentic detect]', line),\n }),\n // The agent has no abort plumbing, so a timed-out scan is abandoned in the\n // background rather than cancelled; the run stops waiting on it either way.\n new Promise<typeof TIMED_OUT>((resolve) =>\n setTimeout(() => resolve(TIMED_OUT), AGENTIC_DETECTION_TIMEOUT_MS),\n ),\n ]);\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n analytics.captureException(error, { step: 'agentic_detection' });\n captureOutcome('error', {\n duration_ms: Date.now() - startedAt,\n error_message: error.message,\n });\n getUI().log.warn(\n `Project scan failed (${error.message}); continuing with the install dir as-is.`,\n );\n return;\n }\n\n if (report === TIMED_OUT) {\n captureOutcome('timeout', { duration_ms: Date.now() - startedAt });\n getUI().log.warn(\n `Project scan timed out after ${\n AGENTIC_DETECTION_TIMEOUT_MS / 1000\n }s; continuing with the install dir as-is.`,\n );\n return;\n }\n\n const { projects } = report;\n const recommended = projects.find((p) => p.recommended === true);\n // The event carries at most this many projects; project_count is the true total.\n const MAX_PROJECTS_CAPTURED = 25;\n const scanProperties = {\n duration_ms: Date.now() - startedAt,\n repo_type: report.repoType,\n project_count: projects.length,\n supported_count: projects.filter((p) => p.targetId != null).length,\n has_recommendation: recommended !== undefined,\n recommended_path: recommended?.path ?? null,\n projects: projects.slice(0, MAX_PROJECTS_CAPTURED),\n };\n\n const project = chooseIntegrationProject(projects);\n if (!project) {\n captureOutcome('no-project', scanProperties);\n getUI().log.info(\n 'The scan found no supported project; continuing with the install dir as-is.',\n );\n return;\n }\n\n session.installDir = resolveProjectDir(session.installDir, project.path);\n captureOutcome(project.recommended ? 'recommended' : 'first-instrumentable', {\n ...scanProperties,\n chosen_framework: project.targetId,\n chosen_path: project.path,\n });\n getUI().log.info(`Continuing with ${project.path} (${project.framework}).`);\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 },\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 kind: 'BigQuery',\n label: 'BigQuery',\n mode: 'in-cli',\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","/**\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 '@lib/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).\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 detected: DetectedSource[] = [];\n for (const detector of SOURCE_DETECTORS) {\n const match = matchDetector(detector, signals);\n if (match) {\n detected.push({\n kind: detector.kind,\n label: detector.label,\n mode: detector.mode,\n matchedSignal: match,\n });\n }\n }\n return detected;\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 '@lib/agent/agent-runner';\nimport { detectWarehouseSources } from '@lib/warehouse-sources/detect';\nimport type { DetectedSource } from '@lib/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 * Shared health-check step used by every program that runs an agent.\n *\n * Renders the HealthCheckScreen between intro and auth, kicks off the\n * readiness probe in onInit, and gates the screen on either a clean\n * readiness result or an explicit user dismissal of the outage.\n *\n * Programs without this step that hit a blocking outage gridlock the\n * router: agent-runner calls wizardAbort, which awaits outroDismissed,\n * but the router can't advance past the still-incomplete auth step to\n * render the OutroScreen.\n */\n\nimport type { ProgramStep } from '@lib/programs/program-step';\nimport type { WizardSession } from '@lib/wizard-session';\nimport {\n evaluateWizardReadiness,\n WizardReadiness,\n SIGNUP_WIZARD_READINESS_CONFIG,\n getBlockingServiceKeys,\n} from '@lib/health-checks/readiness';\nimport { logToFile } from '@utils/debug';\n\nexport function healthCheckReady(session: WizardSession): boolean {\n if (!session.readinessResult) return false;\n\n if (session.signup) {\n const hardBlocking = getBlockingServiceKeys(\n session.readinessResult.health,\n SIGNUP_WIZARD_READINESS_CONFIG,\n );\n const defaultBlocking = getBlockingServiceKeys(\n session.readinessResult.health,\n );\n if (hardBlocking.length === 0 && defaultBlocking.length === 0) return true;\n return session.outageDismissed;\n }\n\n if (session.readinessResult.decision === WizardReadiness.No) {\n return session.outageDismissed;\n }\n return true;\n}\n\nexport const HEALTH_CHECK_STEP: ProgramStep = {\n id: 'health-check',\n label: 'Health check',\n screenId: 'health-check',\n gate: healthCheckReady,\n onInit: (ctx) => {\n evaluateWizardReadiness()\n .then((readiness) => {\n logToFile(\n `[health-checks] TUI pre-flight complete: decision=${readiness.decision}`,\n );\n ctx.setReadinessResult(readiness);\n })\n .catch((err) => {\n logToFile('[health-checks] TUI pre-flight failed:', err);\n ctx.setReadinessResult({\n decision: WizardReadiness.Yes,\n health: {} as never,\n reasons: [],\n });\n });\n },\n};\n","/**\n * Core integration detection step.\n *\n * Runs framework detection, context gathering, version checking,\n * and feature discovery. Writes results to the store via the\n * ProgramReadyContext so the IntroScreen can display them.\n *\n * This is the same work that bin.ts $0 handler does inline —\n * extracted here so the `integrate` subcommand can reuse it.\n */\n\nimport type { ProgramReadyContext } from '@lib/programs/program-step';\nimport {\n DiscoveredFeature,\n mayReportScanResults,\n ScanConsent,\n type WizardSession,\n} from '@lib/wizard-session';\nimport { FRAMEWORK_REGISTRY } from '@lib/registry';\nimport {\n detectFramework,\n discoverFeatures,\n gatherFrameworkContext,\n checkFrameworkVersion,\n} from '@lib/detection/index';\nimport { analytics } from '@utils/analytics';\nimport { detectWarehouseSources } from '@lib/warehouse-sources/detect';\nimport { AI_SOURCE_KINDS } from '@lib/warehouse-sources/registry';\nimport type { DetectedSource } from '@lib/warehouse-sources/types';\nimport {\n DETECTED_WAREHOUSE_SOURCES_KEY,\n getDetectedWarehouseSources,\n} from '@lib/programs/warehouse-source/detect';\n\nexport async function detectPostHogIntegration(\n ctx: ProgramReadyContext,\n): Promise<void> {\n const session = ctx.session;\n const installDir = session.installDir;\n\n const detectedIntegration = await detectFramework(installDir);\n\n if (detectedIntegration) {\n const config = FRAMEWORK_REGISTRY[detectedIntegration];\n\n const sessionOptions = {\n installDir,\n debug: session.debug,\n signup: session.signup,\n ci: session.ci,\n benchmark: session.benchmark,\n yaraReport: session.yaraReport,\n };\n\n // Gather framework-specific context (e.g., router type)\n const context = await gatherFrameworkContext(config, sessionOptions);\n for (const [key, value] of Object.entries(context)) {\n if (!(key in session.frameworkContext)) {\n ctx.setFrameworkContext(key, value);\n }\n }\n\n ctx.setFrameworkConfig(detectedIntegration, config);\n // Must go through the store setter: setFrameworkConfig (above) calls\n // nanostore setKey, which replaces the session with a shallow copy —\n // a direct `session.skillId = ...` here would write to the stale\n // pre-copy object and the live session would never see it.\n ctx.setSkillId(detectedIntegration);\n\n if (!session.detectedFrameworkLabel) {\n ctx.setDetectedFramework(config.metadata.name);\n }\n\n // Version check\n const versionResult = await checkFrameworkVersion(config, sessionOptions);\n if (versionResult.supported !== true) {\n ctx.setUnsupportedVersion(versionResult.supported);\n }\n }\n\n // Feature discovery\n for (const feature of discoverFeatures(installDir)) {\n ctx.addDiscoveredFeature(feature);\n }\n\n detectWarehouseSourcesForSuggestion(ctx, installDir);\n\n ctx.setDetectionComplete();\n}\n\n/**\n * How the scan went, for the reporter to read later. Three states, and the\n * absent one carries the most weight:\n *\n * absent this program never scanned. Only `posthog-integration` runs the\n * scan below, but every program's intro screen resolves consent\n * through the same store method, so the reporter is reached on runs\n * where no scan ever happened.\n * 'failed' the scan threw. A zero-count row would read as \"scanned, found\n * nothing\", which is a different fact.\n * 'ok' the scan ran. Zero sources is a real result and gets reported.\n */\nconst WAREHOUSE_SCAN_STATE_KEY = 'warehouseScanState';\ntype WarehouseScanState = 'ok' | 'failed';\n\n/**\n * Scan for data warehouse source signals (Postgres, Stripe, Hubspot, …) and,\n * when found, stash them for a `wizard warehouse` suggestion on the outro.\n * Runs unconditionally during `detect`, before the intro screen has asked\n * about sharing. Reporting what this finds is a separate, later concern.\n * See `reportWarehouseSourcesDetected` below.\n *\n * Deliberately a suggestion, not an inline agent run: a second credential-\n * collecting agent run before the outro could `process.exit()` on any of its\n * failure paths and cost the user the success outro on a run where PostHog\n * installed fine.\n *\n * Calls `detectWarehouseSources` (a pure scan) rather than the warehouse\n * program's `detectWarehousePrerequisites`, which writes a `detectError` when\n * it finds nothing — that's right for `wizard warehouse` but here would show a\n * spurious error and trip the CI prerequisites abort. No sources is a no-op.\n *\n * Best-effort: never let a scan failure break the wizard flow.\n */\nfunction detectWarehouseSourcesForSuggestion(\n ctx: ProgramReadyContext,\n installDir: string,\n): void {\n try {\n const sources = detectWarehouseSources(installDir);\n // Before the empty-list return: a scan that found nothing still ran, and\n // those rows are the denominator.\n ctx.setFrameworkContext(WAREHOUSE_SCAN_STATE_KEY, 'ok');\n if (sources.length === 0) return;\n ctx.setFrameworkContext(DETECTED_WAREHOUSE_SOURCES_KEY, sources);\n } catch (error) {\n ctx.setFrameworkContext(WAREHOUSE_SCAN_STATE_KEY, 'failed');\n analytics.captureException(\n error instanceof Error ? error : new Error(String(error)),\n { step: 'detectWarehouseSourcesForSuggestion' },\n );\n }\n}\n\nfunction hasAiSdkEvidence(\n session: WizardSession,\n sources: DetectedSource[],\n): boolean {\n return (\n sources.some((s) => AI_SOURCE_KINDS.has(s.kind)) ||\n session.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 */\nfunction stampAiSdkDetected(\n session: WizardSession,\n sources: DetectedSource[],\n): void {\n const organizationId = session.apiUser?.organization?.id;\n if (!organizationId) return;\n if (!hasAiSdkEvidence(session, sources)) return;\n\n analytics.groupIdentify('organization', organizationId, {\n wizard_ai_sdk_detected: true,\n });\n}\n\n/**\n * The single place scan results become telemetry. Called from\n * `WizardStore.completeSetup()`, the point consent becomes final — the privacy\n * panel's choice is reversible until then, so nothing may report earlier.\n *\n * Returns true when consent has resolved and the caller should latch\n * `warehouseSourcesReported`, which is not the same as \"this sent something\":\n * a decline, a failed scan, and a program that never scanned all resolve\n * without sending.\n */\nexport function reportWarehouseSourcesDetected(\n session: WizardSession,\n): boolean {\n if (session.warehouseSourcesReported) return false;\n // 'undecided' means come back later, not no.\n if (session.scanConsent === ScanConsent.Undecided) return false;\n\n if (mayReportScanResults(session)) {\n const sources = getDetectedWarehouseSources(session);\n stampAiSdkDetected(session, sources);\n\n // Only an 'ok' scan has something to say. Absent means this program never\n // scanned, and reporting a zero count there would invent a scan that never\n // ran; 'failed' already fired captureException.\n const scanState = session.frameworkContext[WAREHOUSE_SCAN_STATE_KEY] as\n | WarehouseScanState\n | undefined;\n if (scanState !== 'ok') return true;\n\n // Captured on every run, including the empty case. The denominator is\n // the whole point: without the zero rows, \"20% of runs have a Postgres\"\n // is unanswerable.\n analytics.wizardCapture('warehouse sources detected', {\n warehouse_source_count: sources.length,\n warehouse_source_kinds: sources.map((s) => s.kind),\n warehouse_source_modes: sources.map((s) => s.mode),\n });\n\n if (sources.length > 0) {\n // Tag subsequent events too, so any downstream funnel can slice on what the\n // project had available without re-joining to the event above.\n analytics.setTag(\n 'warehouse_source_kinds',\n sources.map((s) => s.kind).join(','),\n );\n analytics.setTag('warehouse_source_count', sources.length);\n }\n }\n // Nothing on 'declined': saved insights read every row of this event as a\n // scan that ran. Decline rate comes from 'intro menu selected' instead.\n\n return true;\n}\n","/**\n * PostHog integration program — the default wizard flow.\n *\n * Steps define their own gate predicates and onInit callbacks.\n * The store derives gate promises and fires init work from these\n * definitions — no hardcoded per-flow logic in the store.\n */\n\nimport type { ProgramStep } from '@lib/programs/program-step';\nimport type { WizardSession } from '@lib/wizard-session';\nimport { RunPhase } from '@lib/wizard-session';\nimport { HEALTH_CHECK_STEP } from '@lib/programs/shared/health-check-step';\nimport { detectPostHogIntegration } from './detect.js';\n\nfunction needsSetup(session: WizardSession): boolean {\n const config = session.frameworkConfig;\n if (!config?.metadata.setup?.questions) return false;\n\n return config.metadata.setup.questions.some(\n (q: { key: string }) => !(q.key in session.frameworkContext),\n );\n}\n\nexport const POSTHOG_INTEGRATION_PROGRAM: ProgramStep[] = [\n {\n id: 'detect',\n label: 'Detecting framework',\n // Headless step: no screen. onReady fires after bin.ts assigns the\n // session — runs framework detection, context gathering, version\n // check, and feature discovery. Results are written to the store\n // for the IntroScreen to render.\n onReady: (ctx) => detectPostHogIntegration(ctx),\n },\n {\n id: 'intro',\n label: 'Welcome',\n screenId: 'intro',\n gate: (session) => session.setupConfirmed,\n },\n HEALTH_CHECK_STEP,\n {\n id: 'setup',\n label: 'Setup',\n screenId: 'setup',\n show: needsSetup,\n isComplete: (session) => !needsSetup(session),\n },\n {\n id: 'auth',\n label: 'Authentication',\n screenId: 'auth',\n isComplete: (session) => session.credentials !== null,\n },\n {\n id: 'run',\n label: 'Integration',\n screenId: 'run',\n isComplete: (session) =>\n session.runPhase === RunPhase.Completed ||\n session.runPhase === RunPhase.Error,\n },\n {\n id: 'outro',\n label: 'Done',\n screenId: 'outro',\n isComplete: (session) => session.outroDismissed,\n },\n {\n id: 'mcp',\n label: 'MCP servers',\n screenId: 'mcp',\n isComplete: (session) => session.mcpComplete,\n },\n {\n id: 'slack-connect',\n label: 'Connect Slack',\n screenId: 'slack-connect',\n // Always shown — the user declines via Skip/esc, never bypassed.\n isComplete: (session) => session.slackStepDismissed,\n },\n {\n id: 'keep-skills',\n label: 'Keep Skills',\n screenId: 'keep-skills',\n },\n];\n","/**\n * Shared style constants for TUI layout primitives.\n */\n\nexport enum HAlign {\n Left = 'flex-start',\n Center = 'center',\n Right = 'flex-end',\n}\n\nexport enum VAlign {\n Top = 'flex-start',\n Center = 'center',\n Bottom = 'flex-end',\n}\n\nexport const Colors = {\n primary: 'cyan',\n accent: '#DC9300',\n titleColor: '#3D2800',\n success: 'green',\n error: 'red',\n muted: 'gray',\n} as const;\n\nexport const Icons = {\n diamond: '\\u25C6',\n diamondOpen: '\\u25C7',\n check: '\\u2714',\n warning: '\\u26A0',\n squareFilled: '\\u25FC',\n squareOpen: '\\u25FB',\n triangleRight: '\\u25B6',\n triangleSmallRight: '\\u25B8',\n bullet: '\\u2022',\n} as const;\n","/**\n * Text-splitting helpers for sentence boundary detection.\n * Used by TextBlock for animation pauses at punctuation.\n */\n\n/** Split text into sentences (keeps the delimiter attached) */\nexport function splitSentences(text: string): string[] {\n const parts: string[] = [];\n const re = /[^.!?]*[.!?]+\\s*/g;\n let match: RegExpExecArray | null;\n let lastIndex = 0;\n while ((match = re.exec(text)) !== null) {\n parts.push(match[0]);\n lastIndex = re.lastIndex;\n }\n if (lastIndex < text.length) {\n parts.push(text.slice(lastIndex));\n }\n return parts;\n}\n\n/** Build a set of character indices where sentences end (for typewriter pause) */\nexport function sentenceEndChars(text: string): Set<number> {\n const ends = new Set<number>();\n const sentences = splitSentences(text);\n let pos = 0;\n for (const s of sentences) {\n pos += s.length;\n ends.add(pos - 1);\n }\n return ends;\n}\n\n/** Build a set of word indices where sentences end (for word-by-word pause) */\nexport function sentenceEndWords(text: string): Set<number> {\n const ends = new Set<number>();\n const sentences = splitSentences(text);\n let wordCount = 0;\n for (const s of sentences) {\n const words = s.trim().split(/\\s+/).filter(Boolean);\n wordCount += words.length;\n ends.add(wordCount - 1);\n }\n return ends;\n}\n","/**\n * Content block types and type guards.\n *\n * Extracted from ContentSequencer so that pure-logic modules (like\n * layout-helpers) can import them without pulling in Ink/React.\n */\n\nimport type { ReactNode } from 'react';\nimport type { TextRevealMode } from './TextBlock.js';\n\n/** Object form — string or ReactNode content with per-block overrides. */\nexport interface ContentObjectBlock {\n content: string | ReactNode;\n mode?: TextRevealMode;\n animationInterval?: number;\n sentenceInterval?: number;\n pause?: number;\n persist?: boolean;\n /**\n * When the sequencer advances past this block, should it render dim?\n * Defaults to `true` — the standard \"completed step\" treatment. Set to\n * `false` to keep the block at full opacity even after it's complete\n * (useful for headings or greetings that should stay readable while\n * later blocks animate in).\n *\n * Only meaningful for blocks whose `content` is a string (TextBlock\n * renders the dim treatment). NodeBlocks render whatever JSX you pass\n * verbatim regardless of completion state.\n */\n dimWhenComplete?: boolean;\n}\n\n/** Lines block — reveals ReactNode lines one at a time. */\nexport interface ContentLinesBlock {\n type: 'lines';\n lines: ReactNode[];\n interval?: number;\n pause?: number;\n}\n\n/** Clear block — page break that hides all prior blocks. */\nexport interface ContentClearBlock {\n type: 'clear';\n pause?: number;\n}\n\n/** A content block in the sequence. Bare strings are sugar for { content: '...' }. */\nexport type ContentBlock =\n | string\n | ContentObjectBlock\n | ContentLinesBlock\n | ContentClearBlock;\n\n/** Type guard for lines blocks. */\nexport function isLinesBlock(block: ContentBlock): block is ContentLinesBlock {\n return typeof block !== 'string' && 'type' in block && block.type === 'lines';\n}\n\n/** Type guard for clear blocks. */\nexport function isClearBlock(block: ContentBlock): block is ContentClearBlock {\n return typeof block !== 'string' && 'type' in block && block.type === 'clear';\n}\n\n/** Type guard for object blocks (text or node content). */\nexport function isObjectBlock(\n block: ContentBlock,\n): block is ContentObjectBlock {\n return typeof block !== 'string' && !('type' in block);\n}\n","/**\n * Layout helpers — pure functions for height estimation and viewport eviction.\n *\n * These are the core of the responsive content system. They estimate how many\n * terminal rows a content block will occupy and determine which blocks fit\n * within a given height budget.\n */\n\nimport type { ContentBlock } from './content-types.js';\nimport { isLinesBlock, isClearBlock, isObjectBlock } from './content-types.js';\n\n/**\n * Estimate the number of terminal rows a content block will occupy,\n * including 1 row of marginBottom.\n */\nexport function estimateBlockHeight(\n block: ContentBlock,\n availableWidth: number,\n): number {\n if (typeof block === 'string') {\n return wordWrap(block, availableWidth).length + 1; // +1 for marginBottom\n }\n\n if (isClearBlock(block)) return 0;\n\n if (isLinesBlock(block)) {\n return block.lines.length + 1;\n }\n\n if (isObjectBlock(block)) {\n if (typeof block.content === 'string') {\n return wordWrap(block.content, availableWidth).length + 1;\n }\n return 4; // conservative fixed estimate for ReactNode\n }\n\n return 1;\n}\n\n/**\n * Given all blocks, the active index, available width, and a row budget,\n * return [startIdx, endIdx] — the range of blocks to render.\n *\n * Always includes activeIdx. Walks backward to include as many completed\n * blocks as fit within maxHeight.\n */\nexport function computeVisibleRange(\n blocks: ContentBlock[],\n activeIdx: number,\n availableWidth: number,\n maxHeight: number,\n): [number, number] {\n // Reserve a 2-row buffer so resize-induced estimate drift doesn't\n // cause overflow=\"hidden\" to clip the margin between blocks.\n const budget = Math.max(4, maxHeight - 2);\n\n let totalHeight = estimateBlockHeight(blocks[activeIdx], availableWidth);\n let start = activeIdx;\n\n for (let i = activeIdx - 1; i >= 0; i--) {\n // Clear blocks act as a hard boundary — don't show anything before them\n if (isClearBlock(blocks[i])) break;\n const h = estimateBlockHeight(blocks[i], availableWidth);\n if (totalHeight + h > budget) break;\n totalHeight += h;\n start = i;\n }\n\n return [start, activeIdx];\n}\n\n/**\n * Word-wrap text at clean word boundaries. Always returns pre-wrapped text\n * joined with \\n — this avoids Ink's native wrap which can leave leading\n * spaces on continuation lines.\n *\n * Uses a 1-char safety margin so slight width estimate mismatches don't\n * cause Ink to re-wrap our already-wrapped lines.\n */\nexport function wordWrap(text: string, availableWidth: number): string[] {\n const safeWidth = Math.max(10, availableWidth - 1);\n const words = text.split(/\\s+/);\n const lines: string[] = [];\n let currentLine = '';\n\n for (const word of words) {\n if (\n currentLine.length + word.length + 1 > safeWidth &&\n currentLine.length > 0\n ) {\n lines.push(currentLine);\n currentLine = word;\n } else {\n currentLine += (currentLine.length > 0 ? ' ' : '') + word;\n }\n }\n if (currentLine.length > 0) {\n lines.push(currentLine);\n }\n\n return lines;\n}\n\n/**\n * Word-wrap text and return only the last `maxRows` lines.\n * Used for intra-block truncation when a single text block exceeds the viewport.\n * Also used for normal rendering to avoid Ink's leading-space wrap artifacts.\n */\nexport function wrapAndTruncate(\n text: string,\n availableWidth: number,\n maxRows: number,\n): string {\n const lines = wordWrap(text, availableWidth);\n\n if (lines.length <= maxRows) {\n return lines.join('\\n');\n }\n\n return lines.slice(-maxRows).join('\\n');\n}\n","/**\n * TextBlock — Animates a single string paragraph.\n *\n * Self-contained: owns its own animIdx and timer.\n * Calls onComplete() when the animation finishes.\n *\n * Five animation modes:\n * 1. Typewriter — character-by-character reveal\n * 2. Word by word — each word appears in order\n * 3. Sentence by sentence — sentences appear one at a time\n * 4. Paragraph fade — paragraph appears at full opacity immediately\n * 5. Sentence fade — paragraph dim, sentences light up in order\n */\n\nimport { Text } from 'ink';\nimport { useState, useEffect, useRef, useMemo, type ReactNode } from 'react';\nimport { Colors } from '@ui/tui/styles';\nimport {\n splitSentences,\n sentenceEndChars,\n sentenceEndWords,\n} from './text-helpers.js';\nimport { wrapAndTruncate } from './layout-helpers.js';\n\nexport enum TextRevealMode {\n Typewriter = 0,\n WordByWord = 1,\n SentenceBySentence = 2,\n ParagraphFade = 3,\n SentenceFade = 4,\n}\n\nexport const TEXT_REVEAL_MODE_LABELS = [\n 'Typewriter',\n 'Word by word',\n 'Sentence by sentence',\n 'Paragraph fade',\n 'Sentence fade',\n];\n\nexport const TEXT_REVEAL_MODE_COUNT = 5;\n\n/** Default interval per mode (ms) */\nexport const TEXT_REVEAL_MODE_DEFAULTS: Record<TextRevealMode, number> = {\n [TextRevealMode.WordByWord]: 240,\n [TextRevealMode.Typewriter]: 32,\n [TextRevealMode.SentenceBySentence]: 1800,\n [TextRevealMode.ParagraphFade]: 4800,\n [TextRevealMode.SentenceFade]: 2400,\n};\n\ninterface TextBlockProps {\n text: string;\n active: boolean;\n completed: boolean;\n onComplete: () => void;\n mode: TextRevealMode;\n bullet?: ReactNode;\n animationInterval?: number;\n sentenceInterval?: number;\n /** Max rows this block may occupy. When exceeded, top lines are truncated. */\n maxHeight?: number;\n /** Available text width in columns (for truncation wrapping). */\n availableWidth?: number;\n /**\n * When `completed === true`, render the text dim. Defaults to `true` —\n * the standard \"completed step\" treatment. Pass `false` to keep the\n * text at full opacity even after the sequencer has moved on.\n */\n dimWhenComplete?: boolean;\n}\n\nexport const TextBlock = ({\n text,\n active,\n completed,\n onComplete,\n mode,\n bullet,\n animationInterval,\n sentenceInterval = 1600,\n maxHeight,\n availableWidth,\n dimWhenComplete = true,\n}: TextBlockProps) => {\n const speed = animationInterval ?? TEXT_REVEAL_MODE_DEFAULTS[mode];\n\n const [animIdx, setAnimIdx] = useState(\n mode === TextRevealMode.SentenceFade ? 1 : 0,\n );\n\n // Reset synchronously during render to avoid a one-frame flash\n const resetRef = useRef(0);\n const prevMode = useRef(mode);\n if (prevMode.current !== mode) {\n prevMode.current = mode;\n resetRef.current += 1;\n setAnimIdx(mode === TextRevealMode.SentenceFade ? 1 : 0);\n }\n\n const words = text.split(/\\s+/);\n const sentences = splitSentences(text);\n\n const sentenceCharEnds = useMemo(() => sentenceEndChars(text), [text]);\n const sentenceWordEnds = useMemo(() => sentenceEndWords(text), [text]);\n\n const isDone =\n mode === TextRevealMode.Typewriter\n ? animIdx >= text.length\n : mode === TextRevealMode.ParagraphFade\n ? true\n : mode === TextRevealMode.WordByWord\n ? animIdx >= words.length\n : mode === TextRevealMode.SentenceFade ||\n mode === TextRevealMode.SentenceBySentence\n ? animIdx >= sentences.length\n : true;\n\n // Fire onComplete when done\n useEffect(() => {\n if (isDone && active) onComplete();\n }, [isDone, active, onComplete]);\n\n // Animate: single effect for all tick-based modes\n useEffect(() => {\n if (!active || mode === TextRevealMode.ParagraphFade || isDone) return;\n const token = resetRef.current;\n\n const isFirstTick = animIdx === 0;\n\n let delay = isFirstTick ? 0 : speed;\n if (\n !isFirstTick &&\n mode === TextRevealMode.Typewriter &&\n animIdx > 0 &&\n sentenceCharEnds.has(animIdx - 1)\n ) {\n delay = sentenceInterval;\n } else if (\n !isFirstTick &&\n mode === TextRevealMode.WordByWord &&\n animIdx > 0 &&\n sentenceWordEnds.has(animIdx - 1)\n ) {\n delay = sentenceInterval;\n }\n\n const timer = setTimeout(() => {\n if (token !== resetRef.current) return;\n setAnimIdx((c) => c + 1);\n }, delay);\n return () => clearTimeout(timer);\n }, [\n active,\n mode,\n animIdx,\n isDone,\n speed,\n sentenceInterval,\n sentenceCharEnds,\n sentenceWordEnds,\n ]);\n\n // Pre-wrap text ourselves to avoid Ink's native wrap leaving leading spaces\n // on continuation lines. When maxHeight is set, also truncates to last N rows.\n const wrap = (visibleText: string): string => {\n if (availableWidth == null) return visibleText;\n if (maxHeight == null) {\n return wrapAndTruncate(visibleText, availableWidth, Infinity);\n }\n return wrapAndTruncate(visibleText, availableWidth, maxHeight);\n };\n\n // Completed: dimmed by default, but can be overridden per-block.\n if (completed) {\n return (\n <Text dimColor={dimWhenComplete}>\n {bullet}\n {wrap(text)}\n </Text>\n );\n }\n\n // Active: mode-specific rendering\n if (mode === TextRevealMode.Typewriter) {\n const revealed = text.slice(0, animIdx);\n const atSentenceEnd = /[.!?]\\s*$/.test(revealed);\n const display = atSentenceEnd ? revealed.trimEnd() : revealed;\n return (\n <Text>\n {bullet}\n {wrap(display)}\n <Text color={Colors.muted}>{'\\u258C'}</Text>\n </Text>\n );\n }\n\n if (mode === TextRevealMode.WordByWord) {\n const visible = words.slice(0, animIdx).join(' ');\n return (\n <Text>\n {bullet}\n {wrap(visible)}\n </Text>\n );\n }\n\n if (mode === TextRevealMode.ParagraphFade) {\n return (\n <Text>\n {bullet}\n {wrap(text)}\n </Text>\n );\n }\n\n if (mode === TextRevealMode.SentenceBySentence) {\n const visible = sentences.slice(0, animIdx).join('');\n return (\n <Text>\n {bullet}\n {wrap(visible)}\n </Text>\n );\n }\n\n // SentenceFade\n return (\n <Text>\n {bullet}\n {sentences.map((s, si) => (\n <Text key={si} dimColor={si >= animIdx}>\n {s}\n </Text>\n ))}\n </Text>\n );\n};\n","/**\n * StatusPeekTrigger — Fires the status-bar expansion once, renders a hint.\n *\n * Module-level `peekedOnce` guards against re-mounts (resize, tab switch)\n * so the peek only happens a single time per process.\n */\n\nimport { Text } from 'ink';\nimport { useEffect } from 'react';\nimport type { WizardStore } from '@ui/tui/store';\n\nlet peekedOnce = false;\n\ninterface StatusPeekTriggerProps {\n store?: WizardStore;\n /** How long the status bar stays expanded, in ms. */\n duration?: number;\n}\n\nexport const StatusPeekTrigger = ({\n store,\n duration = 10000,\n}: StatusPeekTriggerProps) => {\n useEffect(() => {\n if (peekedOnce) return;\n peekedOnce = true;\n store?.setStatusExpanded(true);\n // No cleanup — the store call is safe after unmount and the component\n // may be evicted before the timer fires (non-persist NodeBlock).\n setTimeout(() => {\n store?.setStatusExpanded(false);\n }, duration);\n }, [store, duration]);\n\n return <Text>You can view the Wizard's status below.</Text>;\n};\n","/**\n * POSTHOG_DATA_FLOW — ASCII diagram of the PostHog event ingestion flow.\n */\n\nimport { Text } from 'ink';\nimport { Colors } from '@ui/tui/styles';\nimport type { ContentBlock } from '@ui/tui/primitives/content-types';\n\nexport const POSTHOG_DATA_FLOW: ContentBlock = {\n type: 'lines',\n interval: 500,\n pause: 8000,\n // Box is 30 chars wide between │ borders.\n // Labels: 1-char indent. Arrows: \" ↓ \" (5). Sub-items: \" │ \" (7).\n lines: [\n <Text color=\"gray\">{' ┌──────────────────────────────┐'}</Text>,\n <Text>\n <Text color=\"gray\">{' │ '}</Text>\n <Text bold color=\"cyan\">\n Your App\n </Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ │ '}</Text>\n <Text>posthog.capture()</Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ │ '}</Text>\n <Text dimColor>custom events</Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ │ '}</Text>\n <Text dimColor>custom properties</Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ │ '}</Text>\n <Text dimColor>person profiles</Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ ↓ '}</Text>\n <Text dimColor>groups</Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ '}</Text>\n <Text bold color={Colors.accent}>\n PostHog SDK\n </Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ ↓ '}</Text>\n <Text>HTTP</Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ '}</Text>\n <Text bold color={Colors.accent}>\n PostHog Cloud\n </Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ ↓ '}</Text>\n <Text>query + visualize</Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │ '}</Text>\n <Text bold color=\"green\">\n Dashboards & Insights\n </Text>\n <Text color=\"gray\">{' │'}</Text>\n </Text>,\n <Text color=\"gray\">{' └──────────────────────────────┘'}</Text>,\n ],\n};\n","/**\n * PRODUCT_SUITE_BLOCK — Two-column listing of PostHog products.\n */\n\nimport { Text } from 'ink';\nimport type { ContentBlock } from '@ui/tui/primitives/content-types';\n\nexport const PRODUCT_SUITE_BLOCK: ContentBlock = {\n type: 'lines',\n interval: 1000,\n pause: 15000,\n lines: [\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'Product Analytics '}\n <Text color=\"cyan\">{'◆ '}</Text>\n {'Error Tracking'}\n </Text>,\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'Web Analytics '}\n <Text color=\"cyan\">{'◆ '}</Text>\n {'Session Replay'}\n </Text>,\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'Feature Flags '}\n <Text color=\"cyan\">{'◆ '}</Text>\n {'Data Pipelines'}\n </Text>,\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'Experiments '}\n <Text color=\"cyan\">{'◆ '}</Text>\n {'Data Warehouse'}\n </Text>,\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'AI Observability '}\n <Text color=\"cyan\">{'◆ '}</Text>\n {'Surveys'}\n </Text>,\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'Workflows '}\n <Text color=\"cyan\">{'◆ '}</Text>\n {'Logs'}\n </Text>,\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'Product Tours '}\n <Text color=\"cyan\">{'◆ '}</Text>\n {'Support'}\n </Text>,\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'Revenue Analytics '}\n <Text color=\"cyan\">{'◆ '}</Text>\n {'Endpoints'}\n </Text>,\n <Text>\n <Text color=\"cyan\">{' ◆ '}</Text>\n {'Customer Analytics '}\n <Text color=\"cyan\">{'◆ '}</Text>\n {'PostHog Code'}\n </Text>,\n ],\n};\n","/**\n * LINE_CHART_BLOCK — ASCII trends chart illustrating an insight.\n */\n\nimport { Text } from 'ink';\nimport type { ContentBlock } from '@ui/tui/primitives/content-types';\n\nexport const LINE_CHART_BLOCK: ContentBlock = {\n type: 'lines',\n interval: 300,\n pause: 6000,\n lines: [\n <Text bold>{' Trends · user signups (monthly)'}</Text>,\n <Text> </Text>,\n // 10k\n <Text>\n <Text color=\"gray\">{' 10k ┤'}</Text>\n {' '}\n <Text color=\"cyan\">{'╭──'}</Text>\n <Text dimColor>{' 9,575'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │'}</Text>\n {' '}\n <Text color=\"cyan\">{'╭╯'}</Text>\n </Text>,\n // 7.5k\n <Text>\n <Text color=\"gray\">{' 7.5k ┤'}</Text>\n {' '}\n <Text color=\"cyan\">{'╭╯'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │'}</Text>\n {' '}\n <Text color=\"cyan\">{'╭─╯'}</Text>\n </Text>,\n // 5k\n <Text>\n <Text color=\"gray\">{' 5k ┤'}</Text>\n {' '}\n <Text color=\"cyan\">{'╭─╯'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │'}</Text>\n {' '}\n <Text color=\"cyan\">{'╭──╯'}</Text>\n </Text>,\n // 2.5k\n <Text>\n <Text color=\"gray\">{' 2.5k ┤'}</Text>\n {' '}\n <Text color=\"cyan\">{'╭───╯'}</Text>\n </Text>,\n <Text>\n <Text color=\"gray\">{' │'}</Text>\n {' '}\n <Text color=\"cyan\">{'╭──────╯'}</Text>\n </Text>,\n // 0\n <Text>\n <Text color=\"gray\">{' 0 ┤'}</Text>\n <Text color=\"cyan\">{'──────╯'}</Text>\n </Text>,\n // X-axis\n <Text color=\"gray\">{' └┬─────┬─────┬─────┬─────┬──'}</Text>,\n <Text dimColor>{' May Aug Nov Feb May'}</Text>,\n ],\n};\n","/**\n * FUNNEL_BLOCK — ASCII funnel illustrating step conversion.\n */\n\nimport { Text } from 'ink';\nimport type { ContentBlock } from '@ui/tui/primitives/content-types';\n\nexport const FUNNEL_BLOCK: ContentBlock = {\n type: 'lines',\n interval: 200,\n pause: 8000,\n lines: [\n <Text bold>{' Funnel · ride conversion'}</Text>,\n <Text> </Text>,\n // Step 1\n <Text>\n {' '}\n <Text bold>1</Text>\n {' app_launched'}\n {' '}\n <Text bold color=\"green\">\n 100.00%\n </Text>\n </Text>,\n <Text color=\"cyan\">{' ██████████████████████████████'}</Text>,\n <Text dimColor>{' → 1,200 users'}</Text>,\n <Text> </Text>,\n // Step 2\n <Text>\n {' '}\n <Text bold>2</Text>\n {' ride_requested'}\n {' '}\n <Text dimColor>{'avg 2m 30s'}</Text>\n {' '}\n <Text bold color=\"green\">\n 72.00%\n </Text>\n </Text>,\n <Text>\n {' '}\n <Text color=\"cyan\">{'██████████████████████'}</Text>\n <Text dimColor>{'░░░░░░░░░'}</Text>\n </Text>,\n <Text>\n {' '}\n <Text dimColor>→ 864 users</Text>\n {' '}\n <Text color=\"red\">↘</Text>\n <Text dimColor>{' 336 (28%)'}</Text>\n </Text>,\n <Text> </Text>,\n // Step 3\n <Text>\n {' '}\n <Text bold>3</Text>\n {' ride_accepted'}\n {' '}\n <Text dimColor>{'avg 5m 12s'}</Text>\n {' '}\n <Text bold color=\"green\">\n 51.00%\n </Text>\n </Text>,\n <Text>\n {' '}\n <Text color=\"cyan\">{'██████████████████'}</Text>\n <Text dimColor>{'░░░░░░░░░░░░░'}</Text>\n </Text>,\n <Text>\n {' '}\n <Text dimColor>→ 612 users</Text>\n {' '}\n <Text color=\"red\">↘</Text>\n <Text dimColor>{' 252 (29%)'}</Text>\n </Text>,\n <Text> </Text>,\n // Step 4\n <Text>\n {' '}\n <Text bold>4</Text>\n {' ride_started'}\n {' '}\n <Text dimColor>{'avg 1m 45s'}</Text>\n {' '}\n <Text bold color=\"green\">\n 38.00%\n </Text>\n </Text>,\n <Text>\n {' '}\n <Text color=\"cyan\">{'█████████████'}</Text>\n <Text dimColor>{'░░░░░░░░░░░░░░░░░░'}</Text>\n </Text>,\n <Text>\n {' '}\n <Text dimColor>→ 456 users</Text>\n {' '}\n <Text color=\"red\">↘</Text>\n <Text dimColor>{' 156 (25%)'}</Text>\n </Text>,\n ],\n};\n","/**\n * Integration learn-deck — the narrative script played while the agent\n * runs the PostHog integration flow. Weaves typewriter lines, pauses,\n * `clear` markers, and the diagram blocks into one sequence.\n */\n\nimport { Text } from 'ink';\nimport { Colors } from '@ui/tui/styles';\nimport type { WizardStore } from '@ui/tui/store';\nimport { TextRevealMode } from '@ui/tui/primitives/TextBlock';\nimport type { ContentBlock } from '@ui/tui/primitives/content-types';\nimport { StatusPeekTrigger } from '@ui/tui/components/StatusPeekTrigger';\nimport { POSTHOG_DATA_FLOW } from './data-flow.js';\nimport { PRODUCT_SUITE_BLOCK } from './product-suite.js';\nimport { LINE_CHART_BLOCK } from './line-chart.js';\nimport { FUNNEL_BLOCK } from './funnel.js';\n\nexport const getContentBlocks = (store?: WizardStore): ContentBlock[] => [\n {\n // Name comes from the login profile; falls back when absent (CI keys).\n content: store?.session.apiUser?.first_name\n ? `Welcome, ${store.session.apiUser.first_name}.`\n : 'Welcome.',\n pause: 3000,\n mode: TextRevealMode.Typewriter,\n animationInterval: 160,\n },\n\n { content: 'The Wizard is an agent.', pause: 4000 },\n\n {\n content: 'It handles the entire PostHog setup process on your behalf.',\n pause: 5000,\n },\n\n {\n content:\n \"As we speak, it's building a plan to set up PostHog in your project.\",\n pause: 6000,\n },\n\n { type: 'clear', pause: 2000 },\n\n {\n pause: 5000,\n persist: true,\n content: <StatusPeekTrigger store={store} />,\n },\n\n {\n pause: 6000,\n content: (\n <Text>\n Press{' '}\n <Text color={Colors.accent} bold>\n S\n </Text>{' '}\n to expand or collapse the status.\n </Text>\n ),\n },\n\n { type: 'clear', pause: 2000 },\n\n {\n content: 'It takes about eight minutes.',\n pause: 2000,\n },\n\n {\n content: 'So grab some coffee ☕️.',\n pause: 2000,\n },\n\n {\n content: 'Or stick around and learn about PostHog.',\n pause: 5000,\n },\n\n { type: 'clear', pause: 3000 },\n\n {\n content: 'Events are the foundation of the PostHog platform.',\n pause: 4000,\n },\n\n {\n content:\n 'Every time an action is performed in your codebase — like button clicks, function calls, or thrown errors — we can capture an event.',\n pause: 6000,\n },\n\n {\n content: 'Events are sent to PostHog and joined with other product data.',\n pause: 6000,\n },\n\n { type: 'clear', pause: 1000 },\n\n { content: \"Here's the flow.\", pause: 1000 },\n\n POSTHOG_DATA_FLOW,\n\n { type: 'clear', pause: 2000 },\n\n {\n content:\n 'With enough event data, you can answer powerful questions about your product.',\n pause: 4000,\n },\n\n { content: 'And create insights.', pause: 4000 },\n\n { type: 'clear', pause: 500 },\n\n { content: 'Like trends to measure growth.', pause: 2500 },\n\n LINE_CHART_BLOCK,\n\n { type: 'clear', pause: 500 },\n\n { content: 'Or funnels to reveal bottlenecks.', pause: 2500 },\n\n FUNNEL_BLOCK,\n\n { type: 'clear', pause: 1000 },\n\n {\n content: 'Use those signals to decide what to build next.',\n pause: 4000,\n },\n\n { content: 'PostHog has all the dev tools you need.', pause: 3000 },\n\n PRODUCT_SUITE_BLOCK,\n];\n","/**\n * The one-line prompt the operator pastes into their own coding agent after a\n * run: open the setup-report notebook, work its \"Verify before merging\"\n * checklist. Surfaced via `OutroData.handoffPrompt` (printed to scrollback on\n * exit); only exists when the run captured a notebook URL, since no report\n * file is written. The wording demands investigate-then-approval, and stops\n * there — the operator's own agent governs how changes land. Background:\n * https://github.com/PostHog/wizard/issues/447\n */\nexport function buildCodingAgentPrompt(notebookUrl: string): string {\n return `Open ${notebookUrl} (the PostHog setup report) and work through its \"Verify before merging\" checklist: investigate each item, then list the changes you'd make and get my approval before applying any of them.`;\n}\n","import type { ProgramConfig, ProgramStep } from '@lib/programs/program-step';\nimport { runAgent, type ProgramRun } from '@lib/agent/agent-runner';\nimport { WIZARD_TOOL_NAMES } from '@lib/wizard-tools';\nimport type { WizardSession } from '@lib/wizard-session';\nimport { mayReportScanResults, OutroKind, RunPhase } from '@lib/wizard-session';\nimport { AgentSignals } from '@lib/agent/agent-interface';\nimport {\n DEFAULT_PACKAGE_INSTALLATION,\n SPINNER_MESSAGE,\n} from '@lib/framework-config';\nimport { tryGetPackageJson, isUsingTypeScript } from '@utils/setup-utils';\nimport { analytics } from '@utils/analytics';\nimport { detectFramework, gatherFrameworkContext } from '@lib/detection/index';\nimport { scopeInstallDirToProject } from '@lib/detection/project-scope';\nimport { FRAMEWORK_REGISTRY } from '@lib/registry';\nimport { wizardAbort } from '@utils/wizard-abort';\nimport { ErrorCodes } from '@lib/errors';\nimport { WIZARD_INTERACTION_EVENT_NAME } from '@lib/constants';\nimport { getUI } from '@ui/index';\nimport { requestDeepLink } from '@utils/provisioning';\nimport { openTrackedLink, withUtm } from '@utils/links';\nimport type { HostResolution } from '@lib/host-resolution';\nimport { getDetectedWarehouseSources } from '@lib/programs/warehouse-source/detect';\nimport { shouldDisableAsk } from '@lib/agent/runner/shared/bootstrap';\nimport { POSTHOG_INTEGRATION_PROGRAM } from './steps.js';\nimport { getContentBlocks } from './content/index.js';\nimport { buildCodingAgentPrompt } from './handoff.js';\nimport { EVENT_PLAN_FILE } from './constants.js';\n\nconst DASHBOARD_DEEP_LINK_KEY = 'dashboardDeepLink';\n\nconst WAREHOUSE_SOURCES_DOCS_URL =\n 'https://posthog.com/docs/data-warehouse/sources';\n\nfunction resolveContinueUrl(\n sess: WizardSession,\n host: HostResolution,\n deepLink: unknown,\n): string | undefined {\n if (!sess.signup) return undefined;\n if (typeof deepLink === 'string' && deepLink) return deepLink;\n return withUtm(`${host.appHost}/products?source=wizard`, 'outro-continue');\n}\n\n/** Sources listed with their own link before the outro falls back to a summary line. */\nconst WAREHOUSE_LINK_LIMIT = 3;\n\n/**\n * The app's new-source page, pre-selected to one source kind.\n *\n * `kind` is matched case-insensitively against the connector list, and a kind\n * the app cannot resolve lands on the source catalog rather than erroring. So a\n * source we detect but the app has not shipped a connector for still takes the\n * user somewhere useful.\n */\nfunction warehouseSourceUrl(\n host: HostResolution,\n projectId: number | string,\n kind: string,\n): string {\n const path = `${\n host.appHost\n }/project/${projectId}/data-warehouse/new-source?kind=${encodeURIComponent(\n kind,\n )}`;\n return withUtm(path, 'outro-warehouse');\n}\n\n/**\n * Outro suggestion for data sources found in the project but not connected.\n *\n * A pointer at the app, not an inline flow. Connecting a source needs\n * interactive credential collection, and chaining that as a second agent run\n * before the outro would let any of its terminal failure paths `process.exit()`\n * — costing the user the success outro and the post-outro MCP / Slack steps on\n * a run where PostHog installed fine.\n *\n * Each source gets its own pre-filled link, because the alternative we shipped\n * first — naming the `wizard warehouse` command — asks the user to start a\n * second CLI run before they can connect anything. A link opens the form for\n * that one source. The command line stays for anyone who wants every source in\n * one pass, and it is the only route offered once the list is too long to read.\n *\n * Returns undefined when nothing was detected, so the outro is unchanged for\n * projects with no connectable source.\n */\nfunction buildWarehouseNextSteps(\n sess: WizardSession,\n host: HostResolution,\n projectId: number | string,\n): { heading: string; items: string[] } | undefined {\n const sources = getDetectedWarehouseSources(sess);\n if (sources.length === 0) return undefined;\n\n const listed = sources.slice(0, WAREHOUSE_LINK_LIMIT);\n const items = listed.map(\n (s) => `Connect ${s.label}: ${warehouseSourceUrl(host, projectId, s.kind)}`,\n );\n\n const remaining = sources.length - listed.length;\n if (remaining > 0) {\n items.push(`And ${remaining} more we found in this project.`);\n }\n items.push('Connect them all at once with: npx @posthog/wizard warehouse');\n\n return { heading: 'Query your other data in PostHog:', items };\n}\n\n/**\n * Prompt fragment asking the agent to note the detected data sources in the\n * setup report's checklist.\n *\n * Empty string when nothing was detected, so the prompt is byte-identical to\n * today for projects with no connectable source. Best-effort by nature — the\n * agent may word it differently or skip it. That is acceptable here precisely\n * because it is a note in a report: the outro `nextSteps` bullet carries the\n * same information deterministically, so nothing is lost if the agent drops it.\n */\nfunction warehouseReportInstruction(sess: WizardSession): string {\n const sources = getDetectedWarehouseSources(sess);\n if (sources.length === 0) return '';\n\n const labels = sources.map((s) => s.label).join(', ');\n return `Finally: this project also contains data sources PostHog can import (${labels}). In the setup report's \"Verify before merging\" checklist, add one item noting these were found and that \\`npx @posthog/wizard warehouse\\` will connect them to PostHog's data warehouse. Do not attempt to set them up yourself in this run.`;\n}\n\n/**\n * The orchestrator task that connects the data sources detection found in the\n * project — the one step of the flow that stops to ask the user for\n * credentials. Queued here rather than by the planner: whether it belongs in\n * the run is a fact about the project the wizard already scanned, so a model\n * can neither invent it nor forget it.\n *\n * It runs at the end of the queue, not the start. Where exactly is the agent\n * prompt's business (`dependsOn` in the warehouse agent's frontmatter, resolved\n * by `seeded-deps.ts` once the planner has run) — this file only decides whether\n * the task belongs in the run at all.\n *\n * Empty when nothing was detected, and in CI, signup, and any other run where\n * `wizard_ask` is disabled — a credential prompt nobody can answer would burn\n * the task's whole timeout and then fail the run.\n */\nconst warehouseSeedTasks: NonNullable<ProgramConfig['seedTasks']> = (sess) => {\n if (shouldDisableAsk(sess)) return [];\n const sources = getDetectedWarehouseSources(sess);\n if (sources.length === 0) return [];\n\n // The task is queued either way. A decline withholds reporting, not the\n // feature. See the matching gate in reportWarehouseSourcesDetected.\n if (mayReportScanResults(sess)) {\n analytics.wizardCapture('orchestrator warehouse task queued', {\n warehouse_source_count: sources.length,\n warehouse_source_kinds: sources.map((s) => s.kind),\n });\n }\n return [\n {\n type: 'warehouse',\n inputs: {\n sources: sources.map((s) => ({\n kind: s.kind,\n label: s.label,\n mode: s.mode,\n matchedSignal: s.matchedSignal,\n })),\n },\n notice: {\n title: 'Connect your data sources',\n // Two moments, and the copy has to name both. The answer is given here,\n // at the start of the run. The credential questions arrive at the end of\n // it, minutes later. So this must not read as \"expect a prompt any\n // moment now\", and equally must not read as \"walk away for the run\".\n body: [\n 'We detected some warehouse sources we can connect to enrich your PostHog data. Answer now, and we connect them at the end of the run, after your code changes. We will ask you for the credentials at that point, and beep when we do.',\n \"You can select [Skip] if you'd like to do this later in PostHog.\",\n ],\n items: sources.map((s) => s.label),\n docsLabel: 'Learn more about warehouse sources',\n docsUrl: WAREHOUSE_SOURCES_DOCS_URL,\n prompt: 'Connect these during setup?',\n confirmLabel: 'Continue [Enter]',\n cancelLabel: 'Skip [Esc]',\n },\n },\n ];\n};\n\nexport const SETUP_REPORT_FILE = 'posthog-setup-report.md';\nexport { EVENT_PLAN_FILE } from './constants.js';\n\nexport const posthogIntegrationConfig: ProgramConfig = {\n command: 'integrate',\n description: 'Set up PostHog SDK integration',\n id: 'posthog-integration',\n agentFlow: 'integration-v2',\n eventPlanFile: EVENT_PLAN_FILE,\n steps: POSTHOG_INTEGRATION_PROGRAM,\n getContentBlocks,\n // Basic integration runs without structured user input; drop wizard_ask\n // so the model can't pop modal prompts mid-run. The runner forwards this\n // list to the general-purpose subagent as well, so dispatched subagents\n // can't reach around the parent and ask either.\n disallowedTools: [WIZARD_TOOL_NAMES.wizardAsk],\n\n seedTasks: warehouseSeedTasks,\n\n // CI-mode prerequisite work: the headless equivalent of the detect step's\n // onReady hook. Auto-detect the framework, then gather context.\n ciPreRun: async (session: WizardSession): Promise<void> => {\n await scopeInstallDirToProject(session);\n\n const integration = await detectFramework(session.installDir);\n if (!integration) {\n await wizardAbort({\n code: ErrorCodes.DetectNoFramework,\n message: 'Could not auto-detect your framework for this project.',\n });\n return;\n }\n session.integration = integration;\n analytics.setTag('integration', integration);\n\n const frameworkConfig = FRAMEWORK_REGISTRY[integration];\n session.frameworkConfig = frameworkConfig;\n\n const context = await gatherFrameworkContext(frameworkConfig, {\n installDir: session.installDir,\n debug: session.debug,\n signup: session.signup,\n ci: true,\n benchmark: session.benchmark,\n yaraReport: session.yaraReport,\n });\n for (const [key, value] of Object.entries(context)) {\n if (!(key in session.frameworkContext)) {\n session.frameworkContext[key] = value;\n }\n }\n },\n\n run: async (session: WizardSession): Promise<ProgramRun> => {\n const config = session.frameworkConfig!;\n\n const typeScriptDetected = isUsingTypeScript({\n installDir: session.installDir,\n });\n session.typescript = typeScriptDetected;\n analytics.setTag('typescript', typeScriptDetected);\n\n // Read package.json and resolve framework version\n const usesPackageJson = config.detection.usesPackageJson !== false;\n let frameworkVersion: string | undefined;\n\n if (usesPackageJson) {\n const packageJson = await tryGetPackageJson({\n installDir: session.installDir,\n });\n if (packageJson) {\n const { hasDeclaredDependency } = await import('@utils/package-json');\n if (!hasDeclaredDependency(config.detection.packageName, packageJson)) {\n getUI().log.warn(\n `${config.detection.packageDisplayName} does not seem to be installed. Continuing anyway — the agent will handle it.`,\n );\n }\n frameworkVersion = config.detection.getVersion(packageJson);\n } else {\n getUI().log.warn(\n 'Could not find package.json. Continuing anyway — the agent will handle it.',\n );\n }\n } else {\n frameworkVersion = config.detection.getVersion(null);\n }\n\n // Analytics tags\n if (frameworkVersion && config.detection.getVersionBucket) {\n const versionBucket = config.detection.getVersionBucket(frameworkVersion);\n analytics.setTag(`${config.metadata.integration}-version`, versionBucket);\n }\n const frameworkContext = session.frameworkContext;\n const contextTags = config.analytics.getTags(frameworkContext);\n Object.entries(contextTags).forEach(([key, value]) => {\n analytics.setTag(key, value);\n });\n\n return {\n integrationLabel: config.metadata.integration,\n additionalMcpServers: config.metadata.additionalMcpServers,\n detectPackageManager: config.detection.detectPackageManager,\n spinnerMessage: SPINNER_MESSAGE,\n successMessage: config.ui.successMessage,\n estimatedDurationMinutes: config.ui.estimatedDurationMinutes,\n reportFile: SETUP_REPORT_FILE,\n docsUrl: config.metadata.docsUrl,\n errorMessage: 'Integration failed',\n additionalFeatureQueue: session.additionalFeatureQueue,\n // The seeded warehouse task's fallback, when a user cannot hand over a\n // credential, is to give them the pre-filled new-source URL. That only\n // works if the overlay renders it as a link they can open or copy.\n richLinks: true,\n\n customPrompt: (ctx) => {\n const additionalLines = config.prompts.getAdditionalContextLines\n ? config.prompts.getAdditionalContextLines(frameworkContext)\n : [];\n const additionalContext =\n additionalLines.length > 0\n ? '\\n' + additionalLines.map((line) => `- ${line}`).join('\\n')\n : '';\n\n return `You have access to the PostHog MCP server which provides skills to integrate PostHog into this ${\n config.metadata.name\n } project.\n\nProject context:\n- PostHog Project ID: ${ctx.projectId}\n- Framework: ${config.metadata.name} ${frameworkVersion || 'latest'}\n- TypeScript: ${typeScriptDetected ? 'Yes' : 'No'}\n- PostHog public token: ${ctx.projectApiKey}\n- PostHog Host: ${ctx.host.apiHost}\n- Project type: ${config.prompts.projectTypeDetection}\n- Package installation: ${\n config.prompts.packageInstallation ?? DEFAULT_PACKAGE_INSTALLATION\n }${additionalContext}\n\nInstructions (follow these steps IN ORDER - do not skip or reorder):\n\nSTEP 1: Call load_skill_menu (from the wizard-tools MCP server) to see available skills.\n If the tool fails, emit: ${\n AgentSignals.ERROR_MCP_MISSING\n } Could not load skill menu and halt.\n\n Choose a skill from the \\`integration\\` category that matches this project's framework. Do NOT pick skills from other categories (llm-analytics, error-tracking, feature-flags, omnibus, etc.) — those are handled separately.\n If no suitable integration skill is found, emit: ${\n AgentSignals.ERROR_RESOURCE_MISSING\n } Could not find a suitable skill for this project.\n\nSTEP 2: Call install_skill (from the wizard-tools MCP server) with the chosen skill ID (e.g., \"integration-nextjs-app-router\").\n Do NOT run any shell commands to install skills.\n If install_skill fails, emit on its own line: ${\n AgentSignals.SKILL_INSTALL_FAILED\n } <skill id — one-line reason>. Then CONTINUE and SKIP to STEP 5 the integration without the skill, following these steps and your knowledge of ${\n config.metadata.name\n } and PostHog's official docs, and note in the setup report that the skill could not be installed.\n\nSTEP 3: Load the installed skill's SKILL.md file to understand what references are available.\n\nSTEP 4: Follow the skill's program files in sequence. Look for numbered program files in the references (e.g., files with patterns like \"1-\", \"2-\", \"3-\"). Start with the first one and proceed through each step until completion. Each program file will tell you what to do and which file comes next. Never directly write PostHog tokens directly to code files; always use environment variables.\n\nSTEP 5: Set up environment variables for PostHog using the wizard-tools MCP server (this runs locally — secret values never leave the machine):\n - Use check_env_keys to see which keys the project already sets, and where. Omit filePath and it scans every .env file in the project, so you don't have to guess between .env, .env.local and a nested one. It answers { status, foundIn } per key: \"present\" means a real env file sets the key, while a key found only in a committed template (.env.example and friends) reads as \"missing\" — a template documents a key rather than setting it, and is never a file to write credentials into.\n - Use set_env_values to create or update the PostHog public token and host, using the appropriate environment variable naming convention for ${\n config.metadata.name\n }, which you'll find in example code. The tool will also ensure .gitignore coverage. Don't assume the presence of keys means the value is up to date. Write the correct value each time.\n - Reference these environment variables in the code files you create instead of hardcoding the public token and host.\n\nImportant: Use the detect_package_manager tool (from the wizard-tools MCP server) to determine which package manager the project uses, then run its install command to add the SDK. Do not manually search for lockfiles or config files. If a file already EXISTS, read it immediately before you edit or overwrite it — writing from a stale read causes a tool failure. Creating a brand-new file needs no prior read: never read a path that does not exist yet; just write it.\n\n${warehouseReportInstruction(session)}\n`;\n },\n\n postRun: async (sess, credentials) => {\n const envVars = config.environment.getEnvVars(\n credentials.projectApiKey,\n credentials.host.apiHost,\n );\n if (config.environment.uploadToHosting) {\n const { uploadEnvironmentVariablesStep } = await import(\n '@steps/index'\n );\n const uploadedEnvVars = await uploadEnvironmentVariablesStep(\n envVars,\n {\n integration: config.metadata.integration,\n session: sess,\n },\n );\n if (uploadedEnvVars.length > 0) {\n analytics.capture(WIZARD_INTERACTION_EVENT_NAME, {\n action: 'wizard_env_vars_uploaded',\n integration: config.metadata.integration,\n variable_count: uploadedEnvVars.length,\n variable_keys: uploadedEnvVars,\n });\n }\n }\n\n if (sess.signup) {\n const deepLink = await requestDeepLink(\n credentials.accessToken,\n credentials.host,\n );\n if (deepLink) {\n const taggedDeepLink = withUtm(deepLink, 'dashboard-deeplink');\n sess.frameworkContext[DASHBOARD_DEEP_LINK_KEY] = taggedDeepLink;\n openTrackedLink(taggedDeepLink, 'dashboard-deeplink', {\n auto: true,\n });\n }\n }\n },\n\n buildOutroData: (sess, credentials) => {\n const envVars = config.environment.getEnvVars(\n credentials.projectApiKey,\n credentials.host.apiHost,\n );\n const deepLink = sess.frameworkContext[DASHBOARD_DEEP_LINK_KEY];\n const continueUrl = resolveContinueUrl(\n sess,\n credentials.host,\n deepLink,\n );\n\n const changes = [\n ...config.ui.getOutroChanges(frameworkContext),\n Object.keys(envVars).length > 0\n ? 'Added environment variables to .env file'\n : '',\n ].filter(Boolean);\n\n return {\n kind: OutroKind.Success as const,\n message: 'Successfully installed PostHog!',\n changes,\n docsUrl: config.metadata.docsUrl,\n continueUrl,\n nextSteps: buildWarehouseNextSteps(\n sess,\n credentials.host,\n credentials.projectId,\n ),\n // Set once the agent mirrors the report into a notebook and emits [NOTEBOOK_URL].\n notebookUrl: sess.notebookUrl ?? undefined,\n // No report file — the prompt points at the notebook, when the run captured one.\n handoffPrompt: sess.notebookUrl\n ? buildCodingAgentPrompt(sess.notebookUrl)\n : undefined,\n };\n },\n };\n },\n};\n\nexport { POSTHOG_INTEGRATION_PROGRAM } from './steps.js';\n\n/**\n * Self-contained run step that runs the integration agent. Other programs\n * import this and splice it into their own step list to compose the\n * integration's work as one of their run steps — self-driving sets up PostHog\n * this way before its own run. The host program supplies `show`/`onRunPrep`/\n * `targetDir`; this carries the run.\n */\nexport const integrationRunStep: ProgramStep = {\n id: 'run',\n label: 'Integration',\n screenId: 'run',\n // composed: runs inside the host program (self-driving), so skip the\n // integration's terminal outro + analytics shutdown of the shared client.\n run: (session) =>\n runAgent(posthogIntegrationConfig, session, { composed: true }),\n isComplete: (session) =>\n session.runPhase === RunPhase.Completed ||\n session.runPhase === RunPhase.Error,\n};\n"],"mappings":"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"}
|