@posthog/wizard 2.82.0 → 2.84.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -29
- package/dist/{PickerMenu-BGGeYqd-.js → PickerMenu-BtheKi1o.js} +1 -1
- package/dist/{PickerMenu-BGGeYqd-.js.map → PickerMenu-BtheKi1o.js.map} +1 -1
- package/dist/_dev-only-stub-B0db0Klc.js +1 -0
- package/dist/{agent-interface-3YfIWZmY.js → agent-interface-BNssNetq.js} +86 -32
- package/dist/agent-interface-BNssNetq.js.map +1 -0
- package/dist/{agent-prompt-loader-hOHONY7u.js → agent-prompt-loader-iV11XVEF.js} +16 -8
- package/dist/agent-prompt-loader-iV11XVEF.js.map +1 -0
- package/dist/{analytics-B_xFshPY.js → analytics-Drox5LSW.js} +7 -5
- package/dist/analytics-Drox5LSW.js.map +1 -0
- package/dist/analytics-Ix9HEra3.js +2 -0
- package/dist/{api-C_9KsN-7.js → api-Dfu655Qt.js} +2 -2
- package/dist/{api-C_9KsN-7.js.map → api-Dfu655Qt.js.map} +1 -1
- package/dist/api-H2UaPgjv.js +2 -0
- package/dist/{api-key-login-oUJQDmOV.js → api-key-login-BgwfAXfv.js} +5 -5
- package/dist/{api-key-login-oUJQDmOV.js.map → api-key-login-BgwfAXfv.js.map} +1 -1
- package/dist/api-key-login-Cow3UDAN.js +2 -0
- package/dist/bin.js +1 -1
- package/dist/{bounded-fs-iRaQcKYL.js → bounded-fs-TRL6IsoU.js} +32 -16
- package/dist/bounded-fs-TRL6IsoU.js.map +1 -0
- package/dist/{ci-install-BGlijoTo.js → ci-install-nc1IKuX2.js} +6 -6
- package/dist/{ci-install-BGlijoTo.js.map → ci-install-nc1IKuX2.js.map} +1 -1
- package/dist/{console-log-DJiTqYT2.js → console-log-BMhBoX-o.js} +2 -2
- package/dist/{console-log-DJiTqYT2.js.map → console-log-BMhBoX-o.js.map} +1 -1
- package/dist/{debug-BvEbemym.js → debug-BfO_Txo8.js} +3 -3
- package/dist/debug-BfO_Txo8.js.map +1 -0
- package/dist/{defaults-DDVl3tKN.js → defaults-BWLIffh5.js} +1 -1
- package/dist/{defaults-DDVl3tKN.js.map → defaults-BWLIffh5.js.map} +1 -1
- package/dist/{errors-DhFeR8Sp.js → errors-BXlWujEw.js} +1 -1
- package/dist/{errors-DhFeR8Sp.js.map → errors-BXlWujEw.js.map} +1 -1
- package/dist/{family-picker-BKs-tTyu.js → family-picker-CAW_VtYf.js} +2 -2
- package/dist/{family-picker-BKs-tTyu.js.map → family-picker-CAW_VtYf.js.map} +1 -1
- package/dist/{gateway-CWoYlPz7.js → gateway-CLQQb96F.js} +39 -9
- package/dist/{gateway-CWoYlPz7.js.map → gateway-CLQQb96F.js.map} +1 -1
- package/dist/headless-CHGNEzO3.js +3 -0
- package/dist/{headless-Bfi950Qh.js → headless-DMO8N_FD.js} +2 -2
- package/dist/{headless-Bfi950Qh.js.map → headless-DMO8N_FD.js.map} +1 -1
- package/dist/{host-resolution-BxnNn8Jm.js → host-resolution-DftfSjJD.js} +4 -4
- package/dist/{host-resolution-BxnNn8Jm.js.map → host-resolution-DftfSjJD.js.map} +1 -1
- package/dist/{install-CDVeUT_5.js → install-C9FPM37m.js} +6 -6
- package/dist/{install-CDVeUT_5.js.map → install-C9FPM37m.js.map} +1 -1
- package/dist/{install-CX65IxGa.js → install-MWoo1hXL.js} +1 -1
- package/dist/{interactive-5-Numwwb.js → interactive-DOnolJHB.js} +3 -3
- package/dist/{interactive-5-Numwwb.js.map → interactive-DOnolJHB.js.map} +1 -1
- package/dist/{links-Dmj3Wj9X.js → links-CatXPRxH.js} +3 -3
- package/dist/{links-Dmj3Wj9X.js.map → links-CatXPRxH.js.map} +1 -1
- package/dist/{main-5KNn80Vt.js → main-CINmZtoW.js} +27 -24
- package/dist/main-CINmZtoW.js.map +1 -0
- package/dist/{mcp-Buf9sfFm.js → mcp-KVV6Z_bq.js} +3 -3
- package/dist/{mcp-Buf9sfFm.js.map → mcp-KVV6Z_bq.js.map} +1 -1
- package/dist/{mcp-prompt-streaming-DHPxJK-F.js → mcp-prompt-streaming-M6UnLgGX.js} +5 -5
- package/dist/{mcp-prompt-streaming-DHPxJK-F.js.map → mcp-prompt-streaming-M6UnLgGX.js.map} +1 -1
- package/dist/{mode-label-DB3ol_sj.js → mode-label--bJuXny5.js} +1 -1
- package/dist/{mode-label-DB3ol_sj.js.map → mode-label--bJuXny5.js.map} +1 -1
- package/dist/{models-C9rjXPZ6.js → models-B0huHItG.js} +6 -2
- package/dist/models-B0huHItG.js.map +1 -0
- package/dist/{non-interactive-DkldwWDM.js → non-interactive-DiEu4_6l.js} +3 -3
- package/dist/{non-interactive-DkldwWDM.js.map → non-interactive-DiEu4_6l.js.map} +1 -1
- package/dist/{oauth-session-Bi1MLRCC.js → oauth-session-9EU3ky0v.js} +2 -2
- package/dist/{oauth-session-Bi1MLRCC.js.map → oauth-session-9EU3ky0v.js.map} +1 -1
- package/dist/{orchestrator-tools-DyKws92o.js → orchestrator-tools-QWyDLu_7.js} +3 -3
- package/dist/{orchestrator-tools-DyKws92o.js.map → orchestrator-tools-QWyDLu_7.js.map} +1 -1
- package/dist/package-json-BAtJRHSq.js +2 -0
- package/dist/{package-json-2UrhE6kP.js → package-json-z1agAYXs.js} +1 -1
- package/dist/{package-json-2UrhE6kP.js.map → package-json-z1agAYXs.js.map} +1 -1
- package/dist/{package-manager-DpCdmMmB.js → package-manager-B-9I_fAT.js} +4 -4
- package/dist/{package-manager-DpCdmMmB.js.map → package-manager-B-9I_fAT.js.map} +1 -1
- package/dist/{pi-DTj1hsJe.js → pi-BSnSk6rv.js} +50 -31
- package/dist/pi-BSnSk6rv.js.map +1 -0
- package/dist/{playground-CiH6zZPb.js → playground-Drz1qszs.js} +4 -4
- package/dist/{playground-CiH6zZPb.js.map → playground-Drz1qszs.js.map} +1 -1
- package/dist/{posthog-integration-CpinLWNO.js → posthog-integration-mIQGBc1f.js} +883 -2513
- package/dist/posthog-integration-mIQGBc1f.js.map +1 -0
- package/dist/programs-Bv0_YHzE.js +3 -0
- package/dist/{programs-Bq9Ju9xk.js → programs-mxhRXwP-.js} +306 -125
- package/dist/programs-mxhRXwP-.js.map +1 -0
- package/dist/provisioning-BVsxSNve.js +2 -0
- package/dist/{provisioning-D-AM_7DG.js → provisioning-CHUjae9V.js} +4 -4
- package/dist/{provisioning-D-AM_7DG.js.map → provisioning-CHUjae9V.js.map} +1 -1
- package/dist/{queue-tools-BoIITT7w.js → queue-tools-PFG6H93Q.js} +14 -5
- package/dist/queue-tools-PFG6H93Q.js.map +1 -0
- package/dist/{results-CDqlHogZ.js → results-5yCKf2cI.js} +2 -2
- package/dist/{results-CDqlHogZ.js.map → results-5yCKf2cI.js.map} +1 -1
- package/dist/{run-CfMArkpV.js → run-D5TKJuSL.js} +10 -10
- package/dist/{run-CfMArkpV.js.map → run-D5TKJuSL.js.map} +1 -1
- package/dist/{run-DcaVJSeI.js → run-W03b6jNM.js} +12 -12
- package/dist/{run-DcaVJSeI.js.map → run-W03b6jNM.js.map} +1 -1
- package/dist/{run-tool-DJZWnnR9.js → run-tool-DTQF8mmI.js} +17 -17
- package/dist/{run-tool-DJZWnnR9.js.map → run-tool-DTQF8mmI.js.map} +1 -1
- package/dist/run-tool-DjERhu7G.js +2 -0
- package/dist/{runners-Cvnk9BcA.js → runners-B_84kPyf.js} +11 -11
- package/dist/{runners-Cvnk9BcA.js.map → runners-B_84kPyf.js.map} +1 -1
- package/dist/{security-Cz3a-d7r.js → security-pApVawYb.js} +6 -5
- package/dist/{security-Cz3a-d7r.js.map → security-pApVawYb.js.map} +1 -1
- package/dist/{setup-utils-C7kaDP5X.js → setup-utils-CQY8PHjR.js} +3 -3
- package/dist/{setup-utils-C7kaDP5X.js.map → setup-utils-CQY8PHjR.js.map} +1 -1
- package/dist/{start-playground-B62_pYfu.js → start-playground-DAw1GbLt.js} +8 -8
- package/dist/{start-playground-B62_pYfu.js.map → start-playground-DAw1GbLt.js.map} +1 -1
- package/dist/{subagent-BBfETG17.js → subagent-YLGSvgoZ.js} +13 -5
- package/dist/subagent-YLGSvgoZ.js.map +1 -0
- package/dist/{task-CmNe3xeg.js → task-3hRSovmK.js} +39 -29
- package/dist/task-3hRSovmK.js.map +1 -0
- package/dist/{tasks-BfJhVky2.js → tasks-C03QbXTx.js} +1 -1
- package/dist/{tasks-BfJhVky2.js.map → tasks-C03QbXTx.js.map} +1 -1
- package/dist/{telemetry-DKM7VGuJ.js → telemetry-BPBzqsb_.js} +2 -2
- package/dist/{telemetry-DKM7VGuJ.js.map → telemetry-BPBzqsb_.js.map} +1 -1
- package/dist/{terminal-Bkxwzkhn.js → terminal-DZsYFbm9.js} +471 -81
- package/dist/terminal-DZsYFbm9.js.map +1 -0
- package/dist/{tools-DZCEvDv9.js → tools-D_AtrhbO.js} +15 -15
- package/dist/{tools-DZCEvDv9.js.map → tools-D_AtrhbO.js.map} +1 -1
- package/dist/{tools-Bm0FDT6f.js → tools-DyzRi_dQ.js} +8 -8
- package/dist/{tools-Bm0FDT6f.js.map → tools-DyzRi_dQ.js.map} +1 -1
- package/dist/{tui-B56jvkbi.js → tui-CRp0iCuT.js} +5 -5
- package/dist/tui-CRp0iCuT.js.map +1 -0
- package/dist/{tui-tKI95MSr.js → tui-UI6ctBQJ.js} +1 -1
- package/dist/{upload-step-DqTgn6UB.js → upload-step-DrYXnpzI.js} +3 -3
- package/dist/{upload-step-DqTgn6UB.js.map → upload-step-DrYXnpzI.js.map} +1 -1
- package/dist/{urls-B82v7gfO.js → urls-WeqfBLP4.js} +2 -2
- package/dist/{urls-B82v7gfO.js.map → urls-WeqfBLP4.js.map} +1 -1
- package/dist/{wizard-abort-Cd-7sfCw.js → wizard-abort-BwEefm6P.js} +5 -5
- package/dist/{wizard-abort-Cd-7sfCw.js.map → wizard-abort-BwEefm6P.js.map} +1 -1
- package/dist/yara-hooks-MDtFbuoM.js +2 -0
- package/dist/{yara-hooks-BS0n3ekf.js → yara-hooks-aDbdsitJ.js} +41 -5
- package/dist/{yara-hooks-BS0n3ekf.js.map → yara-hooks-aDbdsitJ.js.map} +1 -1
- package/package.json +9 -7
- package/dist/agent-interface-3YfIWZmY.js.map +0 -1
- package/dist/agent-prompt-loader-hOHONY7u.js.map +0 -1
- package/dist/analytics-B_xFshPY.js.map +0 -1
- package/dist/analytics-DGDr6-iD.js +0 -2
- package/dist/api-DhLSO3ai.js +0 -2
- package/dist/api-key-login-DiRuZ8Lm.js +0 -2
- package/dist/bounded-fs-iRaQcKYL.js.map +0 -1
- package/dist/debug-BvEbemym.js.map +0 -1
- package/dist/headless-Gisv3faN.js +0 -3
- package/dist/main-5KNn80Vt.js.map +0 -1
- package/dist/models-C9rjXPZ6.js.map +0 -1
- package/dist/package-json-Dblip2_X.js +0 -2
- package/dist/pi-DTj1hsJe.js.map +0 -1
- package/dist/posthog-integration-CpinLWNO.js.map +0 -1
- package/dist/programs-Bq9Ju9xk.js.map +0 -1
- package/dist/programs-CnOSdQo1.js +0 -3
- package/dist/provisioning-D6Cqbc36.js +0 -2
- package/dist/queue-tools-BoIITT7w.js.map +0 -1
- package/dist/run-tool-zMLQroVh.js +0 -2
- package/dist/subagent-BBfETG17.js.map +0 -1
- package/dist/task-CmNe3xeg.js.map +0 -1
- package/dist/terminal-Bkxwzkhn.js.map +0 -1
- package/dist/tui-B56jvkbi.js.map +0 -1
- package/dist/yara-hooks-CxksH-GZ.js +0 -2
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"posthog-integration-CpinLWNO.js","names":["executeAgent","scanInstalledSkill","path","scanInstalledSkill","detectPackageManager","getPackageManagerName","detectPythonPM","fs","path","IGNORE_PATTERNS","EXTRA_IGNORE","SOURCE_PROBE_LIMIT","path","EXTRA_IGNORE","SOURCE_PROBE_LIMIT","path","fs","EXTRA_IGNORE","fs","EXTRA_IGNORE","path","EXTRA_IGNORE","path","EXTRA_IGNORE","SOURCE_PROBE_LIMIT","path","EXTRA_IGNORE","path","EXTRA_IGNORE","SOURCE_PROBE_LIMIT","path","EXTRA_IGNORE","path","EXTRA_IGNORE","SOURCE_PROBE_LIMIT","path","fs","path","fs","path","fs","EXTRA_IGNORE","fs","path","fs","path","path","path","fs","fs","path","path","fs","path","fs","path","fs","path","fs","path","fs","detectPackageManager","fs","path","getPackageManagerName","path","fs","fs","path","fs","path"],"sources":["../src/agent/runner/shared/bootstrap.ts","../src/agent/runner/shared/transcript-tail.ts","../src/agent/runner/harness/anthropic/index.ts","../src/agent/runner/switchboard/flags/orchestrator.ts","../src/agent/runner/switchboard/flags/self-driving.ts","../src/agent/runner/switchboard/flags/schemes.ts","../src/agent/runner/switchboard/flags/index.ts","../src/agent/runner/switchboard/harness.ts","../src/agent/middleware/phase-detector.ts","../src/agent/middleware/pipeline.ts","../src/agent/middleware/config.ts","../src/agent/middleware/benchmarks/turn-counter.ts","../src/agent/middleware/benchmarks/token-tracker.ts","../src/agent/middleware/benchmarks/cache-tracker.ts","../src/agent/middleware/benchmarks/compaction-tracker.ts","../src/agent/middleware/benchmarks/context-size-tracker.ts","../src/shared/token-pricing.ts","../src/agent/middleware/benchmarks/cost-tracker.ts","../src/agent/middleware/benchmarks/duration-tracker.ts","../src/agent/middleware/benchmarks/summary.ts","../src/agent/middleware/benchmarks/json-writer.ts","../src/agent/middleware/benchmarks/index.ts","../src/agent/middleware/benchmark.ts","../src/agent/error-map.ts","../src/agent/agent-prompt.ts","../src/agent/runner/shared/errors.ts","../src/agent/runner/shared/ask.ts","../src/agent/runner/sequence/linear.ts","../src/shared/utils/terminal-bell.ts","../src/agent/runner/sequence/orchestrator/executor.ts","../src/agent/runner/sequence/orchestrator/run-metrics.ts","../src/agent/runner/sequence/orchestrator/seeded-deps.ts","../src/agent/runner/sequence/orchestrator/orchestrator-runner.ts","../src/agent/runner/switchboard/sequence.ts","../src/agent/runner/switchboard/index.ts","../src/agent/runner/switchboard/resolve-run.ts","../src/agent/runner/index.ts","../src/agent/index.ts","../src/programs/frameworks/python/utils.ts","../src/programs/detection/package-manager.ts","../src/programs/frameworks/nextjs/utils.ts","../src/programs/frameworks/nextjs/nextjs-wizard-agent.ts","../src/programs/frameworks/nuxt/nuxt-wizard-agent.ts","../src/programs/frameworks/vue/vue-wizard-agent.ts","../src/programs/frameworks/react-router/utils.ts","../src/programs/frameworks/react-router/react-router-wizard-agent.ts","../src/programs/frameworks/tanstack-router/utils.ts","../src/programs/frameworks/tanstack-router/tanstack-router-wizard-agent.ts","../src/programs/frameworks/tanstack-start/utils.ts","../src/programs/frameworks/tanstack-start/tanstack-start-wizard-agent.ts","../src/programs/frameworks/react-native/utils.ts","../src/programs/frameworks/react-native/react-native-wizard-agent.ts","../src/programs/frameworks/angular/utils.ts","../src/programs/frameworks/angular/angular-wizard-agent.ts","../src/programs/frameworks/astro/utils.ts","../src/programs/frameworks/astro/astro-wizard-agent.ts","../src/programs/framework-config.ts","../src/programs/frameworks/django/utils.ts","../src/programs/frameworks/django/django-wizard-agent.ts","../src/programs/frameworks/flask/utils.ts","../src/programs/frameworks/flask/flask-wizard-agent.ts","../src/programs/frameworks/fastapi/utils.ts","../src/programs/frameworks/fastapi/fastapi-wizard-agent.ts","../src/programs/frameworks/laravel/utils.ts","../src/programs/frameworks/laravel/laravel-wizard-agent.ts","../src/programs/frameworks/svelte/svelte-wizard-agent.ts","../src/programs/frameworks/flutter/flutter-wizard-agent.ts","../src/programs/frameworks/swift/utils.ts","../src/programs/frameworks/swift/swift-wizard-agent.ts","../src/programs/frameworks/kmp/kmp-wizard-agent.ts","../src/programs/frameworks/android/utils.ts","../src/programs/frameworks/android/android-wizard-agent.ts","../src/programs/frameworks/rails/utils.ts","../src/programs/frameworks/rails/rails-wizard-agent.ts","../src/programs/frameworks/elixir/elixir-wizard-agent.ts","../src/programs/frameworks/go/go-wizard-agent.ts","../src/programs/frameworks/java/java-wizard-agent.ts","../src/programs/frameworks/rust/rust-wizard-agent.ts","../src/programs/frameworks/python/python-wizard-agent.ts","../src/programs/frameworks/ruby/utils.ts","../src/programs/frameworks/ruby/ruby-wizard-agent.ts","../src/programs/frameworks/javascript-node/javascript-node-wizard-agent.ts","../src/programs/frameworks/javascript-web/utils.ts","../src/programs/frameworks/javascript-web/javascript-web-wizard-agent.ts","../src/programs/frameworks/registry.ts","../src/programs/detection/framework.ts","../src/programs/detection/context.ts","../src/programs/detection/detected-framework.ts","../src/programs/wizard-flags.ts","../src/programs/detection/agentic.ts","../src/programs/detection/project-scope.ts","../src/programs/detection/features.ts","../src/programs/warehouse-sources/registry.ts","../src/programs/warehouse-sources/detect.ts","../src/programs/shared/package-scanning.ts","../src/programs/detection/ai-sdk-stamp.ts","../src/programs/detection/integration.ts","../src/programs/program-abort.ts","../src/programs/shared/abort-no-framework.ts","../src/programs/posthog-integration/handoff.ts","../src/programs/oauth/program-scopes.ts","../src/programs/posthog-integration/index.ts"],"sourcesContent":["/**\n * Shared preparation for the runner pipeline.\n *\n * Runs before the fork into the linear or orchestrator arm: logging targets,\n * the gateway mint and the scan-triage classifier built on it. Everything the\n * caller must decide first — health gates, settings conflicts, authentication,\n * the AI opt-in gate, post-auth gates, feature flags, run tags, token refresh —\n * arrives already resolved in `ResolvedRunConfig` and `RunInput`.\n */\n\nimport { createTriageLLMProvider } from '../../triage-provider';\nimport { gatewayAuth } from '../../gateway-session';\nimport { currentAccessToken } from '@shared/oauth-session';\nimport { logToFile } from '@utils/debug';\nimport { CallType, IS_DEV } from '@shared/constants';\nimport { VERSION } from '@shared/version';\nimport { mcpUrlFor } from '@shared/host-resolution';\nimport type { WizardRunOptions } from '@utils/types';\nimport type { BootstrapResult, ResolvedRunConfig, RunInput } from './types';\n\n// ── Helpers ──────────────────────────────────────────────────────────\n\n/** The option bag the agent interface and the middleware read. */\nexport function runOptions(input: RunInput): WizardRunOptions {\n return {\n installDir: input.installDir,\n debug: input.flags.debug,\n signup: input.flags.signup,\n ci: input.flags.ci,\n benchmark: input.flags.benchmark,\n projectId: input.host.projectId,\n apiKey: input.host.apiKey,\n yaraReport: input.flags.yaraReport,\n };\n}\n\n// ── Prepare ───────────────────────────────────────────────────────────\n\n/**\n * Shared setup for both arms: logging targets, then the gateway mint and the\n * triage classifier. Throws when the mint is refused, so the run fails before\n * any agent starts — the caller maps that the way it maps any unexpected error.\n */\nexport async function prepareRun(\n config: ResolvedRunConfig,\n input: RunInput,\n): Promise<BootstrapResult> {\n const { skillsBaseUrl } = config;\n\n // Where this run actually points. The three services switch independently,\n // so otherwise \"why did it use prod skills?\" means reading three call sites.\n logToFile(\n `[agent-runner] targets build=${VERSION}${IS_DEV ? '/dev' : ''} ` +\n `skills=${skillsBaseUrl} ` +\n `mcp=${mcpUrlFor(input.flags.localMcp)} ` +\n `posthog=${input.host.baseUrl ?? 'region-resolved'}`,\n );\n\n const { credentials } = input;\n const { wizardFlags, wizardFlagPayloads, wizardMetadata, programId } = config;\n\n // Mint now so a refusal fails the boot before any agent starts. Later\n // readers re-resolve through the cache, which re-mints past the refresh\n // point.\n const currentGatewayAuth = () =>\n // TODO: the agent must not mint inference auth. It receives the\n // PostHog token here and derives a gateway token from it, re-minting near\n // expiry. Programs own credentials (stack plan 4.5): pass a resolved\n // inference-auth provider on RunInput.credentials and move\n // gateway-session.ts out of src/agent with it.\n currentAccessToken(credentials).then((token) =>\n gatewayAuth(credentials.host, token, programId),\n );\n await currentGatewayAuth();\n\n return {\n skillsBaseUrl,\n credentials,\n // Carried so per-task sessions re-resolve against the same program the boot\n // minted for, rather than digging it back out of the metadata bag.\n programId,\n handoffNotebook: config.handoffNotebook,\n wizardFlags,\n wizardFlagPayloads,\n wizardMetadata,\n project: input.project,\n // Resolved once, here: the only place holding both the run-level harness\n // and the gateway auth. Every skill install downstream reads it off boot.\n triageProvider: createTriageLLMProvider(async () => {\n const auth = await currentGatewayAuth();\n return {\n baseURL: auth.gatewayUrl,\n authToken: auth.token,\n teamId: auth.teamId,\n // `call_type` splits scan spend out of the program's agent cost,\n // the same tag the in-run triage provider carries.\n wizardMetadata: { ...wizardMetadata, call_type: CallType.yaraTriage },\n wizardFlags,\n };\n }, config.binding.harness),\n };\n}\n","/** The SDK message observer behind `collectTranscript`: a capped text tail plus one `activity` line per step. */\n\nimport type { ProgressEmitter } from '../../progress';\nimport type { RunMiddleware } from '../harness/types';\n\n/** Only the tail is kept: a caller's report is the run's last output. */\nexport const TRANSCRIPT_TAIL_CHARS = 256 * 1024;\nconst ACTIVITY_LINE_CHARS = 100;\n\nexport interface TranscriptTail extends RunMiddleware {\n /** The kept assistant text, one block per line, then the final result. */\n text(): string;\n}\n\nexport function createTranscriptTail(emit: ProgressEmitter): TranscriptTail {\n const collected: string[] = [];\n let collectedChars = 0;\n let resultText = '';\n\n const collect = (text: string): void => {\n collected.push(text);\n collectedChars += text.length;\n while (collectedChars > TRANSCRIPT_TAIL_CHARS && collected.length > 1) {\n collectedChars -= collected.shift()?.length ?? 0;\n }\n };\n const activity = (line: string): void => emit({ kind: 'activity', line });\n\n return {\n onMessage(message: any): void {\n if (message?.type === 'assistant') {\n const content = message.message?.content;\n if (!Array.isArray(content)) return;\n for (const block of content) {\n if (block?.type === 'text' && typeof block.text === 'string') {\n collect(block.text);\n const line = block.text.trim();\n if (line) {\n activity(\n line.length > ACTIVITY_LINE_CHARS\n ? `${line.slice(0, ACTIVITY_LINE_CHARS)}…`\n : line,\n );\n }\n } else if (block?.type === 'tool_use') {\n activity(formatToolUse(block));\n }\n }\n } else if (\n message?.type === 'result' &&\n typeof message.result === 'string'\n ) {\n resultText = message.result;\n }\n },\n finalize: () => undefined,\n text: () => `${collected.join('\\n')}\\n${resultText}`,\n };\n}\n\n/** Put the tail in front of any other middleware, so both see every message. */\nexport function withTranscript(\n middleware: RunMiddleware | undefined,\n transcript: TranscriptTail | undefined,\n): RunMiddleware | undefined {\n if (!transcript) return middleware;\n if (!middleware) return transcript;\n return {\n onMessage(message) {\n transcript.onMessage(message);\n middleware.onMessage(message);\n },\n finalize(resultMessage, totalDurationMs) {\n transcript.finalize(resultMessage, totalDurationMs);\n return middleware.finalize(resultMessage, totalDurationMs);\n },\n };\n}\n\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","// Supported legacy SDK fallback; both this adapter and Pi implement run and runTask.\n\nimport { Harness } from '@shared/constants';\nimport {\n initializeAgent,\n runAgent as executeAgent,\n} from '../../../agent-interface';\nimport { createAioCapture } from '../../../aio-capture';\nimport { getLogFilePath, logToFile } from '@utils/debug';\nimport { detectNodePackageManagers } from '@utils/package-manager';\nimport { runOptions } from '../../shared/bootstrap';\nimport { currentAccessToken } from '@shared/oauth-session';\nimport { createEmitLog } from '../../shared/progress-collector';\nimport type {\n AgentResult,\n AgentHarness,\n BackendRunInputs,\n TaskRunInputs,\n} from '../types';\n\nexport const anthropicBackend: AgentHarness = {\n name: Harness.anthropic,\n\n async run(inputs: BackendRunInputs): Promise<AgentResult> {\n const {\n config: runConfig,\n input,\n boot,\n emit,\n prompt,\n spinner,\n askBridge,\n middleware,\n model,\n structured,\n } = inputs;\n const config = runConfig.run;\n const { skillsBaseUrl, credentials, wizardFlags, wizardMetadata } = boot;\n const { accessToken, host, projectApiKey } = credentials;\n const log = createEmitLog(emit);\n\n const capture = createAioCapture({\n enabled: input.flags.captureAio,\n projectApiKey,\n apiHost: host.apiHost,\n runTags: wizardMetadata,\n });\n\n if (!structured) log.step('Initializing Claude agent...');\n const agent = await initializeAgent(\n {\n workingDirectory: input.installDir,\n posthogMcpUrl: host.mcpUrl,\n posthogApiKey: accessToken,\n currentPosthogApiKey: () => currentAccessToken(credentials),\n host,\n additionalMcpServers: config.additionalMcpServers,\n detectPackageManager:\n config.detectPackageManager ?? detectNodePackageManagers,\n skillsBaseUrl,\n wizardFlags,\n wizardMetadata,\n programId: boot.programId,\n handoffNotebook: boot.handoffNotebook,\n integrationLabel: config.integrationLabel,\n askBridge,\n getPendingQuestion: askBridge?.getPendingQuestion,\n askMaxQuestions: config.maxQuestions,\n readOnly: config.readOnly,\n allowedTools: runConfig.allowedTools,\n disallowedTools: runConfig.disallowedTools,\n modelOverride: model,\n outputFormat: structured && {\n type: 'json_schema',\n schema: structured.schema,\n },\n capture,\n emit,\n },\n runOptions(input),\n );\n if (!structured) {\n log.step(`Verbose logs: ${getLogFilePath()}`);\n log.success(\"Agent initialized. Let's get cooking!\");\n }\n logToFile('[agent-runner] agent initialized');\n\n return executeAgent(\n { ...agent, signal: inputs.signal },\n prompt,\n runOptions(input),\n spinner,\n {\n timeoutMs: structured?.timeoutMs,\n estimatedDurationMinutes: config.estimatedDurationMinutes,\n spinnerMessage: config.spinnerMessage,\n successMessage: config.successMessage,\n errorMessage:\n config.errorMessage ?? `${config.integrationLabel} failed`,\n abortCases: config.abortCases,\n emitStepEvents: config.trackStepProgress ?? false,\n resolveStepKey: config.resolveStepKey,\n requestRemark: structured ? false : config.requestRemark,\n triageProvider: boot.triageProvider,\n },\n middleware,\n );\n },\n\n async runTask(inputs: TaskRunInputs): Promise<AgentResult> {\n const {\n config,\n input,\n boot,\n emit,\n prompt,\n spinner,\n model,\n allowedTools,\n disallowedTools,\n askBridge,\n orchestrator,\n spinnerMessage,\n successMessage,\n errorMessage,\n requestRemark,\n analyticsProperties,\n } = inputs;\n const options = runOptions(input);\n\n const capture = createAioCapture({\n enabled: input.flags.captureAio,\n projectApiKey: boot.credentials.projectApiKey,\n apiHost: boot.credentials.host.apiHost,\n runTags: boot.wizardMetadata,\n });\n\n // Per-task agent config — the wizard-tools MCP server is bound to the\n // orchestrator context (queue store + current task id) so complete_task /\n // enqueue_task attribute to the right agent when tasks run in parallel.\n const agent = await initializeAgent(\n {\n workingDirectory: input.installDir,\n posthogMcpUrl: boot.credentials.host.mcpUrl,\n posthogApiKey: boot.credentials.accessToken,\n currentPosthogApiKey: () => currentAccessToken(boot.credentials),\n host: boot.credentials.host,\n detectPackageManager: detectNodePackageManagers,\n skillsBaseUrl: boot.skillsBaseUrl,\n programId: boot.programId,\n handoffNotebook: boot.handoffNotebook,\n wizardFlags: boot.wizardFlags,\n wizardMetadata: boot.wizardMetadata,\n integrationLabel: config.programId,\n // Only a task allowed to ask carries a bridge, so the Write/Edit pause\n // that rides on a pending question stays inside that task's agent.\n askBridge,\n getPendingQuestion: askBridge?.getPendingQuestion,\n orchestrator,\n capture,\n emit,\n },\n options,\n );\n\n return executeAgent(\n { ...agent, model, allowedTools, disallowedTools, signal: inputs.signal },\n prompt,\n options,\n spinner,\n {\n spinnerMessage,\n successMessage,\n errorMessage,\n requestRemark,\n analyticsProperties,\n },\n );\n },\n};\n","/** Orchestrator gate: wizard-orchestrator on/off. On routes the declared programs to the orchestrator on pi; every model/effort comes from prompt frontmatter. */\nimport {\n Harness,\n Sequence,\n WIZARD_ORCHESTRATOR_FLAG_KEY,\n WIZARD_ORCHESTRATOR_OVERRIDE_FLAG_KEY,\n WIZARD_ORCHESTRATOR_SEEDED_TASKS_FLAG_KEY,\n} from '@shared/constants';\nimport type { HarnessExperiment, SequenceExperiment } from './schemes';\n\nexport const ORCHESTRATOR_SEQUENCE_ROUTE: SequenceExperiment = {\n programs: ['posthog-integration'],\n flag: WIZARD_ORCHESTRATOR_FLAG_KEY,\n sequence: Sequence.orchestrator,\n};\n\n/** Same flag, harness axis: the orchestrator drives tasks through pi. */\nexport const ORCHESTRATOR_HARNESS_ROUTE: HarnessExperiment = {\n program: 'posthog-integration',\n flags: { useFlag: WIZARD_ORCHESTRATOR_FLAG_KEY, harness: Harness.pi },\n};\n\n/** Same programs, per-stage overrides: the variant payload (`{stage: {model?, effort?}}`) outranks prompt frontmatter for the stages it names. */\nexport const ORCHESTRATOR_STAGE_OVERRIDES = {\n programs: ORCHESTRATOR_SEQUENCE_ROUTE.programs,\n flag: WIZARD_ORCHESTRATOR_OVERRIDE_FLAG_KEY,\n} as const;\n\n/**\n * Kill switch for the runner-seeded task mechanism (the optional warehouse\n * step). Off or unset, the orchestrator queues nothing itself and the run is\n * identical to a project with no detected sources.\n */\nexport function areSeededTasksEnabled(\n flags: Record<string, string> = {},\n): boolean {\n return flags[WIZARD_ORCHESTRATOR_SEEDED_TASKS_FLAG_KEY] === 'true';\n}\n\n/** Raw flag read — for telemetry/log lines only, never for routing. */\nexport function isOrchestratorEnabled(\n flags: Record<string, string> = {},\n): boolean {\n return flags[ORCHESTRATOR_SEQUENCE_ROUTE.flag] === 'true';\n}\n","/**\n * Self-driving pi experiment.\n *\n * Flag: wizard-self-driving-use-pi-harness (bool; payload `{model, effort?,\n * harness?, sequence?}`)\n * Routes: ONLY `self-driving` — any axis the payload pins. A missing or\n * invalid payload keeps the non-flagged binding default.\n */\nimport { WIZARD_SELF_DRIVING_USE_PI_HARNESS_FLAG_KEY } from '@shared/constants';\nimport type { HarnessExperiment } from './schemes';\n\nexport const SELF_DRIVING_EXPERIMENT: HarnessExperiment = {\n program: 'self-driving',\n flags: {\n useFlag: WIZARD_SELF_DRIVING_USE_PI_HARNESS_FLAG_KEY,\n },\n};\n","/**\n * Flag config schemes — the shapes a PostHog flag set can take to route a\n * program to the pi harness, plus the shared vocabulary and the per-config\n * resolution. Experiment modules in this folder declare *which* flags they\n * use; this module owns *how* a config resolves to a route.\n */\nimport { z } from 'zod';\nimport {\n GPT5_6_LUNA_MODEL,\n GPT5_6_SOL_MODEL,\n GPT5_6_TERRA_MODEL,\n Harness,\n Sequence,\n SONNET_5_MODEL,\n} from '@shared/constants';\nimport { logToFile } from '@utils/debug';\nimport type { EffortLevel } from '../models';\n\n// ── Shared vocabulary ─────────────────────────────────────────────────────\n\n/** Model variant key → gateway id. A key the gateway no longer mints is dropped\n * rather than re-aimed: the payload then fails validation and the binding\n * default stands, which is visible in the log instead of silently rerouting. */\nconst MODEL_FLAG_VARIANTS: Record<string, string> = {\n 'gpt-5-6-luna': GPT5_6_LUNA_MODEL,\n 'gpt-5-6-terra': GPT5_6_TERRA_MODEL,\n 'gpt-5-6-sol': GPT5_6_SOL_MODEL,\n 'sonnet-5': SONNET_5_MODEL,\n};\n\n/** Valid effort variants; anything else leaves the model's table default. */\nconst EFFORT_FLAG_VARIANTS = [\n 'minimal',\n 'low',\n 'medium',\n 'high',\n 'xhigh',\n] as const satisfies readonly EffortLevel[];\n\n/** A resolved flag route. Absent fields keep the axis's default (pi harness, sequence resolved by its own chain, table effort). */\nexport interface FlagRoute {\n model?: string;\n thinkingLevel?: EffortLevel;\n harness?: Harness;\n sequence?: Sequence;\n}\n\n// ── Config schemes ────────────────────────────────────────────────────────\n\n/** Harness-only scheme: the useFlag routes the harness; model/effort stay at the binding default so prompt frontmatter governs. */\nexport interface HarnessConfigFlag {\n useFlag: string;\n harness: Harness;\n}\n\n/** Boolean-flag scheme: the useFlag's zod-validated `{model, effort?, harness?, sequence?}` payload picks the route; anything invalid keeps the non-flagged binding default. */\nexport interface PayloadConfigFlag {\n useFlag: string;\n harness?: never;\n}\n\nexport type ConfigFlag = HarnessConfigFlag | PayloadConfigFlag;\n\n/**\n * A harness-axis experiment: ONE program and the flags that route it. The\n * scope is part of the declaration — the flags are inert for every other\n * program.\n */\nexport interface HarnessExperiment {\n program: string;\n flags: ConfigFlag;\n}\n\n/** A sequence-axis experiment: one boolean flag, inert outside its listed programs. */\nexport interface SequenceExperiment {\n programs: readonly string[];\n flag: string;\n /** Sequence the flag routes covered programs to. */\n sequence: Sequence;\n}\n\n/** Variant key validated against the shared vocabulary, transformed to its gateway id. */\nconst modelVariantSchema = z\n .string()\n .refine((key) => key in MODEL_FLAG_VARIANTS)\n .transform((key) => MODEL_FLAG_VARIANTS[key]);\n\n/** `{model, effort?, harness?, sequence?}` payload shape; extra keys tolerated for forward compat. */\nconst payloadConfigFlagSchema = z.object({\n model: modelVariantSchema,\n effort: z.enum(EFFORT_FLAG_VARIANTS).optional(),\n harness: z.nativeEnum(Harness).optional(),\n sequence: z.nativeEnum(Sequence).optional(),\n});\n\n/**\n * PostHog serves a variant's payload as a JSON string, e.g. the\n * wizard-orchestrator-override `terra-review` variant arrives as\n * `'{\"review\":{\"model\":\"gpt-5-6-terra\",\"effort\":\"medium\"}}'`; local CI\n * overrides inject the same payloads as already-parsed objects. Coerce both\n * to the value; anything unparseable is undefined.\n */\nfunction coerceJson(raw: unknown): unknown {\n if (typeof raw !== 'string') return raw;\n try {\n return JSON.parse(raw) as unknown;\n } catch {\n return undefined;\n }\n}\n\n// ── Resolution ────────────────────────────────────────────────────────────\n\n/** Per-stage overrides keyed by stage; a whole-payload parse failure fails closed to frontmatter everywhere. */\nconst stageOverridesSchema = z.record(\n z.object({\n model: modelVariantSchema.optional(),\n effort: z.enum(EFFORT_FLAG_VARIANTS).optional(),\n }),\n);\n\nexport type StageOverride = { model?: string; effort?: EffortLevel };\n\n/** Validate a stage-override payload (object or JSON string); undefined on any unexpected shape. */\nexport function stageOverridesFromPayload(\n raw: unknown,\n): Record<string, StageOverride> | undefined {\n const parsed = stageOverridesSchema.safeParse(coerceJson(raw));\n return parsed.success ? parsed.data : undefined;\n}\n\n/** Validate a payload (object or JSON string) into a route; undefined on any unexpected shape. */\nfunction parseFlagPayload(raw: unknown): FlagRoute | undefined {\n const parsed = payloadConfigFlagSchema.safeParse(coerceJson(raw));\n if (!parsed.success) return undefined;\n return {\n model: parsed.data.model,\n thinkingLevel: parsed.data.effort,\n harness: parsed.data.harness,\n sequence: parsed.data.sequence,\n };\n}\n\n/**\n * Resolve one config against the flag snapshot, or undefined when it doesn't\n * validly route: use flag off, or a payload that fails validation — the\n * caller then keeps the non-flagged binding default.\n */\nexport function routeFromConfigFlag(\n cfg: ConfigFlag,\n flags: Record<string, string>,\n flagPayloads?: Record<string, unknown>,\n): FlagRoute | undefined {\n if (flags[cfg.useFlag] !== 'true') return undefined;\n if (cfg.harness) return { harness: cfg.harness };\n const route = parseFlagPayload(flagPayloads?.[cfg.useFlag]);\n if (!route) {\n logToFile(\n `[switchboard] ${cfg.useFlag} on but payload missing/invalid — keeping the non-flagged default`,\n );\n }\n return route;\n}\n","/**\n * Switchboard flags, one module per experiment. Every experiment declares its\n * own scope — which program(s) its flags route — so the flag→program mapping\n * is readable per file, never implied. `schemes.ts` owns the shared config\n * shapes and resolution.\n */\nimport { RUN_SURFACE } from '@env';\nimport { logToFile } from '@utils/debug';\nimport type { Sequence } from '@shared/constants';\nimport {\n ORCHESTRATOR_HARNESS_ROUTE,\n ORCHESTRATOR_SEQUENCE_ROUTE,\n ORCHESTRATOR_STAGE_OVERRIDES,\n} from './orchestrator';\nimport { SELF_DRIVING_EXPERIMENT } from './self-driving';\nimport {\n routeFromConfigFlag,\n stageOverridesFromPayload,\n type FlagRoute,\n type HarnessExperiment,\n type SequenceExperiment,\n type StageOverride,\n} from './schemes';\n\n/** Every experiment on each axis. An experiment routes ONLY by being listed here, and only for the programs it declares. */\nexport const HARNESS_EXPERIMENTS: readonly HarnessExperiment[] = [\n ORCHESTRATOR_HARNESS_ROUTE,\n SELF_DRIVING_EXPERIMENT,\n];\nexport const SEQUENCE_EXPERIMENTS: readonly SequenceExperiment[] = [\n ORCHESTRATOR_SEQUENCE_ROUTE,\n];\n\n/** The flag-driven route for a program, or undefined when no experiment covers it or its flags don't validly route. */\nexport function resolveFlagRoute(\n program: string,\n flags: Record<string, string>,\n flagPayloads?: Record<string, unknown>,\n): FlagRoute | undefined {\n const experiment = HARNESS_EXPERIMENTS.find((e) => e.program === program);\n return (\n experiment && routeFromConfigFlag(experiment.flags, flags, flagPayloads)\n );\n}\n\n/** The flag-driven sequence for a program, or undefined when no sequence experiment covers it with its flag on. Surface/build scoping is the flag's own job (see `flagPersonProperties`). */\nexport function resolveFlagSequence(\n program: string,\n flags: Record<string, string>,\n): Sequence | undefined {\n return SEQUENCE_EXPERIMENTS.find(\n (e) => e.programs.includes(program) && flags[e.flag] === 'true',\n )?.sequence;\n}\n\n/** The per-stage overrides for a program's run, or undefined (prompt frontmatter stays). Applied once, where the agent prompts are loaded. */\nexport function resolveStageOverrides(\n program: string,\n flags: Record<string, string>,\n flagPayloads?: Record<string, unknown>,\n): Record<string, StageOverride> | undefined {\n if (RUN_SURFACE === 'cloud') return undefined;\n const exp = ORCHESTRATOR_STAGE_OVERRIDES;\n if (!exp.programs.includes(program)) return undefined;\n const variant = flags[exp.flag];\n if (!variant || variant === 'false') return undefined;\n const overrides = stageOverridesFromPayload(flagPayloads?.[exp.flag]);\n if (!overrides) {\n logToFile(\n `[switchboard] ${exp.flag}=${variant} but payload missing/invalid — keeping frontmatter`,\n );\n }\n return overrides;\n}\n\nexport { isOrchestratorEnabled, areSeededTasksEnabled } from './orchestrator';\nexport type {\n ConfigFlag,\n FlagRoute,\n HarnessExperiment,\n SequenceExperiment,\n StageOverride,\n} from './schemes';\n","/**\n * Harness axis: registry, middleware, resolver. Mirrors `sequence.ts`.\n */\n\nimport { IS_PRODUCTION_BUILD } from '@env';\nimport { Harness } from '@shared/constants';\nimport { logToFile } from '@utils/debug';\nimport { anthropicBackend } from '../harness/anthropic';\nimport { piBackend } from '../harness/pi';\nimport type { AgentHarness } from '../harness/types';\nimport { resolveFlagRoute } from './flags';\nimport {\n runChain,\n type HarnessPick,\n type Middleware,\n type SwitchboardCtx,\n} from '.';\n\nexport const HARNESS_OPTIONS: Partial<Record<Harness, AgentHarness>> = {\n [Harness.anthropic]: anthropicBackend,\n [Harness.pi]: piBackend,\n};\n\nexport function getHarness(name: Harness): AgentHarness {\n const harness = HARNESS_OPTIONS[name];\n if (!harness) {\n throw new Error(`No harness registered for '${name}'.`);\n }\n return harness;\n}\n\n/**\n * PostHog-flag routing to pi (see `./flags`). No valid route — flag off, no\n * config, or an invalid payload — keeps the non-flagged binding default.\n */\nconst flagRunnerOverride: Middleware<HarnessPick> = (ctx, next) => {\n const pick = next();\n const route = resolveFlagRoute(ctx.program, ctx.flags, ctx.flagPayloads);\n if (!route) return pick;\n if (ctx.trace) {\n ctx.trace.harness = 'flag';\n // Harness-only routes keep the binding's model — trace it truthfully so\n // analytics never attributes the fallback model to the flag.\n if (route.model) ctx.trace.model = 'flag';\n }\n return {\n harness: route.harness ?? Harness.pi,\n model: route.model ?? pick.model,\n thinkingLevel: route.thinkingLevel ?? pick.thinkingLevel,\n };\n};\n\n/** `--harness` override. Dev/test only — the option is gated out of published builds. */\nconst cliHarnessOverride: Middleware<HarnessPick> = (ctx, next) => {\n const pick = next();\n if (!ctx.cliHarness) return pick;\n if (ctx.trace) ctx.trace.harness = 'cli';\n return { ...pick, harness: ctx.cliHarness };\n};\n\n/** `--model` override. Dev/test only — the option is gated out of published builds. */\nconst cliModelOverride: Middleware<HarnessPick> = (ctx, next) => {\n const pick = next();\n if (!ctx.cliModel) return pick;\n if (ctx.trace) ctx.trace.model = 'cli';\n return { ...pick, model: ctx.cliModel };\n};\n\n// Order = precedence: CLI > flag > binding default. The prod spread collapses\n// to [], dropping the CLI overrides from the chain.\nconst HARNESS_MIDDLEWARE: Middleware<HarnessPick>[] = [\n ...(IS_PRODUCTION_BUILD ? [] : [cliHarnessOverride, cliModelOverride]),\n flagRunnerOverride,\n];\n\n/**\n * Resolve the harness for a role. Linear callers omit `role`; orchestrator\n * callers pass `'seed'` or `task.type`. `contextMillOverride[role]` overlays.\n */\nexport function resolveHarness(\n ctx: SwitchboardCtx,\n role = 'default',\n): HarnessPick {\n const pick = runChain(HARNESS_MIDDLEWARE, ctx, () => {\n if (ctx.trace)\n Object.assign(ctx.trace, { harness: 'binding', model: 'binding' });\n const { binding } = ctx;\n return {\n harness: binding.harness,\n model: binding.model,\n thinkingLevel: binding.thinkingLevel,\n ...binding.contextMillOverride?.[role],\n };\n });\n logToFile(\n `[switchboard] resolved: program=${ctx.program} harness=${pick.harness}` +\n `${ctx.trace?.harness ? ` (${ctx.trace.harness})` : ''} model=${\n pick.model\n }` +\n `${ctx.trace?.model ? ` (${ctx.trace.model})` : ''}`,\n );\n return pick;\n}\n","/** Phase transitions from [STATUS] in assistant text. Keep in sync with program \"Status to report\" bullets. */\n\nconst PHASES_ORDER = [\n '1.0-begin',\n '1.1-edit',\n '1.2-revise',\n '1.3-conclude',\n] as const;\n\nconst STATUS_PHRASES_BY_PHASE: Record<(typeof PHASES_ORDER)[number], string[]> =\n {\n '1.0-begin': [\n 'Checking project structure',\n 'Verifying PostHog dependencies',\n 'Generating events based on project',\n ],\n '1.1-edit': ['Inserting PostHog capture code'],\n '1.2-revise': [\n 'Finding and correcting errors',\n 'Report details of any errors you fix',\n 'Linting, building and prettying',\n ],\n '1.3-conclude': ['Configured dashboard', 'Created setup report'],\n };\n\nexport class PhaseDetector {\n private currentPhase: 'setup' | (typeof PHASES_ORDER)[number] = 'setup';\n\n detect(message: any): string | null {\n if (message.type !== 'assistant') return null;\n\n const nextPhase = this.getNextPhase();\n if (nextPhase === null) return null;\n\n const content = message.message?.content;\n if (!Array.isArray(content)) return null;\n\n for (const block of content) {\n if (block.type !== 'text' || typeof block.text !== 'string') continue;\n if (!block.text.includes('[STATUS]')) continue;\n\n const phrases = STATUS_PHRASES_BY_PHASE[nextPhase];\n for (const phrase of phrases) {\n if (block.text.includes(phrase)) {\n this.currentPhase = nextPhase;\n return nextPhase;\n }\n }\n }\n\n return null;\n }\n\n private getNextPhase(): (typeof PHASES_ORDER)[number] | null {\n if (this.currentPhase === 'setup') return '1.0-begin';\n const i = PHASES_ORDER.indexOf(this.currentPhase);\n if (i < 0 || i >= PHASES_ORDER.length - 1) return null;\n return PHASES_ORDER[i + 1];\n }\n\n reset(): void {\n this.currentPhase = 'setup';\n }\n}\n","/**\n * Middleware pipeline orchestrator.\n *\n * Implements the same { onMessage, finalize } interface that runAgent() expects,\n * while internally dispatching to an ordered list of middleware plugins.\n */\n\nimport { PhaseDetector } from './phase-detector';\nimport type {\n Middleware,\n MiddlewareContext,\n MiddlewareStore,\n SDKMessage,\n} from './types';\n\nexport class MiddlewarePipeline {\n private middlewares: Middleware[];\n private store = new Map<string, unknown>();\n private phaseDetector: PhaseDetector;\n private autoDetectPhases: boolean;\n private _currentPhase = 'setup';\n private _currentPhaseFreshContext = true;\n\n constructor(\n middlewares: Middleware[],\n opts?: { phaseDetector?: PhaseDetector; autoDetectPhases?: boolean },\n ) {\n this.middlewares = middlewares;\n this.phaseDetector = opts?.phaseDetector ?? new PhaseDetector();\n this.autoDetectPhases = opts?.autoDetectPhases ?? true;\n\n const ctx = this.createContext();\n for (const mw of this.middlewares) {\n mw.onInit?.(ctx);\n }\n }\n\n /** Feed an SDK message through all middleware (satisfies tracker.onMessage) */\n onMessage(message: SDKMessage): void {\n // Phase detection first — updates context before middleware sees it\n if (this.autoDetectPhases) {\n const newPhase = this.phaseDetector.detect(message);\n if (newPhase && newPhase !== this._currentPhase) {\n this.transitionPhase(newPhase, false);\n }\n }\n\n const ctx = this.createContext();\n const storeHandle = this.createStore();\n for (const mw of this.middlewares) {\n mw.onMessage?.(message, ctx, storeHandle);\n }\n }\n\n /** Finalize the run (satisfies tracker.finalize) */\n finalize(resultMessage: any, totalDurationMs: number): any {\n const ctx = this.createContext();\n const storeHandle = this.createStore();\n let result: any;\n for (const mw of this.middlewares) {\n const r = mw.onFinalize?.(\n resultMessage,\n totalDurationMs,\n ctx,\n storeHandle,\n );\n if (r !== undefined) result = r;\n }\n return result;\n }\n\n /** Explicit phase start (for phased runner support) */\n startPhase(name: string, freshContext: boolean): void {\n this.transitionPhase(name, freshContext);\n }\n\n private transitionPhase(newPhase: string, freshContext: boolean): void {\n const oldPhase = this._currentPhase;\n this._currentPhase = newPhase;\n this._currentPhaseFreshContext = freshContext;\n const ctx = this.createContext();\n const storeHandle = this.createStore();\n for (const mw of this.middlewares) {\n mw.onPhaseTransition?.(oldPhase, newPhase, ctx, storeHandle);\n }\n }\n\n private createContext(): MiddlewareContext {\n return {\n currentPhase: this._currentPhase,\n currentPhaseFreshContext: this._currentPhaseFreshContext,\n get: <T>(key: string) => this.store.get(key) as T | undefined,\n };\n }\n\n private createStore(): MiddlewareStore {\n return {\n set: (key: string, value: unknown) => this.store.set(key, value),\n };\n }\n}\n","/**\n * Benchmark configuration loader.\n *\n * Loads .benchmark-config.json from the working directory with sensible defaults.\n * All fields are optional — missing fields fall back to defaults.\n */\n\nimport fs from 'fs';\nimport path from 'path';\nimport { logToFile } from '@utils/debug';\nimport { AgentSignals } from '../agent-interface';\nimport { runtimeEnv } from '@env';\nimport { WIZARD_BENCHMARK_FILE, WIZARD_LOG_FILE } from '@utils/paths';\n\nexport interface BenchmarkConfig {\n /** Enable/disable individual metric plugins */\n plugins: Record<string, boolean>;\n output: {\n /** Path for the benchmark JSON output file */\n benchmarkPath: string;\n /** Whether to write the benchmark JSON file */\n benchmarkEnabled: boolean;\n /** Path for the main wizard debug log file */\n logPath: string;\n /** Whether to write the main wizard debug log */\n logEnabled: boolean;\n /** Suppress benchmark console output (disables the summary plugin) */\n suppressWizardLogs: boolean;\n };\n}\n\nconst DEFAULT_CONFIG: BenchmarkConfig = {\n plugins: {\n tokens: true,\n cache: true,\n turns: true,\n compactions: true,\n contextSize: true,\n cost: true,\n duration: true,\n summary: true,\n jsonWriter: true,\n },\n output: {\n benchmarkPath: WIZARD_BENCHMARK_FILE,\n benchmarkEnabled: true,\n logPath: WIZARD_LOG_FILE,\n logEnabled: true,\n suppressWizardLogs: false,\n },\n};\n\nexport function loadBenchmarkConfig(installDir: string): BenchmarkConfig {\n const configPath =\n runtimeEnv('POSTHOG_WIZARD_BENCHMARK_CONFIG') ??\n path.join(installDir, '.benchmark-config.json');\n try {\n const raw = fs.readFileSync(configPath, 'utf-8');\n const parsed = JSON.parse(raw);\n const config: BenchmarkConfig = {\n plugins: { ...DEFAULT_CONFIG.plugins, ...parsed.plugins },\n output: { ...DEFAULT_CONFIG.output, ...parsed.output },\n };\n\n // Env var overrides for parallel runs\n const benchFile = runtimeEnv('POSTHOG_WIZARD_BENCHMARK_FILE');\n if (benchFile) {\n config.output.benchmarkPath = benchFile;\n }\n const logDir = runtimeEnv('POSTHOG_WIZARD_LOG_DIR');\n if (logDir) {\n config.output.logPath = path.join(logDir, 'posthog-wizard.log');\n }\n\n // If benchmark output is disabled, disable the jsonWriter plugin\n if (!config.output.benchmarkEnabled) {\n config.plugins.jsonWriter = false;\n }\n\n logToFile(`${AgentSignals.BENCHMARK} Loaded config from ${configPath}`);\n return config;\n } catch {\n // No config file or invalid JSON — use defaults\n const config = structuredClone(DEFAULT_CONFIG);\n\n // Env var overrides\n const benchFile2 = runtimeEnv('POSTHOG_WIZARD_BENCHMARK_FILE');\n if (benchFile2) {\n config.output.benchmarkPath = benchFile2;\n }\n const logDir2 = runtimeEnv('POSTHOG_WIZARD_LOG_DIR');\n if (logDir2) {\n config.output.logPath = path.join(logDir2, 'posthog-wizard.log');\n }\n\n return config;\n }\n}\n\nexport function getDefaultConfig(): BenchmarkConfig {\n return structuredClone(DEFAULT_CONFIG);\n}\n","/**\n * Turn counting plugin with message deduplication.\n *\n * The SDK emits multiple assistant events per turn (one per content block)\n * with the same message ID. This plugin deduplicates and publishes turn\n * counts + a duplicate flag for downstream plugins.\n */\n\nimport type { Middleware, MiddlewareContext, MiddlewareStore } from '../types';\n\nexport interface TurnData {\n /** Whether the current message is a duplicate of the last processed turn */\n isDuplicate: boolean;\n /** Turns in the current phase */\n phaseTurns: number;\n /** Total turns across all phases */\n totalTurns: number;\n /** Per-phase turn snapshots: [{ phase, turns }] */\n phaseSnapshots: Array<{ phase: string; turns: number }>;\n}\n\nexport class TurnCounterPlugin implements Middleware {\n readonly name = 'turns';\n\n private lastMessageId: string | null = null;\n private phaseTurns = 0;\n private totalTurns = 0;\n private isDuplicate = false;\n private phaseSnapshots: Array<{ phase: string; turns: number }> = [];\n private currentPhase = 'setup';\n\n onMessage(\n message: any,\n _ctx: MiddlewareContext,\n store: MiddlewareStore,\n ): void {\n if (message.type !== 'assistant') {\n this.isDuplicate = false;\n store.set('turns', this.getData());\n return;\n }\n\n const msgId: string | undefined = message.message?.id;\n this.isDuplicate = msgId != null && msgId === this.lastMessageId;\n if (msgId) this.lastMessageId = msgId;\n\n if (!this.isDuplicate) {\n this.phaseTurns++;\n this.totalTurns++;\n }\n\n store.set('turns', this.getData());\n }\n\n onPhaseTransition(\n fromPhase: string,\n _toPhase: string,\n _ctx: MiddlewareContext,\n store: MiddlewareStore,\n ): void {\n this.phaseSnapshots.push({ phase: fromPhase, turns: this.phaseTurns });\n this.currentPhase = _toPhase;\n this.phaseTurns = 0;\n this.lastMessageId = null;\n store.set('turns', this.getData());\n }\n\n onFinalize(\n _resultMessage: any,\n _totalDurationMs: number,\n _ctx: MiddlewareContext,\n store: MiddlewareStore,\n ): void {\n this.phaseSnapshots.push({\n phase: this.currentPhase,\n turns: this.phaseTurns,\n });\n store.set('turns', this.getData());\n }\n\n private getData(): TurnData {\n return {\n isDuplicate: this.isDuplicate,\n phaseTurns: this.phaseTurns,\n totalTurns: this.totalTurns,\n phaseSnapshots: [...this.phaseSnapshots],\n };\n }\n}\n","/**\n * Token tracking plugin for input/output tokens.\n *\n * Accumulates per-turn token usage (input_tokens + cache_read_input_tokens\n * + cache_creation_input_tokens = total input; output_tokens = output).\n * Respects the dedup flag from TurnCounterPlugin. Cache breakdown (r/5m/1h)\n * is tracked by CacheTrackerPlugin for reporting and pricing.\n */\n\nimport type { Middleware, MiddlewareContext, MiddlewareStore } from '../types';\nimport type { TurnData } from './turn-counter';\n\nexport interface TokenData {\n phaseInput: number;\n phaseOutput: number;\n totalInput: number;\n totalOutput: number;\n /** The raw usage object from the last non-duplicate assistant message */\n lastUsage: any;\n /** Per-phase token snapshots */\n phaseSnapshots: Array<{\n phase: string;\n inputTokens: number;\n outputTokens: number;\n /** Number of turns in this phase that had usage (SDK may not report all) */\n messagesWithUsage: number;\n }>;\n}\n\nexport class TokenTrackerPlugin implements Middleware {\n readonly name = 'tokens';\n\n private phaseInput = 0;\n private phaseOutput = 0;\n private totalInput = 0;\n private totalOutput = 0;\n private lastUsage: any = null;\n private phaseSnapshots: Array<{\n phase: string;\n inputTokens: number;\n outputTokens: number;\n messagesWithUsage: number;\n }> = [];\n private currentPhase = 'setup';\n private phaseMessagesWithUsage = 0;\n\n onMessage(\n message: any,\n ctx: MiddlewareContext,\n store: MiddlewareStore,\n ): void {\n if (message.type !== 'assistant') return;\n\n const turns = ctx.get<TurnData>('turns');\n if (turns?.isDuplicate) return;\n\n const usage = message.message?.usage;\n if (usage) {\n const input =\n Number(usage.input_tokens ?? 0) +\n Number(usage.cache_read_input_tokens ?? 0) +\n Number(usage.cache_creation_input_tokens ?? 0);\n const output = Number(usage.output_tokens ?? 0);\n this.phaseInput += input;\n this.phaseOutput += output;\n this.totalInput += input;\n this.totalOutput += output;\n this.lastUsage = usage;\n this.phaseMessagesWithUsage += 1;\n }\n\n store.set('tokens', this.getData());\n }\n\n onPhaseTransition(\n fromPhase: string,\n toPhase: string,\n _ctx: MiddlewareContext,\n store: MiddlewareStore,\n ): void {\n this.phaseSnapshots.push({\n phase: fromPhase,\n inputTokens: this.phaseInput,\n outputTokens: this.phaseOutput,\n messagesWithUsage: this.phaseMessagesWithUsage,\n });\n this.currentPhase = toPhase;\n this.phaseInput = 0;\n this.phaseOutput = 0;\n this.phaseMessagesWithUsage = 0;\n store.set('tokens', this.getData());\n }\n\n onFinalize(\n _resultMessage: any,\n _totalDurationMs: number,\n _ctx: MiddlewareContext,\n store: MiddlewareStore,\n ): void {\n this.phaseSnapshots.push({\n phase: this.currentPhase,\n inputTokens: this.phaseInput,\n outputTokens: this.phaseOutput,\n messagesWithUsage: this.phaseMessagesWithUsage,\n });\n store.set('tokens', this.getData());\n }\n\n private getData(): TokenData {\n return {\n phaseInput: this.phaseInput,\n phaseOutput: this.phaseOutput,\n totalInput: this.totalInput,\n totalOutput: this.totalOutput,\n lastUsage: this.lastUsage,\n phaseSnapshots: [...this.phaseSnapshots],\n };\n }\n}\n","/**\n * Cache token tracking plugin (cache_read and cache_creation).\n *\n * Respects the dedup flag from TurnCounterPlugin.\n */\n\nimport type { Middleware, MiddlewareContext, MiddlewareStore } from '../types';\nimport type { TurnData } from './turn-counter';\n\n/** Matches SDK usage.cache_creation (ephemeral 5m vs 1h for pricing). */\nexport interface CacheCreationBreakdown {\n ephemeral_5m_input_tokens: number;\n ephemeral_1h_input_tokens: number;\n}\n\nexport interface CacheData {\n phaseRead: number;\n phaseCreation: number;\n totalRead: number;\n totalCreation: number;\n totalCreation5m: number;\n totalCreation1h: number;\n phaseSnapshots: Array<{\n phase: string;\n cacheReadTokens: number;\n cacheCreationTokens: number;\n /** When present, use for pricing (5m vs 1h rates). */\n cacheCreation5m: number;\n cacheCreation1h: number;\n }>;\n}\n\nexport class CacheTrackerPlugin implements Middleware {\n readonly name = 'cache';\n\n private phaseRead = 0;\n private phaseCreation = 0;\n private phaseCreation5m = 0;\n private phaseCreation1h = 0;\n private totalRead = 0;\n private totalCreation = 0;\n private totalCreation5m = 0;\n private totalCreation1h = 0;\n private phaseSnapshots: Array<{\n phase: string;\n cacheReadTokens: number;\n cacheCreationTokens: number;\n cacheCreation5m: number;\n cacheCreation1h: number;\n }> = [];\n private currentPhase = 'setup';\n\n onMessage(\n message: any,\n ctx: MiddlewareContext,\n store: MiddlewareStore,\n ): void {\n if (message.type !== 'assistant') return;\n\n const turns = ctx.get<TurnData>('turns');\n if (turns?.isDuplicate) return;\n\n const usage = message.message?.usage;\n if (usage) {\n const read = Number(usage.cache_read_input_tokens ?? 0);\n const creation = Number(usage.cache_creation_input_tokens ?? 0);\n const cc = usage.cache_creation;\n const creation5m = Number(cc?.ephemeral_5m_input_tokens ?? 0);\n const creation1h = Number(cc?.ephemeral_1h_input_tokens ?? 0);\n this.phaseRead += read;\n this.phaseCreation += creation;\n this.phaseCreation5m += creation5m;\n this.phaseCreation1h += creation1h;\n this.totalRead += read;\n this.totalCreation += creation;\n }\n\n store.set('cache', this.getData());\n }\n\n onPhaseTransition(\n fromPhase: string,\n toPhase: string,\n _ctx: MiddlewareContext,\n store: MiddlewareStore,\n ): void {\n this.phaseSnapshots.push({\n phase: fromPhase,\n cacheReadTokens: this.phaseRead,\n cacheCreationTokens: this.phaseCreation,\n cacheCreation5m: this.phaseCreation5m,\n cacheCreation1h: this.phaseCreation1h,\n });\n this.currentPhase = toPhase;\n this.phaseRead = 0;\n this.phaseCreation = 0;\n this.phaseCreation5m = 0;\n this.phaseCreation1h = 0;\n store.set('cache', this.getData());\n }\n\n onFinalize(\n _resultMessage: any,\n _totalDurationMs: number,\n _ctx: MiddlewareContext,\n store: MiddlewareStore,\n ): void {\n this.phaseSnapshots.push({\n phase: this.currentPhase,\n cacheReadTokens: this.phaseRead,\n cacheCreationTokens: this.phaseCreation,\n cacheCreation5m: this.phaseCreation5m,\n cacheCreation1h: this.phaseCreation1h,\n });\n store.set('cache', this.getData());\n }\n\n private getData(): CacheData {\n return {\n phaseRead: this.phaseRead,\n phaseCreation: this.phaseCreation,\n totalRead: this.totalRead,\n totalCreation: this.totalCreation,\n totalCreation5m: this.totalCreation5m,\n totalCreation1h: this.totalCreation1h,\n phaseSnapshots: [...this.phaseSnapshots],\n };\n }\n}\n","/**\n * Compaction event tracking plugin.\n *\n * Tracks context compaction events (compact_boundary system messages)\n * including pre-compaction token counts per phase.\n */\n\nimport type { Middleware, MiddlewareContext, MiddlewareStore } from '../types';\nimport { logToFile } from '@utils/debug';\nimport { AgentSignals } from '../../agent-interface';\n\nexport interface CompactionData {\n phaseCompactions: number;\n phasePreTokens: number[];\n totalCompactions: number;\n phaseSnapshots: Array<{\n phase: string;\n compactions: number;\n preTokens: number[];\n }>;\n}\n\nexport class CompactionTrackerPlugin implements Middleware {\n readonly name = 'compactions';\n\n private phaseCompactions = 0;\n private phasePreTokens: number[] = [];\n private totalCompactions = 0;\n private phaseSnapshots: Array<{\n phase: string;\n compactions: number;\n preTokens: number[];\n }> = [];\n private currentPhase = 'setup';\n\n onMessage(\n message: any,\n ctx: MiddlewareContext,\n store: MiddlewareStore,\n ): void {\n if (message.type !== 'system' || message.subtype !== 'compact_boundary') {\n return;\n }\n\n const preTokens = message.compact_metadata?.pre_tokens ?? 0;\n const trigger = message.compact_metadata?.trigger ?? 'unknown';\n this.phaseCompactions++;\n this.totalCompactions++;\n this.phasePreTokens.push(preTokens);\n\n logToFile(\n `${AgentSignals.BENCHMARK} [COMPACTION] Context compacted during \"${ctx.currentPhase}\" (trigger: ${trigger}, pre_tokens: ${preTokens})`,\n );\n\n store.set('compactions', this.getData());\n }\n\n onPhaseTransition(\n fromPhase: string,\n toPhase: string,\n _ctx: MiddlewareContext,\n store: MiddlewareStore,\n ): void {\n this.phaseSnapshots.push({\n phase: fromPhase,\n compactions: this.phaseCompactions,\n preTokens: [...this.phasePreTokens],\n });\n this.currentPhase = toPhase;\n this.phaseCompactions = 0;\n this.phasePreTokens = [];\n store.set('compactions', this.getData());\n }\n\n onFinalize(\n _resultMessage: any,\n _totalDurationMs: number,\n _ctx: MiddlewareContext,\n store: MiddlewareStore,\n ): void {\n this.phaseSnapshots.push({\n phase: this.currentPhase,\n compactions: this.phaseCompactions,\n preTokens: [...this.phasePreTokens],\n });\n store.set('compactions', this.getData());\n }\n\n private getData(): CompactionData {\n return {\n phaseCompactions: this.phaseCompactions,\n phasePreTokens: [...this.phasePreTokens],\n totalCompactions: this.totalCompactions,\n phaseSnapshots: [...this.phaseSnapshots],\n };\n }\n}\n","/**\n * Context size tracking plugin (context tokens in/out per phase).\n *\n * Context tokens out = sum of input + cache_read + cache_creation from the\n * last assistant message's usage (per-turn, NOT aggregate).\n * Context tokens in = previous phase's context tokens out.\n */\n\nimport type { Middleware, MiddlewareContext, MiddlewareStore } from '../types';\nimport type { TokenData } from './token-tracker';\n\nexport interface ContextSizeData {\n /** Per-phase context size snapshots */\n phaseSnapshots: Array<{\n phase: string;\n contextTokensIn?: number;\n contextTokensOut?: number;\n freshContext: boolean;\n }>;\n}\n\nexport class ContextSizeTrackerPlugin implements Middleware {\n readonly name = 'contextSize';\n\n private phaseSnapshots: Array<{\n phase: string;\n contextTokensIn?: number;\n contextTokensOut?: number;\n freshContext: boolean;\n }> = [];\n private lastContextTokensOut?: number;\n\n onPhaseTransition(\n fromPhase: string,\n _toPhase: string,\n ctx: MiddlewareContext,\n store: MiddlewareStore,\n ): void {\n const tokens = ctx.get<TokenData>('tokens');\n const contextTokensOut = this.computeContextTokensOut(tokens?.lastUsage);\n\n this.phaseSnapshots.push({\n phase: fromPhase,\n contextTokensIn: ctx.currentPhaseFreshContext\n ? undefined\n : this.lastContextTokensOut,\n contextTokensOut,\n freshContext: ctx.currentPhaseFreshContext,\n });\n\n this.lastContextTokensOut = contextTokensOut;\n store.set('contextSize', this.getData());\n }\n\n onFinalize(\n _resultMessage: any,\n _totalDurationMs: number,\n ctx: MiddlewareContext,\n store: MiddlewareStore,\n ): void {\n const tokens = ctx.get<TokenData>('tokens');\n const contextTokensOut = this.computeContextTokensOut(tokens?.lastUsage);\n\n this.phaseSnapshots.push({\n phase: ctx.currentPhase,\n contextTokensIn: ctx.currentPhaseFreshContext\n ? undefined\n : this.lastContextTokensOut,\n contextTokensOut,\n freshContext: ctx.currentPhaseFreshContext,\n });\n\n store.set('contextSize', this.getData());\n }\n\n private computeContextTokensOut(usage: any): number | undefined {\n if (!usage) return undefined;\n return (\n Number(usage.input_tokens ?? 0) +\n Number(usage.cache_read_input_tokens ?? 0) +\n Number(usage.cache_creation_input_tokens ?? 0)\n );\n }\n\n private getData(): ContextSizeData {\n return {\n phaseSnapshots: [...this.phaseSnapshots],\n };\n }\n}\n","/**\n * Shared exact-match USD-per-token pricing by model id, and the cost formula\n * applied to a token usage delta.\n *\n * Single source of truth for both the benchmark's `CostTrackerPlugin`\n * (`@agent/middleware/benchmarks/cost-tracker`) and the live token/cost HUD\n * (`agent-interface.ts`'s per-turn usage accumulation), so the two estimates\n * never drift apart. Both reconcile against the SDK's own authoritative\n * `total_cost_usd` once the run finishes — this table only prices the\n * *live-updating* estimate shown while the agent is still running.\n *\n * Model-aware because a run's model isn't fixed: `AgentConfig.modelOverride`\n * switches specific programs to Haiku (e.g. source-map detection), and the\n * SDK reports a `model` string on every individual assistant turn (subagents\n * dispatched via the Agent tool can run on a different model than the main\n * session).\n *\n * Deliberately matched by *exact* model id, not family name (no\n * `model.includes('opus')`-style fallback): different versions of the same\n * family are priced differently — e.g. Claude Opus 4.5 ($5/$25 per Mtok) is\n * half of Opus 4.1's rate ($15/$75) — so matching on \"opus\" or \"sonnet\"\n * alone silently mis-prices a newer/older sibling at the wrong rate. The\n * only normalization applied is stripping a trailing release-date suffix\n * (`stripDateSuffix`), since Anthropic's dated and undated ids for the\n * *same* version always carry the same price (verified for every entry\n * below). Claude Sonnet 5 is the one exception with a *time-dependent*\n * price — see `sonnet5Price` — rather than a fixed table entry.\n *\n * Prices verified against https://models.dev/api.json (Anthropic section)\n * on 2026-07-01 — re-verify there when adding an entry or bumping\n * DEFAULT_AGENT_MODEL/HAIKU_MODEL, since this table isn't fetched live.\n */\n\nimport {\n DEFAULT_AGENT_MODEL,\n HAIKU_MODEL,\n SONNET_5_MODEL,\n} from '@shared/constants';\n\nexport interface PricePerMtok {\n input: number;\n output: number;\n cacheRead: number;\n cacheCreation5m: number;\n cacheCreation1h: number;\n}\n\n/**\n * `cacheCreation1h` isn't published by models.dev (it only has one\n * cache-write rate); extrapolated at `input × 2`, the ratio that holds for\n * every model below (mirrors `cacheCreation5m` = `input × 1.25`, `cacheRead`\n * = `input × 0.1` — Anthropic's standard prompt-caching multipliers).\n * Rounded to 6 decimal places to clean up binary float noise from the\n * multiplication (e.g. `3 * 0.1` is `0.30000000000000004`, not `0.3`) — well\n * past cent-level precision at the 1M-token scale these prices are quoted at.\n */\nfunction pricingFromInput(input: number, output: number): PricePerMtok {\n const round = (n: number): number => Math.round(n * 1e6) / 1e6;\n return {\n input,\n output,\n cacheRead: round(input * 0.1),\n cacheCreation5m: round(input * 1.25),\n cacheCreation1h: round(input * 2),\n };\n}\n\n/**\n * Exact-match price table, keyed by the *undated* model id prefix —\n * `pricePerMtokForModel` strips a dated suffix before falling back to this\n * table, so a dated Anthropic id resolves via its undated entry without\n * needing a duplicate key. Ids the wizard no longer dispatches on stay\n * priced, since a subagent turn or the SDK can still report one (a turn on\n * an id NOT in this table contributes $0 to the live estimate rather than\n * guessing, see `pricePerMtokForModel`).\n *\n * `SONNET_5_MODEL` is intentionally absent: its price is time-dependent\n * (promotional launch discount), so `pricePerMtokForModel` resolves it via\n * `sonnet5Price`. It is also `DEFAULT_AGENT_MODEL`, so the no-model fallback\n * goes through that branch.\n */\nconst PRICE_TABLE: Record<string, PricePerMtok> = {\n 'claude-sonnet-4-6': pricingFromInput(3, 15),\n [HAIKU_MODEL]: pricingFromInput(1, 5),\n 'claude-opus-4-5': pricingFromInput(5, 25),\n};\n\n/**\n * Claude Sonnet 5 launched at a promotional discount through 2026-08-31\n * UTC; from 2026-09-01 it reverts to the same rate as Sonnet 4.6 ($3/$15)\n * — not a coincidence, Anthropic prices it identically to 4.6 once the\n * promo ends. Re-verify against https://models.dev/api.json if this ever\n * looks off, and fold this special case into a flat `PRICE_TABLE` entry at\n * the post-promo rate once the window is well past.\n */\nconst SONNET_5_PROMO_ENDS_UTC = new Date('2026-09-01T00:00:00Z');\n\nfunction sonnet5Price(now: Date): PricePerMtok {\n return now < SONNET_5_PROMO_ENDS_UTC\n ? pricingFromInput(2, 10)\n : pricingFromInput(3, 15);\n}\n\n/** Strips a trailing 8-digit release-date suffix (e.g. `-20251001`) — never\n * the version segment, so differently-versioned models are never conflated.\n * `claude-haiku-4-5-20251001` → `claude-haiku-4-5`; `claude-sonnet-4-6` (no\n * date suffix) is returned unchanged. */\nfunction stripDateSuffix(model: string): string {\n return model.replace(/-\\d{8}$/, '');\n}\n\n/**\n * Exact-match pricing lookup. `undefined` model (a caller with no model\n * context, e.g. the benchmark's `CostTrackerPlugin`) falls back to\n * `DEFAULT_AGENT_MODEL`'s price, the default for interactive runs. A\n * *given* but unrecognized model id returns `undefined` rather than\n * guessing from its family name — seeing `undefined` and skipping that\n * delta is strictly more accurate than the family-fallback this replaced,\n * which silently priced e.g. every Opus turn at Opus 4.1's rate.\n *\n * `now` is injectable (defaults to the real clock) only so\n * `sonnet5Price`'s promo-window check is deterministic in tests — no\n * other entry in this table is time-dependent.\n */\nexport function pricePerMtokForModel(\n model?: string,\n now: Date = new Date(),\n): PricePerMtok | undefined {\n const id = model ?? DEFAULT_AGENT_MODEL;\n const undated = stripDateSuffix(id);\n if (undated === SONNET_5_MODEL) return sonnet5Price(now);\n return PRICE_TABLE[id] ?? PRICE_TABLE[undated];\n}\n\n/**\n * Cost in USD for one usage delta, priced at `usage.model`'s exact rates\n * (see `pricePerMtokForModel`) — 0 when `model` is given but not in the\n * table, rather than guessing. `cacheCreation5m`/`cacheCreation1h` come from\n * the SDK's `usage.cache_creation` breakdown, which is only reported on\n * some turns — when both are 0, `cacheCreationTokens` (the plain\n * `cache_creation_input_tokens` total) is priced at the 5m rate instead, so\n * a turn without the breakdown still gets a reasonable estimate rather than\n * being priced at $0.\n *\n * Takes the same shape as `TokenUsageDelta` (`@agent/types`) so a caller\n * that already has one — `WizardStore.addTokenUsage` — can pass it straight\n * through instead of re-listing its fields in a fixed positional order.\n */\nexport function computeTokenCostUsd(usage: {\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheCreation5m: number;\n cacheCreation1h: number;\n cacheCreationTokens: number;\n model?: string;\n}): number {\n const price = pricePerMtokForModel(usage.model);\n if (!price) return 0;\n const hasBreakdown = usage.cacheCreation5m > 0 || usage.cacheCreation1h > 0;\n return (\n usage.inputTokens * (price.input / 1e6) +\n usage.outputTokens * (price.output / 1e6) +\n usage.cacheReadTokens * (price.cacheRead / 1e6) +\n (hasBreakdown\n ? usage.cacheCreation5m * (price.cacheCreation5m / 1e6) +\n usage.cacheCreation1h * (price.cacheCreation1h / 1e6)\n : usage.cacheCreationTokens * (price.cacheCreation5m / 1e6))\n );\n}\n\n/**\n * Shared display formatters for the hidden Ctrl+T HUD (`TokenCostHud`) and\n * the post-exit scrollback line (`exit-line.ts`) — kept here, not in either\n * of those files, since `exit-line.ts` is deliberately free of `ink`/React\n * imports (it must stay a pure, unit-testable function), and importing a\n * named export from a `.tsx` file would pull `ink` into its module graph\n * anyway. This module has no such dependency.\n */\nexport function formatTokenCount(n: number): string {\n if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(2)}M`;\n if (n >= 1_000) return `${(n / 1000).toFixed(1)}K`;\n return n.toLocaleString();\n}\n\nexport function formatCostUsd(usd: number): string {\n if (usd > 0 && usd < 0.01) return `$${usd.toFixed(4)}`;\n return `$${usd.toFixed(2)}`;\n}\n","import type { Middleware, MiddlewareContext, MiddlewareStore } from '../types';\nimport { computeTokenCostUsd } from '@shared/token-pricing';\nimport type { TokenData } from './token-tracker';\nimport type { CacheData } from './cache-tracker';\n\nexport interface CostData {\n totalCost: number;\n phaseCosts: Array<{ phase: string; cost: number }>;\n}\n\n// Pricing table + formula moved to `@shared/token-pricing` so the live\n// token/cost HUD's per-turn estimate can't drift from this benchmark's.\n// No model is passed to computeTokenCostUsd below (falls back to Sonnet\n// pricing) -- MiddlewareContext has no model field to thread through, and\n// `--benchmark` always measures the default flow, never a Haiku-overridden\n// program. Still reconciles to the SDK's authoritative total_cost_usd in\n// onFinalize below, same as the live HUD, so this only risks the\n// unreconciled per-phase breakdown.\n\nexport class CostTrackerPlugin implements Middleware {\n readonly name = 'cost';\n\n private phaseCosts: Array<{ phase: string; cost: number }> = [];\n private totalCost = 0;\n\n onPhaseTransition(\n fromPhase: string,\n _toPhase: string,\n ctx: MiddlewareContext,\n store: MiddlewareStore,\n ): void {\n const tokens = ctx.get<TokenData>('tokens');\n const cache = ctx.get<CacheData>('cache');\n const tokenSnap = tokens?.phaseSnapshots.at(-1);\n const cacheSnap = cache?.phaseSnapshots.at(-1);\n\n const totalIn = tokenSnap?.inputTokens ?? 0;\n const read = cacheSnap?.cacheReadTokens ?? 0;\n const creation = cacheSnap?.cacheCreationTokens ?? 0;\n const c5m = cacheSnap?.cacheCreation5m ?? 0;\n const c1h = cacheSnap?.cacheCreation1h ?? 0;\n const baseIn = Math.max(0, totalIn - read - creation);\n\n const phaseCost = computeTokenCostUsd({\n inputTokens: baseIn,\n outputTokens: tokenSnap?.outputTokens ?? 0,\n cacheReadTokens: read,\n cacheCreation5m: c5m,\n cacheCreation1h: c1h,\n cacheCreationTokens: creation,\n });\n\n this.phaseCosts.push({ phase: fromPhase, cost: phaseCost });\n this.totalCost += phaseCost;\n store.set('cost', this.getData());\n }\n\n onFinalize(\n resultMessage: any,\n _totalDurationMs: number,\n ctx: MiddlewareContext,\n store: MiddlewareStore,\n ): void {\n const tokens = ctx.get<TokenData>('tokens');\n const cache = ctx.get<CacheData>('cache');\n const tokenSnap = tokens?.phaseSnapshots.at(-1);\n const cacheSnap = cache?.phaseSnapshots.at(-1);\n\n const totalIn = tokenSnap?.inputTokens ?? 0;\n const read = cacheSnap?.cacheReadTokens ?? 0;\n const creation = cacheSnap?.cacheCreationTokens ?? 0;\n const c5m = cacheSnap?.cacheCreation5m ?? 0;\n const c1h = cacheSnap?.cacheCreation1h ?? 0;\n const baseIn = Math.max(0, totalIn - read - creation);\n\n const lastPhaseCost = computeTokenCostUsd({\n inputTokens: baseIn,\n outputTokens: tokenSnap?.outputTokens ?? 0,\n cacheReadTokens: read,\n cacheCreation5m: c5m,\n cacheCreation1h: c1h,\n cacheCreationTokens: creation,\n });\n\n this.phaseCosts.push({ phase: ctx.currentPhase, cost: lastPhaseCost });\n this.totalCost += lastPhaseCost;\n\n const sdkTotal =\n Number(resultMessage?.usage?.total_cost_usd ?? 0) ||\n Number(resultMessage?.total_cost_usd ?? 0);\n\n if (sdkTotal > 0 && this.totalCost > 0) {\n const scale = sdkTotal / this.totalCost;\n this.phaseCosts = this.phaseCosts.map((p) => ({\n phase: p.phase,\n cost: p.cost * scale,\n }));\n this.totalCost = sdkTotal;\n }\n\n store.set('cost', this.getData());\n }\n\n private getData(): CostData {\n return {\n totalCost: this.totalCost,\n phaseCosts: [...this.phaseCosts],\n };\n }\n}\n","/**\n * Duration tracking plugin (per-phase and total).\n */\n\nimport type { Middleware, MiddlewareContext, MiddlewareStore } from '../types';\n\nexport interface DurationData {\n phaseSnapshots: Array<{\n phase: string;\n startTime: number;\n endTime: number;\n durationMs: number;\n }>;\n totalDurationMs: number;\n}\n\nexport class DurationTrackerPlugin implements Middleware {\n readonly name = 'duration';\n\n private phaseStartTime = Date.now();\n private phaseSnapshots: Array<{\n phase: string;\n startTime: number;\n endTime: number;\n durationMs: number;\n }> = [];\n\n onPhaseTransition(\n fromPhase: string,\n _toPhase: string,\n _ctx: MiddlewareContext,\n store: MiddlewareStore,\n ): void {\n const now = Date.now();\n this.phaseSnapshots.push({\n phase: fromPhase,\n startTime: this.phaseStartTime,\n endTime: now,\n durationMs: now - this.phaseStartTime,\n });\n this.phaseStartTime = now;\n store.set('duration', {\n phaseSnapshots: [...this.phaseSnapshots],\n totalDurationMs: 0,\n } satisfies DurationData);\n }\n\n onFinalize(\n _resultMessage: any,\n totalDurationMs: number,\n ctx: MiddlewareContext,\n store: MiddlewareStore,\n ): void {\n const now = Date.now();\n this.phaseSnapshots.push({\n phase: ctx.currentPhase,\n startTime: this.phaseStartTime,\n endTime: now,\n durationMs: now - this.phaseStartTime,\n });\n\n store.set('duration', {\n phaseSnapshots: [...this.phaseSnapshots],\n totalDurationMs,\n } satisfies DurationData);\n }\n}\n","import type { ProgressEmitter, SpinnerHandle } from '../../progress';\nimport { AgentSignals } from '../../agent-interface';\nimport type { Middleware, MiddlewareContext, MiddlewareStore } from '../types';\nimport type { TokenData } from './token-tracker';\nimport type { TurnData } from './turn-counter';\nimport type { CostData } from './cost-tracker';\nimport type { DurationData } from './duration-tracker';\nimport type { CompactionData } from './compaction-tracker';\nimport type { ContextSizeData } from './context-size-tracker';\nimport type { CacheData } from './cache-tracker';\n\nfunction fmtDuration(ms: number): string {\n const s = Math.round(ms / 1000);\n const m = Math.floor(s / 60);\n return m > 0 ? `${m}m ${s % 60}s` : `${s}s`;\n}\n\nfunction fmtTok(n: number): string {\n if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`;\n if (n >= 1_000) return `${(n / 1000).toFixed(1)}K`;\n return n.toLocaleString();\n}\n\nfunction fmtCost(usd: number): string {\n if (usd > 0 && usd < 0.01) return `$${usd.toFixed(4)}`;\n return `$${usd.toFixed(2)}`;\n}\n\ninterface PhaseStats {\n phase: string;\n durationMs: number;\n turns: number;\n inputTokens: number;\n outputTokens: number;\n cacheRead: number;\n cacheCreation5m: number;\n cacheCreation1h: number;\n cost: number;\n compactions: number;\n contextOut: number | undefined;\n}\n\nfunction printPhase(s: PhaseStats): string {\n const baseIn = Math.max(\n 0,\n s.inputTokens - s.cacheRead - s.cacheCreation5m - s.cacheCreation1h,\n );\n return [\n `${s.phase}: ${fmtDuration(s.durationMs)}, ${\n s.turns\n } turns, cost: ${fmtCost(s.cost)}`,\n ` in: ${fmtTok(baseIn)}, out: ${fmtTok(\n s.outputTokens,\n )}, cache_read: ${fmtTok(s.cacheRead)}, cache_5m: ${fmtTok(\n s.cacheCreation5m,\n )}, cache_1h: ${fmtTok(s.cacheCreation1h)}`,\n s.compactions > 0 ? ` ${s.compactions} compaction(s)` : null,\n s.contextOut !== undefined ? ` ctx_out: ${fmtTok(s.contextOut)}` : null,\n ]\n .filter(Boolean)\n .join('\\n');\n}\n\nfunction getPhaseStats(i: number, ctx: MiddlewareContext): PhaseStats | null {\n const duration = ctx.get<DurationData>('duration');\n const dur = duration?.phaseSnapshots[i];\n if (!dur) return null;\n\n const tokens = ctx.get<TokenData>('tokens');\n const turns = ctx.get<TurnData>('turns');\n const cost = ctx.get<CostData>('cost');\n const compactions = ctx.get<CompactionData>('compactions');\n const contextSize = ctx.get<ContextSizeData>('contextSize');\n const cache = ctx.get<CacheData>('cache');\n\n return {\n phase: dur.phase,\n durationMs: dur.durationMs,\n turns: turns?.phaseSnapshots[i]?.turns ?? 0,\n inputTokens: tokens?.phaseSnapshots[i]?.inputTokens ?? 0,\n outputTokens: tokens?.phaseSnapshots[i]?.outputTokens ?? 0,\n cacheRead: cache?.phaseSnapshots[i]?.cacheReadTokens ?? 0,\n cacheCreation5m: cache?.phaseSnapshots[i]?.cacheCreation5m ?? 0,\n cacheCreation1h: cache?.phaseSnapshots[i]?.cacheCreation1h ?? 0,\n cost: cost?.phaseCosts[i]?.cost ?? 0,\n compactions: compactions?.phaseSnapshots[i]?.compactions ?? 0,\n contextOut: contextSize?.phaseSnapshots[i]?.contextTokensOut,\n };\n}\n\nexport class SummaryPlugin implements Middleware {\n readonly name = 'summary';\n\n private spinner: SpinnerHandle;\n\n private readonly info: (message: string) => void;\n\n constructor(spinner: SpinnerHandle, emit: ProgressEmitter) {\n this.spinner = spinner;\n this.info = (message) => emit({ kind: 'log', level: 'info', message });\n }\n\n onPhaseTransition(\n fromPhase: string,\n toPhase: string,\n ctx: MiddlewareContext,\n _store: MiddlewareStore,\n ): void {\n const duration = ctx.get<DurationData>('duration');\n const idx = (duration?.phaseSnapshots.length ?? 1) - 1;\n const stats = getPhaseStats(idx, ctx);\n\n if (stats) {\n this.spinner.stop(`${AgentSignals.BENCHMARK} ${printPhase(stats)}`);\n } else {\n this.spinner.stop(`${AgentSignals.BENCHMARK} ${fromPhase}`);\n }\n\n this.info(`${AgentSignals.BENCHMARK} Starting phase: ${toPhase}`);\n this.spinner.start(`Integrating PostHog (${toPhase})...`);\n }\n\n onFinalize(\n _resultMessage: any,\n totalDurationMs: number,\n ctx: MiddlewareContext,\n _store: MiddlewareStore,\n ): void {\n const duration = ctx.get<DurationData>('duration');\n const cost = ctx.get<CostData>('cost');\n const tokens = ctx.get<TokenData>('tokens');\n const cache = ctx.get<CacheData>('cache');\n\n const phaseCount = duration?.phaseSnapshots.length ?? 0;\n const totalCost = cost?.totalCost ?? 0;\n\n this.info('');\n this.info(\n `◇ ${AgentSignals.BENCHMARK} ${phaseCount} phases in ${fmtDuration(\n totalDurationMs,\n )}, cost: ${fmtCost(totalCost)}`,\n );\n this.info(\n ` total in: ${fmtTok(tokens?.totalInput ?? 0)}, out: ${fmtTok(\n tokens?.totalOutput ?? 0,\n )}, cache_read: ${fmtTok(cache?.totalRead ?? 0)}, cache_5m: ${fmtTok(\n cache?.totalCreation5m ?? 0,\n )}, cache_1h: ${fmtTok(cache?.totalCreation1h ?? 0)}`,\n );\n this.info('');\n this.info(`● ${AgentSignals.BENCHMARK} Summary by phase:`);\n\n if (duration?.phaseSnapshots) {\n for (let i = 0; i < duration.phaseSnapshots.length; i++) {\n const stats = getPhaseStats(i, ctx);\n if (stats) {\n this.info(printPhase(stats));\n }\n }\n }\n\n this.info('');\n }\n}\n","/**\n * JSON file output plugin.\n *\n * Assembles the BenchmarkData structure from all upstream plugin data\n * and writes it to a JSON file. Returns the BenchmarkData for backward compat.\n */\n\nimport fs from 'fs';\nimport type { ProgressEmitter } from '../../progress';\nimport { logToFile } from '@utils/debug';\nimport { AgentSignals } from '../../agent-interface';\nimport type { Middleware, MiddlewareContext, MiddlewareStore } from '../types';\nimport type { TokenData } from './token-tracker';\nimport type { CacheData } from './cache-tracker';\nimport type { TurnData } from './turn-counter';\nimport type { CostData } from './cost-tracker';\nimport type { DurationData } from './duration-tracker';\nimport type { CompactionData } from './compaction-tracker';\nimport type { ContextSizeData } from './context-size-tracker';\nimport type { BenchmarkData, StepUsage } from '../benchmark';\n\n/**\n * Sum token usage across all models from the SDK's modelUsage field.\n */\nfunction sumModelUsage(modelUsage: Record<string, any>): {\n input_tokens: number;\n output_tokens: number;\n cache_creation_input_tokens: number;\n cache_read_input_tokens: number;\n} {\n let input_tokens = 0;\n let output_tokens = 0;\n let cache_creation_input_tokens = 0;\n let cache_read_input_tokens = 0;\n\n for (const model of Object.values(modelUsage)) {\n input_tokens += model.inputTokens ?? 0;\n output_tokens += model.outputTokens ?? 0;\n cache_creation_input_tokens += model.cacheCreationInputTokens ?? 0;\n cache_read_input_tokens += model.cacheReadInputTokens ?? 0;\n }\n\n return {\n input_tokens,\n output_tokens,\n cache_creation_input_tokens,\n cache_read_input_tokens,\n };\n}\n\nexport class JsonWriterPlugin implements Middleware {\n readonly name = 'jsonWriter';\n\n private outputPath: string;\n private readonly info: (message: string) => void;\n\n constructor(outputPath: string, emit: ProgressEmitter) {\n this.outputPath = outputPath;\n this.info = (message) => emit({ kind: 'log', level: 'info', message });\n }\n\n onFinalize(\n resultMessage: any,\n totalDurationMs: number,\n ctx: MiddlewareContext,\n _store: MiddlewareStore,\n ): BenchmarkData {\n const tokens = ctx.get<TokenData>('tokens');\n const cache = ctx.get<CacheData>('cache');\n const turns = ctx.get<TurnData>('turns');\n const cost = ctx.get<CostData>('cost');\n const duration = ctx.get<DurationData>('duration');\n const compactions = ctx.get<CompactionData>('compactions');\n const contextSize = ctx.get<ContextSizeData>('contextSize');\n\n const modelUsage = resultMessage?.modelUsage ?? {};\n const aggregateUsage = sumModelUsage(modelUsage);\n\n const phaseCount = duration?.phaseSnapshots.length ?? 0;\n const steps: StepUsage[] = [];\n\n for (let i = 0; i < phaseCount; i++) {\n const dur = duration!.phaseSnapshots[i];\n const tokenSnap = tokens?.phaseSnapshots[i];\n const cacheSnap = cache?.phaseSnapshots[i];\n const turnSnap = turns?.phaseSnapshots[i];\n const costSnap = cost?.phaseCosts[i];\n const compSnap = compactions?.phaseSnapshots[i];\n const ctxSnap = contextSize?.phaseSnapshots[i];\n\n const step: StepUsage = {\n name: dur.phase,\n usage: {\n input_tokens: tokenSnap?.inputTokens ?? 0,\n output_tokens: tokenSnap?.outputTokens ?? 0,\n cache_creation_input_tokens: cacheSnap?.cacheCreationTokens ?? 0,\n cache_read_input_tokens: cacheSnap?.cacheReadTokens ?? 0,\n ...((cacheSnap?.cacheCreation5m ?? 0) +\n (cacheSnap?.cacheCreation1h ?? 0) >\n 0 && {\n cache_creation: {\n ephemeral_5m_input_tokens: cacheSnap?.cacheCreation5m ?? 0,\n ephemeral_1h_input_tokens: cacheSnap?.cacheCreation1h ?? 0,\n },\n }),\n },\n modelUsage: {},\n totalCostUsd: costSnap?.cost ?? 0,\n durationMs: dur.durationMs,\n durationApiMs: 0,\n numTurns: turnSnap?.turns ?? 0,\n ...(ctxSnap?.contextTokensIn !== undefined && {\n contextTokensIn: ctxSnap.contextTokensIn,\n }),\n ...(ctxSnap?.contextTokensOut !== undefined && {\n contextTokensOut: ctxSnap.contextTokensOut,\n }),\n ...(compSnap && compSnap.compactions > 0\n ? {\n compactions: compSnap.compactions,\n compactionPreTokens: compSnap.preTokens,\n }\n : {}),\n };\n\n steps.push(step);\n }\n\n const totalTurns = turns?.totalTurns ?? 0;\n const totalCost = cost?.totalCost ?? 0;\n const totalCompactions = compactions?.totalCompactions ?? 0;\n const fromModelUsage =\n aggregateUsage.input_tokens +\n aggregateUsage.cache_read_input_tokens +\n aggregateUsage.cache_creation_input_tokens;\n const inputTokens =\n fromModelUsage > 0\n ? fromModelUsage\n : (tokens?.totalInput ?? 0) +\n (cache?.totalRead ?? 0) +\n (cache?.totalCreation ?? 0);\n const outputTokens =\n aggregateUsage.output_tokens > 0\n ? aggregateUsage.output_tokens\n : tokens?.totalOutput ?? 0;\n\n const benchmark: BenchmarkData = {\n timestamp: new Date().toISOString(),\n steps,\n totals: {\n totalCostUsd: totalCost,\n durationMs: totalDurationMs,\n inputTokens,\n outputTokens,\n numTurns: resultMessage?.num_turns ?? totalTurns,\n totalCompactions,\n totalCacheReadTokens: cache?.totalRead ?? 0,\n totalCacheCreation5mTokens: cache?.totalCreation5m ?? 0,\n totalCacheCreation1hTokens: cache?.totalCreation1h ?? 0,\n },\n };\n\n this.writeBenchmarkData(benchmark);\n return benchmark;\n }\n\n private writeBenchmarkData(data: BenchmarkData): void {\n try {\n fs.writeFileSync(this.outputPath, JSON.stringify(data, null, 2));\n logToFile(`Benchmark data written to ${this.outputPath}`);\n this.info(\n `● ${AgentSignals.BENCHMARK} Results written to ${this.outputPath}`,\n );\n } catch (error) {\n logToFile('Failed to write benchmark data:', error);\n }\n }\n}\n","/**\n * Plugin registry and factory.\n *\n * Maps plugin names to constructors and creates the ordered plugin list\n * from a BenchmarkConfig.\n */\n\nimport type { Middleware, MiddlewareFactoryOptions } from '../types';\nimport type { BenchmarkConfig } from '../config';\nimport { TurnCounterPlugin } from './turn-counter';\nimport { TokenTrackerPlugin } from './token-tracker';\nimport { CacheTrackerPlugin } from './cache-tracker';\nimport { CompactionTrackerPlugin } from './compaction-tracker';\nimport { ContextSizeTrackerPlugin } from './context-size-tracker';\nimport { CostTrackerPlugin } from './cost-tracker';\nimport { DurationTrackerPlugin } from './duration-tracker';\nimport { SummaryPlugin } from './summary';\nimport { JsonWriterPlugin } from './json-writer';\n\ntype PluginFactory = (opts: MiddlewareFactoryOptions) => Middleware;\n\nconst PLUGIN_REGISTRY: Record<string, PluginFactory> = {\n turns: () => new TurnCounterPlugin(),\n tokens: () => new TokenTrackerPlugin(),\n cache: () => new CacheTrackerPlugin(),\n compactions: () => new CompactionTrackerPlugin(),\n contextSize: () => new ContextSizeTrackerPlugin(),\n cost: () => new CostTrackerPlugin(),\n duration: () => new DurationTrackerPlugin(),\n summary: (opts) => new SummaryPlugin(opts.spinner!, opts.emit),\n jsonWriter: (opts) => new JsonWriterPlugin(opts.outputPath!, opts.emit),\n};\n\n/**\n * Execution order — data producers before consumers:\n * turns (dedup) -> tokens -> cache -> compactions -> contextSize -> cost -> duration -> summary -> jsonWriter\n */\nconst PLUGIN_ORDER = [\n 'turns',\n 'tokens',\n 'cache',\n 'compactions',\n 'contextSize',\n 'cost',\n 'duration',\n 'summary',\n 'jsonWriter',\n];\n\nexport function createPluginsFromConfig(\n config: BenchmarkConfig,\n opts: MiddlewareFactoryOptions,\n): Middleware[] {\n const resolvedOpts: MiddlewareFactoryOptions = {\n ...opts,\n outputPath: opts.outputPath ?? config.output.benchmarkPath,\n };\n\n // If suppressWizardLogs is set, disable the summary plugin\n const effectivePlugins = { ...config.plugins };\n if (config.output.suppressWizardLogs) {\n effectivePlugins.summary = false;\n }\n\n return PLUGIN_ORDER.filter((name) => effectivePlugins[name] !== false)\n .map((name) => PLUGIN_REGISTRY[name])\n .filter(Boolean)\n .map((factory) => factory(resolvedOpts));\n}\n","/**\n * Benchmark tracking for wizard runs.\n *\n * Usage:\n * const pipeline = createBenchmarkPipeline(emit, spinner, options);\n * pipeline.onMessage(message);\n * pipeline.finalize(resultMessage, durationMs);\n */\n\nimport type { ProgressEmitter, SpinnerHandle } from '../progress';\nimport { logToFile, getLogFilePath, configureLogFile } from '@utils/debug';\nimport { MiddlewarePipeline } from './pipeline';\nimport { PhaseDetector } from './phase-detector';\nimport { loadBenchmarkConfig } from './config';\nimport { createPluginsFromConfig } from './benchmarks';\nimport type { BenchmarkConfig } from './config';\nimport type { WizardRunOptions } from '@utils/types';\nimport { AgentSignals } from '../agent-interface';\n\n// ── Types ──────────────────────────────────────────────────────────────\n\nexport interface StepUsage {\n name: string;\n usage: {\n input_tokens: number;\n output_tokens: number;\n cache_creation_input_tokens: number;\n cache_read_input_tokens: number;\n cache_creation?: {\n ephemeral_5m_input_tokens: number;\n ephemeral_1h_input_tokens: number;\n };\n };\n modelUsage: Record<string, unknown>;\n totalCostUsd: number;\n durationMs: number;\n durationApiMs: number;\n numTurns: number;\n contextTokensIn?: number;\n contextTokensOut?: number;\n compactions?: number;\n compactionPreTokens?: number[];\n}\n\nexport interface BenchmarkData {\n timestamp: string;\n steps: StepUsage[];\n totals: {\n totalCostUsd: number;\n durationMs: number;\n inputTokens: number;\n outputTokens: number;\n numTurns: number;\n totalCompactions: number;\n totalCacheReadTokens: number;\n totalCacheCreation5mTokens: number;\n totalCacheCreation1hTokens: number;\n };\n}\n\n// ── Factory ────────────────────────────────────────────────────────────\n\n/**\n * Create a middleware pipeline configured for benchmarking.\n * Loads .benchmark-config.json from the install dir, falls back to defaults.\n */\nexport function createBenchmarkPipeline(\n emit: ProgressEmitter,\n spinner: SpinnerHandle,\n options: WizardRunOptions,\n configOverride?: BenchmarkConfig,\n): MiddlewarePipeline {\n const config = configOverride ?? loadBenchmarkConfig(options.installDir);\n const info = (message: string) =>\n emit({ kind: 'log', level: 'info', message });\n\n configureLogFile({\n path: config.output.logPath,\n enabled: config.output.logEnabled,\n });\n\n const plugins = createPluginsFromConfig(config, {\n emit,\n spinner,\n phased: false,\n outputPath: config.output.benchmarkPath,\n });\n\n if (!config.output.suppressWizardLogs) {\n info(`${AgentSignals.BENCHMARK} Verbose logs: ${getLogFilePath()}`);\n info(\n `${AgentSignals.BENCHMARK} Benchmark data will be written to: ${config.output.benchmarkPath}`,\n );\n }\n\n logToFile(\n `${AgentSignals.BENCHMARK} Tracking enabled, starting with setup phase`,\n );\n\n return new MiddlewarePipeline(plugins, {\n phaseDetector: new PhaseDetector(),\n autoDetectPhases: true,\n });\n}\n","import { AgentErrorType } from './signals';\nimport { ErrorCodes, type ErrorCode } from '@shared/errors';\n\nexport const AGENT_ERROR_CODE: Record<AgentErrorType, ErrorCode> = {\n [AgentErrorType.AGENTIC_DETECTION_TIMEOUT]:\n ErrorCodes.AgenticDetectionTimeout,\n [AgentErrorType.MCP_MISSING]: ErrorCodes.AgentMcpMissing,\n [AgentErrorType.RESOURCE_MISSING]: ErrorCodes.AgentResourceMissing,\n [AgentErrorType.RATE_LIMIT]: ErrorCodes.AgentRateLimit,\n [AgentErrorType.API_ERROR]: ErrorCodes.AgentApiError,\n [AgentErrorType.YARA_VIOLATION]: ErrorCodes.AgentYaraViolation,\n [AgentErrorType.ABORT]: ErrorCodes.AgentAbort,\n [AgentErrorType.NO_PROGRESS]: ErrorCodes.AgentNoProgress,\n [AgentErrorType.INVALID_STRUCTURED_OUTPUT]:\n ErrorCodes.AgentInvalidStructuredOutput,\n [AgentErrorType.INCOMPLETE_TASKS]: ErrorCodes.AgentIncompleteTasks,\n};\n","/**\n * Agent prompt assembly.\n *\n * Three sections, always in this order:\n * 1. Default project prompt — credentials and base context (always included)\n * 2. Custom prompt — additional program-specific instructions (if set)\n * 3. Skill prompt — \"follow SKILL.md\" instructions (if a skill was installed)\n */\n\nimport type { AgentRunDefinition } from './runner/shared/types';\nimport type { HostResolution } from '@shared/host-resolution';\n\n/**\n * Values available to prompt builders after OAuth completes.\n */\nexport interface PromptContext {\n projectId: number;\n projectApiKey: string;\n host: HostResolution;\n /** Set when skillId was provided and the skill was installed successfully. */\n skillPath?: string;\n /**\n * Org-level AI consent (`is_ai_data_processing_approved`) read from the\n * `/api/users/@me/` payload at auth time. `null` = unknown (older orgs,\n * or the user fetch failed). Lets prompts pre-resolve consent state so\n * agents only ask the user when it is actually off or unknown.\n */\n orgAiDataProcessingApproved?: boolean | null;\n /**\n * Team product opt-ins from the `/api/projects/:id/` payload at auth\n * time. Project-level truth for \"is this product enabled\" — products\n * can be instrumented from other repos or the snippet, so repo-local\n * evidence must never rule them out. `null` field = unknown.\n */\n teamProductOptIns?: {\n sessionReplay?: boolean | null;\n exceptionAutocapture?: boolean | null;\n surveys?: boolean | null;\n } | null;\n}\n\nfunction defaultProjectPrompt(ctx: PromptContext): string {\n return `You have access to the PostHog MCP server.\n\nProject context:\n- PostHog Project ID: ${ctx.projectId}\n- PostHog public token: ${ctx.projectApiKey}\n- PostHog Host: ${ctx.host.apiHost}`;\n}\n\nfunction skillPrompt(skillPath: string, reportFile: string): string {\n return `A PostHog skill has been installed at ${skillPath}/. Read ${skillPath}/SKILL.md and follow its instructions completely.\n\nAfter completing the skill workflow, write a brief markdown report to ./${reportFile} summarizing:\n- What changes were made to the project\n- Which files were modified or created\n- Any manual steps the user should take next\n\nImportant: You must read a file immediately before attempting to write it, even if you have previously read it; failure to do so will cause a tool failure.`;\n}\n\n/**\n * Assemble the final agent prompt from the program's run config.\n */\nexport function assemblePrompt(\n runDef: AgentRunDefinition,\n ctx: PromptContext,\n): string {\n const parts: string[] = [];\n\n // Always include the default project prompt\n parts.push(defaultProjectPrompt(ctx));\n\n // Additional program-specific instructions\n if (runDef.customPrompt) {\n parts.push(runDef.customPrompt(ctx));\n }\n\n // Skill prompt (appended when a skill was pre-installed)\n if (ctx.skillPath) {\n parts.push(skillPrompt(ctx.skillPath, runDef.reportFile));\n }\n\n return parts.join('\\n\\n');\n}\n","/**\n * Shared error helpers for the runner pipeline.\n */\n\nimport type { InstallSkillResult } from '@shared/skill-install';\nimport { ErrorCodes, skillErrorCode } from '@shared/errors';\nimport { RunOutcome, type AgentFailure, type SequenceResult } from './types';\n\nexport const failed = (failure: AgentFailure): SequenceResult => ({\n outcome: RunOutcome.Failed,\n failure,\n});\n\n/** The failure a skill install error decides. The caller reports and exits. */\nexport function installFailure(\n integrationLabel: string,\n result: Exclude<InstallSkillResult, { kind: 'ok' }>,\n): AgentFailure {\n const code = skillErrorCode(result) ?? ErrorCodes.InternalUnhandled;\n\n const message = (() => {\n switch (result.kind) {\n case 'menu-fetch-failed':\n return 'Could not fetch the skill menu from context-mill.\\nCheck your network connection and try again.';\n case 'skill-not-found':\n return `Could not find the \"${result.skillId}\" skill in the context-mill menu.\\nPlease try again later.`;\n case 'download-failed':\n return `Failed to install skill: ${result.message}\\nPlease try again.`;\n }\n })();\n\n return {\n message,\n code,\n detail: {\n integration: integrationLabel,\n error_type: result.kind,\n platform: process.platform,\n ...(result.kind === 'download-failed'\n ? { error_detail: result.message.slice(0, 500) }\n : {}),\n },\n };\n}\n","/**\n * The ask bridge over an injected answerer.\n *\n * `createWizardAskBridge` already owns request ids, the timeout race, the\n * `__cancelled__` sentinel and the analytics; it only ever needed a\n * `showQuestion` that honours each question's own signal. Here that comes from\n * `AgentInteraction` instead of `getUI()`. With no answerer there is no bridge,\n * so `wizard_ask` reports its existing \"not available\" error rather than\n * hanging on a question nobody can see.\n */\n\nimport {\n createWizardAskBridge,\n type WizardAskBridge,\n} from '../../wizard-ask-bridge';\nimport type { AgentInteraction } from '../../progress';\n\nexport function createAskBridge(\n interaction: AgentInteraction | undefined,\n options: {\n getSource: () => string;\n richLinks: boolean;\n timeoutMs?: number;\n signal?: AbortSignal;\n /** Runs before each question is shown (the orchestrator's bell and metric). */\n beforeShow?: () => void;\n },\n): WizardAskBridge | undefined {\n const ask = interaction?.ask;\n if (!ask) return undefined;\n\n return createWizardAskBridge({\n getSource: options.getSource,\n showQuestion: (question, context) => {\n options.beforeShow?.();\n return ask(question, context);\n },\n richLinks: options.richLinks,\n timeoutMs: options.timeoutMs,\n signal: options.signal,\n });\n}\n","/**\n * The linear pipeline. Single execution path for all non-orchestrator programs,\n * both skill-based (revenue analytics) and framework-based (core integration).\n * The `AgentRunDefinition` controls what varies between them; `ResolvedRunConfig`\n * carries the program-level static metadata (tool allow/disallow lists, etc.).\n *\n * Reports through `emit`, asks through `interaction`, and returns a decided\n * `RunResult`. Every former `getUI()` call is one progress event in the same\n * place; every former `wizardAbort` is a returned failure with the same\n * arguments, so the caller's exit sequence is unchanged.\n */\n\nimport { OutroKind, type OutroData } from '@shared/outro';\nimport { AgentErrorType } from '../../agent-interface';\nimport { logToFile } from '@utils/debug';\nimport { createBenchmarkPipeline } from '../../middleware/benchmark';\nimport { ErrorCodes } from '@shared/errors';\nimport { AGENT_ERROR_CODE } from '../../error-map';\nimport { analytics } from '@utils/analytics';\nimport { formatYaraAbortMessage, scanInstalledSkill } from '../../yara-hooks';\nimport { installSkillById } from '@shared/skill-install';\nimport { assemblePrompt, type PromptContext } from '../../agent-prompt';\nimport type { SequenceResult, SequenceContext } from '../shared/types';\nimport { failed, installFailure } from '../shared/errors';\nimport { RunOutcome } from '../shared/types';\nimport { runOptions } from '../shared/bootstrap';\nimport { shouldDisableAsk } from '@shared/ask-policy';\nimport { createEmitSpinner } from '../shared/progress-collector';\nimport { createAskBridge } from '../shared/ask';\nimport { withTranscript } from '../shared/transcript-tail';\nimport { getHarness } from '../switchboard';\n\nexport async function runLinearProgram(\n context: SequenceContext,\n): Promise<SequenceResult> {\n // Aborts on the caller's signal or when the run ends, so no ask outlives it.\n const controller = new AbortController();\n const abortFromHost = () => controller.abort();\n context.signal?.addEventListener('abort', abortFromHost, { once: true });\n if (context.signal?.aborted) abortFromHost();\n try {\n return await executeLinear(context, controller.signal);\n } finally {\n context.signal?.removeEventListener('abort', abortFromHost);\n controller.abort();\n }\n}\n\n/** The caller's `signal` decides the outcome; `runSignal` also ends with the run. */\nasync function executeLinear(\n {\n config,\n input,\n boot,\n emit,\n interaction,\n signal,\n transcript,\n }: SequenceContext,\n runSignal: AbortSignal,\n): Promise<SequenceResult> {\n const { run, composed } = config;\n const { skillsBaseUrl, credentials, project } = boot;\n const { projectApiKey, host, projectId } = credentials;\n const aborted = (): SequenceResult => ({\n outcome: RunOutcome.Aborted,\n failure: { code: ErrorCodes.AgentAbort, message: 'Agent run cancelled' },\n });\n if (signal?.aborted) return aborted();\n\n // 5. Skill install (if skillId provided)\n let skillPath: string | undefined;\n if (run.skillId) {\n logToFile(`[agent-runner] installing skill ${run.skillId}`);\n const installResult = await installSkillById(\n run.skillId,\n input.installDir,\n skillsBaseUrl,\n { scan: (dir) => scanInstalledSkill(dir, boot.triageProvider) },\n );\n if (signal?.aborted) return aborted();\n if (installResult.kind !== 'ok') {\n return failed(installFailure(run.integrationLabel, installResult));\n }\n skillPath = installResult.path;\n logToFile(`[agent-runner] skill installed at ${skillPath}`);\n }\n\n // 6. Initialize agent\n const spinner = createEmitSpinner(emit);\n\n if (!run.structured) emit({ kind: 'lifecycle', phase: 'started' });\n\n // wizard_ask needs an answerer. A human answers at the keyboard; the e2e\n // snapshot/MCP host answers via its driver and sets WIZARD_ASK_AUTODRIVE.\n // CI/signup with neither has no answerer, so we omit the bridge and the tool\n // returns an actionable error rather than hanging on a never-resolving prompt.\n const askDisabled =\n !!run.structured ||\n (shouldDisableAsk(input.flags) && process.env.WIZARD_ASK_AUTODRIVE !== '1');\n const ask = askDisabled\n ? undefined\n : createAskBridge(interaction, {\n getSource: () => input.skillId ?? run.integrationLabel,\n richLinks: run.richLinks ?? false,\n timeoutMs: run.askTimeoutMs,\n signal: runSignal,\n });\n\n const middleware = withTranscript(\n input.flags.benchmark\n ? createBenchmarkPipeline(emit, spinner, runOptions(input))\n : undefined,\n transcript,\n );\n\n // 7. Build prompt\n const promptContext: PromptContext = {\n projectId,\n projectApiKey,\n host,\n skillPath,\n orgAiDataProcessingApproved:\n input.apiUser?.organization?.is_ai_data_processing_approved ?? null,\n teamProductOptIns: project\n ? {\n sessionReplay: project.session_recording_opt_in ?? null,\n exceptionAutocapture: project.autocapture_exceptions_opt_in ?? null,\n surveys: project.surveys_opt_in ?? null,\n }\n : null,\n };\n const prompt = run.prompt\n ? run.prompt(promptContext)\n : assemblePrompt(run, promptContext);\n logToFile(`[agent-runner] prompt assembled (${prompt.length} chars)`);\n if (signal?.aborted) return aborted();\n\n // 8. Run the agent through the run-level harness. The harness owns the agent\n // loop + model transport; everything around it (skill install, prompt, ask\n // bridge, error routing, outro) stays here so every harness shares it.\n const { harness, model, thinkingLevel } = config.binding;\n const agentResult = await getHarness(harness).run({\n config,\n input,\n boot,\n emit,\n prompt,\n skillPath,\n spinner,\n askBridge: ask,\n middleware,\n model,\n thinkingLevel,\n signal: runSignal,\n structured: run.structured,\n });\n if (signal?.aborted && agentResult.kind === 'success') return aborted();\n\n // 9. Error handling (full set from both harnesses)\n if (agentResult.kind === 'decided_failure') {\n return failed(agentResult.failure);\n }\n\n if (agentResult.kind === 'success') {\n // Success continues through the post-run hooks and outro below.\n } else if (agentResult.kind !== 'abort' && agentResult.kind !== 'failure') {\n const _exhaustive: never = agentResult;\n return _exhaustive;\n }\n\n if (agentResult.kind === 'abort') {\n const reason = agentResult.message ?? '';\n const matched = run.abortCases?.find((c) => c.match.test(reason));\n const abortCode = matched?.errorCode ?? ErrorCodes.AgentAbort;\n const outroData: OutroData = matched\n ? {\n kind: OutroKind.Error,\n message: matched.message,\n body: matched.body,\n docsUrl: matched.docsUrl,\n errorCode: abortCode,\n errorDetail: { reason },\n }\n : {\n kind: OutroKind.Error,\n message: `${run.integrationLabel} aborted`,\n body: reason || 'The agent aborted the program.',\n docsUrl: run.docsUrl,\n errorCode: abortCode,\n errorDetail: { reason },\n };\n analytics.wizardCapture('agent aborted', {\n integration: run.integrationLabel,\n reason,\n matched: matched?.message ?? null,\n });\n return {\n // An agent that stops itself failed the run; only the caller's signal cancels it.\n outcome: signal?.aborted ? RunOutcome.Aborted : RunOutcome.Failed,\n failure: {\n message: matched?.message ?? `${run.integrationLabel} aborted`,\n outroData,\n code: abortCode,\n error: agentResult.error,\n },\n };\n }\n\n const classification =\n agentResult.kind === 'failure' ? agentResult.classification : undefined;\n const failureMessage =\n agentResult.kind === 'failure' ? agentResult.message : undefined;\n\n if (classification === AgentErrorType.MCP_MISSING) {\n return failed({\n code: AGENT_ERROR_CODE[AgentErrorType.MCP_MISSING],\n message:\n 'Could not access the PostHog MCP server\\n\\n' +\n 'The wizard was unable to connect to the PostHog MCP server.\\n' +\n 'This could be due to a network issue or a configuration problem.\\n\\n' +\n `Please try again, or check the documentation:\\n${run.docsUrl}`,\n error: agentResult.kind === 'failure' ? agentResult.error : undefined,\n });\n }\n\n if (classification === AgentErrorType.RESOURCE_MISSING) {\n return failed({\n code: AGENT_ERROR_CODE[AgentErrorType.RESOURCE_MISSING],\n message:\n 'Could not access the setup resource\\n\\n' +\n 'This may indicate a version mismatch or a temporary service issue.\\n\\n' +\n `Please try again, or check the documentation:\\n${run.docsUrl}`,\n error: agentResult.kind === 'failure' ? agentResult.error : undefined,\n });\n }\n\n if (classification === AgentErrorType.YARA_VIOLATION) {\n return failed({\n code: AGENT_ERROR_CODE[AgentErrorType.YARA_VIOLATION],\n message: formatYaraAbortMessage(),\n error: agentResult.kind === 'failure' ? agentResult.error : undefined,\n });\n }\n\n if (classification === AgentErrorType.NO_PROGRESS) {\n analytics.wizardCapture('agent no progress', {\n integration: run.integrationLabel,\n error_type: AgentErrorType.NO_PROGRESS,\n });\n return failed({\n code: AGENT_ERROR_CODE[AgentErrorType.NO_PROGRESS],\n message:\n 'The Wizard exited without changing your project. Please contact the ' +\n 'PostHog team with wizard@posthog.com about this error.',\n error: agentResult.kind === 'failure' ? agentResult.error : undefined,\n });\n }\n\n if (classification === AgentErrorType.INCOMPLETE_TASKS) {\n analytics.wizardCapture('agent incomplete tasks', {\n integration: run.integrationLabel,\n error_type: AgentErrorType.INCOMPLETE_TASKS,\n });\n return failed({\n code: AGENT_ERROR_CODE[AgentErrorType.INCOMPLETE_TASKS],\n message:\n 'The Wizard exited without completing its planned tasks. Please contact ' +\n 'the PostHog team with wizard@posthog.com about this error.',\n error: agentResult.kind === 'failure' ? agentResult.error : undefined,\n });\n }\n\n if (\n classification === AgentErrorType.RATE_LIMIT ||\n classification === AgentErrorType.API_ERROR\n ) {\n analytics.wizardCapture('agent api error', {\n integration: run.integrationLabel,\n error_type: classification,\n error_message: failureMessage,\n });\n\n return failed({\n code: AGENT_ERROR_CODE[classification],\n message: `API Error\\n\\n${\n failureMessage || 'Unknown error'\n }\\n\\nPlease report this to: wizard@posthog.com`,\n error: agentResult.kind === 'failure' ? agentResult.error : undefined,\n });\n }\n\n if (agentResult.kind === 'failure') {\n return failed({\n code: AGENT_ERROR_CODE[agentResult.classification],\n message: agentResult.message ?? 'Agent failed',\n error: agentResult.error,\n });\n }\n\n if (run.structured) {\n return {\n outcome: RunOutcome.Success,\n structuredOutput: agentResult.structuredOutput,\n };\n }\n\n // 10. Post-run hooks\n if (config.hooks?.postRun) {\n await config.hooks.postRun(credentials);\n if (signal?.aborted) return aborted();\n }\n\n // A composed sub-run leaves the terminal outro to its host.\n if (composed) {\n return { outcome: RunOutcome.Success };\n }\n\n // 11. Outro\n const outroData: OutroData | undefined = config.hooks?.buildOutroData\n ? config.hooks.buildOutroData(credentials)\n : {\n kind: OutroKind.Success,\n message: run.successMessage,\n reportFile: run.reportFile,\n docsUrl: run.docsUrl,\n continueUrl: input.flags.signup\n ? `${host.appHost}/products?source=wizard`\n : undefined,\n };\n if (outroData) {\n emit({ kind: 'completion', outro: outroData });\n }\n\n emit({ kind: 'lifecycle', phase: 'completed', message: run.successMessage });\n\n return { outcome: RunOutcome.Success, outro: outroData };\n}\n","/**\n * Ring the terminal bell (BEL, U+0007).\n *\n * The orchestrator takes consent for the warehouse step at the top of the run\n * and asks for the credentials at the end of it, several autonomous minutes\n * later. The person who agreed is often looking at something else by then. A\n * bell is the one attention signal a terminal in a background tab can still\n * deliver, and it costs a user who is watching nothing.\n *\n * Written to stderr, not stdout: Ink owns stdout and repaints whole frames, so\n * a byte written there can land inside one. Silent when stderr is not a TTY —\n * a pipe or a CI log cannot ring, and the byte would only pollute the capture.\n */\nexport function ringTerminalBell(): void {\n if (!process.stderr.isTTY) return;\n try {\n process.stderr.write('\\u0007');\n } catch {\n // A bell is a nicety. It must never be the thing that ends a run.\n }\n}\n","/**\n * The executor drains the queue. It starts every runnable task (dependencies\n * satisfied) as soon as it becomes runnable — parallelism is decided by the\n * task graph, not by an executor knob. Each task runs through an injected\n * `runTask` function and reports its outcome via `complete_task`; a task that\n * ends without reporting is retried while attempts remain, then failed. A\n * `maxStarts` backstop guarantees termination.\n *\n * The drain loop is independent of how a task actually runs. `runTask` is\n * injected: the real one spins up a fresh agent, the tests use a fake.\n */\nimport { analytics } from '@utils/analytics';\nimport { RunOutcome, type AgentFailure } from '../../shared/types';\nimport { logToFile } from '@utils/debug';\nimport { TaskStatus, type QueueStore, type QueuedTask } from './queue';\n\n/** Per-task agent configuration the resolver produces from a task's type.\n * The model is resolved separately (per-harness profile), not here. */\nexport interface ResolvedTask {\n allowedTools: readonly string[];\n disallowedTools: readonly string[];\n /** Mini-skills to install before the task runs (the HOW). */\n skills: readonly string[];\n prompt: string;\n}\n\n/** Resolves a queued task to what the agent needs. The real one is markdown-backed. */\nexport type TaskResolver = (\n task: QueuedTask,\n store: QueueStore,\n) => ResolvedTask;\n\n/** Runs one task's agent. It is expected to drive the task to a terminal state\n * (via the task agent calling complete_task). */\nexport type RunTask = (task: QueuedTask) => Promise<void>;\n\n/**\n * Thrown by a `RunTask` when its harness returned a decided failure that ends\n * the whole run (a 401 the auth screen already reported), not just the task.\n * `drainQueue` lets it through so the sequence can return the failure where\n * the harness used to exit the process.\n */\nexport class RunTaskFatal extends Error {\n constructor(\n public readonly failure: AgentFailure,\n public readonly outcome:\n | RunOutcome.Aborted\n | RunOutcome.Failed = RunOutcome.Failed,\n /** The type of the task that ended the run, for the steps it stopped. */\n public readonly taskType?: string,\n ) {\n super(failure.message ?? 'agent run failed');\n this.name = 'RunTaskFatal';\n }\n}\n\nexport interface DrainOptions {\n /** Backstop against a pathological always-one-more-pending loop. */\n maxStarts: number;\n signal?: AbortSignal;\n onFatal?: () => void;\n}\n\nexport const DEFAULT_DRAIN_OPTIONS: DrainOptions = {\n maxStarts: 200,\n};\n\nasync function runOne(\n store: QueueStore,\n runTask: RunTask,\n task: QueuedTask,\n signal?: AbortSignal,\n): Promise<void> {\n if (signal?.aborted) return;\n store.start(task.id);\n try {\n await runTask(task);\n } catch (error) {\n if (signal?.aborted) return;\n if (error instanceof RunTaskFatal) throw error;\n // The task threw rather than reporting. The outcome check below handles\n // the queue; the exception itself should never be silent.\n logToFile(`[executor] runTask threw for ${task.type}:`, error);\n analytics.captureException(\n error instanceof Error ? error : new Error(String(error)),\n { step: 'orchestrator_run_task', task_type: task.type },\n );\n }\n\n if (signal?.aborted) return;\n\n const after = store.get(task.id);\n if (!after) return;\n\n if (after.status === TaskStatus.Running) {\n // The agent ended without calling complete_task. Retry or fail.\n if (after.attempts < after.maxAttempts) {\n store.requeue(task.id);\n } else {\n store.fail(task.id, {\n type: 'no-report',\n message: 'Task ended without calling complete_task.',\n });\n }\n return;\n }\n\n if (\n after.status === TaskStatus.Failed &&\n after.attempts < after.maxAttempts\n ) {\n store.requeue(task.id);\n }\n}\n\n/**\n * Drain the queue to a terminal state. Every runnable task starts the moment\n * its dependencies finish; independent branches run concurrently. Returns when\n * every task is done, failed, or blocked by a failed dependency, or when the\n * start backstop trips.\n */\nexport async function drainQueue(\n store: QueueStore,\n runTask: RunTask,\n opts: DrainOptions = DEFAULT_DRAIN_OPTIONS,\n): Promise<void> {\n const running = new Map<string, Promise<void>>();\n let starts = 0;\n let failure: { error: unknown } | undefined;\n\n try {\n for (;;) {\n if (opts.signal?.aborted) break;\n if (failure) throw failure.error;\n for (const task of store.nextRunnable()) {\n if (opts.signal?.aborted) break;\n if (++starts > opts.maxStarts) break;\n const p = runOne(store, runTask, task, opts.signal)\n .catch((error: unknown) => {\n if (!failure) {\n failure = { error };\n try {\n opts.onFatal?.();\n } catch (abortError) {\n try {\n logToFile(\n '[executor] fatal cancellation failed:',\n abortError,\n );\n } catch {\n // Reporting cancellation failure cannot replace the fatal.\n }\n }\n }\n })\n .finally(() => running.delete(task.id));\n running.set(task.id, p);\n }\n if (running.size === 0) break;\n await Promise.race(running.values());\n }\n } finally {\n // No queue or skill cleanup may run while a sibling still uses them.\n await Promise.allSettled(running.values());\n }\n if (failure) throw failure.error;\n}\n","/**\n * Responsiveness metrics for an orchestrator run.\n *\n * Responsiveness is the experiment's headline: how quickly the user sees the\n * first progress, and whether progress stays steady (no long silences). The math\n * is accumulated from queue transitions but kept here, pure and time-injected, so\n * it is unit-testable away from the runner. Wall-clock times are passed in as\n * milliseconds; the caller owns the clock.\n */\n\nexport interface RunMetricsSummary {\n /** Run start → first task started. */\n time_to_first_task_ms?: number;\n /** Run start → first task completed (the first visible \"done\"). */\n time_to_first_completion_ms?: number;\n /** Longest silence between two consecutive user-visible transitions. */\n max_gap_ms?: number;\n /**\n * Run start → the first question put to the user. The number that says whether\n * a task which waits on a person actually runs late: small means it interrupted\n * the autonomous work, large means it waited for it. `undefined` on a run that\n * asked nothing, which is most of them.\n */\n time_to_first_ask_ms?: number;\n}\n\n/** The per-event timing the `orchestrator task started` event reports. */\nexport interface StartTiming {\n ms_since_run_start: number;\n gap_since_prev_start_ms?: number;\n}\n\nexport class RunMetrics {\n private firstStartMs?: number;\n private lastStartMs?: number;\n private firstCompleteMs?: number;\n private firstAskMs?: number;\n private lastVisibleMs?: number;\n private maxGapMs = 0;\n\n constructor(private readonly runStartMs: number) {}\n\n /** A task started. Returns the per-start-event timing for the start event. */\n recordStart(nowMs: number): StartTiming {\n const timing: StartTiming = {\n ms_since_run_start: nowMs - this.runStartMs,\n gap_since_prev_start_ms:\n this.lastStartMs === undefined ? undefined : nowMs - this.lastStartMs,\n };\n this.firstStartMs ??= nowMs;\n this.lastStartMs = nowMs;\n this.markVisible(nowMs);\n return timing;\n }\n\n /** A task completed. */\n recordComplete(nowMs: number): void {\n this.firstCompleteMs ??= nowMs;\n this.markVisible(nowMs);\n }\n\n /** A task reached a terminal non-complete state the user sees (skip/fail). */\n recordTerminal(nowMs: number): void {\n this.markVisible(nowMs);\n }\n\n /**\n * A question was put to the user. Only the first matters here, and it is not a\n * queue transition — waiting on a person is not the silence `max_gap_ms`\n * measures, so this deliberately does not mark visible progress.\n */\n recordAsk(nowMs: number): void {\n this.firstAskMs ??= nowMs;\n }\n\n /**\n * The run-level responsiveness summary. Timings are `undefined` when the\n * relevant transition never happened (e.g. a run that started no task), so a\n * no-task run stays distinguishable from a genuine zero.\n */\n summary(): RunMetricsSummary {\n return {\n time_to_first_task_ms:\n this.firstStartMs === undefined\n ? undefined\n : this.firstStartMs - this.runStartMs,\n time_to_first_completion_ms:\n this.firstCompleteMs === undefined\n ? undefined\n : this.firstCompleteMs - this.runStartMs,\n max_gap_ms: this.lastVisibleMs === undefined ? undefined : this.maxGapMs,\n time_to_first_ask_ms:\n this.firstAskMs === undefined\n ? undefined\n : this.firstAskMs - this.runStartMs,\n };\n }\n\n /** requeue is not user-visible, so a retry stall counts as silence here. */\n private markVisible(nowMs: number): void {\n if (this.lastVisibleMs !== undefined) {\n this.maxGapMs = Math.max(this.maxGapMs, nowMs - this.lastVisibleMs);\n }\n this.lastVisibleMs = nowMs;\n }\n}\n","/**\n * Where a runner-seeded task sits in the planner's graph.\n *\n * A runner-seeded task is queued from what the wizard detected, before the\n * planner runs (see `ProgramConfig.seedTasks`). At that moment the tasks it\n * should wait for do not exist, so it cannot name them: it is enqueued with no\n * dependencies and is therefore runnable in the first drain tier, alongside the\n * first coding tasks. For a task that stops to ask the user for credentials that\n * is the wrong place — the questions land while the coding agents are still\n * mid-flight.\n *\n * This module answers \"what should it wait for?\" once the planner has seeded the\n * queue. The task's agent prompt names the types it follows (`dependsOn` in\n * frontmatter); a prompt that names none waits for everything that is not the\n * sink, which puts it last but still ahead of the reporting step.\n *\n * Pure and store-reading only — the runner applies what this returns, and the\n * queue enforces the DAG.\n */\nimport type { QueuedTask, QueueStore } from './queue';\nimport { dependencyClosure } from './queue-tools';\n\nexport interface SeededDepsResult {\n /** Ids the seeded task should be made to wait for. */\n depIds: string[];\n /**\n * Declared types with no task of that type in the queue — the planner chose\n * not to queue one. Not an error: the edge is simply dropped, and the task\n * still runs after whatever else was declared.\n */\n unresolvedTypes: string[];\n /** Whether the ids came from the prompt's declared types or from the default. */\n declared: boolean;\n}\n\n/**\n * Resolve a runner-seeded task's dependencies against the planned queue.\n *\n * Two exclusions apply to both the declared and the default path:\n *\n * - **Sinks are never dependencies.** A sink runs last and must depend on the\n * whole queue, this task included. Depending on it back would invert the edge\n * and cost the report this task's `reportSection`. Leaving sinks out means a\n * planner that forgot the sink→seeded edge is still caught by the sink\n * invariant check rather than silently papered over here.\n * - **Anything already downstream of this task is never a dependency**, which is\n * what makes the result cycle-free by construction rather than by the queue's\n * per-edge refusal.\n */\nexport function seededDependencies(\n store: QueueStore,\n seededTaskId: string,\n declaredTypes: readonly string[],\n sinkTypes: readonly string[],\n): SeededDepsResult {\n const eligible = store.list().filter((task) => {\n if (task.id === seededTaskId) return false;\n if (sinkTypes.includes(task.type)) return false;\n // Downstream of us already (the planner hung it off this task): depending on\n // it would close a loop.\n return !dependencyClosure(store, [task.id]).has(seededTaskId);\n });\n\n if (declaredTypes.length === 0) {\n return {\n depIds: eligible.map((t) => t.id),\n unresolvedTypes: [],\n declared: false,\n };\n }\n\n const depIds: string[] = [];\n const unresolvedTypes: string[] = [];\n for (const type of declaredTypes) {\n // Against the whole queue, not just `eligible` — a declared type that was\n // queued but is downstream of us was resolved, just not usable as an edge.\n // Only a type the planner never queued at all is unresolved.\n if (!store.list().some((t) => t.type === type)) {\n unresolvedTypes.push(type);\n continue;\n }\n for (const task of eligible) {\n // Every task of the type, so a fanned-out step (one `capture` per event)\n // is waited for in full rather than by its first task alone.\n if (task.type === type && !depIds.includes(task.id)) depIds.push(task.id);\n }\n }\n\n return { depIds, unresolvedTypes, declared: true };\n}\n\n/** What deferring one seeded task did, for the runner to log and report. */\nexport interface DeferredSeededTask {\n type: string;\n /** Types the prompt declared; empty when it fell back to the default. */\n declaredTypes: string[];\n declared: boolean;\n /** Edges actually added to the queue. */\n added: string[];\n /**\n * Edges the queue refused — a cycle or an unknown id. Always empty in a\n * healthy run: this resolver already excludes both, so anything here means the\n * two disagree and is worth a telemetry look.\n */\n refused: string[];\n unresolvedTypes: string[];\n}\n\n/**\n * Give every runner-seeded task the dependencies it could not name at enqueue,\n * and report what happened per task.\n *\n * The runner calls this once, after the planner has seeded the queue and before\n * the sink invariant is checked. Kept here rather than inline in the runner so\n * the wiring — which prompt's types feed which task — is testable without\n * standing up a whole run.\n */\nexport function deferSeededTasks(\n store: QueueStore,\n seededTasks: readonly QueuedTask[],\n declaredTypesFor: (type: string) => readonly string[],\n sinkTypes: readonly string[],\n): DeferredSeededTask[] {\n return seededTasks.map((seeded) => {\n const declaredTypes = [...declaredTypesFor(seeded.type)];\n const resolved = seededDependencies(\n store,\n seeded.id,\n declaredTypes,\n sinkTypes,\n );\n const { added, refused } = store.addDependencies(\n seeded.id,\n resolved.depIds,\n );\n return {\n type: seeded.type,\n declaredTypes,\n declared: resolved.declared,\n added,\n refused,\n unresolvedTypes: resolved.unresolvedTypes,\n };\n });\n}\n","/**\n * Experimental task-queue orchestrator runner.\n *\n * Branches from the linear runner when the `wizard-orchestrator` flag is on. An\n * orchestrator agent inspects the repo and seeds an in-memory task queue; an\n * executor drains it, running one fresh agent per task.\n *\n * Both the WHAT (agent prompts: model, goal, success criteria, tools) and the\n * HOW (mini-skills) are markdown served from context-mill — the seed and every\n * task resolve to a prompt fetched at startup into the registry. The wizard side\n * stays product-ignorant: it is the queue, the executor, and the loader.\n */\nimport { failed } from '../../shared/errors';\nimport { RunOutcome } from '../../shared/types';\nimport { randomUUID } from 'crypto';\nimport {\n cpSync,\n existsSync,\n mkdirSync,\n readdirSync,\n rmSync,\n writeFileSync,\n} from 'fs';\nimport * as path from 'path';\nimport { OutroKind } from '@shared/outro';\nimport type { AgentProgress, TaskNotice } from '../../../progress';\nimport {\n POSTHOG_DOCS_URL,\n WIZARD_CONTACT_EMAIL,\n WIZARD_OAUTH_SCOPES,\n WIZARD_PROVISIONING_SCOPES,\n} from '@shared/constants';\nimport { installSkillById } from '@shared/skill-install';\nimport {\n formatYaraAbortMessage,\n scanInstalledSkill,\n} from '../../../yara-hooks';\nimport { fetchSkillMenu, type SkillEntry } from '@shared/skill-menu';\nimport { analytics } from '@utils/analytics';\nimport { ciExcludedTaskTypes } from '@utils/ci-flag-overrides';\nimport { logToFile } from '@utils/debug';\nimport { ringTerminalBell } from '@utils/terminal-bell';\nimport { AGENT_ERROR_CODE } from '../../../error-map';\nimport { AgentErrorType } from '../../../agent-interface';\nimport {\n classifyRunFailure,\n type ErrorCode,\n ErrorCodes,\n WizardError,\n} from '@shared/errors';\nimport type { AgentResult } from '../../harness/types';\nimport type { AgentInteraction } from '../../../progress';\nimport type {\n AgentFailure,\n ResolvedRunConfig,\n SequenceResult,\n SequenceContext,\n} from '../../shared/types';\nimport { createEmitSpinner } from '../../shared/progress-collector';\nimport { createAskBridge } from '../../shared/ask';\nimport {\n areSeededTasksEnabled,\n getHarness,\n resolveHarness,\n resolveStageOverrides,\n type HarnessPick,\n} from '../../switchboard';\nimport { isValidModel, requireKnownModel } from '../../switchboard/models';\nimport type { AgentHarness } from '../../harness/types';\nimport {\n QueueStore,\n QUEUE_DIR_NAME,\n SkipReason,\n TaskStatus,\n type QueuedTask,\n type TaskOutcome,\n} from './queue';\nimport {\n DEFAULT_DRAIN_OPTIONS,\n drainQueue,\n RunTaskFatal,\n type RunTask,\n} from './executor';\nimport { RunMetrics } from './run-metrics';\nimport { dependencyClosure, uncoveredBySink } from './queue-tools';\nimport { deferSeededTasks } from './seeded-deps';\nimport { LONGER_ASK_TIMEOUT_MS, shouldDisableAsk } from '@shared/ask-policy';\nimport {\n agentRunTools,\n assembleSeedPrompt,\n assembleTaskPrompt,\n loadAgentRegistry,\n promptModelFor,\n resolveTask,\n taskModelSpec,\n ASK_TOOL,\n type AgentPrompt,\n type OrchestratorPromptContext,\n} from '../../../agent-prompt-loader';\n\n/** Docs page (`django.md`, `nuxt-js-3-6.md`) — steps start with a digit, agent artifacts (`SKILL.md`, `EXAMPLE*`, `COMMANDMENTS.md`) have uppercase. */\nconst isDocPage = (name: string): boolean =>\n name.endsWith('.md') && name === name.toLowerCase() && !/^\\d/.test(name);\n\n/** Copy only the framework docs pages out of the run cache into .claude/skills — the one durable artifact an orchestrator run leaves. Never clobbers an existing install. */\nexport function promoteReferenceSkill(\n referenceDir: string,\n claudeSkillsDir: string,\n referenceSkillId: string,\n): void {\n const target = path.join(claudeSkillsDir, referenceSkillId);\n const refs = path.join(referenceDir, 'references');\n if (!existsSync(refs) || existsSync(target)) return;\n const docs = readdirSync(refs).filter(isDocPage);\n if (docs.length === 0) return;\n mkdirSync(path.join(target, 'references'), { recursive: true });\n for (const f of docs) {\n cpSync(path.join(refs, f), path.join(target, 'references', f));\n }\n writeFileSync(path.join(target, '.posthog-wizard'), '');\n}\n\n/**\n * Remove skills that task agents installed durably mid-run (load_skill):\n * wizard-marked, new this run, and not the framework reference docs.\n * User-authored and pre-existing skills stay.\n */\nexport function sweepRunInstalledSkills(\n claudeSkillsDir: string,\n preexistingSkills: ReadonlySet<string>,\n referenceSkillId: string | undefined,\n): void {\n if (!existsSync(claudeSkillsDir)) return;\n for (const id of readdirSync(claudeSkillsDir)) {\n if (preexistingSkills.has(id) || id === referenceSkillId) continue;\n if (!existsSync(path.join(claudeSkillsDir, id, '.posthog-wizard'))) {\n continue;\n }\n rmSync(path.join(claudeSkillsDir, id), { recursive: true, force: true });\n logToFile(`[orchestrator] removed run-installed skill ${id}`);\n }\n}\n\nfunction toTodoStatus(status: TaskStatus): string {\n switch (status) {\n case TaskStatus.Running:\n return 'in_progress';\n case TaskStatus.Done:\n return 'completed';\n case TaskStatus.Failed:\n return 'failed';\n case TaskStatus.Skipped:\n return 'skipped';\n default:\n return 'pending';\n }\n}\n\n/**\n * Look up the harness impl for a resolved pick and enforce the `runTask`\n * capability. Pi trips this today with the honest impl-gap error instead of\n * silently downgrading to anthropic.\n */\nfunction requireTaskHarness(pick: HarnessPick): AgentHarness & {\n runTask: NonNullable<AgentHarness['runTask']>;\n} {\n const harness = getHarness(pick.harness);\n if (!harness.runTask) {\n throw new Error(\n `Harness \"${pick.harness}\" does not implement runTask; orchestrator mode requires it.`,\n );\n }\n return harness as AgentHarness & {\n runTask: NonNullable<AgentHarness['runTask']>;\n };\n}\n\n/** How an agent result ends the run, or undefined when it doesn't. */\nexport function terminalResult(\n result: AgentResult,\n): { outcome: RunOutcome.Failed; failure: AgentFailure } | undefined {\n switch (result.kind) {\n case 'success':\n return undefined;\n case 'decided_failure':\n return { outcome: RunOutcome.Failed, failure: result.failure };\n case 'abort':\n // Callers return first on the run's signal, so this abort is the agent's own.\n return {\n outcome: RunOutcome.Failed,\n failure: {\n code: AGENT_ERROR_CODE[result.classification],\n message: result.message ?? 'Agent aborted',\n error: result.error,\n },\n };\n case 'failure':\n return {\n outcome: RunOutcome.Failed,\n failure: {\n code: AGENT_ERROR_CODE[result.classification],\n // A security stop says so, as the linear sequence does.\n message:\n result.classification === AgentErrorType.YARA_VIOLATION\n ? formatYaraAbortMessage()\n : result.message ?? 'Agent failed',\n error: result.error,\n },\n };\n }\n}\n\nfunction cancelledRun(): SequenceResult {\n return {\n outcome: RunOutcome.Aborted,\n failure: { code: ErrorCodes.AgentAbort, message: 'Agent run cancelled' },\n };\n}\n\n/** Every skill entry the menu knows, across categories. */\nasync function fetchSkillMenuEntries(\n skillsBaseUrl: string,\n): Promise<SkillEntry[]> {\n const menu = await fetchSkillMenu(skillsBaseUrl);\n if (!menu) return [];\n return Object.values(menu.categories).flat();\n}\n\n/** Menu id for a bare skill id + framework via the menu's declared group/framework/default fields; undefined when nothing matches. */\nexport function resolveSkillVariantId(\n entries: readonly SkillEntry[],\n skillId: string,\n framework: string | undefined,\n): string | undefined {\n if (entries.some((e) => e.id === skillId)) return skillId;\n if (!framework) return undefined;\n const family = entries.filter(\n (e) => e.group === skillId && e.framework === framework,\n );\n return (family.find((e) => e.default) ?? family[0])?.id;\n}\n\n/**\n * The framework reference is the full `integration` skill. `input.skillId` is\n * the bare framework (e.g. `django`), but the skill menu ids it as\n * `integration-<variant>`.\n */\nfunction resolveReferenceSkillId(\n entries: readonly SkillEntry[],\n framework: string,\n): string | undefined {\n return resolveSkillVariantId(entries, 'integration', framework);\n}\n\n/**\n * How long an optional step's notice waits for an answer.\n *\n * Much shorter than LONGER_ASK_TIMEOUT_MS, because it is asking for something\n * much smaller: one keypress to accept or decline, not \"go mint a restricted\n * Stripe key\". It cannot be unbounded either — the notice is a modal, and a run\n * that stops forever behind one nobody is looking at is worse than one that\n * takes the safe answer and carries on.\n *\n * The offer is made at seed time, seconds into the run, so five minutes is a\n * generous allowance for a person who is by then still watching the wizard\n * start. It was not: from 2.63.0 to 2.65.0 the offer was made at the moment the\n * step became runnable — a median seven minutes in, after every coding task —\n * and this timeout became the answer for about a quarter of all runs.\n */\nexport const TASK_NOTICE_TIMEOUT_MS = 5 * 60 * 1000;\n\ninterface SeededTaskOptions {\n timeoutMs?: number;\n interaction?: AgentInteraction;\n signal?: AbortSignal;\n}\n\n/**\n * Offer an optional step, defaulting to declining it if nobody answers.\n *\n * Skip is the right default on a timeout: continuing would send the step on to\n * ask for credentials that the same absent user cannot supply either, burning\n * {@link LONGER_ASK_TIMEOUT_MS} per question before falling back to the same\n * links declining gives immediately.\n */\nexport async function offerSeededTask(\n notice: TaskNotice,\n {\n timeoutMs = TASK_NOTICE_TIMEOUT_MS,\n interaction,\n signal,\n }: SeededTaskOptions = {},\n): Promise<{ keep: boolean; timedOut: boolean }> {\n if (signal?.aborted) return { keep: false, timedOut: false };\n // No one to show the notice to: a step nobody can answer for must not run.\n // The same answer a non-interactive host gives today.\n if (!interaction?.taskNotice) return { keep: false, timedOut: false };\n const { taskNotice } = interaction;\n\n // This notice's own signal: its timeout or the run's cancellation aborts it.\n const controller = new AbortController();\n let timer: ReturnType<typeof setTimeout> | undefined;\n let timedOut = false;\n let cancelForAbort: (() => void) | undefined;\n const timeout = new Promise<boolean>((resolve) => {\n timer = setTimeout(() => {\n timedOut = true;\n // Settle first: a host that rejects once dismissed must not win.\n resolve(false);\n // The host dismisses this notice's overlay and settles its promise too,\n // so the losing side of the race cannot leave a modal on screen.\n controller.abort();\n }, timeoutMs);\n });\n const aborted = new Promise<boolean>((resolve) => {\n cancelForAbort = () => {\n resolve(false);\n controller.abort();\n };\n signal?.addEventListener('abort', cancelForAbort, { once: true });\n });\n try {\n const keep = await Promise.race([\n taskNotice(notice, { signal: controller.signal }),\n timeout,\n aborted,\n ]);\n return { keep, timedOut };\n } finally {\n if (timer) clearTimeout(timer);\n if (cancelForAbort) signal?.removeEventListener('abort', cancelForAbort);\n }\n}\n\n/**\n * Which runner-seeded task types finished successfully.\n *\n * Handed to the program's `buildOutroNextSteps` so it can drop a next step its\n * own seeded task already carried out. Only `Done` counts: a skipped, declined\n * or failed step left the work undone, and that is exactly when the outro\n * bullet pointing at the app is the one thing the user still needs.\n */\nexport function completedSeededTypes(\n store: QueueStore,\n seededTasks: readonly QueuedTask[],\n): string[] {\n return seededTasks\n .filter((task) => store.get(task.id)?.status === TaskStatus.Done)\n .map((task) => task.type);\n}\n\n/** One seeded task's answer to its notice, taken once, at seed time. */\nexport interface SeededConsent {\n keep: boolean;\n timedOut: boolean;\n /** The notice could not be shown at all. Read as a decline, never as a yes. */\n errored: boolean;\n}\n\n/** Which skip reason a negative {@link SeededConsent} carries onto the event. */\nexport function consentSkipReason(consent: SeededConsent): SkipReason {\n if (consent.errored) return SkipReason.NoticeError;\n return consent.timedOut ? SkipReason.NoticeTimeout : SkipReason.UserDeclined;\n}\n\n/**\n * Apply the seed-time answers to the queue, before the drain starts.\n *\n * A declined task is skipped rather than dropped, so the graph the planner saw\n * is the graph that ran — the sink already depends on this task, and\n * `nextRunnable` treats a skipped dependency as satisfied, so the report still\n * runs and can say the step was declined. The decline also stays in the funnel,\n * arriving as a `skipped` event carrying the reason that caused it rather than\n * as a task that silently never existed.\n *\n * It happens here rather than inside `runTask` because the executor marks a\n * task running — and fires `orchestrator task started` — before it hands the\n * task over. A decline applied on the far side of that emitted a start for a\n * task no agent ever ran, so every rate measured against starts counted the\n * declines twice: once in the denominator as a task that began, and again in\n * the numerator as a task that was skipped. Nothing upstream of the drain reads\n * task status, so applying the answers here changes only what the drain sees.\n *\n * Returns how many tasks were skipped, so the caller can redraw once.\n */\nexport function skipDeclinedSeededTasks(\n store: Pick<QueueStore, 'get' | 'skip'>,\n consentByTaskId: ReadonlyMap<string, SeededConsent>,\n labelFor: (task: { type: string; label?: string }) => string,\n): number {\n let skipped = 0;\n for (const [taskId, consent] of consentByTaskId) {\n if (consent.keep) continue;\n const task = store.get(taskId);\n if (!task) continue;\n const reason = consentSkipReason(consent);\n logToFile(`[orchestrator] runner-seeded ${task.type} skipped: ${reason}`);\n const declinedByUser = reason === SkipReason.UserDeclined;\n store.skip(taskId, reason, {\n goals: labelFor(task),\n did: declinedByUser\n ? 'Nothing — the user chose to skip this step when offered it.'\n : 'Nothing — the step was offered at the start of the run and never accepted.',\n forNextAgent: declinedByUser\n ? 'This step was offered and declined, so it did no work. Report it as skipped at the user’s request, not as failed.'\n : 'This step was offered and never accepted, so it did no work. Report it as not set up, and point the user at how to do it later.',\n });\n skipped += 1;\n }\n return skipped;\n}\n\n/**\n * Ask for one seeded task's consent, and record how the answer came about.\n *\n * Consent and execution are separate concerns, and this is the consent half.\n * It runs at seed time — seconds into the run, with the user still watching —\n * while `seeded-deps.ts` keeps the work itself at the end of the queue. Asking\n * at the moment of execution instead, as 2.63.0 did, put the question in front\n * of a user who had long since tabbed away.\n *\n * Fails closed. The step this gates goes on to ask for live database and API\n * credentials, so a question that could not be put to the user is never read as\n * a yes.\n */\nexport async function askSeededConsent(\n type: string,\n notice: TaskNotice,\n options: SeededTaskOptions = {},\n): Promise<SeededConsent> {\n const consent = await offerSeededTask(notice, options).then(\n (answer): SeededConsent => ({ ...answer, errored: false }),\n (err: unknown): SeededConsent => {\n logToFile(\n `[orchestrator] notice failed for ${type}, declining: ${String(err)}`,\n );\n analytics.captureException(\n err instanceof Error ? err : new Error(String(err)),\n { step: 'orchestrator_task_notice' },\n );\n return { keep: false, timedOut: false, errored: true };\n },\n );\n analytics.wizardCapture('orchestrator task notice answered', {\n type,\n kept: consent.keep,\n timed_out: consent.timedOut,\n errored: consent.errored,\n });\n return consent;\n}\n\n/** Whether a task's prompt lets it ask the user, and so needs the ask bridge. */\nfunction canAsk(prompt: AgentPrompt | undefined): boolean {\n return (prompt?.allowedTools ?? []).includes(ASK_TOOL);\n}\n\n/** Every task holds publish_handoff, but only the flow's sink owns the run report. */\nexport function deliversRunReport(\n sinkTypes: readonly string[],\n taskType: string,\n event: AgentProgress,\n): boolean {\n return event.kind === 'handoff' && sinkTypes.includes(taskType);\n}\n\n/**\n * Splits terminal failures into run-failing (required) and reported-only:\n * optional tasks, and required tasks that failed after they delivered the run\n * report to the user.\n */\nexport function drainVerdict(\n tasks: readonly QueuedTask[],\n reportDeliveredIds: ReadonlySet<string> = new Set(),\n): {\n requiredFailedTypes: string[];\n optionalFailedTypes: string[];\n deliveredFailedTypes: string[];\n blocked: number;\n blockedTypes: string[];\n} {\n const failed = tasks.filter((t) => t.status === TaskStatus.Failed);\n const pending = tasks.filter((t) => t.status === TaskStatus.Pending);\n const optional = (t: QueuedTask) => t.optional === true;\n const delivered = (t: QueuedTask) =>\n !optional(t) && reportDeliveredIds.has(t.id);\n return {\n requiredFailedTypes: failed\n .filter((t) => !optional(t) && !delivered(t))\n .map((t) => t.type),\n optionalFailedTypes: failed.filter(optional).map((t) => t.type),\n deliveredFailedTypes: failed.filter(delivered).map((t) => t.type),\n blocked: pending.length,\n blockedTypes: pending.map((t) => t.type),\n };\n}\n\n/** A drain where a required step failed, or where nothing failed but steps were blocked and never ran. */\nexport function drainFailureCode(verdict: {\n requiredFailedTypes: readonly string[];\n}): ErrorCode {\n return verdict.requiredFailedTypes.length > 0\n ? ErrorCodes.AgentOrchestratorTasksFailed\n : ErrorCodes.AgentOrchestratorTasksBlocked;\n}\n\n/**\n * The one-line \"what went wrong\" the abort message leads with.\n *\n * Both halves are named. A drain that ends with work still pending used to\n * report only how many steps never ran, which is the least useful fact about\n * them: a user who agreed to connect their data sources and then read that\n * \"2 steps never ran\" had no way to tell whether that step was one of them.\n */\nexport function describeDrainFailure(verdict: {\n requiredFailedTypes: string[];\n blockedTypes: string[];\n}): string {\n const parts: string[] = [];\n if (verdict.requiredFailedTypes.length > 0) {\n parts.push(`the ${verdict.requiredFailedTypes.join(', ')} step failed`);\n }\n if (verdict.blockedTypes.length > 0) {\n parts.push(\n `the ${verdict.blockedTypes.join(', ')} step${\n verdict.blockedTypes.length === 1 ? '' : 's'\n } never ran`,\n );\n }\n return parts.join(', so ');\n}\n\n/** One `orchestrator task blocked` event per pending task, best effort once the outcome is decided. */\nfunction reportBlockedTasks(\n tasks: readonly QueuedTask[],\n failedTypes: readonly string[],\n): void {\n for (const task of tasks) {\n if (task.status !== TaskStatus.Pending) continue;\n try {\n analytics.wizardCapture('orchestrator task blocked', {\n type: task.type,\n optional: task.optional === true,\n failed_types: failedTypes.join(',') || 'none',\n });\n } catch {\n // Reporting must not replace the run result.\n }\n }\n}\n\n/** How many tasks deep in the graph a task sits — 0 when it depends on nothing. */\nfunction graphDepth(\n task: QueuedTask,\n byId: ReadonlyMap<string, QueuedTask>,\n memo: Map<string, number>,\n): number {\n const cached = memo.get(task.id);\n if (cached !== undefined) return cached;\n memo.set(task.id, 0); // breaks a cycle rather than recursing forever\n const depth = task.dependsOn.reduce((deepest, id) => {\n const dep = byId.get(id);\n return dep ? Math.max(deepest, graphDepth(dep, byId, memo) + 1) : deepest;\n }, 0);\n memo.set(task.id, depth);\n return depth;\n}\n\n/**\n * The queue in the order the user should read it, which is not the order tasks\n * were queued. Tasks the wizard seeded before the planner ran are queued first\n * but are optional side quests, so they sit at the end of the tier they run in\n * — the list reads as the run unfolds, and the first line is work that actually\n * started. Ordering only; nothing here changes what runs when.\n */\nexport function displayOrder(\n tasks: readonly QueuedTask[],\n isOptional: (task: QueuedTask) => boolean,\n): QueuedTask[] {\n const byId = new Map(tasks.map((t) => [t.id, t]));\n const memo = new Map<string, number>();\n const rank = tasks.map((task, index) => ({\n task,\n depth: graphDepth(task, byId, memo),\n optional: isOptional(task) ? 1 : 0,\n index,\n }));\n return rank\n .sort(\n (a, b) =>\n a.depth - b.depth || a.optional - b.optional || a.index - b.index,\n )\n .map((entry) => entry.task);\n}\n\n/**\n * The run's excluded task types: CI gates plus the program's flag mapping.\n * Exported so a test can pin the flag→exclusion hookup against the real\n * program config — the registry and seed note both read this one list.\n */\nexport function effectiveExcludedTaskTypes(\n source: Pick<ResolvedRunConfig, 'excludedTaskTypes'>,\n flags: Record<string, string>,\n): string[] {\n return [\n ...ciExcludedTaskTypes(),\n ...(source.excludedTaskTypes?.(flags) ?? []),\n ];\n}\n\nexport async function runOrchestrator(\n context: SequenceContext,\n): Promise<SequenceResult> {\n const controller = new AbortController();\n let hostCancelled = false;\n const abortFromHost = () => {\n hostCancelled = true;\n controller.abort();\n };\n context.signal?.addEventListener('abort', abortFromHost, { once: true });\n if (context.signal?.aborted) abortFromHost();\n let cleaned = false;\n const cleanupQueue = (): void => {\n if (cleaned) return;\n cleaned = true;\n try {\n rmSync(path.join(context.input.installDir, QUEUE_DIR_NAME), {\n recursive: true,\n force: true,\n });\n } catch (error) {\n try {\n analytics.captureException(\n error instanceof Error ? error : new Error(String(error)),\n { step: 'orchestrator_cache_cleanup' },\n );\n } catch {\n // Cleanup reporting must not replace the run result.\n }\n }\n };\n try {\n return await executeOrchestrator(\n { ...context, signal: controller.signal },\n cleanupQueue,\n controller,\n () => hostCancelled,\n );\n } finally {\n context.signal?.removeEventListener('abort', abortFromHost);\n cleanupQueue();\n }\n}\n\nasync function executeOrchestrator(\n { config, input, boot, emit, interaction, signal }: SequenceContext,\n cleanupQueue: () => void,\n controller: AbortController,\n hostCancelled: () => boolean,\n): Promise<SequenceResult> {\n if (signal?.aborted) return cancelledRun();\n const runId = randomUUID();\n const { run } = config;\n const programId = config.programId;\n\n // Switchboard context — reused for every per-role harness resolution below.\n // The caller resolved the run-level binding from it; per-task roles overlay\n // `binding.contextMillOverride[role]` on the same inputs.\n const switchboardCtx = { ...config.switchboard, trace: undefined };\n\n // The WHAT (agent prompts) is served from context-mill. Fetch the registry\n // once up front: its types drive enqueue validation, and resolving a task to\n // its run config is then synchronous, with no mid-drain network latency.\n const flow = config.agentFlow ?? programId;\n const registry = await loadAgentRegistry(boot.skillsBaseUrl, flow, {\n exclude: effectiveExcludedTaskTypes(config, boot.wizardFlags),\n // Baked into the prompts at load, so enqueue, dispatch, and telemetry all read one effective spec.\n overrides: resolveStageOverrides(\n programId,\n boot.wizardFlags,\n boot.wizardFlagPayloads,\n ),\n });\n if (signal?.aborted) return cancelledRun();\n const seedPrompt = registry.seed;\n if (!seedPrompt) {\n throw new Error(\n `No seed agent prompt (frontmatter \\`seed: true\\`) for flow \"${flow}\" is available from ${boot.skillsBaseUrl}.`,\n );\n }\n\n // The end decision the switchboard event defers to: the model each task will actually run on.\n const taskModels = Object.fromEntries(\n ['seed', ...registry.types].map((type) => {\n const prompt = type === 'seed' ? seedPrompt : registry.get(type);\n const pick = resolveHarness(switchboardCtx, type);\n const specModel = prompt && promptModelFor(prompt, pick.harness).model;\n return [type, isValidModel(specModel) ? specModel : pick.model];\n }),\n );\n logToFile(\n `[orchestrator] task models: ${Object.entries(taskModels)\n .map(([t, m]) => `${t}=${m}`)\n .join(' ')}`,\n );\n analytics.wizardCapture('orchestrator task models', taskModels);\n\n // Responsiveness is the headline metric of the dark launch: time to first\n // visible progress, and no single step dominating wall-clock. Track it from\n // queue transitions, with the resolved model so cheap work is attributable\n // to cheap models.\n const runStartMs = Date.now();\n const metrics = new RunMetrics(runStartMs);\n const durationMs = (t: QueuedTask) =>\n t.startedAt && t.finishedAt\n ? Date.parse(t.finishedAt) - Date.parse(t.startedAt)\n : undefined;\n\n // Tasks that published the run report: any failure after that point leaves the user's report intact.\n const reportDeliveredIds = new Set<string>();\n\n const store = new QueueStore(input.installDir, runId, {\n onTransition: (event, task) => {\n const pick = resolveHarness(switchboardCtx, task.type);\n // Mirror dispatch's allow-list fallback so attribution names the model that runs.\n const specModel = taskModelSpec(registry, task, pick.harness).model;\n const base = {\n type: task.type,\n model: isValidModel(specModel) ? specModel : pick.model,\n attempts: task.attempts,\n // A failed optional task aborts nothing (see drainVerdict).\n optional: task.optional === true,\n };\n switch (event) {\n case 'enqueue':\n analytics.wizardCapture('orchestrator task enqueued', {\n type: task.type,\n enqueued_by: task.enqueuedBy,\n dynamic: task.enqueuedBy !== 'orchestrator',\n });\n break;\n case 'start':\n analytics.wizardCapture('orchestrator task started', {\n ...base,\n ...metrics.recordStart(Date.now()),\n });\n break;\n case 'complete':\n metrics.recordComplete(Date.now());\n analytics.wizardCapture('orchestrator task completed', {\n ...base,\n duration_ms: durationMs(task),\n });\n break;\n case 'skip':\n metrics.recordTerminal(Date.now());\n analytics.wizardCapture('orchestrator task skipped', {\n ...base,\n duration_ms: durationMs(task),\n // Additive: the event's name and every other property are unchanged,\n // so existing dashboards keep reading. Without this a step the user\n // declined, a step nobody answered for, and a step the agent found\n // did not apply were one number — which is how a regression that\n // halved the warehouse completion rate stayed invisible for a week.\n reason: task.skipReason,\n // Also additive, and only ever set alongside `agent-not-needed`:\n // that reason names the agent as the decider without saying what it\n // decided, so a step the user withheld a credential for counted as\n // a step that did not apply to the project.\n not_needed_reason: task.notNeededReason,\n });\n break;\n case 'fail':\n metrics.recordTerminal(Date.now());\n analytics.wizardCapture('orchestrator task failed', {\n ...base,\n duration_ms: durationMs(task),\n error: task.error?.type,\n report_delivered: reportDeliveredIds.has(task.id),\n });\n break;\n case 'requeue':\n break;\n }\n },\n });\n\n // Give task agents the framework's finished reference integration to match,\n // the same EXAMPLE.md the linear flow uses. Install it under the run dir rather\n // than .claude/skills so its \"do everything\" workflow is not auto-loaded as a\n // skill — only the example file is read, when the agent's prompt points at it.\n let examplePath: string | undefined;\n let commandmentsPath: string | undefined;\n let referenceInstallPath: string | undefined;\n const menuSkillEntries = await fetchSkillMenuEntries(boot.skillsBaseUrl);\n if (signal?.aborted) return cancelledRun();\n // The framework key for reference + variant resolution. `input.integration`\n // is the detected framework and always wins; `input.skillId` is the\n // fallback for the basic-integration path, where the caller sets it to the\n // framework label. Programs whose run config carries their own skill id\n // (agent-skill commands like replay-vision) would otherwise leak that id in\n // here as a bogus framework after the caller overwrites the detect result.\n const framework = input.integration ?? input.skillId ?? undefined;\n const referenceSkillId = framework\n ? resolveReferenceSkillId(menuSkillEntries, framework)\n : undefined;\n if (referenceSkillId) {\n const ref = await installSkillById(\n referenceSkillId,\n input.installDir,\n boot.skillsBaseUrl,\n {\n skillsRoot: path.join(QUEUE_DIR_NAME, 'reference'),\n scan: (dir) => scanInstalledSkill(dir, boot.triageProvider),\n },\n );\n if (signal?.aborted) return cancelledRun();\n if (ref.kind === 'ok') {\n referenceInstallPath = ref.path;\n const example = path.join(ref.path, 'references', 'EXAMPLE.md');\n if (existsSync(path.join(input.installDir, example))) {\n examplePath = example;\n }\n const commandments = path.join(ref.path, 'references', 'COMMANDMENTS.md');\n if (existsSync(path.join(input.installDir, commandments))) {\n commandmentsPath = commandments;\n }\n } else {\n logToFile(\n `[orchestrator] reference unavailable: ${ref.kind} (${referenceSkillId})`,\n );\n }\n } else if (framework) {\n logToFile(\n `[orchestrator] no integration skill for framework \"${framework}\"`,\n );\n }\n\n // Preflight every task's mini-skills: a miss would run tasks skill-less, so fail properly instead.\n const missingVariants: string[] = [];\n for (const type of registry.types) {\n for (const skillId of registry.get(type)?.skills ?? []) {\n if (resolveSkillVariantId(menuSkillEntries, skillId, framework)) {\n continue;\n }\n missingVariants.push(`${type}/${skillId}`);\n logToFile(\n `[orchestrator] no skill variant type=${type} skill=${skillId} framework=${\n framework ?? 'none'\n }`,\n );\n analytics.wizardCapture('orchestrator skill variant missing', {\n task_type: type,\n skill: skillId,\n framework,\n });\n }\n }\n if (missingVariants.length > 0) {\n // The framework's own docs page, resolved by the caller; generic docs when detection found none.\n const docsUrl = framework ? input.frameworkDocsUrl : undefined;\n return failed({\n code: ErrorCodes.AgentOrchestratorSkillVariantMissing,\n message:\n 'Setup instructions for this project failed to download.\\n' +\n 'Please try again, or contact wizard@posthog.com.\\n\\n' +\n 'You can also set up with your agent by downloading the skills here:\\n' +\n ' https://github.com/PostHog/context-mill/releases\\n' +\n 'or integrate manually here:\\n' +\n ` ${docsUrl ?? POSTHOG_DOCS_URL}`,\n error: new WizardError(\n 'Orchestrator preflight: skill variant missing',\n {\n missing: missingVariants.join(', '),\n framework,\n },\n ErrorCodes.AgentOrchestratorSkillVariantMissing,\n ),\n });\n }\n\n // The client injects the basics (project context + the I/O contract) around\n // every authored agent-prompt body.\n const promptContext: OrchestratorPromptContext = {\n projectId: boot.credentials.projectId,\n projectApiKey: boot.credentials.projectApiKey,\n host: boot.credentials.host,\n examplePath,\n commandmentsPath,\n };\n\n logToFile(\n `[orchestrator] START program=${programId} dir=${input.installDir} run=${runId}`,\n );\n analytics.wizardCapture('orchestrator started', {\n program_id: programId,\n });\n emit({ kind: 'lifecycle', phase: 'started' });\n\n // Label precedence: what the orchestrator set at enqueue, then the agent\n // prompt's default, then the bare type.\n const labelFor = (t: { type: string; label?: string }) =>\n t.label ?? registry.get(t.type)?.label ?? t.type;\n const renderQueue = () =>\n emit({\n kind: 'tasks',\n tasks: displayOrder(store.list(), (t) =>\n registry.runnerSeededTypes.includes(t.type),\n ).map((t) => ({\n id: `${runId}:${t.id}`,\n source: runId,\n content: labelFor(t),\n status: toTodoStatus(t.status),\n activeForm: labelFor(t),\n })),\n });\n\n // Each task's run binds the wizard-tools MCP server to a per-task\n // orchestrator context so complete_task / enqueue_task attribute correctly\n // when independent tasks run in parallel. The seed is not a task, so its\n // context has no task id.\n const orchestratorCtx = (currentTaskId?: string) => ({\n store,\n // The planner is offered only the types an agent may queue. A runner-seeded\n // type is not among them, so an attempt to queue one trips the unknown-type\n // guard instead of duplicating work the wizard already placed.\n validTypes: registry.enqueueableTypes,\n sinkTypes: registry.sinkTypes,\n // The edge to a runner-seeded task is one-way: the sink may wait for it,\n // nothing else may. Enforced at enqueue, because prose alone cannot hold it\n // — a single planner edge is enough to pull the task back to the front of\n // the drain and put its prompt in front of the code work again.\n runnerSeededTypes: registry.runnerSeededTypes,\n // Optionality comes from the task's frontmatter, never from the enqueue call.\n optionalTypes: registry.optionalTypes,\n currentTaskId,\n });\n\n // Tasks the wizard queues itself, from what detection found. They exist\n // before the planner runs, so the sink guard forces the reporting task to\n // depend on them, and no prompt has to remember they are there.\n // Kill switch: off (or unset), the wizard queues nothing itself and the run\n // is byte-identical to a project with no detected sources.\n const seedEntries = areSeededTasksEnabled(boot.wizardFlags)\n ? config.seedTasks?.() ?? []\n : [];\n const seededTypes: string[] = [];\n // Kept so their dependencies can be resolved once the planner has run — they\n // are queued before it, so they cannot name what they wait for yet.\n const seededTasks: QueuedTask[] = [];\n // Each seeded task's answer to its notice, taken here and applied later.\n //\n // Consent belongs at seed time: the user is at the keyboard, watching the run\n // start, and one keypress is all the question needs. The work does not — the\n // warehouse step asks for credentials, and those questions belong after the\n // autonomous coding, which is what `seeded-deps.ts` arranges. 2.63.0 collapsed\n // the two onto one modal at the moment of execution, a median seven minutes\n // in, by which time the user had gone; the five-minute timeout then answered\n // for them, and it answers \"skip\".\n //\n // The answer is recorded rather than acted on, so a declined task still enters\n // the queue as an ordinary pending task. The planner plans around it,\n // `deferSeededTasks` can still add its edges, and the sink invariant still\n // covers it — none of which is true of a task that was enqueued and skipped\n // before the planner ever ran. `runTask` applies the answer when the drain\n // reaches the task.\n const seededConsent = new Map<string, SeededConsent>();\n for (const seeded of seedEntries) {\n if (!registry.runnerSeededTypes.includes(seeded.type)) {\n logToFile(\n `[orchestrator] skipping runner-seeded task \"${seeded.type}\": not a runner-seeded type in this flow`,\n );\n continue;\n }\n const task = store.enqueue({\n type: seeded.type,\n label: seeded.label,\n inputs: seeded.inputs,\n enqueuedBy: 'orchestrator',\n // Terminal failure is reported per-task and never aborts the run.\n optional: true,\n });\n seededTypes.push(seeded.type);\n seededTasks.push(task);\n if (seeded.notice) {\n // Awaited inside the loop, so at most one notice is ever on screen. The\n // store holds a single pending-notice slot: a second `showTaskNotice`\n // overwrites the first's resolver, the first promise never settles, and\n // its task hangs for the rest of the run. A serial loop makes that\n // unreachable; the drain, which starts every runnable task at once, does\n // not, which is why the offer lives here and not there.\n seededConsent.set(\n task.id,\n await askSeededConsent(seeded.type, seeded.notice, {\n interaction,\n signal,\n }),\n );\n if (signal?.aborted) return cancelledRun();\n }\n logToFile(`[orchestrator] runner-seeded task ${seeded.type}`);\n }\n\n // A run that stops to ask a person is not comparable with one that does not\n // — its wall-clock is the user's, not the model's. Tag every event of the run\n // from here on, so those runs filter out cleanly.\n //\n // A declined step asks nothing, and the answer is known by now, so it leaves\n // the tag alone. While the offer was made mid-drain this was unknowable here,\n // and roughly a quarter of runs were tagged as waiting on a user who had in\n // fact already been auto-declined out of the only step that asks.\n const askingTypes = seededTasks\n .filter((task) => seededConsent.get(task.id)?.keep !== false)\n .map((task) => task.type)\n .filter((type) => canAsk(registry.get(type)));\n analytics.setTag('orchestrator_awaits_user', askingTypes.length > 0);\n analytics.setTag(\n 'orchestrator_runner_seeded_types',\n seededTypes.join(',') || 'none',\n );\n if (askingTypes.length > 0) {\n analytics.wizardCapture('orchestrator awaits user', {\n task_types: askingTypes,\n ask_timeout_ms: LONGER_ASK_TIMEOUT_MS,\n });\n }\n\n // One bridge for the run, handed only to a task whose prompt allows asking.\n // Absent in CI and signup, where nobody can answer.\n const askBridge = shouldDisableAsk(input.flags)\n ? undefined\n : createAskBridge(interaction, {\n signal,\n getSource: () => input.skillId ?? programId,\n beforeShow: () => {\n // How late the first ask lands is the measure of this run shape: it\n // should follow the autonomous work, not interrupt it.\n metrics.recordAsk(Date.now());\n // Consent is taken in the first seconds of the run and these questions\n // arrive at the end of it, so the user who agreed may well be looking\n // at another window by now. Nothing here waits on the bell — an\n // unanswered ask still times out into the deep-link fallback — it just\n // gives a person who stepped away a chance to come back first.\n ringTerminalBell();\n },\n richLinks: run.richLinks ?? false,\n // A task ask waits on a person, and the drain waits it out — the\n // executor holds the task's promise — so this is the only real limit.\n timeoutMs: LONGER_ASK_TIMEOUT_MS,\n });\n\n const spinner = createEmitSpinner(emit);\n\n // 1. Seed the queue with the orchestrator agent. It is itself an agent prompt\n // (the WHAT), so its model and tools come from its frontmatter. The seed\n // plans the graph, it is not a task.\n //\n // Prompt-frontmatter model wins over the switchboard pick (§3.6 of the\n // switchboard plan) — the switchboard's model is the fallback when the\n // prompt is silent.\n const seedPick = resolveHarness(switchboardCtx, 'seed');\n const seedHarness = requireTaskHarness(seedPick);\n const seedModel = promptModelFor(seedPrompt, seedPick.harness);\n const seedResult = await seedHarness.runTask({\n signal,\n config,\n input,\n boot,\n emit,\n // The exclusion note names `registry.excludedTypes` — the excluded types\n // this flow actually had — so the planner never hears about work that was\n // never available, and overlapping exclusion sources cannot double-list.\n prompt: assembleSeedPrompt(\n promptContext,\n seedPrompt.body,\n store.list(),\n registry.excludedTypes,\n ),\n spinner,\n model: requireKnownModel(seedModel.model, seedPick.model),\n effort: seedModel.effort,\n ...agentRunTools(seedPrompt),\n orchestrator: orchestratorCtx(),\n spinnerMessage: 'Planning the integration...',\n successMessage: 'Planned the integration',\n requestRemark: false,\n analyticsProperties: { task_type: 'seed', harness: seedPick.harness },\n });\n if (signal?.aborted) return cancelledRun();\n const seedTerminal = terminalResult(seedResult);\n if (seedTerminal) return seedTerminal;\n analytics.wizardCapture('orchestrator seeded', {\n task_count: store.list().length,\n types: store.list().map((t) => t.type),\n });\n renderQueue();\n\n // Now that the graph exists, give each runner-seeded task the dependencies it\n // could not name when it was queued. Without this it sits at depth 0 and runs\n // in the first tier — which for the warehouse step means its credential\n // prompts arrive while the coding tasks are still writing files. Deferred, the\n // one step that waits on a person waits until the autonomous work is done.\n //\n // Before the sink check below on purpose: sinks are never added as\n // dependencies, so a planner that forgot to make its sink wait for a seeded\n // task is still caught there rather than masked here.\n const deferred = deferSeededTasks(\n store,\n seededTasks,\n (type) => registry.get(type)?.dependsOn ?? [],\n registry.sinkTypes,\n );\n for (const entry of deferred) {\n logToFile(\n `[orchestrator] deferred runner-seeded ${entry.type}: ` +\n `${entry.added.length} deps (${\n entry.declared\n ? `declared: ${entry.declaredTypes.join(', ')}`\n : 'default'\n })${\n entry.refused.length > 0 ? `, ${entry.refused.length} refused` : ''\n }${\n entry.unresolvedTypes.length > 0\n ? `, unresolved: ${entry.unresolvedTypes.join(', ')}`\n : ''\n }`,\n );\n analytics.wizardCapture('orchestrator seeded task deferred', {\n type: entry.type,\n dep_count: entry.added.length,\n declared: entry.declared,\n declared_types: entry.declaredTypes,\n unresolved_types: entry.unresolvedTypes,\n // Non-empty means a cycle or an unknown id was rejected — the resolver and\n // the queue disagreeing, never expected in a good run.\n refused_count: entry.refused.length,\n });\n }\n if (deferred.length > 0) renderQueue();\n\n // Canary for the one-way rule. The enqueue guard rejects the edge outright, so\n // this should never fire — but if it ever does, the seeded task has been\n // pulled back toward the front of the drain and its prompt lands mid-run\n // again, which is precisely the failure this whole step exists to prevent.\n // Silent regressions here would look like \"the ordering just stopped\n // working\", so make it visible rather than abort a run that is otherwise fine.\n for (const seeded of seededTasks) {\n const dependants = store\n .list()\n .filter(\n (t) =>\n !registry.sinkTypes.includes(t.type) &&\n t.id !== seeded.id &&\n dependencyClosure(store, [t.id]).has(seeded.id),\n );\n if (dependants.length === 0) continue;\n logToFile(\n `[orchestrator] one-way rule broken: ${dependants\n .map((t) => t.type)\n .join(', ')} depend on runner-seeded ${seeded.type}`,\n );\n analytics.wizardCapture('orchestrator seeded task depended on', {\n type: seeded.type,\n dependant_types: dependants.map((t) => t.type),\n });\n }\n\n // The enqueue guard rejects a sink that misses part of the queue, so a\n // planner that respected its errors cannot get here with a broken graph.\n // Check it again anyway: a run whose report never sees a task's handoff is\n // worse than a run that stops and says so.\n const unwaited = store\n .list()\n .filter((t) => registry.sinkTypes.includes(t.type))\n .flatMap((sink) =>\n uncoveredBySink(\n { store, validTypes: registry.types, sinkTypes: registry.sinkTypes },\n { type: sink.type, dependsOn: sink.dependsOn },\n ).filter((t) => t.id !== sink.id),\n );\n if (unwaited.length > 0) {\n analytics.wizardCapture('orchestrator sink invariant violated', {\n uncovered_types: unwaited.map((t) => t.type),\n });\n return failed({\n code: ErrorCodes.AgentOrchestratorSinkInvariant,\n message: `The wizard could not plan this setup: the final step would have skipped ${unwaited\n .map((t) => t.type)\n .join(', ')}.\\n\\nPlease report this to: ${WIZARD_CONTACT_EMAIL}`,\n error: new WizardError(\n 'orchestrator sink does not cover the queue',\n {\n uncovered: unwaited.map((t) => `${t.type} (${t.id})`).join(', '),\n queue_state: JSON.stringify(store.list()),\n },\n ErrorCodes.AgentOrchestratorSinkInvariant,\n ),\n });\n }\n\n // 2. Drain the queue, one fresh agent per task; independent tasks run in\n // parallel, the seed's graph being the only schedule. Each task resolves to\n // its agent prompt (the WHAT) and the mini-skills it needs (the HOW), then\n // runs on its own model and tools.\n const taskSkillsRoot = path.join(QUEUE_DIR_NAME, 'skills');\n // Task agents can install durable skills mid-run (load_skill), and only the\n // framework reference docs earn a place — snapshot what was already there so\n // the sweeps remove exactly what this run added.\n const claudeSkillsDir = path.join(input.installDir, '.claude', 'skills');\n const preexistingSkills = new Set(\n existsSync(claudeSkillsDir) ? readdirSync(claudeSkillsDir) : [],\n );\n const runTask: RunTask = async (task) => {\n if (signal?.aborted) return;\n renderQueue();\n\n try {\n const resolved = resolveTask(registry, task, store);\n // Task instructions are one-run scaffolding, not durable skills, so they\n // install under the run dir rather than .claude/skills — the SDK must not\n // auto-load them and they must never land in the project (or a CI PR).\n // The prompt points the agent at them instead.\n const skillPaths: string[] = [];\n for (const skillId of resolved.skills) {\n if (signal?.aborted) return;\n // Agent prompts name the bare step-skill (`integration-v2-install`);\n // SDK-divergent steps ship per-framework variants, so resolve against\n // the menu with the session's framework before installing.\n const variantId = resolveSkillVariantId(\n menuSkillEntries,\n skillId,\n framework,\n );\n if (!variantId) {\n logToFile(\n `[orchestrator] no skill variant type=${\n task.type\n } skill=${skillId} framework=${framework ?? 'none'}`,\n );\n continue;\n }\n const result = await installSkillById(\n variantId,\n input.installDir,\n boot.skillsBaseUrl,\n {\n skillsRoot: taskSkillsRoot,\n scan: (dir) => scanInstalledSkill(dir, boot.triageProvider),\n },\n );\n if (signal?.aborted) return;\n if (result.kind === 'ok') {\n skillPaths.push(path.join(result.path, 'SKILL.md'));\n } else {\n logToFile(\n `[orchestrator] skill install failed type=${task.type} skill=${variantId} ${result.kind}`,\n );\n // A task without its instructions must fail here, not run blind:\n // run 91cf40eb's report task started after two EACCES install\n // failures (unwritable external-volume cache) and died silently.\n // The executor catches this, captures the exception, and fails the\n // task through the normal outcome check.\n throw new Error(\n `Skill \"${variantId}\" for task \"${task.type}\" could not be installed (${result.kind}). ` +\n 'If this is a permissions error, check that the project directory is writable.',\n );\n }\n }\n // Empty spinner messages suppress the per-task spinner line (the queue\n // panel shows progress); errors still surface — the harness stops the\n // spinner with its own error text.\n //\n // Per-task role = task.type — the switchboard consults the program\n // binding's contextMillOverride?.[task.type] for wizard-side per-agent\n // overrides. Prompt-frontmatter model still wins (§3.6).\n const taskPick = resolveHarness(switchboardCtx, task.type);\n const taskHarness = requireTaskHarness(taskPick);\n const taskModel = taskModelSpec(registry, task, taskPick.harness);\n let taskResult: AgentResult;\n try {\n taskResult = await taskHarness.runTask({\n signal,\n config,\n input,\n boot,\n emit: (event) => {\n if (deliversRunReport(registry.sinkTypes, task.type, event)) {\n reportDeliveredIds.add(task.id);\n }\n emit(event);\n },\n prompt: assembleTaskPrompt(\n promptContext,\n resolved.prompt,\n skillPaths,\n ),\n spinner,\n model: requireKnownModel(taskModel.model, taskPick.model),\n effort: taskModel.effort,\n allowedTools: resolved.allowedTools,\n disallowedTools: resolved.disallowedTools,\n askBridge: canAsk(registry.get(task.type)) ? askBridge : undefined,\n orchestrator: orchestratorCtx(task.id),\n spinnerMessage: '',\n successMessage: '',\n requestRemark: false,\n analyticsProperties: {\n task_type: task.type,\n task_id: task.id,\n harness: taskPick.harness,\n },\n });\n } catch (error) {\n if (signal?.aborted) return;\n if (error instanceof RunTaskFatal) throw error;\n const failure = classifyRunFailure(error);\n throw new RunTaskFatal(\n {\n code: failure.code,\n message: failure.message,\n error: error instanceof Error ? error : undefined,\n },\n RunOutcome.Failed,\n task.type,\n );\n }\n if (signal?.aborted) return;\n const terminal = terminalResult(taskResult);\n if (terminal)\n throw new RunTaskFatal(terminal.failure, terminal.outcome, task.type);\n } finally {\n // Durable skills a task installed are irrelevant to later tasks — and\n // the sdk harness auto-loads .claude/skills into every agent — so sweep\n // as each task ends, not only at run end.\n try {\n sweepRunInstalledSkills(\n claudeSkillsDir,\n preexistingSkills,\n referenceSkillId,\n );\n } catch (err) {\n try {\n logToFile('[orchestrator] per-task skill sweep failed:', err);\n } catch {\n // Cleanup logging must not replace the task result.\n }\n }\n try {\n renderQueue();\n } catch (err) {\n try {\n logToFile('[orchestrator] per-task queue render failed:', err);\n } catch {\n // Cleanup logging must not replace the task result.\n }\n }\n }\n };\n // A task that stops for the user is offered, not imposed, and the answer was\n // taken at seed time. Apply it before the drain begins, so the drain only\n // ever starts tasks that are going to run.\n if (skipDeclinedSeededTasks(store, seededConsent, labelFor) > 0) {\n renderQueue();\n }\n\n let fatal: RunTaskFatal | undefined;\n // A fatal from the sink after it published the report, settled as a failed task.\n let deliveredFatal = false;\n try {\n await drainQueue(store, runTask, {\n ...DEFAULT_DRAIN_OPTIONS,\n signal,\n onFatal: () => controller.abort(),\n });\n } catch (error) {\n if (!(error instanceof RunTaskFatal)) throw error;\n fatal = error;\n // The fatal task is still Running in the store; the sink that already\n // published the report ends Failed, as if it had failed on its own.\n const running = store.list().filter((t) => t.status === TaskStatus.Running);\n const sink = running.find(\n (t) => t.type === fatal?.taskType && reportDeliveredIds.has(t.id),\n );\n if (!hostCancelled() && sink && running.length === 1) {\n const verdict = drainVerdict(store.list(), reportDeliveredIds);\n if (verdict.requiredFailedTypes.length === 0 && verdict.blocked === 0) {\n store.fail(sink.id, {\n type: 'fatal-after-report',\n message: fatal.message,\n });\n deliveredFatal = true;\n fatal = undefined;\n }\n }\n } finally {\n // The queue file is wiped below; the e2e harness reads outcomes from here.\n config.hooks?.recordTaskOutcomes?.(\n store.list().map((t) => ({\n type: t.type,\n status: t.status,\n optional: t.optional === true,\n })) satisfies TaskOutcome[],\n );\n try {\n if (\n (!signal?.aborted || deliveredFatal) &&\n referenceSkillId &&\n referenceInstallPath\n ) {\n promoteReferenceSkill(\n path.join(input.installDir, referenceInstallPath),\n claudeSkillsDir,\n referenceSkillId,\n );\n }\n } catch (err) {\n try {\n analytics.captureException(\n err instanceof Error ? err : new Error(String(err)),\n { step: 'orchestrator_reference_promote' },\n );\n } catch {\n // Cleanup reporting must not replace the run result.\n }\n }\n cleanupQueue();\n try {\n sweepRunInstalledSkills(\n claudeSkillsDir,\n preexistingSkills,\n referenceSkillId,\n );\n } catch (err) {\n try {\n analytics.captureException(\n err instanceof Error ? err : new Error(String(err)),\n { step: 'orchestrator_skill_sweep' },\n );\n } catch {\n // Cleanup reporting must not replace the run result.\n }\n }\n }\n\n if (hostCancelled()) return cancelledRun();\n if (fatal) {\n // The steps the fatal task stopped still get their terminal event.\n const stoppedBy = drainVerdict(\n store.list(),\n reportDeliveredIds,\n ).requiredFailedTypes;\n if (fatal.taskType && !stoppedBy.includes(fatal.taskType)) {\n stoppedBy.push(fatal.taskType);\n }\n reportBlockedTasks(store.list(), stoppedBy);\n return { outcome: fatal.outcome, failure: fatal.failure };\n }\n if (signal?.aborted && !deliveredFatal) return cancelledRun();\n\n renderQueue();\n\n const summary = store.summary();\n logToFile(\n `[orchestrator] DONE done=${summary.done} failed=${summary.failed} total=${summary.total}`,\n );\n\n analytics.wizardCapture('orchestrator run finished', {\n tasks_total: summary.total,\n tasks_done: summary.done,\n tasks_failed: summary.failed,\n tasks_skipped: summary[TaskStatus.Skipped],\n total_duration_ms: Date.now() - runStartMs,\n ...metrics.summary(),\n dynamic_enqueue_count: store\n .list()\n .filter((t) => t.enqueuedBy !== 'orchestrator').length,\n retried_task_count: store.list().filter((t) => t.attempts > 1).length,\n });\n\n // The review step flags any unresolved conflict in its handoff; surface the\n // one-liner here and point the user at the report for the detail.\n const reviewTask = store.list().find((t) => t.type === 'review');\n const conflict = reviewTask\n ? store.readHandoff(reviewTask.id)?.conflict\n : undefined;\n\n // Not-needed tasks were never work, so they leave the denominator too.\n const notRequired = summary[TaskStatus.Skipped];\n\n // A drain that ends with failed tasks (retries exhausted) or tasks still\n // pending (blocked behind a failed dependency) did NOT set PostHog up —\n // abort like a linear agent failure instead of claiming success.\n // A failed optional task is exempt: reported per-task, never run-failing.\n const verdict = drainVerdict(store.list(), reportDeliveredIds);\n const blocked = verdict.blocked;\n // A pending task at this point never ran and never will — its dependency\n // failed. No transition fires for it, so without this the step leaves no\n // terminal event at all: a step the user was offered and accepted simply\n // drops out of the funnel. The queue itself is left alone, because the run\n // cache is already wiped by here and writing to it would recreate the folder\n // the cleanup just removed.\n reportBlockedTasks(store.list(), verdict.requiredFailedTypes);\n if (verdict.requiredFailedTypes.length > 0 || blocked > 0) {\n const failedTypes = verdict.requiredFailedTypes.join(', ');\n const whatFailed = describeDrainFailure(verdict);\n // A grant narrowed at login is the one failure cause the user can fix\n // alone — lead with the fix, and only fall back to the report-a-bug line\n // when trying again doesn't work.\n const missingScopes = (boot.credentials.missingScopes ?? []).filter(\n (scope) =>\n WIZARD_PROVISIONING_SCOPES.some((required) => required === scope) ||\n !WIZARD_OAUTH_SCOPES.some((requested) => requested === scope),\n );\n const message =\n missingScopes.length > 0\n ? `The wizard could not finish setup: ${whatFailed}, and this run was authorized without the following permission${\n missingScopes.length === 1 ? '' : 's'\n }: ${missingScopes.join(\n ', ',\n )}.\\n\\nPlease try again, approving all permissions on the PostHog authorization screen. If it still fails, report it to: ${WIZARD_CONTACT_EMAIL}`\n : `The wizard was unable to set up PostHog: ${whatFailed}.\\n\\nPlease report this to: ${WIZARD_CONTACT_EMAIL}`;\n const code = drainFailureCode(verdict);\n return failed({\n code,\n message,\n error: new WizardError(\n code === ErrorCodes.AgentOrchestratorTasksFailed\n ? 'orchestrator drain ended with failed tasks'\n : 'orchestrator drain ended with blocked tasks',\n {\n tasks_failed: summary.failed,\n tasks_blocked: blocked,\n failed_types: failedTypes,\n missing_oauth_scopes: missingScopes.join(' '),\n queue_state: JSON.stringify(store.list()),\n },\n code,\n ),\n });\n }\n\n // A drain that produced no tasks at all means the seed step never got a\n // usable model response (e.g. the gateway returned empty completions).\n // \"0/0 completed\" is a dead run, not a success with an empty denominator.\n if (summary.total === 0) {\n return failed({\n code: ErrorCodes.AgentOrchestratorHollowRun,\n message: `The wizard was unable to set up PostHog: the planning step produced no work, so nothing ran.\\n\\nPlease try again — and if it happens again, report it to: ${WIZARD_CONTACT_EMAIL}`,\n error: new WizardError(\n 'orchestrator drain produced zero tasks',\n { queue_state: JSON.stringify(store.list()) },\n ErrorCodes.AgentOrchestratorHollowRun,\n ),\n });\n }\n\n // A failed optional step leaves the denominator and is named instead.\n const optionalFailedCount = verdict.optionalFailedTypes.length;\n const stepNotes = [\n notRequired > 0 ? `${notRequired} skipped as not required` : '',\n optionalFailedCount > 0\n ? `${optionalFailedCount} optional step failed`\n : '',\n // The report step still counts as a step: it stays in the denominator.\n verdict.deliveredFailedTypes.length > 0\n ? 'report delivered, then its step failed'\n : '',\n ].filter(Boolean);\n const message = conflict\n ? 'PostHog set up, with one conflict to review.'\n : `PostHog set up: ${summary.done}/${\n summary.total - notRequired - optionalFailedCount\n } steps completed${\n stepNotes.length > 0 ? ` (${stepNotes.join(', ')})` : ''\n }.`;\n const outro = {\n kind: OutroKind.Success,\n message,\n body: conflict\n ? `⚠ Build conflict: ${conflict}\\nFull details are in the setup report.`\n : undefined,\n docsUrl: 'https://posthog.com/docs/ai-engineering/ai-wizard',\n nextSteps: config.hooks?.buildOutroNextSteps?.(\n boot.credentials,\n completedSeededTypes(store, seededTasks),\n ),\n };\n emit({ kind: 'completion', outro });\n emit({ kind: 'lifecycle', phase: 'completed', message });\n return { outcome: RunOutcome.Success, outro };\n}\n","/**\n * Sequence axis: gate helpers, registry, middleware, resolver.\n * Percentage rollouts are PostHog-side — the gate just reads the resolved bool.\n */\n\nimport { IS_PRODUCTION_BUILD } from '@env';\nimport { Sequence } from '@shared/constants';\nimport { logToFile } from '@utils/debug';\nimport {\n isOrchestratorEnabled,\n resolveFlagRoute,\n resolveFlagSequence,\n} from './flags';\nimport { getHarness, resolveHarness } from './harness';\nimport type { SequenceResult, SequenceContext } from '../shared/types';\nimport { runLinearProgram } from '../sequence/linear';\nimport { runOrchestrator } from '../sequence/orchestrator/orchestrator-runner';\nimport { runChain, type Middleware, type SwitchboardCtx } from '.';\n\n// ── Registry ────────────────────────────────────────────────────────────\n\nexport interface SequenceRunner {\n readonly name: Sequence;\n /** Run one program to a decided result. Unexpected errors propagate. */\n run(ctx: SequenceContext): Promise<SequenceResult>;\n}\n\nexport const SEQUENCE_OPTIONS: Partial<Record<Sequence, SequenceRunner>> = {\n [Sequence.linear]: {\n name: Sequence.linear,\n run: (ctx) => runLinearProgram(ctx),\n },\n [Sequence.orchestrator]: {\n name: Sequence.orchestrator,\n run: (ctx) => runOrchestrator(ctx),\n },\n};\n\nexport function getSequence(name: Sequence): SequenceRunner {\n const sequence = SEQUENCE_OPTIONS[name];\n if (!sequence) {\n throw new Error(`No sequence registered for '${name}'.`);\n }\n return sequence;\n}\n\n// ── Middleware + resolver ───────────────────────────────────────────────\n\n/**\n * A composed sub-run (integration inside self-driving) is structurally\n * linear: the orchestrator owns the full run lifecycle (queue, outro) and\n * cannot nest. Sits above every override, including CLI.\n */\nconst composedClampMw: Middleware<Sequence> = (ctx, next) => {\n if (!ctx.composed) return next();\n if (ctx.trace) ctx.trace.sequence = 'composed';\n return Sequence.linear;\n};\n\n/** `--sequence` override. Dev/test only — the option is gated out of published builds. */\nconst cliSequenceMw: Middleware<Sequence> = (ctx, next) => {\n if (!ctx.cliSequence) return next();\n if (ctx.trace) ctx.trace.sequence = 'cli';\n return ctx.cliSequence;\n};\n\n/** A program's own flag route may pin the sequence; wins over the global orchestrator flag. Traced as 'payload' to stay distinguishable from sequence experiments ('flag'). */\nconst flagRouteSequenceMw: Middleware<Sequence> = (ctx, next) => {\n const route = resolveFlagRoute(ctx.program, ctx.flags, ctx.flagPayloads);\n if (!route?.sequence) return next();\n if (ctx.trace) ctx.trace.sequence = 'payload';\n return route.sequence;\n};\n\n/** Sequence experiments (e.g. wizard-orchestrator), each inert outside its declared programs. */\nconst sequenceExperimentMw: Middleware<Sequence> = (ctx, next) => {\n const sequence = resolveFlagSequence(ctx.program, ctx.flags);\n if (!sequence) return next();\n if (ctx.trace) ctx.trace.sequence = 'flag';\n return sequence;\n};\n\n/**\n * The orchestrator drives harnesses through `runTask`; a harness that has not\n * implemented it clamps the run to linear. A capability check, not a harness\n * identity check — a harness gains orchestrator support by implementing the\n * method, with no switchboard change. Sits below the CLI override so\n * `--sequence orchestrator` still reproduces the hard error in dev builds.\n */\nconst runTaskCapabilityClampMw: Middleware<Sequence> = (ctx, next) => {\n const pick = resolveHarness(ctx);\n if (getHarness(pick.harness).runTask) return next();\n if (isOrchestratorEnabled(ctx.flags)) {\n logToFile(\n `[switchboard] wizard-orchestrator ignored: ${pick.harness} has no runTask, clamping to linear`,\n );\n }\n if (ctx.trace) ctx.trace.sequence = 'runtask-clamp';\n return Sequence.linear;\n};\n\n// Order = precedence: CLI > capability clamp > flag > binding default. The\n// prod spread collapses to [], dropping cliSequenceMw from the chain.\nconst SEQUENCE_MIDDLEWARE: Middleware<Sequence>[] = [\n composedClampMw,\n ...(IS_PRODUCTION_BUILD ? [] : [cliSequenceMw]),\n runTaskCapabilityClampMw,\n flagRouteSequenceMw,\n sequenceExperimentMw,\n];\n\n/** CLI wins over `wizard-orchestrator` flag wins over binding default. */\nexport function resolveSequence(ctx: SwitchboardCtx): Sequence {\n const sequence = runChain(SEQUENCE_MIDDLEWARE, ctx, () => {\n if (ctx.trace) ctx.trace.sequence = 'binding';\n const { binding } = ctx;\n return binding.sequence;\n });\n logToFile(\n `[switchboard] resolved: program=${ctx.program} sequence=${sequence}` +\n `${ctx.trace?.sequence ? ` (${ctx.trace.sequence})` : ''}`,\n );\n return sequence;\n}\n","// Resolves routing; model additions also require mint allowlists and gateway prompt/transport support.\n\nimport { GPT5_6_SOL_MODEL, Harness, Sequence } from '@shared/constants';\nimport { resolveHarness } from './harness';\nimport { triageModelFor, type EffortLevel } from './models';\nimport { resolveSequence } from './sequence';\n\n// ── Shared machinery ────────────────────────────────────────────────────\n\n/** Which precedence rung decided each axis. Stamped by middlewares as they assert. */\nexport interface SwitchboardTrace {\n harness?: 'cli' | 'flag' | 'binding';\n model?: 'cli' | 'flag' | 'binding';\n sequence?:\n | 'cli'\n | 'composed'\n | 'runtask-clamp'\n | 'payload'\n | 'flag'\n | 'binding';\n}\n\n/** Everything a resolver middleware may branch on. Built once per run. */\nexport interface SwitchboardCtx {\n program: string;\n /** The program's own binding: the base every override and flag lands on. */\n binding: ProgramBinding;\n /** Composed sub-run (a dependency inside a parent program). Structurally linear — no override can orchestrate it. */\n composed?: boolean;\n flags: Record<string, string>;\n /** Flag payloads from the same snapshot (payload-carrying flags, e.g. self-driving pi). */\n flagPayloads?: Record<string, unknown>;\n /** CLI override (`--harness`). Wins over `flags`. */\n cliHarness?: Harness;\n /** CLI override (`--sequence`). Wins over `flags`. */\n cliSequence?: Sequence;\n /** CLI override (`--model`, gateway id). Wins over the binding's model. */\n cliModel?: string;\n /** Filled during resolution; read by the caller for telemetry. */\n trace?: SwitchboardTrace;\n}\n\n/** A resolver middleware: defer via `next()`, or assert by returning a value. */\nexport type Middleware<D> = (ctx: SwitchboardCtx, next: () => D) => D;\n\n/**\n * Run a middleware chain over `ctx`. Each middleware receives `next` (which\n * runs the rest of the chain) and can either:\n * - defer: call `next()` and optionally modify its result (overlay pattern)\n * - short-circuit: return a value without calling `next()` (skip the rest)\n *\n * **Earlier in the array = higher precedence.** Index 0 runs first and can\n * short-circuit the rest; index 1 only runs if index 0 deferred. So\n * `[cliSequenceMw, orchestratorFeatureFlagMw]` means CLI takes precedence over the\n * flag, not the other way around.\n *\n * `fallback` runs at the end — reached only when every middleware deferred.\n * Typically the map read for the base value.\n */\nexport function runChain<D>(\n chain: Middleware<D>[],\n ctx: SwitchboardCtx,\n fallback: () => D,\n): D {\n function step(index: number): D {\n if (index >= chain.length) return fallback();\n const middleware = chain[index];\n const next = () => step(index + 1);\n return middleware(ctx, next);\n }\n return step(0);\n}\n\n// ── Data model ──────────────────────────────────────────────────────────\n\n/** Harness + model for one leaf of agent work. */\nexport interface HarnessPick {\n harness: Harness;\n /** Gateway model id (string). */\n model: string;\n /** Reasoning-effort override. Absent → the model's table default. */\n thinkingLevel?: EffortLevel;\n}\n\nexport interface ProgramBinding {\n sequence: Sequence;\n harness: Harness;\n model: string;\n /** Reasoning-effort override for the model. Absent → the model's table default. */\n thinkingLevel?: EffortLevel;\n /**\n * Per-role overrides applied only in orchestrator mode — keys are\n * agent-prompt `type` values published by context-mill (`'seed'`,\n * `'install'`, `'capture'`, etc.). Linear runs use role `'default'` and\n * skip this map.\n */\n contextMillOverride?: Record<string, Partial<HarnessPick>>;\n}\n\n// Legacy fallback; new programs should explicitly choose Pi and prefer orchestration.\nexport const DEFAULT_BINDING: ProgramBinding = {\n sequence: Sequence.linear,\n harness: Harness.pi,\n model: GPT5_6_SOL_MODEL,\n thinkingLevel: 'medium',\n};\n\n// ── Unified resolver ────────────────────────────────────────────────────\n\n/** Compose both axes. Callers needing only one axis use the per-axis resolver. */\nexport function resolveBinding(\n ctx: SwitchboardCtx,\n role = 'default',\n): ProgramBinding {\n ctx.trace ??= {};\n const sequence = resolveSequence(ctx);\n const { harness, model, thinkingLevel } = resolveHarness(ctx, role);\n return { sequence, harness, model, thinkingLevel };\n}\n\n/**\n * A scan's binding: linear on a triage model. The first attempt takes the\n * harness the run resolves to; the retry runs the SDK, a second provider,\n * whatever the flags say.\n */\nexport function resolveScanBinding(\n ctx: SwitchboardCtx,\n attempt: 'first' | 'retry',\n): ProgramBinding {\n const harness =\n attempt === 'retry' ? Harness.anthropic : resolveBinding(ctx).harness;\n return { sequence: Sequence.linear, harness, model: triageModelFor(harness) };\n}\n\n// ── Unified re-export surface ───────────────────────────────────────────\nexport { HARNESS_OPTIONS, getHarness, resolveHarness } from './harness';\nexport {\n SEQUENCE_OPTIONS,\n getSequence,\n resolveSequence,\n type SequenceRunner,\n} from './sequence';\nexport {\n isOrchestratorEnabled,\n areSeededTasksEnabled,\n resolveStageOverrides,\n} from './flags';\n","// Turns a caller's routing into the resolved config the sequences read.\n\nimport {\n Sequence,\n WIZARD_ORCHESTRATOR_FLAG_KEY,\n WIZARD_SELF_DRIVING_USE_PI_HARNESS_FLAG_KEY,\n} from '@shared/constants';\nimport { analytics } from '@utils/analytics';\nimport { logToFile } from '@utils/debug';\nimport { buildRunTags } from '../../agent-interface';\nimport type {\n ResolvedBinding,\n ResolvedRunConfig,\n RunConfig,\n} from '../shared/types';\nimport { resolveBinding, resolveScanBinding, type SwitchboardCtx } from '.';\n\n/** Resolve the run's binding from its routing, and build its trace tags. */\nexport function resolveRunConfig(config: RunConfig): ResolvedRunConfig {\n const { routing, tags, ...rest } = config;\n const switchboard: SwitchboardCtx = {\n program: config.programId,\n binding: routing.binding,\n composed: config.composed,\n flags: config.wizardFlags,\n flagPayloads: config.wizardFlagPayloads,\n cliHarness: routing.overrides?.harness,\n cliSequence: routing.overrides?.sequence,\n cliModel: routing.overrides?.model,\n };\n const binding = routing.scan\n ? resolveScanBinding(switchboard, routing.scan)\n : resolveBinding(switchboard);\n const record = routing.record ?? true;\n if (record) {\n analytics.setTag('sequence', binding.sequence);\n analytics.setTag('harness', binding.harness);\n captureSwitchboardDecision(switchboard, binding);\n }\n const wizardMetadata = {\n ...buildRunTags({\n programId: config.programId,\n integration: config.run.integrationLabel,\n runId: analytics.runId,\n build: analytics.build,\n skillId: config.run.skillId,\n }),\n ...(record ? { SEQUENCE: binding.sequence, HARNESS: binding.harness } : {}),\n ...tags,\n };\n return { ...rest, binding, switchboard, wizardMetadata };\n}\n\n/**\n * One event + one log line per run: what entered the switchboard, which\n * precedence rung decided each axis, and the final pick.\n */\nfunction captureSwitchboardDecision(\n ctx: SwitchboardCtx,\n binding: ResolvedBinding,\n): void {\n const trace = ctx.trace ?? {};\n // Unpinned orchestrator runs choose a model per task from the context-mill agent prompts; the orchestrator logs that map once the prompts load.\n const perTaskModel =\n binding.sequence === Sequence.orchestrator && trace.model === 'binding';\n const model = perTaskModel ? 'chosen-per-task' : binding.model;\n const modelSource = perTaskModel ? 'agent-prompts' : trace.model;\n analytics.wizardCapture('switchboard resolved', {\n program: ctx.program,\n flag_self_driving_use_pi_harness:\n ctx.flags[WIZARD_SELF_DRIVING_USE_PI_HARNESS_FLAG_KEY],\n flag_self_driving_pi_payload: JSON.stringify(\n ctx.flagPayloads?.[WIZARD_SELF_DRIVING_USE_PI_HARNESS_FLAG_KEY] ?? null,\n ),\n flag_orchestrator: ctx.flags[WIZARD_ORCHESTRATOR_FLAG_KEY],\n cli_harness: ctx.cliHarness,\n cli_sequence: ctx.cliSequence,\n cli_model: ctx.cliModel,\n harness_source: trace.harness,\n model_source: modelSource,\n sequence_source: trace.sequence,\n harness: binding.harness,\n model,\n thinking_level: binding.thinkingLevel,\n sequence: binding.sequence,\n });\n logToFile(\n `[switchboard] decision: program=${ctx.program}` +\n ` in(orchestrator=${ctx.flags[WIZARD_ORCHESTRATOR_FLAG_KEY] ?? '-'},` +\n ` cli=${ctx.cliHarness ?? '-'}/${ctx.cliSequence ?? '-'}/${\n ctx.cliModel ?? '-'\n })` +\n ` → harness=${binding.harness} (${trace.harness ?? '?'})` +\n ` model=${model} (${modelSource ?? '?'})` +\n ` sequence=${binding.sequence} (${trace.sequence ?? '?'})`,\n );\n}\n","/**\n * Unified program runner — dispatcher.\n *\n * One callable, `runAgent(config, input, options)`, runs a program's agent\n * pipeline to a decided result. `config` is resolved execution data (which\n * program, how it is routed, which flags apply); `input` is the invocation\n * snapshot (directory, credentials, project); `options` carries an optional\n * progress observer, an optional answerer.\n *\n * The pipeline prepares the run (logging targets, gateway mint, scan triage),\n * then forks. The `orchestrator` variant routes to the task-queue runner.\n * Every other variant runs the fixed linear pipeline:\n * [skill install] → agent init → prompt → run → errors → [postRun] → outro\n *\n * The agent reports and asks, it never renders, never reads a session, never\n * exits the process, never sends the process's terminal analytics and never\n * rejects. A decided failure comes back in\n * `RunResult.failure` with the same fields `wizardAbort` takes; an error the\n * agent did not decide (a refused mint, an SDK crash) comes back as\n * `outcome: RunOutcome.Crashed` with the original error attached, so a caller can keep\n * handling it the way it always did. `runProgram` is the program layer's caller.\n */\n\nimport { Sequence } from '@shared/constants';\nimport { RunOutcome } from './shared/types';\nexport { RunOutcome } from './shared/types';\nimport { classifyRunFailure, ErrorCodes } from '@shared/errors';\nimport { logToFile } from '@utils/debug';\nimport type {\n RunAgentOptions,\n RunConfig,\n RunInput,\n RunResult,\n} from './shared/types';\nimport { prepareRun } from './shared/bootstrap';\nimport { createProgressCollector } from './shared/progress-collector';\nimport {\n createTranscriptTail,\n type TranscriptTail,\n} from './shared/transcript-tail';\nimport { getSequence } from './switchboard';\nimport { resolveRunConfig } from './switchboard/resolve-run';\nimport { flushScanReport } from '../yara-hooks';\nimport { registerCleanup } from '@utils/cleanup';\nimport { useRunGatewayCredential } from '../gateway-session';\n\nexport type {\n AbortCase,\n AgentFailure,\n BootstrapResult,\n Credentials,\n AgentRunDefinition,\n PromptContext,\n AgentRouting,\n ResolvedBinding,\n RunAgentOptions,\n RunConfig,\n RunFlags,\n RunHooks,\n RunInput,\n RunResult,\n RunSnapshot,\n SeedTaskEntry,\n} from './shared/types';\nexport type {\n AgentInteraction,\n AgentProgress,\n ProgressEmitter,\n} from '../progress';\nexport { DEFAULT_BINDING } from './switchboard';\nexport type { ProgramBinding } from './switchboard';\nexport type { TaskOutcome } from './sequence/orchestrator/queue';\n\n/**\n * Run a program's agent pipeline.\n *\n * Prepare → dispatch to the sequence the binding names → return its result\n * with the agent's own snapshot of what it reported. Missing observers change\n * nothing; a throwing observer is logged and the run continues.\n */\nexport async function runAgent(\n runConfig: RunConfig,\n input: RunInput,\n options: RunAgentOptions = {},\n): Promise<RunResult> {\n let collector: ReturnType<typeof createProgressCollector> | undefined;\n let transcript: TranscriptTail | undefined;\n const snapshot = (): RunResult['snapshot'] => {\n try {\n if (collector) {\n const collected = collector.snapshot();\n return transcript\n ? { ...collected, transcriptTail: transcript.text() }\n : collected;\n }\n } catch {\n // A partial snapshot must not replace the run's primary failure.\n }\n return {\n tasks: [],\n statusMessages: [],\n usage: {\n inputTokens: 0,\n outputTokens: 0,\n cacheReadTokens: 0,\n cacheCreationTokens: 0,\n },\n };\n };\n let unregisterFlush: (() => void) | undefined;\n const flushReport = (): void => {\n unregisterFlush?.();\n // A deferred report keeps counting this run's scans toward the program run's.\n if (runConfig.scanReport === 'defer') return;\n try {\n const report = flushScanReport({ yaraReport: input.flags.yaraReport });\n if (report)\n collector?.emit({ kind: 'log', level: 'info', message: report });\n } catch {\n // Scan reporting is best effort after the run outcome is decided.\n }\n };\n let result: RunResult;\n try {\n collector = createProgressCollector(options.onProgress);\n // An exit mid-run still reports the scans so far; the report is idempotent.\n unregisterFlush = registerCleanup(flushReport);\n const { emit } = collector;\n if (runConfig.run.collectTranscript)\n transcript = createTranscriptTail(emit);\n const log = (message: string) =>\n emit({ kind: 'log', level: 'info', message });\n if (options.signal?.aborted) {\n flushReport();\n return {\n outcome: RunOutcome.Aborted,\n skillId: input.skillId,\n failure: {\n code: ErrorCodes.AgentAbort,\n message: 'Agent run cancelled',\n },\n snapshot: snapshot(),\n };\n }\n // A pre-issued gateway token (dev and test CI runs) stands in for the mint, for this run only.\n useRunGatewayCredential(\n input.credentials.gateway,\n input.credentials.projectId,\n );\n const config = resolveRunConfig(runConfig);\n emit({ kind: 'binding', binding: config.binding });\n const boot = await prepareRun(config, input);\n if (config.binding.sequence === Sequence.orchestrator) {\n log('Task-queue orchestrator enabled.');\n }\n try {\n logToFile(\n `[agent-runner] run program=${config.programId} sequence=${config.binding.sequence}` +\n ` harness=${config.binding.harness} composed=${config.composed}`,\n );\n } catch {\n // Logging is best effort.\n }\n const sequenceResult = await getSequence(config.binding.sequence).run({\n config,\n input,\n boot,\n emit,\n interaction: options.interaction,\n signal: options.signal,\n transcript,\n });\n result = {\n ...(options.signal?.aborted &&\n sequenceResult.outcome === RunOutcome.Success\n ? {\n outcome: RunOutcome.Aborted as const,\n failure: {\n code: ErrorCodes.AgentAbort,\n message: 'Agent run cancelled',\n },\n }\n : sequenceResult),\n skillId: input.skillId,\n snapshot: snapshot(),\n };\n } catch (error) {\n const original =\n error instanceof Error ? error : new Error(safeErrorMessage(error));\n let failure: ReturnType<typeof classifyRunFailure>;\n try {\n failure = classifyRunFailure(original);\n } catch {\n failure = {\n code: ErrorCodes.InternalUnhandled,\n message: 'Unexpected agent error',\n coded: false,\n };\n }\n try {\n logToFile('[agent-runner] run failed:', original);\n } catch {\n // Logging is best effort.\n }\n let abortError = false;\n try {\n abortError = original.name === 'AbortError';\n } catch {\n /* Hostile Error getter. */\n }\n if (failure.coded) {\n result = {\n outcome: RunOutcome.Failed,\n skillId: input?.skillId,\n failure: {\n code: failure.code,\n message: failure.message,\n error: original,\n },\n snapshot: snapshot(),\n };\n } else if (options.signal?.aborted && abortError) {\n result = {\n outcome: RunOutcome.Aborted,\n skillId: input?.skillId,\n failure: {\n code: ErrorCodes.AgentAbort,\n message: 'Agent run cancelled',\n },\n snapshot: snapshot(),\n };\n } else {\n result = {\n outcome: RunOutcome.Crashed,\n skillId: input?.skillId,\n failure: {\n code: failure.code,\n message: failure.message,\n error: original,\n },\n snapshot: snapshot(),\n };\n }\n }\n flushReport();\n return result;\n}\n\nfunction safeErrorMessage(error: unknown): string {\n try {\n return String(error);\n } catch {\n return 'Unknown thrown value';\n }\n}\n","/**\n * Public entry of the agent. Code outside `src/agent` imports runtime values\n * from here and types from `./types`; deeper imports fail `pnpm typecheck`.\n * Keep this list to what callers use, and keep it cheap:\n * the startup chunk imports this module, so anything re-exported here loads\n * before the wizard does any work. Heavy paths stay behind a lazy import.\n */\nimport type { LLMProvider } from '@posthog/warlock';\n\n/**\n * The agent's contract: the one way to run it, the marker strings\n * program prompts embed, and the tool ids programs put in allowedTools and\n * disallowedTools.\n */\nexport type * from './types';\nexport { runAgent, RunOutcome } from './runner';\nexport { AgentSignals } from './agent-interface';\nexport { WIZARD_TOOL_NAMES } from './tools';\n\n/** The binding a program gets when it declares none. */\nexport { DEFAULT_BINDING } from './runner';\n\n/** What a scan's matches decide: end the session or only warn. The Warlock release gate reads it. */\nexport { scanVerdict } from './yara-policy';\n\n/**\n * The scan a freshly installed skill directory goes through: a returned reason\n * means it is poisoned. Callers of `downloadSkill` inject it, since @shared\n * cannot import @agent. It loads the scanner on first call so the startup\n * chunk does not grow.\n */\nexport async function scanInstalledSkill(\n skillDir: string,\n llmProvider: LLMProvider | undefined,\n): Promise<string | null> {\n const yara = await import('./yara-hooks');\n return yara.scanInstalledSkill(skillDir, llmProvider);\n}\n\n/**\n * The MCP tutorial's prompt stream: one prompt against the PostHog MCP server,\n * streamed as chunks. `@tools` re-exports it unchanged, and the TUI reaches it\n * only through there. It loads the streaming module on first call so the\n * startup chunk does not grow.\n */\nexport async function* streamMcpPrompt(\n args: Parameters<typeof import('./mcp-prompt-streaming').streamMcpPrompt>[0],\n): AsyncIterable<import('./types').McpPromptChunk> {\n const streaming = await import('./mcp-prompt-streaming');\n yield* streaming.streamMcpPrompt(args);\n}\n","import { execSync } from 'node:child_process';\nimport type { WizardRunOptions } from '@utils/types';\n\nexport enum PythonPackageManager {\n UV = 'uv',\n POETRY = 'poetry',\n PDM = 'pdm',\n HATCH = 'hatch',\n RYE = 'rye',\n PIPENV = 'pipenv',\n CONDA = 'conda',\n PIP = 'pip',\n UNKNOWN = 'unknown',\n}\n\n/**\n * Get the installed Python version\n */\nexport function getPythonVersion(\n options: WizardRunOptions,\n): string | undefined {\n try {\n const version = execSync('python --version || python3 --version', {\n cwd: options.installDir,\n encoding: 'utf-8',\n })\n .trim()\n .replace('Python ', '');\n return version;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Bucket Python version for analytics (e.g., \"3.11.x\" -> \"3.11\")\n */\nexport function getPythonVersionBucket(version: string): string {\n const match = version.match(/^(\\d+\\.\\d+)/);\n return match ? match[1] : version;\n}\n\n/**\n * Detect which package manager the project uses\n */\nexport async function detectPackageManager(\n options: WizardRunOptions,\n): Promise<PythonPackageManager> {\n const { installDir } = options;\n const fs = await import('node:fs');\n const path = await import('node:path');\n\n // Check for uv (uv.lock)\n if (fs.existsSync(path.join(installDir, 'uv.lock'))) {\n return PythonPackageManager.UV;\n }\n\n // Check pyproject.toml for various tools\n if (fs.existsSync(path.join(installDir, 'pyproject.toml'))) {\n try {\n const content = fs.readFileSync(\n path.join(installDir, 'pyproject.toml'),\n 'utf-8',\n );\n\n // Check for Poetry\n if (content.includes('[tool.poetry]')) {\n return PythonPackageManager.POETRY;\n }\n\n // Check for PDM\n if (content.includes('[tool.pdm]')) {\n return PythonPackageManager.PDM;\n }\n\n // Check for Hatch\n if (content.includes('[tool.hatch]')) {\n return PythonPackageManager.HATCH;\n }\n\n // Check for Rye\n if (content.includes('[tool.rye]')) {\n return PythonPackageManager.RYE;\n }\n } catch {\n // Continue checking\n }\n }\n\n // Check for Poetry lock file\n if (fs.existsSync(path.join(installDir, 'poetry.lock'))) {\n return PythonPackageManager.POETRY;\n }\n\n // Check for PDM lock file\n if (fs.existsSync(path.join(installDir, 'pdm.lock'))) {\n return PythonPackageManager.PDM;\n }\n\n // Check for Pipenv (Pipfile or Pipfile.lock)\n if (\n fs.existsSync(path.join(installDir, 'Pipfile')) ||\n fs.existsSync(path.join(installDir, 'Pipfile.lock'))\n ) {\n return PythonPackageManager.PIPENV;\n }\n\n // Check for Conda (environment.yml or environment.yaml)\n if (\n fs.existsSync(path.join(installDir, 'environment.yml')) ||\n fs.existsSync(path.join(installDir, 'environment.yaml'))\n ) {\n return PythonPackageManager.CONDA;\n }\n\n // Check for pip (requirements.txt, setup.py, setup.cfg, or pyproject.toml)\n if (\n fs.existsSync(path.join(installDir, 'requirements.txt')) ||\n fs.existsSync(path.join(installDir, 'setup.py')) ||\n fs.existsSync(path.join(installDir, 'setup.cfg')) ||\n fs.existsSync(path.join(installDir, 'pyproject.toml'))\n ) {\n return PythonPackageManager.PIP;\n }\n\n // Check for requirements directory\n try {\n const requirementsDir = path.join(installDir, 'requirements');\n if (\n fs.existsSync(requirementsDir) &&\n fs.statSync(requirementsDir).isDirectory()\n ) {\n const files = fs.readdirSync(requirementsDir);\n if (files.some((f) => f.endsWith('.txt'))) {\n return PythonPackageManager.PIP;\n }\n }\n } catch {\n // Continue\n }\n\n return PythonPackageManager.UNKNOWN;\n}\n\n/**\n * Get package manager display name\n */\nexport function getPackageManagerName(\n packageManager: PythonPackageManager,\n): string {\n switch (packageManager) {\n case PythonPackageManager.UV:\n return 'uv';\n case PythonPackageManager.POETRY:\n return 'Poetry';\n case PythonPackageManager.PDM:\n return 'PDM';\n case PythonPackageManager.HATCH:\n return 'Hatch';\n case PythonPackageManager.RYE:\n return 'Rye';\n case PythonPackageManager.PIPENV:\n return 'Pipenv';\n case PythonPackageManager.CONDA:\n return 'Conda';\n case PythonPackageManager.PIP:\n return 'pip';\n case PythonPackageManager.UNKNOWN:\n return 'unknown';\n }\n}\n","/**\n * Cross-ecosystem package manager detection.\n *\n * Each FrameworkConfig implements the PackageManagerDetector contract; the\n * helpers here cover the Python, PHP, Swift, Ruby, Rust, Elixir, Go, Flutter,\n * Android and Java ecosystems (Node is in `@utils/package-manager`). The\n * `detect_package_manager` tool delegates to whatever detector the current\n * framework supplies.\n */\n\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport {\n detectNodePackageManagers,\n type DetectedPackageManager,\n type PackageManagerDetector,\n type PackageManagerInfo,\n} from '@utils/package-manager';\n\n// The detector contract and the Node detector live in `@utils/package-manager`\n// (the agent's tools need them without importing detection); re-exported so\n// every framework keeps its import path.\nexport { detectNodePackageManagers };\nexport type {\n DetectedPackageManager,\n PackageManagerDetector,\n PackageManagerInfo,\n};\nimport {\n detectPackageManager as detectPythonPM,\n PythonPackageManager,\n} from '../frameworks/python/utils';\n\n// ---------------------------------------------------------------------------\n// Python helper\n// ---------------------------------------------------------------------------\n\nconst PYTHON_PM_INFO: Record<PythonPackageManager, DetectedPackageManager> = {\n [PythonPackageManager.UV]: {\n name: 'uv',\n label: 'uv',\n installCommand: 'uv add',\n runCommand: 'uv run',\n },\n [PythonPackageManager.POETRY]: {\n name: 'poetry',\n label: 'Poetry',\n installCommand: 'poetry add',\n runCommand: 'poetry run',\n },\n [PythonPackageManager.PDM]: {\n name: 'pdm',\n label: 'PDM',\n installCommand: 'pdm add',\n runCommand: 'pdm run',\n },\n [PythonPackageManager.HATCH]: {\n name: 'hatch',\n label: 'Hatch',\n installCommand: 'hatch add',\n runCommand: 'hatch run',\n },\n [PythonPackageManager.RYE]: {\n name: 'rye',\n label: 'Rye',\n installCommand: 'rye add',\n runCommand: 'rye run',\n },\n [PythonPackageManager.PIPENV]: {\n name: 'pipenv',\n label: 'Pipenv',\n installCommand: 'pipenv install',\n runCommand: 'pipenv run',\n },\n [PythonPackageManager.CONDA]: {\n name: 'conda',\n label: 'Conda',\n installCommand: 'conda install',\n runCommand: 'conda run',\n },\n [PythonPackageManager.PIP]: {\n name: 'pip',\n label: 'pip',\n installCommand: 'pip install',\n },\n [PythonPackageManager.UNKNOWN]: {\n name: 'pip',\n label: 'pip (default)',\n installCommand: 'pip install',\n },\n};\n\n/**\n * Detect Python package managers via lockfiles and config files.\n * Wraps the existing detectPackageManager() from python/utils.ts.\n */\nexport async function detectPythonPackageManagers(\n installDir: string,\n): Promise<PackageManagerInfo> {\n const pm = await detectPythonPM({ installDir } as any);\n const info = PYTHON_PM_INFO[pm];\n\n return {\n detected: [info],\n primary: info,\n recommendation: `Use ${info.label} (${info.installCommand}).`,\n };\n}\n\n// ---------------------------------------------------------------------------\n// PHP (Composer) helper\n// ---------------------------------------------------------------------------\n\nconst COMPOSER: DetectedPackageManager = {\n name: 'composer',\n label: 'Composer',\n installCommand: 'composer require',\n};\n\nexport function composerPackageManager(): Promise<PackageManagerInfo> {\n return Promise.resolve({\n detected: [COMPOSER],\n primary: COMPOSER,\n recommendation: 'Use Composer (composer require).',\n });\n}\n\n// ---------------------------------------------------------------------------\n// Swift (SPM) helper\n// ---------------------------------------------------------------------------\n\nconst SPM: DetectedPackageManager = {\n name: 'spm',\n label: 'Swift Package Manager',\n installCommand: 'swift package add-dependency',\n};\n\nexport function swiftPackageManager(): Promise<PackageManagerInfo> {\n return Promise.resolve({\n detected: [SPM],\n primary: SPM,\n recommendation:\n 'Use Swift Package Manager. Add the dependency to Package.swift or via Xcode.',\n });\n}\n\n// ---------------------------------------------------------------------------\n// Ruby (Bundler) helper\n// ---------------------------------------------------------------------------\n\nconst BUNDLER: DetectedPackageManager = {\n name: 'bundler',\n label: 'Bundler',\n installCommand: 'bundle add',\n runCommand: 'bundle exec',\n};\n\nexport function bundlerPackageManager(): Promise<PackageManagerInfo> {\n return Promise.resolve({\n detected: [BUNDLER],\n primary: BUNDLER,\n recommendation: 'Use Bundler (bundle add). Run commands with bundle exec.',\n });\n}\n\n// ---------------------------------------------------------------------------\n// Rust (Cargo) helper\n// ---------------------------------------------------------------------------\n\nconst CARGO: DetectedPackageManager = {\n name: 'cargo',\n label: 'Cargo',\n installCommand: 'cargo add',\n};\n\nexport function cargoPackageManager(): Promise<PackageManagerInfo> {\n return Promise.resolve({\n detected: [CARGO],\n primary: CARGO,\n recommendation: 'Use Cargo (cargo add).',\n });\n}\n\n// ---------------------------------------------------------------------------\n// Elixir (Mix) helper\n// ---------------------------------------------------------------------------\n\nconst MIX: DetectedPackageManager = {\n name: 'mix',\n label: 'Mix',\n installCommand: 'mix deps.get',\n};\n\nexport function mixPackageManager(): Promise<PackageManagerInfo> {\n return Promise.resolve({\n detected: [MIX],\n primary: MIX,\n recommendation:\n 'Use Mix. Add the dependency to the deps list in mix.exs, then run mix deps.get.',\n });\n}\n\n// ---------------------------------------------------------------------------\n// Go (modules) helper\n// ---------------------------------------------------------------------------\n\nconst GO_MODULES: DetectedPackageManager = {\n name: 'go',\n label: 'Go modules',\n installCommand: 'go get',\n};\n\nexport function goModulesPackageManager(): Promise<PackageManagerInfo> {\n return Promise.resolve({\n detected: [GO_MODULES],\n primary: GO_MODULES,\n recommendation:\n 'Use Go modules (go get). Run go mod tidy after imports change.',\n });\n}\n\n// ---------------------------------------------------------------------------\n// Flutter (pub) helper\n// ---------------------------------------------------------------------------\n\nconst PUB: DetectedPackageManager = {\n name: 'pub',\n label: 'pub',\n installCommand: 'flutter pub add',\n runCommand: 'flutter',\n};\n\nexport function pubPackageManager(): Promise<PackageManagerInfo> {\n return Promise.resolve({\n detected: [PUB],\n primary: PUB,\n recommendation:\n 'Use flutter pub add to add dependencies; it updates pubspec.yaml automatically.',\n });\n}\n\n// ---------------------------------------------------------------------------\n// Android (Gradle) helper\n// ---------------------------------------------------------------------------\n\nconst GRADLE: DetectedPackageManager = {\n name: 'gradle',\n label: 'Gradle',\n installCommand: 'implementation',\n};\n\nexport function gradlePackageManager(): Promise<PackageManagerInfo> {\n return Promise.resolve({\n detected: [GRADLE],\n primary: GRADLE,\n recommendation:\n 'Add dependencies to build.gradle(.kts) using implementation().',\n });\n}\n\n// ---------------------------------------------------------------------------\n// Java (Maven or Gradle) helper\n// ---------------------------------------------------------------------------\n\nconst MAVEN: DetectedPackageManager = {\n name: 'maven',\n label: 'Maven',\n installCommand: 'mvn install',\n};\n\n/**\n * Java backends split between Maven and Gradle; pom.xml decides.\n * Defaults to Gradle when neither manifest is present.\n */\nexport function detectJavaPackageManagers(\n installDir: string,\n): Promise<PackageManagerInfo> {\n if (fs.existsSync(path.join(installDir, 'pom.xml'))) {\n return Promise.resolve({\n detected: [MAVEN],\n primary: MAVEN,\n recommendation:\n 'Use Maven. Add the dependency to pom.xml, then run mvn install to resolve it.',\n });\n }\n return gradlePackageManager();\n}\n","import type { WizardRunOptions } from '@utils/types';\nimport { boundedGlob } from '@utils/bounded-fs';\nimport { createVersionBucket } from '@utils/semver';\n\nexport const getNextJsVersionBucket = createVersionBucket();\n\nexport enum NextJsRouter {\n APP_ROUTER = 'app-router',\n PAGES_ROUTER = 'pages-router',\n}\n\nexport const IGNORE_PATTERNS = ['**/public/**'];\n\n/**\n * Detect Next.js router type. Pure — returns null if ambiguous.\n */\nexport async function getNextJsRouter({\n installDir,\n}: Pick<WizardRunOptions, 'installDir'>): Promise<NextJsRouter | null> {\n const pagesMatches = await boundedGlob('**/pages/_app.@(ts|tsx|js|jsx)', {\n cwd: installDir,\n extraIgnore: IGNORE_PATTERNS,\n limit: 1,\n });\n\n const hasPagesDir = pagesMatches.length > 0;\n\n const appMatches = await boundedGlob('**/app/**/layout.@(ts|tsx|js|jsx)', {\n cwd: installDir,\n extraIgnore: IGNORE_PATTERNS,\n limit: 1,\n });\n\n const hasAppDir = appMatches.length > 0;\n\n if (hasPagesDir && !hasAppDir) {\n return NextJsRouter.PAGES_ROUTER;\n }\n\n if (hasAppDir && !hasPagesDir) {\n return NextJsRouter.APP_ROUTER;\n }\n\n // Ambiguous (both or neither) — return null, SetupScreen handles it\n return null;\n}\n\nexport const getNextJsRouterName = (router: NextJsRouter) => {\n return router === NextJsRouter.APP_ROUTER ? 'app router' : 'pages router';\n};\n","/* Simplified Next.js wizard using posthog-agent with PostHog MCP */\nimport type { WizardRunOptions } from '@utils/types';\nimport type { FrameworkConfig } from '../../framework-config';\nimport { detectNodePackageManagers } from '../../detection/package-manager';\nimport { Integration } from '@shared/constants';\nimport {\n getDeclaredVersion,\n getInstalledPackageVersion,\n hasDeclaredDependency,\n type PackageJson,\n} from '@utils/package-json';\nimport { tryGetPackageJson } from '@utils/setup-utils';\nimport {\n getNextJsRouter,\n getNextJsVersionBucket,\n getNextJsRouterName,\n NextJsRouter,\n} from './utils';\n\ntype NextjsContext = {\n router?: NextJsRouter;\n};\n\nexport const NEXTJS_AGENT_CONFIG: FrameworkConfig<NextjsContext> = {\n metadata: {\n name: 'Next.js',\n integration: Integration.nextjs,\n docsUrl: 'https://posthog.com/docs/libraries/next-js',\n unsupportedVersionDocsUrl: 'https://posthog.com/docs/libraries/next-js',\n gatherContext: async (options: WizardRunOptions) => {\n const router = await getNextJsRouter(options);\n if (router) {\n return { router };\n }\n return {};\n },\n getDetectedFrameworkLabel: (context) => {\n if (!context.router) return undefined;\n const emoji =\n context.router === NextJsRouter.APP_ROUTER ? '\\u{1F4F1}' : '\\u{1F4C3}';\n return `Next.js ${getNextJsRouterName(context.router)} ${emoji}`;\n },\n setup: {\n questions: [\n {\n key: 'router',\n message: 'Which Next.js router are you using?',\n options: [\n { label: 'App Router', value: NextJsRouter.APP_ROUTER },\n { label: 'Pages Router', value: NextJsRouter.PAGES_ROUTER },\n ],\n detect: async (opts) => {\n const result = await getNextJsRouter(opts);\n return result;\n },\n },\n ],\n },\n },\n\n detection: {\n packageName: 'next',\n packageDisplayName: 'Next.js',\n getVersion: (packageJson: unknown) =>\n getDeclaredVersion('next', packageJson as PackageJson),\n getVersionBucket: getNextJsVersionBucket,\n minimumVersion: '15.3.0',\n getInstalledVersion: (options: WizardRunOptions) =>\n Promise.resolve(getInstalledPackageVersion('next', options.installDir)),\n detect: async (options) => {\n const packageJson = await tryGetPackageJson(options);\n return packageJson ? hasDeclaredDependency('next', packageJson) : false;\n },\n detectPackageManager: detectNodePackageManagers,\n },\n\n environment: {\n uploadToHosting: true,\n getEnvVars: (apiKey: string, host: string) => ({\n NEXT_PUBLIC_POSTHOG_PROJECT_TOKEN: apiKey,\n NEXT_PUBLIC_POSTHOG_HOST: host,\n }),\n },\n\n analytics: {\n getTags: (context) => ({\n router: context.router === NextJsRouter.APP_ROUTER ? 'app' : 'pages',\n }),\n },\n\n prompts: {\n projectTypeDetection:\n 'This is a JavaScript/TypeScript project. Look for package.json and lockfiles (package-lock.json, yarn.lock, pnpm-lock.yaml, bun.lockb) to confirm.',\n getAdditionalContextLines: (context) => {\n const routerType =\n context.router === NextJsRouter.APP_ROUTER ? 'app' : 'pages';\n return [`Router: ${routerType}`];\n },\n },\n\n ui: {\n successMessage: 'PostHog integration complete',\n estimatedDurationMinutes: 8,\n getOutroChanges: (context) => {\n const router = context.router ?? NextJsRouter.APP_ROUTER;\n const routerName = getNextJsRouterName(router);\n return [\n `Analyzed your Next.js project structure (${routerName})`,\n `Created and configured PostHog initializers`,\n `Integrated PostHog into your application`,\n ];\n },\n getOutroNextSteps: () => {\n return [\n 'Start your development server to see PostHog in action',\n 'Visit your PostHog dashboard to see incoming events',\n ];\n },\n },\n};\n","/* Nuxt wizard using posthog-agent with PostHog MCP */\nimport type { WizardRunOptions } from '@utils/types';\nimport type { FrameworkConfig } from '../../framework-config';\nimport { detectNodePackageManagers } from '../../detection/package-manager';\nimport { Integration } from '@shared/constants';\nimport {\n getDeclaredVersion,\n getInstalledPackageVersion,\n hasDeclaredDependency,\n type PackageJson,\n} from '@utils/package-json';\nimport { tryGetPackageJson } from '@utils/setup-utils';\nimport { createVersionBucket } from '@utils/semver';\n\nconst getNuxtVersionBucket = createVersionBucket();\n\ntype NuxtContext = {\n versionBucket?: string;\n};\n\nexport const NUXT_AGENT_CONFIG: FrameworkConfig<NuxtContext> = {\n metadata: {\n name: 'Nuxt',\n integration: Integration.nuxt,\n docsUrl: 'https://posthog.com/docs/libraries/nuxt',\n gatherContext: async (options: WizardRunOptions) => {\n const packageJson = await tryGetPackageJson(options);\n if (!packageJson) return {};\n const version = getDeclaredVersion('nuxt', packageJson);\n const versionBucket = getNuxtVersionBucket(version);\n return { versionBucket };\n },\n },\n\n detection: {\n packageName: 'nuxt',\n packageDisplayName: 'Nuxt',\n getVersion: (packageJson: unknown) =>\n getDeclaredVersion('nuxt', packageJson as PackageJson),\n getVersionBucket: getNuxtVersionBucket,\n getInstalledVersion: (options: WizardRunOptions) =>\n Promise.resolve(getInstalledPackageVersion('nuxt', options.installDir)),\n detect: async (options) => {\n const packageJson = await tryGetPackageJson(options);\n return packageJson ? hasDeclaredDependency('nuxt', packageJson) : false;\n },\n detectPackageManager: detectNodePackageManagers,\n },\n\n environment: {\n uploadToHosting: true,\n getEnvVars: (apiKey: string, host: string) => ({\n NUXT_PUBLIC_POSTHOG_PROJECT_TOKEN: apiKey,\n NUXT_PUBLIC_POSTHOG_HOST: host,\n }),\n },\n\n analytics: {\n getTags: (context) => ({\n ...(context.versionBucket\n ? { versionBucket: context.versionBucket }\n : {}),\n }),\n },\n\n prompts: {\n projectTypeDetection:\n 'This is a JavaScript/TypeScript project. Look for package.json and lockfiles (package-lock.json, yarn.lock, pnpm-lock.yaml, bun.lockb) to confirm.',\n getAdditionalContextLines: (context) => {\n const lines: string[] = [];\n if (context.versionBucket) {\n lines.push(`Nuxt version: ${context.versionBucket}`);\n }\n const frameworkId = 'nuxt';\n lines.push(\n `Framework docs ID: ${frameworkId} (use posthog://docs/frameworks/${frameworkId} for documentation)`,\n );\n return lines;\n },\n },\n\n ui: {\n successMessage: 'PostHog integration complete',\n estimatedDurationMinutes: 5,\n getOutroChanges: () => [\n 'Analyzed your Nuxt project structure',\n 'Configured PostHog module/plugin',\n 'Integrated PostHog into your application',\n ],\n getOutroNextSteps: () => [\n 'Start your development server to see PostHog in action',\n 'Visit your PostHog dashboard to see incoming events',\n ],\n },\n};\n","/* Vue wizard using posthog-agent with PostHog MCP */\nimport type { FrameworkConfig } from '../../framework-config';\nimport { detectNodePackageManagers } from '../../detection/package-manager';\nimport { Integration } from '@shared/constants';\nimport {\n getDeclaredVersion,\n getInstalledPackageVersion,\n hasDeclaredDependency,\n type PackageJson,\n} from '@utils/package-json';\nimport { tryGetPackageJson } from '@utils/setup-utils';\nimport { createVersionBucket } from '@utils/semver';\n\nconst getVueVersionBucket = createVersionBucket();\n\ntype VueContext = Record<string, unknown>;\n\nexport const VUE_AGENT_CONFIG: FrameworkConfig<VueContext> = {\n metadata: {\n name: 'Vue',\n integration: Integration.vue,\n docsUrl: 'https://posthog.com/docs/libraries/vue',\n },\n\n detection: {\n packageName: 'vue',\n packageDisplayName: 'Vue',\n getVersion: (packageJson: unknown) =>\n getDeclaredVersion('vue', packageJson as PackageJson),\n getVersionBucket: getVueVersionBucket,\n getInstalledVersion: (options) =>\n Promise.resolve(getInstalledPackageVersion('vue', options.installDir)),\n detect: async (options) => {\n const packageJson = await tryGetPackageJson(options);\n return packageJson ? hasDeclaredDependency('vue', packageJson) : false;\n },\n detectPackageManager: detectNodePackageManagers,\n },\n\n environment: {\n uploadToHosting: true,\n getEnvVars: (apiKey: string, host: string) => ({\n VITE_POSTHOG_PROJECT_TOKEN: apiKey,\n VITE_POSTHOG_HOST: host,\n }),\n },\n\n analytics: {\n getTags: () => ({}),\n },\n\n prompts: {\n projectTypeDetection:\n 'This is a JavaScript/TypeScript project. Look for package.json and lockfiles (package-lock.json, yarn.lock, pnpm-lock.yaml, bun.lockb) to confirm.',\n getAdditionalContextLines: () => {\n const frameworkId = 'vue';\n return [\n `Framework docs ID: ${frameworkId} (use posthog://docs/frameworks/${frameworkId} for documentation)`,\n ];\n },\n },\n\n ui: {\n successMessage: 'PostHog integration complete',\n estimatedDurationMinutes: 5,\n getOutroChanges: () => [\n 'Analyzed your Vue project structure',\n 'Created and configured PostHog initializers',\n 'Integrated PostHog into your application',\n ],\n getOutroNextSteps: () => [\n 'Start your development server to see PostHog in action',\n 'Visit your PostHog dashboard to see incoming events',\n ],\n },\n};\n","import { major } from 'semver';\nimport { tryGetPackageJson } from '@utils/setup-utils';\nimport type { WizardRunOptions } from '@utils/types';\nimport { boundedGlob, readProjectFile } from '@utils/bounded-fs';\nimport { getDeclaredVersion } from '@utils/package-json';\nimport { createVersionBucket } from '@utils/semver';\nimport * as path from 'node:path';\nimport * as semver from 'semver';\n\nexport enum ReactRouterMode {\n V6 = 'v6',\n V7_FRAMEWORK = 'v7-framework',\n V7_DATA = 'v7-data',\n V7_DECLARATIVE = 'v7-declarative',\n}\n\nconst EXTRA_IGNORE = ['**/public/**'];\n\nexport const getReactRouterVersionBucket = createVersionBucket();\n\n/** Content probes read at most this many files, one in memory at a time. */\nconst SOURCE_PROBE_LIMIT = 200;\n\n/** Files that set up a React Router — never a blanket source sweep. */\nconst ROUTER_FILE_GLOBS = [\n '**/routes/**/*.@(ts|tsx|js|jsx)',\n '**/*[Rr]out*.@(ts|tsx|js|jsx)',\n '**/@(main|app|App|index|root).@(ts|tsx|js|jsx)',\n];\n\nasync function hasReactRouterConfig({\n installDir,\n}: Pick<WizardRunOptions, 'installDir'>): Promise<boolean> {\n const configMatches = await boundedGlob(\n '**/react-router.config.@(ts|js|tsx|jsx)',\n {\n cwd: installDir,\n extraIgnore: EXTRA_IGNORE,\n limit: 1,\n },\n );\n return configMatches.length > 0;\n}\n\nasync function hasCreateBrowserRouter({\n installDir,\n}: Pick<WizardRunOptions, 'installDir'>): Promise<boolean> {\n const sourceFiles = await boundedGlob(ROUTER_FILE_GLOBS, {\n cwd: installDir,\n extraIgnore: EXTRA_IGNORE,\n limit: SOURCE_PROBE_LIMIT,\n });\n\n for (const file of sourceFiles) {\n const content = readProjectFile(path.join(installDir, file));\n if (content?.includes('createBrowserRouter')) {\n return true;\n }\n }\n\n return false;\n}\n\nasync function hasDeclarativeRouter({\n installDir,\n}: Pick<WizardRunOptions, 'installDir'>): Promise<boolean> {\n const sourceFiles = await boundedGlob(ROUTER_FILE_GLOBS, {\n cwd: installDir,\n extraIgnore: EXTRA_IGNORE,\n limit: SOURCE_PROBE_LIMIT,\n });\n\n for (const file of sourceFiles) {\n const content = readProjectFile(path.join(installDir, file));\n if (!content) continue;\n if (\n content.includes('<BrowserRouter') ||\n (content.includes('BrowserRouter') &&\n (content.includes('from \"react-router-dom\"') ||\n content.includes(\"from 'react-router-dom'\")))\n ) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Detect React Router mode. Pure — returns null if ambiguous.\n */\nexport async function getReactRouterMode(\n options: WizardRunOptions,\n): Promise<ReactRouterMode | null> {\n const { installDir } = options;\n\n const packageJson = await tryGetPackageJson(options);\n if (!packageJson) return null;\n\n const reactRouterVersion =\n getDeclaredVersion('react-router-dom', packageJson) ||\n getDeclaredVersion('react-router', packageJson);\n\n if (!reactRouterVersion) {\n return null;\n }\n\n const coercedVersion = semver.coerce(reactRouterVersion);\n const majorVersion = coercedVersion ? major(coercedVersion) : null;\n\n if (majorVersion === 6) {\n return ReactRouterMode.V6;\n }\n\n if (majorVersion === 7) {\n const hasConfig = await hasReactRouterConfig({ installDir });\n if (hasConfig) return ReactRouterMode.V7_FRAMEWORK;\n\n const hasDataMode = await hasCreateBrowserRouter({ installDir });\n if (hasDataMode) return ReactRouterMode.V7_DATA;\n\n const hasDeclarative = await hasDeclarativeRouter({ installDir });\n if (hasDeclarative) return ReactRouterMode.V7_DECLARATIVE;\n\n // v7 but can't detect mode\n return null;\n }\n\n return null;\n}\n\nexport function getReactRouterModeName(mode: ReactRouterMode): string {\n switch (mode) {\n case ReactRouterMode.V6:\n return 'v6';\n case ReactRouterMode.V7_FRAMEWORK:\n return 'v7 Framework mode';\n case ReactRouterMode.V7_DATA:\n return 'v7 Data mode';\n case ReactRouterMode.V7_DECLARATIVE:\n return 'v7 Declarative mode';\n }\n}\n","/* React Router wizard using posthog-agent with PostHog MCP */\nimport type { WizardRunOptions } from '@utils/types';\nimport type { FrameworkConfig } from '../../framework-config';\nimport { detectNodePackageManagers } from '../../detection/package-manager';\nimport { Integration } from '@shared/constants';\nimport {\n getDeclaredVersion,\n getInstalledPackageVersion,\n hasDeclaredDependency,\n type PackageJson,\n} from '@utils/package-json';\nimport { tryGetPackageJson } from '@utils/setup-utils';\nimport {\n getReactRouterMode,\n getReactRouterModeName,\n getReactRouterVersionBucket,\n ReactRouterMode,\n} from './utils';\n\ntype ReactRouterContext = {\n routerMode?: ReactRouterMode;\n};\n\nexport const REACT_ROUTER_AGENT_CONFIG: FrameworkConfig<ReactRouterContext> = {\n metadata: {\n name: 'React Router',\n integration: Integration.reactRouter,\n docsUrl: 'https://posthog.com/docs/libraries/react',\n unsupportedVersionDocsUrl: 'https://posthog.com/docs/libraries/react',\n gatherContext: async (options: WizardRunOptions) => {\n const routerMode = await getReactRouterMode(options);\n if (routerMode) {\n return { routerMode };\n }\n return {};\n },\n getDetectedFrameworkLabel: (context) =>\n context.routerMode\n ? `React Router ${getReactRouterModeName(context.routerMode)}`\n : undefined,\n },\n\n detection: {\n packageName: 'react-router',\n packageDisplayName: 'React Router',\n getVersion: (packageJson: unknown) =>\n getDeclaredVersion('react-router', packageJson as PackageJson),\n getVersionBucket: getReactRouterVersionBucket,\n minimumVersion: '6.0.0',\n getInstalledVersion: (options: WizardRunOptions) =>\n Promise.resolve(\n getInstalledPackageVersion('react-router', options.installDir),\n ),\n detect: async (options) => {\n const packageJson = await tryGetPackageJson(options);\n return packageJson\n ? hasDeclaredDependency('react-router', packageJson)\n : false;\n },\n detectPackageManager: detectNodePackageManagers,\n },\n\n environment: {\n uploadToHosting: false,\n getEnvVars: (apiKey: string, host: string) => ({\n REACT_APP_POSTHOG_PROJECT_TOKEN: apiKey,\n REACT_APP_POSTHOG_HOST: host,\n }),\n },\n\n analytics: {\n getTags: (context) => ({\n routerMode: context.routerMode || 'unknown',\n }),\n },\n\n prompts: {\n projectTypeDetection:\n 'This is a JavaScript/TypeScript project. Look for package.json and lockfiles (package-lock.json, yarn.lock, pnpm-lock.yaml, bun.lockb) to confirm.',\n getAdditionalContextLines: (context) => {\n const routerMode = context.routerMode;\n const modeName = routerMode\n ? getReactRouterModeName(routerMode)\n : 'unknown';\n\n // Map router mode to framework ID for MCP docs resource\n const frameworkIdMap: Record<ReactRouterMode, string> = {\n [ReactRouterMode.V6]: 'react-react-router-6',\n [ReactRouterMode.V7_FRAMEWORK]: 'react-react-router-7-framework',\n [ReactRouterMode.V7_DATA]: 'react-react-router-7-data',\n [ReactRouterMode.V7_DECLARATIVE]: 'react-react-router-7-declarative',\n };\n\n const frameworkId = routerMode\n ? frameworkIdMap[routerMode]\n : ReactRouterMode.V7_FRAMEWORK;\n\n return [\n `Router mode: ${modeName}`,\n `Framework docs ID: ${frameworkId} (use posthog://docs/frameworks/${frameworkId} for documentation)`,\n ];\n },\n },\n\n ui: {\n successMessage: 'PostHog integration complete',\n estimatedDurationMinutes: 8,\n getOutroChanges: (context) => {\n const modeName = context.routerMode\n ? getReactRouterModeName(context.routerMode)\n : 'React Router';\n return [\n `Analyzed your React Router project structure (${modeName})`,\n `Created and configured PostHog initializers`,\n `Integrated PostHog into your application`,\n ];\n },\n getOutroNextSteps: () => [\n 'Start your development server to see PostHog in action',\n 'Visit your PostHog dashboard to see incoming events',\n ],\n },\n};\n","import type { WizardRunOptions } from '@utils/types';\nimport { boundedGlob, readProjectFile } from '@utils/bounded-fs';\nimport { hasDeclaredDependency } from '@utils/package-json';\nimport { createVersionBucket } from '@utils/semver';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nexport enum TanStackRouterMode {\n FILE_BASED = 'file-based',\n CODE_BASED = 'code-based',\n}\n\nconst EXTRA_IGNORE = ['**/public/**', '**/.vinxi/**', '**/.output/**'];\n\nexport const getTanStackRouterVersionBucket = createVersionBucket();\n\n/** Content probes read at most this many files, one in memory at a time. */\nconst SOURCE_PROBE_LIMIT = 200;\n\n/** Files that define TanStack routes — never a blanket source sweep. */\nconst ROUTE_FILE_GLOBS = [\n '**/routes/**/*.@(ts|tsx|js|jsx)',\n '**/*[Rr]oute*.@(ts|tsx|js|jsx)',\n '**/@(main|router|app|App|index).@(ts|tsx|js|jsx)',\n];\n\nasync function hasFileBasedRouting({\n installDir,\n}: Pick<WizardRunOptions, 'installDir'>): Promise<boolean> {\n const generatedFiles = await boundedGlob(\n '**/routeTree.gen.@(ts|tsx|js|jsx)',\n {\n cwd: installDir,\n extraIgnore: EXTRA_IGNORE,\n limit: 1,\n },\n );\n\n if (generatedFiles.length > 0) {\n return true;\n }\n\n try {\n const packageJsonPath = path.join(installDir, 'package.json');\n const content = fs.readFileSync(packageJsonPath, 'utf-8');\n const packageJson = JSON.parse(content) as Record<string, unknown>;\n\n if (\n hasDeclaredDependency('@tanstack/router-plugin', packageJson) ||\n hasDeclaredDependency('@tanstack/router-vite-plugin', packageJson)\n ) {\n return true;\n }\n } catch {\n // package.json not found or unreadable\n }\n\n const sourceFiles = await boundedGlob(ROUTE_FILE_GLOBS, {\n cwd: installDir,\n extraIgnore: EXTRA_IGNORE,\n limit: SOURCE_PROBE_LIMIT,\n });\n\n for (const file of sourceFiles) {\n const content = readProjectFile(path.join(installDir, file));\n if (content?.includes('createFileRoute')) {\n return true;\n }\n }\n\n return false;\n}\n\nasync function hasCodeBasedRouting({\n installDir,\n}: Pick<WizardRunOptions, 'installDir'>): Promise<boolean> {\n const sourceFiles = await boundedGlob(ROUTE_FILE_GLOBS, {\n cwd: installDir,\n extraIgnore: EXTRA_IGNORE,\n limit: SOURCE_PROBE_LIMIT,\n });\n\n let hasCreateRoute = false;\n let hasCreateFileRoute = false;\n\n for (const file of sourceFiles) {\n const content = readProjectFile(path.join(installDir, file));\n if (!content) continue;\n\n if (content.includes('createRoute(')) {\n hasCreateRoute = true;\n }\n if (content.includes('createFileRoute')) {\n hasCreateFileRoute = true;\n }\n }\n\n return hasCreateRoute && !hasCreateFileRoute;\n}\n\n/**\n * Detect TanStack Router mode. Pure — returns null if ambiguous.\n */\nexport async function getTanStackRouterMode(\n options: WizardRunOptions,\n): Promise<TanStackRouterMode | null> {\n const { installDir } = options;\n\n const isFileBased = await hasFileBasedRouting({ installDir });\n if (isFileBased) {\n return TanStackRouterMode.FILE_BASED;\n }\n\n const isCodeBased = await hasCodeBasedRouting({ installDir });\n if (isCodeBased) {\n return TanStackRouterMode.CODE_BASED;\n }\n\n return null;\n}\n\nexport function getTanStackRouterModeName(mode: TanStackRouterMode): string {\n switch (mode) {\n case TanStackRouterMode.FILE_BASED:\n return 'File-based routing';\n case TanStackRouterMode.CODE_BASED:\n return 'Code-based routing';\n }\n}\n","/* TanStack Router wizard using posthog-agent with PostHog MCP */\nimport type { WizardRunOptions } from '@utils/types';\nimport type { FrameworkConfig } from '../../framework-config';\nimport { detectNodePackageManagers } from '../../detection/package-manager';\nimport { Integration } from '@shared/constants';\nimport {\n getDeclaredVersion,\n getInstalledPackageVersion,\n hasDeclaredDependency,\n type PackageJson,\n} from '@utils/package-json';\nimport { tryGetPackageJson } from '@utils/setup-utils';\nimport {\n getTanStackRouterMode,\n getTanStackRouterModeName,\n getTanStackRouterVersionBucket,\n TanStackRouterMode,\n} from './utils';\n\ntype TanStackRouterContext = {\n routerMode?: TanStackRouterMode;\n};\n\nexport const TANSTACK_ROUTER_AGENT_CONFIG: FrameworkConfig<TanStackRouterContext> =\n {\n metadata: {\n name: 'React (TanStack Router)',\n integration: Integration.tanstackRouter,\n docsUrl: 'https://posthog.com/docs/libraries/react',\n gatherContext: async (options: WizardRunOptions) => {\n const routerMode = await getTanStackRouterMode(options);\n if (routerMode) {\n return { routerMode };\n }\n return {};\n },\n getDetectedFrameworkLabel: (context) =>\n context.routerMode\n ? `TanStack Router ${getTanStackRouterModeName(context.routerMode)}`\n : undefined,\n },\n\n detection: {\n packageName: '@tanstack/react-router',\n packageDisplayName: 'TanStack Router',\n getVersion: (packageJson: unknown) =>\n getDeclaredVersion(\n '@tanstack/react-router',\n packageJson as PackageJson,\n ),\n getVersionBucket: getTanStackRouterVersionBucket,\n minimumVersion: '1.0.0',\n getInstalledVersion: (options: WizardRunOptions) =>\n Promise.resolve(\n getInstalledPackageVersion(\n '@tanstack/react-router',\n options.installDir,\n ),\n ),\n detect: async (options) => {\n const packageJson = await tryGetPackageJson(options);\n if (!packageJson) {\n return false;\n }\n // Exclude TanStack Start projects (they have their own integration)\n if (hasDeclaredDependency('@tanstack/react-start', packageJson)) {\n return false;\n }\n return hasDeclaredDependency('@tanstack/react-router', packageJson);\n },\n detectPackageManager: detectNodePackageManagers,\n },\n\n environment: {\n uploadToHosting: false,\n getEnvVars: (apiKey: string, host: string) => ({\n VITE_PUBLIC_POSTHOG_PROJECT_TOKEN: apiKey,\n VITE_PUBLIC_POSTHOG_HOST: host,\n }),\n },\n\n analytics: {\n getTags: (context) => ({\n routerMode: context.routerMode || 'unknown',\n }),\n },\n\n prompts: {\n projectTypeDetection:\n 'This is a JavaScript/TypeScript project. Look for package.json and lockfiles (package-lock.json, yarn.lock, pnpm-lock.yaml, bun.lockb) to confirm.',\n getAdditionalContextLines: (context) => {\n const routerMode = context.routerMode;\n const modeName = routerMode\n ? getTanStackRouterModeName(routerMode)\n : 'unknown';\n\n // Map router mode to framework ID for MCP docs resource\n const frameworkIdMap: Record<TanStackRouterMode, string> = {\n [TanStackRouterMode.FILE_BASED]: 'react-tanstack-router-file-based',\n [TanStackRouterMode.CODE_BASED]: 'react-tanstack-router-code-based',\n };\n\n const frameworkId = routerMode\n ? frameworkIdMap[routerMode]\n : 'react-tanstack-router-file-based';\n\n return [\n `Router mode: ${modeName}`,\n `Framework docs ID: ${frameworkId} (use posthog://docs/frameworks/${frameworkId} for documentation)`,\n ];\n },\n },\n\n ui: {\n successMessage: 'PostHog integration complete',\n estimatedDurationMinutes: 8,\n getOutroChanges: (context) => {\n const modeName = context.routerMode\n ? getTanStackRouterModeName(context.routerMode)\n : 'TanStack Router';\n return [\n `Analyzed your React (TanStack Router) project structure (${modeName})`,\n `Created and configured PostHog initializers`,\n `Integrated PostHog into your application`,\n ];\n },\n getOutroNextSteps: () => [\n 'Start your development server to see PostHog in action',\n 'Visit your PostHog dashboard to see incoming events',\n ],\n },\n };\n","import { createVersionBucket } from '@utils/semver';\n\n/**\n * Get TanStack Start version bucket for analytics\n */\nexport const getTanStackStartVersionBucket = createVersionBucket();\n","/* TanStack Start wizard using posthog-agent with PostHog MCP */\nimport type { WizardRunOptions } from '@utils/types';\nimport type { FrameworkConfig } from '../../framework-config';\nimport { detectNodePackageManagers } from '../../detection/package-manager';\nimport { Integration } from '@shared/constants';\nimport {\n getDeclaredVersion,\n getInstalledPackageVersion,\n hasDeclaredDependency,\n type PackageJson,\n} from '@utils/package-json';\nimport { tryGetPackageJson } from '@utils/setup-utils';\nimport { getTanStackStartVersionBucket } from './utils';\n\ntype TanStackStartContext = Record<string, unknown>;\n\nexport const TANSTACK_START_AGENT_CONFIG: FrameworkConfig<TanStackStartContext> =\n {\n metadata: {\n name: 'TanStack Start',\n integration: Integration.tanstackStart,\n docsUrl: 'https://posthog.com/docs/libraries/react',\n },\n\n detection: {\n packageName: '@tanstack/react-start',\n packageDisplayName: 'TanStack Start',\n getVersion: (packageJson: unknown) =>\n getDeclaredVersion('@tanstack/react-start', packageJson as PackageJson),\n getVersionBucket: getTanStackStartVersionBucket,\n minimumVersion: '1.0.0',\n getInstalledVersion: (options: WizardRunOptions) =>\n Promise.resolve(\n getInstalledPackageVersion(\n '@tanstack/react-start',\n options.installDir,\n ),\n ),\n detect: async (options) => {\n const packageJson = await tryGetPackageJson(options);\n return packageJson\n ? hasDeclaredDependency('@tanstack/react-start', packageJson)\n : false;\n },\n detectPackageManager: detectNodePackageManagers,\n },\n\n environment: {\n uploadToHosting: false,\n getEnvVars: (apiKey: string, host: string) => ({\n VITE_PUBLIC_POSTHOG_PROJECT_TOKEN: apiKey,\n VITE_PUBLIC_POSTHOG_HOST: host,\n }),\n },\n\n analytics: {\n getTags: () => ({}),\n },\n\n prompts: {\n projectTypeDetection:\n 'This is a JavaScript/TypeScript project. Look for package.json and lockfiles (package-lock.json, yarn.lock, pnpm-lock.yaml, bun.lockb) to confirm.',\n getAdditionalContextLines: () => {\n // TanStack Start always uses file-based routing (it's a full-stack framework built on TanStack Router)\n const frameworkId = 'react-tanstack-start';\n\n return [\n `Framework docs ID: ${frameworkId} (use posthog://docs/frameworks/${frameworkId} for documentation)`,\n ];\n },\n },\n\n ui: {\n successMessage: 'PostHog integration complete',\n estimatedDurationMinutes: 8,\n getOutroChanges: () => [\n `Analyzed your TanStack Start project structure`,\n `Created and configured PostHog initializers`,\n `Integrated PostHog into your application`,\n ],\n getOutroNextSteps: () => [\n 'Start your development server to see PostHog in action',\n 'Visit your PostHog dashboard to see incoming events',\n ],\n },\n };\n","import { createVersionBucket } from '@utils/semver';\nimport { tryGetPackageJson } from '@utils/setup-utils';\nimport { hasDeclaredDependency } from '@utils/package-json';\nimport type { WizardRunOptions } from '@utils/types';\n\nexport const getReactNativeVersionBucket = createVersionBucket();\n\nexport enum ReactNativeVariant {\n EXPO = 'expo',\n REACT_NATIVE = 'react-native',\n}\n\nexport function getReactNativeVariantName(variant: ReactNativeVariant): string {\n return variant === ReactNativeVariant.EXPO ? 'Expo' : 'React Native';\n}\n\nexport async function detectReactNativeVariant(\n options: Pick<WizardRunOptions, 'installDir'>,\n): Promise<ReactNativeVariant> {\n const packageJson = await tryGetPackageJson(options);\n\n if (packageJson && hasDeclaredDependency('expo', packageJson)) {\n return ReactNativeVariant.EXPO;\n }\n\n return ReactNativeVariant.REACT_NATIVE;\n}\n","/* React Native wizard using posthog-agent with PostHog MCP */\nimport type { WizardRunOptions } from '@utils/types';\nimport type { FrameworkConfig } from '../../framework-config';\nimport { detectNodePackageManagers } from '../../detection/package-manager';\nimport { Integration } from '@shared/constants';\nimport {\n getDeclaredVersion,\n getInstalledPackageVersion,\n hasDeclaredDependency,\n type PackageJson,\n} from '@utils/package-json';\nimport { tryGetPackageJson } from '@utils/setup-utils';\nimport {\n detectReactNativeVariant,\n getReactNativeVariantName,\n getReactNativeVersionBucket,\n ReactNativeVariant,\n} from './utils';\n\ntype ReactNativeContext = {\n variant?: ReactNativeVariant;\n};\n\nexport const REACT_NATIVE_AGENT_CONFIG: FrameworkConfig<ReactNativeContext> = {\n metadata: {\n name: 'React Native',\n integration: Integration.reactNative,\n docsUrl: 'https://posthog.com/docs/libraries/react-native',\n gatherContext: async (options: WizardRunOptions) => {\n const variant = await detectReactNativeVariant(options);\n return { variant };\n },\n getDetectedFrameworkLabel: (context) =>\n context.variant\n ? `${getReactNativeVariantName(context.variant)} 📱`\n : undefined,\n },\n\n detection: {\n packageName: 'react-native',\n packageDisplayName: 'React Native',\n getVersion: (packageJson: unknown) =>\n getDeclaredVersion('react-native', packageJson as PackageJson),\n getVersionBucket: getReactNativeVersionBucket,\n minimumVersion: '0.73.0',\n getInstalledVersion: (options: WizardRunOptions) =>\n Promise.resolve(\n getInstalledPackageVersion('react-native', options.installDir),\n ),\n detect: async (options) => {\n const packageJson = await tryGetPackageJson(options);\n return packageJson\n ? hasDeclaredDependency('react-native', packageJson)\n : false;\n },\n detectPackageManager: detectNodePackageManagers,\n },\n\n environment: {\n uploadToHosting: false,\n getEnvVars: (apiKey: string, host: string) => ({\n POSTHOG_PROJECT_TOKEN: apiKey,\n POSTHOG_HOST: host,\n }),\n },\n\n analytics: {\n getTags: (context) => ({\n variant:\n context.variant === ReactNativeVariant.EXPO ? 'expo' : 'react-native',\n }),\n },\n\n prompts: {\n projectTypeDetection:\n 'This is a React Native project. Look for package.json, android/ and ios/ directories, and lockfiles to confirm. Check for expo in package.json to determine the variant.',\n getAdditionalContextLines: (context) => {\n const isExpo = context.variant === ReactNativeVariant.EXPO;\n const frameworkId = 'react-native';\n\n const lines = [\n `Framework docs ID: ${frameworkId} (use posthog://docs/frameworks/${frameworkId} for documentation)`,\n `Variant: ${isExpo ? 'Expo' : 'React Native'}`,\n ];\n\n if (isExpo) {\n lines.push(\n 'Use `npx expo install` for package installation.',\n 'Use EXPO_PUBLIC_ prefix for environment variables exposed to the client.',\n );\n } else {\n lines.push(\n 'This is a React Native project without Expo. Native linking may be required.',\n 'For iOS, ensure pods are installed after adding PostHog.',\n );\n }\n\n return lines;\n },\n },\n\n ui: {\n successMessage: 'PostHog integration complete',\n estimatedDurationMinutes: 10,\n getOutroChanges: (context) => {\n const variant = context.variant ?? ReactNativeVariant.REACT_NATIVE;\n const variantName = getReactNativeVariantName(variant);\n return [\n `Analyzed your React Native project structure (${variantName})`,\n `Installed and configured the PostHog React Native SDK`,\n `Integrated PostHog into your application`,\n ];\n },\n getOutroNextSteps: (context) => {\n const isExpo = context.variant === ReactNativeVariant.EXPO;\n const steps = [];\n\n if (!isExpo) {\n steps.push('Run `npx pod-install` to install iOS dependencies');\n }\n\n steps.push(\n isExpo\n ? 'Start your development server with `npx expo start` to see PostHog in action'\n : 'Start your development server to see PostHog in action',\n 'Visit your PostHog dashboard to see incoming events',\n );\n\n return steps;\n },\n },\n};\n","import { createVersionBucket } from '@utils/semver';\n\n/**\n * Get Angular version bucket for analytics\n */\nexport const getAngularVersionBucket = createVersionBucket();\n","/* Angular wizard using posthog-agent with PostHog MCP */\nimport type { WizardRunOptions } from '@utils/types';\nimport type { FrameworkConfig } from '../../framework-config';\nimport { detectNodePackageManagers } from '../../detection/package-manager';\nimport { Integration } from '@shared/constants';\nimport {\n getDeclaredVersion,\n getInstalledPackageVersion,\n hasDeclaredDependency,\n type PackageJson,\n} from '@utils/package-json';\nimport { tryGetPackageJson } from '@utils/setup-utils';\nimport { getAngularVersionBucket } from './utils';\n\ntype AngularContext = Record<string, unknown>;\n\nexport const ANGULAR_AGENT_CONFIG: FrameworkConfig<AngularContext> = {\n metadata: {\n name: 'Angular',\n integration: Integration.angular,\n docsUrl: 'https://posthog.com/docs/libraries/angular',\n },\n\n detection: {\n packageName: '@angular/core',\n packageDisplayName: 'Angular',\n getVersion: (packageJson: unknown) =>\n getDeclaredVersion('@angular/core', packageJson as PackageJson),\n getVersionBucket: getAngularVersionBucket,\n minimumVersion: '19.0.0',\n getInstalledVersion: (options: WizardRunOptions) =>\n Promise.resolve(\n getInstalledPackageVersion('@angular/core', options.installDir),\n ),\n detect: async (options) => {\n const packageJson = await tryGetPackageJson(options);\n return packageJson\n ? hasDeclaredDependency('@angular/core', packageJson)\n : false;\n },\n detectPackageManager: detectNodePackageManagers,\n },\n\n environment: {\n uploadToHosting: false,\n getEnvVars: (apiKey: string, host: string) => ({\n NG_APP_POSTHOG_PROJECT_TOKEN: apiKey,\n NG_APP_POSTHOG_HOST: host,\n }),\n },\n\n analytics: {\n getTags: () => ({}),\n },\n\n prompts: {\n projectTypeDetection:\n 'This is an Angular project. Look for package.json, angular.json, and lockfiles (package-lock.json, yarn.lock, pnpm-lock.yaml) to confirm.',\n getAdditionalContextLines: () => {\n const frameworkId = 'angular';\n\n return [\n `Framework docs ID: ${frameworkId} (use posthog://docs/frameworks/${frameworkId} for documentation)`,\n 'Angular uses dependency injection for services. PostHog should be initialized as a service.',\n 'For standalone components, ensure PostHog is properly provided in the application config.',\n ];\n },\n },\n\n ui: {\n successMessage: 'PostHog integration complete',\n estimatedDurationMinutes: 8,\n getOutroChanges: () => [\n `Analyzed your Angular project structure`,\n `Created and configured PostHog service`,\n `Integrated PostHog into your application`,\n ],\n getOutroNextSteps: () => [\n 'Start your development server with `ng serve` to see PostHog in action',\n 'Visit your PostHog dashboard to see incoming events',\n ],\n },\n};\n","import { boundedGlob, readProjectFile } from '@utils/bounded-fs';\nimport fs from 'fs/promises';\nimport path from 'path';\nimport type { WizardRunOptions } from '@utils/types';\nimport { createVersionBucket } from '@utils/semver';\n\nexport const getAstroVersionBucket = createVersionBucket();\n\nexport enum AstroRenderingMode {\n STATIC = 'static',\n SSR = 'ssr',\n HYBRID = 'hybrid',\n VIEW_TRANSITIONS = 'view-transitions',\n}\n\nconst EXTRA_IGNORE = ['**/.astro/**'];\n\n/**\n * Detect the Astro rendering mode. Pure — always resolves (Astro detection is reliable).\n */\nexport async function getAstroRenderingMode({\n installDir,\n}: Pick<WizardRunOptions, 'installDir'>): Promise<AstroRenderingMode> {\n const configMatches = await boundedGlob('astro.config.@(mjs|ts|js)', {\n cwd: installDir,\n extraIgnore: EXTRA_IGNORE,\n limit: 1,\n });\n\n let hasAdapter = false;\n let outputMode: string | null = null;\n let usesViewTransitions = false;\n\n try {\n const packageJsonPath = path.join(installDir, 'package.json');\n const packageJsonContent = await fs.readFile(packageJsonPath, 'utf-8');\n const packageJson = JSON.parse(packageJsonContent);\n const allDeps = {\n ...packageJson.dependencies,\n ...packageJson.devDependencies,\n };\n\n hasAdapter = Object.keys(allDeps).some(\n (dep) =>\n dep.startsWith('@astrojs/') &&\n (dep.includes('node') ||\n dep.includes('vercel') ||\n dep.includes('netlify') ||\n dep.includes('cloudflare') ||\n dep.includes('deno')),\n );\n } catch {\n // package.json not found or invalid\n }\n\n if (configMatches.length > 0) {\n try {\n const configPath = path.join(installDir, configMatches[0]);\n const configContent = await fs.readFile(configPath, 'utf-8');\n const outputMatch = configContent.match(/output:\\s*['\"](\\w+)['\"]/);\n if (outputMatch) {\n outputMode = outputMatch[1];\n }\n } catch {\n // Config file not readable\n }\n }\n\n const viewTransitionMatches = await boundedGlob(\n '**/*.@(astro|ts|tsx|js|jsx)',\n {\n cwd: installDir,\n extraIgnore: EXTRA_IGNORE,\n limit: 20,\n },\n );\n\n for (const file of viewTransitionMatches) {\n const content = readProjectFile(path.join(installDir, file));\n if (!content) continue;\n if (\n content.includes('ClientRouter') ||\n content.includes('ViewTransitions') ||\n content.includes('astro:transitions')\n ) {\n usesViewTransitions = true;\n break;\n }\n }\n\n if (usesViewTransitions) {\n return AstroRenderingMode.VIEW_TRANSITIONS;\n }\n\n if (outputMode === 'server' && hasAdapter) {\n return AstroRenderingMode.SSR;\n }\n\n if (hasAdapter) {\n return AstroRenderingMode.HYBRID;\n }\n\n return AstroRenderingMode.STATIC;\n}\n\nexport const getAstroRenderingModeName = (mode: AstroRenderingMode): string => {\n switch (mode) {\n case AstroRenderingMode.STATIC:\n return 'Static (SSG)';\n case AstroRenderingMode.VIEW_TRANSITIONS:\n return 'View Transitions';\n case AstroRenderingMode.SSR:\n return 'Server (SSR)';\n case AstroRenderingMode.HYBRID:\n return 'Hybrid';\n default:\n return 'Static';\n }\n};\n","/* Astro wizard using posthog-agent with PostHog MCP */\nimport type { WizardRunOptions } from '@utils/types';\nimport type { FrameworkConfig } from '../../framework-config';\nimport { detectNodePackageManagers } from '../../detection/package-manager';\nimport { Integration } from '@shared/constants';\nimport {\n getDeclaredVersion,\n getInstalledPackageVersion,\n hasDeclaredDependency,\n type PackageJson,\n} from '@utils/package-json';\nimport { tryGetPackageJson } from '@utils/setup-utils';\nimport {\n getAstroRenderingMode,\n getAstroVersionBucket,\n getAstroRenderingModeName,\n AstroRenderingMode,\n} from './utils';\n\ntype AstroContext = {\n renderingMode?: AstroRenderingMode;\n};\n\nexport const ASTRO_AGENT_CONFIG: FrameworkConfig<AstroContext> = {\n metadata: {\n name: 'Astro',\n integration: Integration.astro,\n docsUrl: 'https://posthog.com/docs/libraries/astro',\n gatherContext: async (options: WizardRunOptions) => {\n const renderingMode = await getAstroRenderingMode(options);\n return { renderingMode };\n },\n getDetectedFrameworkLabel: (context) =>\n context.renderingMode\n ? `Astro ${getAstroRenderingModeName(context.renderingMode)}`\n : undefined,\n },\n\n detection: {\n packageName: 'astro',\n packageDisplayName: 'Astro',\n getVersion: (packageJson: unknown) =>\n getDeclaredVersion('astro', packageJson as PackageJson),\n getVersionBucket: getAstroVersionBucket,\n minimumVersion: '4.0.0',\n getInstalledVersion: (options: WizardRunOptions) =>\n Promise.resolve(getInstalledPackageVersion('astro', options.installDir)),\n detect: async (options) => {\n const packageJson = await tryGetPackageJson(options);\n return packageJson ? hasDeclaredDependency('astro', packageJson) : false;\n },\n detectPackageManager: detectNodePackageManagers,\n },\n\n environment: {\n uploadToHosting: true,\n getEnvVars: (apiKey: string, host: string) => ({\n PUBLIC_POSTHOG_PROJECT_TOKEN: apiKey,\n PUBLIC_POSTHOG_HOST: host,\n }),\n },\n\n analytics: {\n getTags: (context) => ({\n 'rendering-mode': context.renderingMode ?? 'static',\n }),\n },\n\n prompts: {\n projectTypeDetection:\n 'This is a JavaScript/TypeScript project. Look for package.json and lockfiles (package-lock.json, yarn.lock, pnpm-lock.yaml, bun.lockb) to confirm.',\n getAdditionalContextLines: (context) => {\n const modeName = getAstroRenderingModeName(\n context.renderingMode ?? AstroRenderingMode.STATIC,\n );\n\n // Map rendering mode to framework ID for MCP docs resource\n const frameworkIdMap: Record<AstroRenderingMode, string> = {\n [AstroRenderingMode.STATIC]: 'astro-static',\n [AstroRenderingMode.VIEW_TRANSITIONS]: 'astro-view-transitions',\n [AstroRenderingMode.SSR]: 'astro-ssr',\n [AstroRenderingMode.HYBRID]: 'astro-hybrid',\n };\n\n const frameworkId =\n frameworkIdMap[context.renderingMode ?? AstroRenderingMode.STATIC];\n\n const lines = [\n `Rendering mode: ${modeName}`,\n `Framework docs ID: ${frameworkId} (use posthog://docs/frameworks/${frameworkId} for documentation)`,\n ];\n\n // Add mode-specific guidance\n if (context.renderingMode === AstroRenderingMode.VIEW_TRANSITIONS) {\n lines.push(\n 'IMPORTANT: Use window.__posthog_initialized guard to prevent re-initialization during soft navigation',\n );\n lines.push(\n \"IMPORTANT: Set capture_pageview: 'history_change' for automatic pageview tracking\",\n );\n }\n\n if (\n context.renderingMode === AstroRenderingMode.SSR ||\n context.renderingMode === AstroRenderingMode.HYBRID\n ) {\n lines.push(\n 'IMPORTANT: Use posthog-node for server-side tracking in API routes',\n );\n lines.push(\n 'IMPORTANT: Create a singleton pattern for the posthog-node client',\n );\n }\n\n return lines;\n },\n },\n\n ui: {\n successMessage: 'PostHog integration complete',\n estimatedDurationMinutes: 6,\n getOutroChanges: (context) => {\n const modeName = getAstroRenderingModeName(\n context.renderingMode ?? AstroRenderingMode.STATIC,\n );\n const changes = [\n `Analyzed your Astro project structure (${modeName})`,\n `Created PostHog component with is:inline script`,\n `Integrated PostHog into your layout`,\n ];\n\n if (\n context.renderingMode === AstroRenderingMode.SSR ||\n context.renderingMode === AstroRenderingMode.HYBRID\n ) {\n changes.push(`Set up posthog-node for server-side tracking`);\n }\n\n if (context.renderingMode === AstroRenderingMode.VIEW_TRANSITIONS) {\n changes.push(\n `Added initialization guard for view transitions compatibility`,\n );\n }\n\n return changes;\n },\n getOutroNextSteps: () => {\n return [\n 'Start your development server to see PostHog in action',\n 'Visit your PostHog dashboard to see incoming events',\n ];\n },\n },\n};\n","import type { Integration } from '@shared/constants';\nimport type { WizardRunOptions } from '@utils/types';\nimport type { PackageManagerDetector } from './detection/package-manager';\n\n/**\n * A setup question that the SetupScreen renders for framework disambiguation.\n * If detect() returns a value, the question is auto-resolved and not shown.\n */\nexport interface SetupQuestion {\n /** Stored in session.frameworkContext[key] */\n key: string;\n /** Displayed to user, e.g. \"Which router are you using?\" */\n message: string;\n /** Picker options */\n options: Array<{ label: string; value: string; hint?: string }>;\n /** Auto-detect; null = ask the user */\n detect: (\n options: Pick<WizardRunOptions, 'installDir'>,\n ) => Promise<string | null>;\n}\n\n/**\n * Configuration interface for framework-specific agent integrations.\n * Each framework exports a FrameworkConfig that the universal runner uses.\n *\n * The TContext generic represents the framework-specific context gathered\n * before the agent runs (e.g., router type for Next.js, project type for Django).\n * The runner threads this opaquely — all framework-specific logic stays inside the config.\n */\nexport interface FrameworkConfig<\n TContext extends Record<string, unknown> = Record<string, unknown>,\n> {\n metadata: FrameworkMetadata<TContext>;\n detection: FrameworkDetection;\n environment: EnvironmentConfig;\n analytics: AnalyticsConfig<TContext>;\n prompts: PromptConfig<TContext>;\n ui: UIConfig<TContext>;\n}\n\n/**\n * Basic framework information and documentation\n */\nexport interface FrameworkMetadata<\n TContext extends Record<string, unknown> = Record<string, unknown>,\n> {\n /** Display name (e.g., \"Next.js\", \"React\") */\n name: string;\n\n /** Integration type from constants */\n integration: Integration;\n\n /** URL to framework-specific PostHog docs */\n docsUrl: string;\n\n /**\n * Optional URL to docs for users with unsupported framework versions.\n * If not provided, defaults to docsUrl.\n */\n unsupportedVersionDocsUrl?: string;\n\n /** If true, shows a beta notice before running the wizard. */\n beta?: boolean;\n\n /** Optional notice shown before the agent runs (e.g., \"Close Xcode before proceeding\"). */\n preRunNotice?: string;\n\n /**\n * Optional function to gather framework-specific context before agent runs.\n * For Next.js: detects router type\n * For React Native: detects Expo vs bare\n */\n gatherContext?: (options: WizardRunOptions) => Promise<TContext>;\n\n /** Label for the gathered variant, if gathering found a more specific name. */\n getDetectedFrameworkLabel?: (context: TContext) => string | undefined;\n\n /** Optional additional MCP servers for this framework (e.g., Svelte MCP). */\n additionalMcpServers?: Record<string, { url: string }>;\n\n /**\n * Setup questions for framework disambiguation.\n * The SetupScreen iterates unresolved questions and renders a PickerMenu for each.\n * If all questions are auto-resolved (or none defined), the screen is skipped.\n */\n setup?: {\n questions: SetupQuestion[];\n };\n}\n\n/**\n * Framework detection and version handling\n */\nexport interface FrameworkDetection {\n /** Package name to check in package.json (e.g., \"next\", \"react\") */\n packageName: string;\n\n /** Human-readable name for error messages (e.g., \"Next.js\") */\n packageDisplayName: string;\n\n /** Extract version from package.json */\n getVersion: (packageJson: unknown) => string | undefined;\n\n /** Optional: Convert version to analytics bucket (e.g., \"15.x\") */\n getVersionBucket?: (version: string) => string;\n\n /**\n * Whether this framework uses package.json (Node.js/JavaScript).\n * If false, skips package.json checks (for Python, Go, etc.)\n * Defaults to true if not specified.\n */\n usesPackageJson?: boolean;\n\n /** Minimum supported version. If set, runner checks before proceeding. */\n minimumVersion?: string;\n\n /** Get the currently installed version. Called by runner for version check. */\n getInstalledVersion?: (\n options: WizardRunOptions,\n ) => Promise<string | undefined>;\n\n /** Detect whether this framework is present in the project. */\n detect: (options: Pick<WizardRunOptions, 'installDir'>) => Promise<boolean>;\n\n /** Detect the project's package manager(s). Used by the in-process MCP tool. */\n detectPackageManager: PackageManagerDetector;\n}\n\n/**\n * Environment variable configuration\n */\nexport interface EnvironmentConfig {\n /** Whether to upload env vars to hosting providers post-agent */\n uploadToHosting: boolean;\n\n /**\n * Build the environment variables object for this framework.\n * Returns the exact variable names and values to upload to hosting providers.\n */\n getEnvVars: (apiKey: string, host: string) => Record<string, string>;\n}\n\n/**\n * Analytics configuration\n */\nexport interface AnalyticsConfig<\n TContext extends Record<string, unknown> = Record<string, unknown>,\n> {\n /** Generate tags from context (e.g., { 'nextjs-version': '15.x', 'router': 'app' }) */\n getTags: (context: TContext) => Record<string, string>;\n\n /** Optional: Additional event properties */\n getEventProperties?: (context: TContext) => Record<string, string>;\n}\n\n/**\n * Default package installation instruction used when frameworks don't\n * provide their own. Frameworks with specific needs (e.g., Swift SPM,\n * Composer) override this in their config.\n */\nexport const DEFAULT_PACKAGE_INSTALLATION =\n 'Use the detect_package_manager tool to determine the package manager. Do not manually edit package.json; the package manager handles it automatically.';\n\nexport const PYTHON_PACKAGE_INSTALLATION =\n 'Use the detect_package_manager tool to determine the package manager. If the detected tool manages dependencies directly (e.g. uv add, poetry add), use it — it will update the manifest automatically. If using pip, you must also add the dependency to requirements.txt or the appropriate manifest file.';\n\n/**\n * Prompt configuration\n */\nexport interface PromptConfig<\n TContext extends Record<string, unknown> = Record<string, unknown>,\n> {\n /**\n * Optional: Additional context lines to append to base prompt\n * For Next.js: \"- Router: app\"\n * For React Native: \"- Platform: Expo\"\n */\n getAdditionalContextLines?: (context: TContext) => string[];\n\n /**\n * How to detect the project type for this framework.\n * Included in the agent prompt as project context.\n * e.g., \"Look for package.json and lockfiles\" or \"Look for requirements.txt and manage.py\"\n */\n projectTypeDetection: string;\n\n /**\n * How to install packages for this framework.\n * Included in the agent prompt as project context.\n * Defaults to DEFAULT_PACKAGE_INSTALLATION. Only override if the framework\n * has specific installation guidance (e.g., Swift SPM, Composer).\n */\n packageInstallation?: string;\n}\n\n/**\n * UI messaging configuration\n */\nexport interface UIConfig<\n TContext extends Record<string, unknown> = Record<string, unknown>,\n> {\n /** Success message when agent completes */\n successMessage: string;\n\n /** Estimated time for agent to complete (in minutes) */\n estimatedDurationMinutes: number;\n\n /** Generate \"What the agent did\" bullets from context */\n getOutroChanges: (context: TContext) => string[];\n\n /** Generate \"Next steps\" bullets from context */\n getOutroNextSteps: (context: TContext) => string[];\n}\n\n/**\n * Generate welcome message from framework name\n */\nexport function getWelcomeMessage(frameworkName: string): string {\n return `PostHog ${frameworkName} wizard (agent-powered)`;\n}\n\n/**\n * Shared spinner message for all frameworks\n */\nexport const SPINNER_MESSAGE =\n 'Writing your PostHog setup with events, error capture and more...';\n","import { boundedGlob, readProjectFile } from '@utils/bounded-fs';\nimport type { WizardRunOptions } from '@utils/types';\nimport { createVersionBucket } from '@utils/semver';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nexport enum DjangoProjectType {\n STANDARD = 'standard', // Traditional Django project (django-admin startproject)\n DRF = 'drf', // Django REST Framework API\n WAGTAIL = 'wagtail', // Wagtail CMS\n CHANNELS = 'channels', // Django Channels (async/websockets)\n}\n\nconst EXTRA_IGNORE = ['**/env/**', '**/.env/**', '**/migrations/**'];\n\n/**\n * Get Django version bucket for analytics\n */\nexport const getDjangoVersionBucket = createVersionBucket();\n\n/**\n * Extract Django version from requirements files or pyproject.toml\n */\nexport async function getDjangoVersion(\n options: Pick<WizardRunOptions, 'installDir'>,\n): Promise<string | undefined> {\n const { installDir } = options;\n\n // Check requirements files\n const requirementsFiles = await boundedGlob(\n ['**/requirements*.txt', '**/pyproject.toml', '**/setup.py', '**/Pipfile'],\n {\n cwd: installDir,\n extraIgnore: EXTRA_IGNORE,\n },\n );\n\n for (const reqFile of requirementsFiles) {\n const content = readProjectFile(path.join(installDir, reqFile));\n if (!content) continue;\n\n // Try to extract version from requirements.txt format (Django==4.2.0 or Django>=4.0)\n const requirementsMatch = content.match(\n /[Dd]jango[=<>~!]+([0-9]+\\.[0-9]+(?:\\.[0-9]+)?)/,\n );\n if (requirementsMatch) {\n return requirementsMatch[1];\n }\n\n // Try to extract from pyproject.toml format\n const pyprojectMatch = content.match(\n /[Dd]jango[\"\\s]*[=<>~!]+\\s*[\"']?([0-9]+\\.[0-9]+(?:\\.[0-9]+)?)/,\n );\n if (pyprojectMatch) {\n return pyprojectMatch[1];\n }\n }\n\n return undefined;\n}\n\n/**\n * Check if Django REST Framework is installed\n */\nasync function hasDRF({\n installDir,\n}: Pick<WizardRunOptions, 'installDir'>): Promise<boolean> {\n const requirementsFiles = await boundedGlob(\n ['**/requirements*.txt', '**/pyproject.toml', '**/Pipfile'],\n {\n cwd: installDir,\n extraIgnore: EXTRA_IGNORE,\n },\n );\n\n for (const reqFile of requirementsFiles) {\n const content = readProjectFile(path.join(installDir, reqFile));\n if (content?.includes('djangorestframework')) {\n return true;\n }\n }\n\n // Also check INSTALLED_APPS in settings\n const settingsFiles = await boundedGlob('**/settings.py', {\n cwd: installDir,\n extraIgnore: EXTRA_IGNORE,\n });\n\n for (const settingsFile of settingsFiles) {\n const content = readProjectFile(path.join(installDir, settingsFile));\n if (content?.includes('rest_framework')) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Check if Wagtail is installed\n */\nasync function hasWagtail({\n installDir,\n}: Pick<WizardRunOptions, 'installDir'>): Promise<boolean> {\n const requirementsFiles = await boundedGlob(\n ['**/requirements*.txt', '**/pyproject.toml', '**/Pipfile'],\n {\n cwd: installDir,\n extraIgnore: EXTRA_IGNORE,\n },\n );\n\n for (const reqFile of requirementsFiles) {\n const content = readProjectFile(path.join(installDir, reqFile));\n if (content?.includes('wagtail')) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Check if Django Channels is installed\n */\nasync function hasChannels({\n installDir,\n}: Pick<WizardRunOptions, 'installDir'>): Promise<boolean> {\n const requirementsFiles = await boundedGlob(\n ['**/requirements*.txt', '**/pyproject.toml', '**/Pipfile'],\n {\n cwd: installDir,\n extraIgnore: EXTRA_IGNORE,\n },\n );\n\n for (const reqFile of requirementsFiles) {\n const content = readProjectFile(path.join(installDir, reqFile));\n if (content?.includes('channels')) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Detect Django project type\n */\nexport async function getDjangoProjectType(\n options: WizardRunOptions,\n): Promise<DjangoProjectType> {\n const { installDir } = options;\n\n // Check for Wagtail first (CMS)\n if (await hasWagtail({ installDir })) {\n return DjangoProjectType.WAGTAIL;\n }\n\n // Check for Django REST Framework\n if (await hasDRF({ installDir })) {\n return DjangoProjectType.DRF;\n }\n\n // Check for Django Channels\n if (await hasChannels({ installDir })) {\n return DjangoProjectType.CHANNELS;\n }\n\n // Default to standard Django\n return DjangoProjectType.STANDARD;\n}\n\n/**\n * Get human-readable name for Django project type\n */\nexport function getDjangoProjectTypeName(\n projectType: DjangoProjectType,\n): string {\n switch (projectType) {\n case DjangoProjectType.STANDARD:\n return 'Standard Django';\n case DjangoProjectType.DRF:\n return 'Django REST Framework';\n case DjangoProjectType.WAGTAIL:\n return 'Wagtail CMS';\n case DjangoProjectType.CHANNELS:\n return 'Django Channels';\n }\n}\n\n/**\n * Find the main Django settings file\n */\nexport async function findDjangoSettingsFile(\n options: Pick<WizardRunOptions, 'installDir'>,\n): Promise<string | undefined> {\n const { installDir } = options;\n\n // Look for settings.py files\n const settingsFiles = await boundedGlob('**/settings.py', {\n cwd: installDir,\n extraIgnore: EXTRA_IGNORE,\n });\n\n if (settingsFiles.length === 0) {\n // Try settings/__init__.py for split settings\n const splitSettingsFiles = await boundedGlob('**/settings/__init__.py', {\n cwd: installDir,\n extraIgnore: EXTRA_IGNORE,\n limit: 1,\n });\n\n if (splitSettingsFiles.length > 0) {\n return splitSettingsFiles[0];\n }\n\n return undefined;\n }\n\n // If multiple settings files, prefer the one next to manage.py or in root\n if (settingsFiles.length === 1) {\n return settingsFiles[0];\n }\n\n // Try to find the main settings file by looking for ROOT_URLCONF\n for (const settingsFile of settingsFiles) {\n const content = readProjectFile(path.join(installDir, settingsFile));\n if (content?.includes('ROOT_URLCONF')) {\n return settingsFile;\n }\n }\n\n // Default to first found\n return settingsFiles[0];\n}\n\n/**\n * Find the main Django urls.py file\n */\nexport async function findDjangoUrlsFile(\n options: Pick<WizardRunOptions, 'installDir'>,\n): Promise<string | undefined> {\n const { installDir } = options;\n\n // First, try to find the root urls.py referenced in settings\n const settingsFile = await findDjangoSettingsFile(options);\n if (settingsFile) {\n const settingsContent = readProjectFile(\n path.join(installDir, settingsFile),\n );\n const urlconfMatch = settingsContent?.match(\n /ROOT_URLCONF\\s*=\\s*['\"]([^'\"]+)['\"]/,\n );\n if (urlconfMatch) {\n const urlconfPath = urlconfMatch[1].replace(/\\./g, '/') + '.py';\n const fullPath = path.join(installDir, urlconfPath);\n if (fs.existsSync(fullPath)) {\n return urlconfPath;\n }\n }\n }\n\n // Fallback to glob search\n const urlsFiles = await boundedGlob('**/urls.py', {\n cwd: installDir,\n extraIgnore: [...EXTRA_IGNORE, '**/admin/**'],\n });\n\n if (urlsFiles.length === 0) {\n return undefined;\n }\n\n // Prefer urls.py files that contain urlpatterns\n for (const urlsFile of urlsFiles) {\n const content = readProjectFile(path.join(installDir, urlsFile));\n if (content?.includes('urlpatterns')) {\n return urlsFile;\n }\n }\n\n return urlsFiles[0];\n}\n","/* Django wizard using posthog-agent with PostHog MCP */\nimport type { WizardRunOptions } from '@utils/types';\nimport type { FrameworkConfig } from '../../framework-config';\nimport { PYTHON_PACKAGE_INSTALLATION } from '../../framework-config';\nimport { detectPythonPackageManagers } from '../../detection/package-manager';\nimport { Integration } from '@shared/constants';\nimport { boundedGlob, readProjectFile } from '@utils/bounded-fs';\nimport * as path from 'node:path';\nimport {\n getDjangoVersion,\n getDjangoProjectType,\n getDjangoProjectTypeName,\n getDjangoVersionBucket,\n DjangoProjectType,\n findDjangoSettingsFile,\n} from './utils';\n\nconst EXTRA_IGNORE = ['**/env/**', '**/.env/**'];\n\ntype DjangoContext = {\n projectType?: DjangoProjectType;\n settingsFile?: string;\n};\n\nexport const DJANGO_AGENT_CONFIG: FrameworkConfig<DjangoContext> = {\n metadata: {\n name: 'Django',\n integration: Integration.django,\n docsUrl: 'https://posthog.com/docs/libraries/django',\n unsupportedVersionDocsUrl: 'https://posthog.com/docs/libraries/python',\n gatherContext: async (options: WizardRunOptions) => {\n const projectType = await getDjangoProjectType(options);\n const settingsFile = await findDjangoSettingsFile(options);\n return { projectType, settingsFile };\n },\n getDetectedFrameworkLabel: (context) => {\n switch (context.projectType) {\n case DjangoProjectType.WAGTAIL:\n return 'Django with Wagtail CMS';\n case DjangoProjectType.DRF:\n return 'Django REST Framework';\n case DjangoProjectType.CHANNELS:\n return 'Django Channels';\n case DjangoProjectType.STANDARD:\n return 'Django';\n }\n },\n },\n\n detection: {\n packageName: 'django',\n packageDisplayName: 'Django',\n usesPackageJson: false,\n getVersion: () => undefined,\n getVersionBucket: getDjangoVersionBucket,\n minimumVersion: '3.0.0',\n getInstalledVersion: (options: WizardRunOptions) =>\n getDjangoVersion(options),\n detect: async (options) => {\n const { installDir } = options;\n\n const managePyMatches = await boundedGlob('**/manage.py', {\n cwd: installDir,\n extraIgnore: EXTRA_IGNORE,\n });\n\n if (managePyMatches.length > 0) {\n for (const match of managePyMatches) {\n const content = readProjectFile(path.join(installDir, match));\n if (!content) continue;\n // Check for actual Django imports and usage\n if (\n content.includes('from django') ||\n content.includes('import django') ||\n content.includes('DJANGO_SETTINGS_MODULE') ||\n /execute_from_command_line/.test(content)\n ) {\n return true;\n }\n }\n }\n\n const requirementsFiles = await boundedGlob(\n ['**/requirements*.txt', '**/pyproject.toml', '**/setup.py'],\n {\n cwd: installDir,\n extraIgnore: EXTRA_IGNORE,\n },\n );\n\n for (const reqFile of requirementsFiles) {\n const content = readProjectFile(path.join(installDir, reqFile));\n if (!content) continue;\n // Match Django as a package requirement, not in comments or other text\n // Look for: django, django>=, django==, django~=, Django (capitalized)\n if (\n /^django([>=~!<\\s]|$)/im.test(content) ||\n /[\"']django[\"']/i.test(content)\n ) {\n return true;\n }\n }\n\n return false;\n },\n detectPackageManager: detectPythonPackageManagers,\n },\n\n environment: {\n uploadToHosting: false,\n getEnvVars: (apiKey: string, host: string) => ({\n POSTHOG_PROJECT_TOKEN: apiKey,\n POSTHOG_HOST: host,\n }),\n },\n\n analytics: {\n getTags: (context) => ({\n projectType: context.projectType || 'unknown',\n }),\n },\n\n prompts: {\n packageInstallation: PYTHON_PACKAGE_INSTALLATION,\n projectTypeDetection:\n 'This is a Python/Django project. Look for requirements.txt, pyproject.toml, setup.py, Pipfile, or manage.py to confirm.',\n getAdditionalContextLines: (context) => {\n const projectTypeName = context.projectType\n ? getDjangoProjectTypeName(context.projectType)\n : 'unknown';\n\n // Map project type to framework ID for MCP docs resource\n const frameworkIdMap: Record<DjangoProjectType, string> = {\n [DjangoProjectType.STANDARD]: 'django',\n [DjangoProjectType.DRF]: 'django',\n [DjangoProjectType.WAGTAIL]: 'django',\n [DjangoProjectType.CHANNELS]: 'django',\n };\n\n const frameworkId = context.projectType\n ? frameworkIdMap[context.projectType]\n : 'django';\n\n const lines = [\n `Project type: ${projectTypeName}`,\n `Framework docs ID: ${frameworkId} (use posthog://docs/frameworks/${frameworkId} for documentation)`,\n ];\n\n if (context.settingsFile) {\n lines.push(`Settings file: ${context.settingsFile}`);\n }\n\n return lines;\n },\n },\n\n ui: {\n successMessage: 'PostHog integration complete',\n estimatedDurationMinutes: 5,\n getOutroChanges: (context) => {\n const projectTypeName = context.projectType\n ? getDjangoProjectTypeName(context.projectType)\n : 'Django';\n return [\n `Analyzed your ${projectTypeName} project structure`,\n `Installed the PostHog Python package`,\n `Configured PostHog in your Django settings`,\n `Added PostHog middleware for automatic event tracking`,\n ];\n },\n getOutroNextSteps: () => [\n 'Start your Django development server to see PostHog in action',\n 'Visit your PostHog dashboard to see incoming events',\n 'Use identify_context() within new_context() to associate events with users',\n ],\n },\n};\n","import { boundedGlob, readProjectFile } from '@utils/bounded-fs';\nimport type { WizardRunOptions } from '@utils/types';\nimport { createVersionBucket } from '@utils/semver';\nimport * as path from 'node:path';\n\nexport enum FlaskProjectType {\n STANDARD = 'standard', // Basic Flask app\n RESTFUL = 'restful', // Flask-RESTful API\n RESTX = 'restx', // Flask-RESTX (Swagger docs)\n SMOREST = 'smorest', // flask-smorest (OpenAPI)\n BLUEPRINT = 'blueprint', // Large app with blueprints\n}\n\nconst EXTRA_IGNORE = [\n '**/env/**',\n '**/.env/**',\n '**/migrations/**',\n '**/instance/**',\n];\n\n/** Content probes read at most this many files, one in memory at a time. */\nconst SOURCE_PROBE_LIMIT = 200;\n\n/**\n * Get Flask version bucket for analytics\n */\nexport const getFlaskVersionBucket = createVersionBucket();\n\n/**\n * Extract Flask version from requirements files or pyproject.toml\n */\nexport async function getFlaskVersion(\n options: Pick<WizardRunOptions, 'installDir'>,\n): Promise<string | undefined> {\n const { installDir } = options;\n\n // Check requirements files\n const requirementsFiles = await boundedGlob(\n ['**/requirements*.txt', '**/pyproject.toml', '**/setup.py', '**/Pipfile'],\n {\n cwd: installDir,\n extraIgnore: EXTRA_IGNORE,\n },\n );\n\n for (const reqFile of requirementsFiles) {\n const content = readProjectFile(path.join(installDir, reqFile));\n if (!content) continue;\n\n // Try to extract version from requirements.txt format (Flask==3.0.0 or flask>=2.0)\n const requirementsMatch = content.match(\n /[Ff]lask[=<>~!]+([0-9]+\\.[0-9]+(?:\\.[0-9]+)?)/,\n );\n if (requirementsMatch) {\n return requirementsMatch[1];\n }\n\n // Try to extract from pyproject.toml format\n const pyprojectMatch = content.match(\n /[Ff]lask[\"\\s]*[=<>~!]+\\s*[\"']?([0-9]+\\.[0-9]+(?:\\.[0-9]+)?)/,\n );\n if (pyprojectMatch) {\n return pyprojectMatch[1];\n }\n }\n\n return undefined;\n}\n\n/**\n * Check if Flask-RESTful is installed\n */\nasync function hasFlaskRESTful({\n installDir,\n}: Pick<WizardRunOptions, 'installDir'>): Promise<boolean> {\n const requirementsFiles = await boundedGlob(\n ['**/requirements*.txt', '**/pyproject.toml', '**/Pipfile'],\n {\n cwd: installDir,\n extraIgnore: EXTRA_IGNORE,\n },\n );\n\n for (const reqFile of requirementsFiles) {\n const content = readProjectFile(path.join(installDir, reqFile));\n if (!content) continue;\n if (\n content.includes('flask-restful') ||\n content.includes('Flask-RESTful')\n ) {\n return true;\n }\n }\n\n // Also check imports in Python files\n const pyFiles = await boundedGlob(['**/*.py'], {\n cwd: installDir,\n extraIgnore: EXTRA_IGNORE,\n limit: SOURCE_PROBE_LIMIT,\n });\n\n for (const pyFile of pyFiles) {\n const content = readProjectFile(path.join(installDir, pyFile));\n if (!content) continue;\n if (\n content.includes('from flask_restful import') ||\n content.includes('import flask_restful')\n ) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Check if Flask-RESTX is installed\n */\nasync function hasFlaskRESTX({\n installDir,\n}: Pick<WizardRunOptions, 'installDir'>): Promise<boolean> {\n const requirementsFiles = await boundedGlob(\n ['**/requirements*.txt', '**/pyproject.toml', '**/Pipfile'],\n {\n cwd: installDir,\n extraIgnore: EXTRA_IGNORE,\n },\n );\n\n for (const reqFile of requirementsFiles) {\n const content = readProjectFile(path.join(installDir, reqFile));\n if (!content) continue;\n if (content.includes('flask-restx') || content.includes('Flask-RESTX')) {\n return true;\n }\n }\n\n // Also check imports in Python files\n const pyFiles = await boundedGlob(['**/*.py'], {\n cwd: installDir,\n extraIgnore: EXTRA_IGNORE,\n limit: SOURCE_PROBE_LIMIT,\n });\n\n for (const pyFile of pyFiles) {\n const content = readProjectFile(path.join(installDir, pyFile));\n if (!content) continue;\n if (\n content.includes('from flask_restx import') ||\n content.includes('import flask_restx')\n ) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Check if flask-smorest is installed\n */\nasync function hasFlaskSmorest({\n installDir,\n}: Pick<WizardRunOptions, 'installDir'>): Promise<boolean> {\n const requirementsFiles = await boundedGlob(\n ['**/requirements*.txt', '**/pyproject.toml', '**/Pipfile'],\n {\n cwd: installDir,\n extraIgnore: EXTRA_IGNORE,\n },\n );\n\n for (const reqFile of requirementsFiles) {\n const content = readProjectFile(path.join(installDir, reqFile));\n if (!content) continue;\n if (content.includes('flask-smorest')) {\n return true;\n }\n }\n\n // Also check imports in Python files\n const pyFiles = await boundedGlob(['**/*.py'], {\n cwd: installDir,\n extraIgnore: EXTRA_IGNORE,\n limit: SOURCE_PROBE_LIMIT,\n });\n\n for (const pyFile of pyFiles) {\n const content = readProjectFile(path.join(installDir, pyFile));\n if (!content) continue;\n if (\n content.includes('from flask_smorest import') ||\n content.includes('import flask_smorest')\n ) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Check if app uses Flask Blueprints\n */\nasync function hasBlueprints({\n installDir,\n}: Pick<WizardRunOptions, 'installDir'>): Promise<boolean> {\n const pyFiles = await boundedGlob(['**/*.py'], {\n cwd: installDir,\n extraIgnore: EXTRA_IGNORE,\n limit: SOURCE_PROBE_LIMIT,\n });\n\n for (const pyFile of pyFiles) {\n const content = readProjectFile(path.join(installDir, pyFile));\n if (!content) continue;\n if (\n content.includes('Blueprint(') ||\n content.includes('register_blueprint(') ||\n content.includes('from flask import Blueprint')\n ) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Detect Flask project type\n */\nexport async function getFlaskProjectType(\n options: WizardRunOptions,\n): Promise<FlaskProjectType> {\n const { installDir } = options;\n\n // Check for Flask-RESTX first (most specific - includes Swagger)\n if (await hasFlaskRESTX({ installDir })) {\n return FlaskProjectType.RESTX;\n }\n\n // Check for flask-smorest (OpenAPI-first)\n if (await hasFlaskSmorest({ installDir })) {\n return FlaskProjectType.SMOREST;\n }\n\n // Check for Flask-RESTful\n if (await hasFlaskRESTful({ installDir })) {\n return FlaskProjectType.RESTFUL;\n }\n\n // Check for Blueprints (large app structure)\n if (await hasBlueprints({ installDir })) {\n return FlaskProjectType.BLUEPRINT;\n }\n\n // Default to standard Flask\n return FlaskProjectType.STANDARD;\n}\n\n/**\n * Get human-readable name for Flask project type\n */\nexport function getFlaskProjectTypeName(projectType: FlaskProjectType): string {\n switch (projectType) {\n case FlaskProjectType.STANDARD:\n return 'Standard Flask';\n case FlaskProjectType.RESTFUL:\n return 'Flask-RESTful';\n case FlaskProjectType.RESTX:\n return 'Flask-RESTX';\n case FlaskProjectType.SMOREST:\n return 'flask-smorest';\n case FlaskProjectType.BLUEPRINT:\n return 'Flask with Blueprints';\n }\n}\n\n/**\n * Find the main Flask app file\n */\nexport async function findFlaskAppFile(\n options: Pick<WizardRunOptions, 'installDir'>,\n): Promise<string | undefined> {\n const { installDir } = options;\n\n // Common Flask app file patterns\n const commonPatterns = [\n '**/app.py',\n '**/wsgi.py',\n '**/application.py',\n '**/run.py',\n '**/main.py',\n '**/__init__.py',\n ];\n\n const appFiles = await boundedGlob(commonPatterns, {\n cwd: installDir,\n extraIgnore: EXTRA_IGNORE,\n });\n\n // Look for files with Flask() instantiation or create_app() factory\n for (const appFile of appFiles) {\n const content = readProjectFile(path.join(installDir, appFile));\n if (!content) continue;\n // Check for Flask app instantiation or application factory\n if (\n content.includes('Flask(__name__)') ||\n content.includes('Flask(') ||\n content.includes('def create_app(')\n ) {\n return appFile;\n }\n }\n\n // If no file with Flask() found, check all Python files\n const allPyFiles = await boundedGlob(['**/*.py'], {\n cwd: installDir,\n extraIgnore: EXTRA_IGNORE,\n limit: SOURCE_PROBE_LIMIT,\n });\n\n for (const pyFile of allPyFiles) {\n const content = readProjectFile(path.join(installDir, pyFile));\n if (!content) continue;\n if (\n content.includes('Flask(__name__)') ||\n content.includes('def create_app(')\n ) {\n return pyFile;\n }\n }\n\n // Return first common pattern file if exists\n if (appFiles.length > 0) {\n return appFiles[0];\n }\n\n return undefined;\n}\n","/* Flask wizard using posthog-agent with PostHog MCP */\nimport type { WizardRunOptions } from '@utils/types';\nimport type { FrameworkConfig } from '../../framework-config';\nimport { PYTHON_PACKAGE_INSTALLATION } from '../../framework-config';\nimport { detectPythonPackageManagers } from '../../detection/package-manager';\nimport { Integration } from '@shared/constants';\nimport { boundedGlob, readProjectFile } from '@utils/bounded-fs';\nimport * as path from 'node:path';\nimport {\n getFlaskVersion,\n getFlaskProjectType,\n getFlaskProjectTypeName,\n getFlaskVersionBucket,\n FlaskProjectType,\n findFlaskAppFile,\n} from './utils';\n\nconst EXTRA_IGNORE = ['**/env/**', '**/.env/**'];\n\ntype FlaskContext = {\n projectType?: FlaskProjectType;\n appFile?: string;\n};\n\nexport const FLASK_AGENT_CONFIG: FrameworkConfig<FlaskContext> = {\n metadata: {\n name: 'Flask',\n integration: Integration.flask,\n docsUrl: 'https://posthog.com/docs/libraries/python',\n unsupportedVersionDocsUrl: 'https://posthog.com/docs/libraries/python',\n gatherContext: async (options: WizardRunOptions) => {\n const projectType = await getFlaskProjectType(options);\n const appFile = await findFlaskAppFile(options);\n return { projectType, appFile };\n },\n getDetectedFrameworkLabel: (context) =>\n context.projectType === FlaskProjectType.STANDARD\n ? 'Flask'\n : context.projectType\n ? getFlaskProjectTypeName(context.projectType)\n : undefined,\n },\n\n detection: {\n packageName: 'flask',\n packageDisplayName: 'Flask',\n usesPackageJson: false,\n getVersion: () => undefined,\n getVersionBucket: getFlaskVersionBucket,\n minimumVersion: '2.0.0',\n getInstalledVersion: (options: WizardRunOptions) =>\n getFlaskVersion(options),\n detect: async (options) => {\n const { installDir } = options;\n\n const requirementsFiles = await boundedGlob(\n [\n '**/requirements*.txt',\n '**/pyproject.toml',\n '**/setup.py',\n '**/Pipfile',\n ],\n {\n cwd: installDir,\n extraIgnore: EXTRA_IGNORE,\n },\n );\n\n for (const reqFile of requirementsFiles) {\n const content = readProjectFile(path.join(installDir, reqFile));\n if (!content) continue;\n if (\n /^flask([<>=~!]|$|\\s)/im.test(content) ||\n /[\"']flask[\"']/i.test(content)\n ) {\n return true;\n }\n }\n\n const pyFiles = await boundedGlob(\n ['**/app.py', '**/wsgi.py', '**/application.py', '**/__init__.py'],\n {\n cwd: installDir,\n extraIgnore: EXTRA_IGNORE,\n },\n );\n\n for (const pyFile of pyFiles) {\n const content = readProjectFile(path.join(installDir, pyFile));\n if (!content) continue;\n if (\n content.includes('from flask import') ||\n content.includes('import flask') ||\n /Flask\\s*\\(/.test(content)\n ) {\n return true;\n }\n }\n\n return false;\n },\n detectPackageManager: detectPythonPackageManagers,\n },\n\n environment: {\n uploadToHosting: false,\n getEnvVars: (apiKey: string, host: string) => ({\n POSTHOG_PROJECT_TOKEN: apiKey,\n POSTHOG_HOST: host,\n }),\n },\n\n analytics: {\n getTags: (context) => ({\n projectType: context.projectType || 'unknown',\n }),\n },\n\n prompts: {\n packageInstallation: PYTHON_PACKAGE_INSTALLATION,\n projectTypeDetection:\n 'This is a Python/Flask project. Look for requirements.txt, pyproject.toml, setup.py, Pipfile, or app.py/wsgi.py to confirm.',\n getAdditionalContextLines: (context) => {\n const projectTypeName = context.projectType\n ? getFlaskProjectTypeName(context.projectType)\n : 'unknown';\n\n // Map project type to framework ID for MCP docs resource\n const frameworkIdMap: Record<FlaskProjectType, string> = {\n [FlaskProjectType.STANDARD]: 'flask',\n [FlaskProjectType.RESTFUL]: 'flask',\n [FlaskProjectType.RESTX]: 'flask',\n [FlaskProjectType.SMOREST]: 'flask',\n [FlaskProjectType.BLUEPRINT]: 'flask',\n };\n\n const frameworkId = context.projectType\n ? frameworkIdMap[context.projectType]\n : 'flask';\n\n const lines = [\n `Project type: ${projectTypeName}`,\n `Framework docs ID: ${frameworkId} (use posthog://docs/frameworks/${frameworkId} for documentation)`,\n ];\n\n if (context.appFile) {\n lines.push(`App file: ${context.appFile}`);\n }\n\n return lines;\n },\n },\n\n ui: {\n successMessage: 'PostHog integration complete',\n estimatedDurationMinutes: 5,\n getOutroChanges: (context) => {\n const projectTypeName = context.projectType\n ? getFlaskProjectTypeName(context.projectType)\n : 'Flask';\n return [\n `Analyzed your ${projectTypeName} project structure`,\n `Installed the PostHog Python package`,\n `Configured PostHog in your Flask application`,\n `Added PostHog initialization with automatic event tracking`,\n ];\n },\n getOutroNextSteps: () => [\n 'Start your Flask development server to see PostHog in action',\n 'Visit your PostHog dashboard to see incoming events',\n 'Use posthog.identify() to associate events with users',\n ],\n },\n};\n","import { major, minVersion } from 'semver';\nimport { boundedGlob, readProjectFile } from '@utils/bounded-fs';\nimport type { WizardRunOptions } from '@utils/types';\nimport * as path from 'node:path';\n\nexport enum FastAPIProjectType {\n STANDARD = 'standard', // Basic FastAPI app\n ROUTER = 'router', // FastAPI with APIRouter\n FULLSTACK = 'fullstack', // FastAPI with templates (Jinja2)\n}\n\nconst EXTRA_IGNORE = ['**/env/**', '**/.env/**', '**/migrations/**'];\n\n/** Content probes read at most this many files, one in memory at a time. */\nconst SOURCE_PROBE_LIMIT = 200;\n\n/**\n * Get FastAPI version bucket for analytics\n */\nexport function getFastAPIVersionBucket(version: string | undefined): string {\n if (!version) {\n return 'none';\n }\n\n try {\n const minVer = minVersion(version);\n if (!minVer) {\n return 'invalid';\n }\n const majorVersion = major(minVer);\n // FastAPI 0.x is still the common version range\n if (majorVersion === 0) {\n return '0.x';\n }\n return `${majorVersion}.x`;\n } catch {\n return 'unknown';\n }\n}\n\n/**\n * Extract FastAPI version from requirements files or pyproject.toml\n */\nexport async function getFastAPIVersion(\n options: Pick<WizardRunOptions, 'installDir'>,\n): Promise<string | undefined> {\n const { installDir } = options;\n\n // Check requirements files\n const requirementsFiles = await boundedGlob(\n ['**/requirements*.txt', '**/pyproject.toml', '**/setup.py', '**/Pipfile'],\n {\n cwd: installDir,\n extraIgnore: EXTRA_IGNORE,\n },\n );\n\n for (const reqFile of requirementsFiles) {\n const content = readProjectFile(path.join(installDir, reqFile));\n if (!content) continue;\n\n // Try to extract version from requirements.txt format (fastapi==0.109.0 or fastapi>=0.100)\n const requirementsMatch = content.match(\n /[Ff]ast[Aa][Pp][Ii][=<>~!]+([0-9]+\\.[0-9]+(?:\\.[0-9]+)?)/,\n );\n if (requirementsMatch) {\n return requirementsMatch[1];\n }\n\n // Try to extract from pyproject.toml format\n const pyprojectMatch = content.match(\n /[Ff]ast[Aa][Pp][Ii][\"\\s]*[=<>~!]+\\s*[\"']?([0-9]+\\.[0-9]+(?:\\.[0-9]+)?)/,\n );\n if (pyprojectMatch) {\n return pyprojectMatch[1];\n }\n }\n\n return undefined;\n}\n\n/**\n * Check if app uses FastAPI APIRouter\n */\nasync function hasAPIRouter({\n installDir,\n}: Pick<WizardRunOptions, 'installDir'>): Promise<boolean> {\n const pyFiles = await boundedGlob(['**/*.py'], {\n cwd: installDir,\n extraIgnore: EXTRA_IGNORE,\n limit: SOURCE_PROBE_LIMIT,\n });\n\n for (const pyFile of pyFiles) {\n const content = readProjectFile(path.join(installDir, pyFile));\n if (!content) continue;\n if (\n content.includes('APIRouter(') ||\n content.includes('include_router(') ||\n content.includes('from fastapi import APIRouter')\n ) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Check if app uses Jinja2 templates (fullstack pattern)\n */\nasync function hasTemplates({\n installDir,\n}: Pick<WizardRunOptions, 'installDir'>): Promise<boolean> {\n // Check for Jinja2Templates usage in Python files\n const pyFiles = await boundedGlob(['**/*.py'], {\n cwd: installDir,\n extraIgnore: EXTRA_IGNORE,\n limit: SOURCE_PROBE_LIMIT,\n });\n\n for (const pyFile of pyFiles) {\n const content = readProjectFile(path.join(installDir, pyFile));\n if (!content) continue;\n if (\n content.includes('Jinja2Templates') ||\n content.includes('from fastapi.templating import')\n ) {\n return true;\n }\n }\n\n // Check for templates directory\n const templateFiles = await boundedGlob(['**/templates/**'], {\n cwd: installDir,\n extraIgnore: EXTRA_IGNORE,\n limit: 1,\n });\n\n return templateFiles.length > 0;\n}\n\n/**\n * Detect FastAPI project type\n */\nexport async function getFastAPIProjectType(\n options: WizardRunOptions,\n): Promise<FastAPIProjectType> {\n const { installDir } = options;\n\n // Check for fullstack pattern (templates)\n if (await hasTemplates({ installDir })) {\n return FastAPIProjectType.FULLSTACK;\n }\n\n // Check for APIRouter (modular structure)\n if (await hasAPIRouter({ installDir })) {\n return FastAPIProjectType.ROUTER;\n }\n\n // Default to standard FastAPI\n return FastAPIProjectType.STANDARD;\n}\n\n/**\n * Get human-readable name for FastAPI project type\n */\nexport function getFastAPIProjectTypeName(\n projectType: FastAPIProjectType,\n): string {\n switch (projectType) {\n case FastAPIProjectType.STANDARD:\n return 'Standard FastAPI';\n case FastAPIProjectType.ROUTER:\n return 'FastAPI with APIRouter';\n case FastAPIProjectType.FULLSTACK:\n return 'FastAPI Fullstack';\n }\n}\n\n/**\n * Find the main FastAPI app file\n */\nexport async function findFastAPIAppFile(\n options: Pick<WizardRunOptions, 'installDir'>,\n): Promise<string | undefined> {\n const { installDir } = options;\n\n // Common FastAPI app file patterns\n const commonPatterns = [\n '**/main.py',\n '**/app.py',\n '**/application.py',\n '**/api.py',\n '**/__init__.py',\n ];\n\n const appFiles = await boundedGlob(commonPatterns, {\n cwd: installDir,\n extraIgnore: EXTRA_IGNORE,\n });\n\n // Look for files with FastAPI() instantiation\n for (const appFile of appFiles) {\n const content = readProjectFile(path.join(installDir, appFile));\n if (!content) continue;\n // Check for FastAPI app instantiation\n if (\n content.includes('FastAPI(') ||\n content.includes('from fastapi import FastAPI')\n ) {\n return appFile;\n }\n }\n\n // If no file with FastAPI() found, check all Python files\n const allPyFiles = await boundedGlob(['**/*.py'], {\n cwd: installDir,\n extraIgnore: EXTRA_IGNORE,\n limit: SOURCE_PROBE_LIMIT,\n });\n\n for (const pyFile of allPyFiles) {\n const content = readProjectFile(path.join(installDir, pyFile));\n if (content?.includes('FastAPI(')) {\n return pyFile;\n }\n }\n\n // Return first common pattern file if exists\n if (appFiles.length > 0) {\n return appFiles[0];\n }\n\n return undefined;\n}\n","/* FastAPI wizard using posthog-agent with PostHog MCP */\nimport type { WizardRunOptions } from '@utils/types';\nimport type { FrameworkConfig } from '../../framework-config';\nimport { PYTHON_PACKAGE_INSTALLATION } from '../../framework-config';\nimport { detectPythonPackageManagers } from '../../detection/package-manager';\nimport { Integration } from '@shared/constants';\nimport {\n getFastAPIVersion,\n getFastAPIProjectType,\n getFastAPIProjectTypeName,\n getFastAPIVersionBucket,\n FastAPIProjectType,\n findFastAPIAppFile,\n} from './utils';\nimport { boundedGlob, readProjectFile } from '@utils/bounded-fs';\nimport * as path from 'node:path';\n\nconst EXTRA_IGNORE = ['**/env/**', '**/.env/**'];\n\ntype FastAPIContext = {\n projectType?: FastAPIProjectType;\n appFile?: string;\n};\n\n/**\n * FastAPI framework configuration for the universal agent runner\n */\n\nexport const FASTAPI_AGENT_CONFIG: FrameworkConfig<FastAPIContext> = {\n metadata: {\n name: 'FastAPI',\n integration: Integration.fastapi,\n docsUrl: 'https://posthog.com/docs/libraries/python',\n unsupportedVersionDocsUrl: 'https://posthog.com/docs/libraries/python',\n gatherContext: async (options: WizardRunOptions) => {\n const projectType = await getFastAPIProjectType(options);\n const appFile = await findFastAPIAppFile(options);\n return { projectType, appFile };\n },\n getDetectedFrameworkLabel: (context) => {\n switch (context.projectType) {\n case FastAPIProjectType.FULLSTACK:\n return 'FastAPI fullstack with templates';\n case FastAPIProjectType.ROUTER:\n return 'FastAPI with APIRouter';\n case FastAPIProjectType.STANDARD:\n return 'FastAPI';\n }\n },\n },\n\n detection: {\n packageName: 'fastapi',\n packageDisplayName: 'FastAPI',\n usesPackageJson: false,\n getVersion: (_packageJson: any) => {\n // For FastAPI, we don't use package.json. Version is extracted separately\n // from requirements.txt or pyproject.toml in the wizard entry point\n return undefined;\n },\n getVersionBucket: getFastAPIVersionBucket,\n getInstalledVersion: getFastAPIVersion,\n detect: async (options) => {\n const { installDir } = options;\n\n // Note: Django and Flask are checked before FastAPI in INTEGRATION_ORDER,\n // so if we get here, the project is not a Django or Flask project.\n\n // Check for FastAPI in requirements files\n const requirementsFiles = await boundedGlob(\n [\n '**/requirements*.txt',\n '**/pyproject.toml',\n '**/setup.py',\n '**/Pipfile',\n ],\n {\n cwd: installDir,\n extraIgnore: EXTRA_IGNORE,\n },\n );\n\n for (const reqFile of requirementsFiles) {\n const content = readProjectFile(path.join(installDir, reqFile));\n if (!content) continue;\n // Check for fastapi package (case-insensitive)\n // Match \"fastapi\" as a standalone package\n if (\n /^fastapi([<>=~!]|$|\\s)/im.test(content) ||\n /[\"']fastapi[\"']/i.test(content)\n ) {\n return true;\n }\n }\n\n // Check for FastAPI app patterns in Python files\n const pyFiles = await boundedGlob(\n ['**/main.py', '**/app.py', '**/application.py', '**/__init__.py'],\n {\n cwd: installDir,\n extraIgnore: EXTRA_IGNORE,\n },\n );\n\n for (const pyFile of pyFiles) {\n const content = readProjectFile(path.join(installDir, pyFile));\n if (!content) continue;\n if (\n content.includes('from fastapi import') ||\n content.includes('import fastapi') ||\n /FastAPI\\s*\\(/.test(content)\n ) {\n return true;\n }\n }\n\n return false;\n },\n detectPackageManager: detectPythonPackageManagers,\n },\n\n environment: {\n uploadToHosting: false,\n getEnvVars: (apiKey: string, host: string) => ({\n POSTHOG_PROJECT_TOKEN: apiKey,\n POSTHOG_HOST: host,\n }),\n },\n\n analytics: {\n getTags: (context: any) => {\n const projectType = context.projectType as FastAPIProjectType;\n return {\n projectType: projectType || 'unknown',\n };\n },\n },\n\n prompts: {\n packageInstallation: PYTHON_PACKAGE_INSTALLATION,\n projectTypeDetection:\n 'This is a Python/FastAPI project. Look for requirements.txt, pyproject.toml, setup.py, Pipfile, or main.py/app.py to confirm.',\n getAdditionalContextLines: (context: any) => {\n const projectType = context.projectType as FastAPIProjectType;\n const projectTypeName = projectType\n ? getFastAPIProjectTypeName(projectType)\n : 'unknown';\n\n // Map project type to framework ID for MCP docs resource\n const frameworkIdMap: Record<FastAPIProjectType, string> = {\n [FastAPIProjectType.STANDARD]: 'fastapi',\n [FastAPIProjectType.ROUTER]: 'fastapi',\n [FastAPIProjectType.FULLSTACK]: 'fastapi',\n };\n\n const frameworkId = projectType ? frameworkIdMap[projectType] : 'fastapi';\n\n const lines = [\n `Project type: ${projectTypeName}`,\n `Framework docs ID: ${frameworkId} (use posthog://docs/frameworks/${frameworkId} for documentation)`,\n ];\n\n if (context.appFile) {\n lines.push(`App file: ${context.appFile}`);\n }\n\n return lines;\n },\n },\n\n ui: {\n successMessage: 'PostHog integration complete',\n estimatedDurationMinutes: 5,\n getOutroChanges: (context: any) => {\n const projectType = context.projectType as FastAPIProjectType;\n const projectTypeName = projectType\n ? getFastAPIProjectTypeName(projectType)\n : 'FastAPI';\n return [\n `Analyzed your ${projectTypeName} project structure`,\n `Installed the PostHog Python package`,\n `Configured PostHog in your FastAPI application`,\n `Added PostHog initialization with lifespan event handling`,\n ];\n },\n getOutroNextSteps: () => [\n 'Start your FastAPI development server to see PostHog in action',\n 'Visit your PostHog dashboard to see incoming events',\n 'Use posthog.identify() to associate events with users',\n ],\n },\n};\n","import { boundedGlob, readProjectFile } from '@utils/bounded-fs';\nimport type { WizardRunOptions } from '@utils/types';\nimport { createVersionBucket } from '@utils/semver';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nexport enum LaravelProjectType {\n STANDARD = 'standard', // Basic Laravel app\n INERTIA = 'inertia', // Inertia.js (Vue/React SPA) - may need JS SDK too\n LIVEWIRE = 'livewire', // Livewire (reactive components, includes Filament)\n}\n\nconst EXTRA_IGNORE = [\n '**/storage/**',\n '**/bootstrap/cache/**',\n '**/.phpunit.cache/**',\n '**/public/build/**',\n '**/public/hot/**',\n];\n\n/** Content probes read at most this many files, one in memory at a time. */\nconst SOURCE_PROBE_LIMIT = 200;\n\n/**\n * Get Laravel version bucket for analytics\n */\nexport const getLaravelVersionBucket = createVersionBucket();\n\n/**\n * Read and parse composer.json\n */\nexport function getComposerJson(\n options: Pick<WizardRunOptions, 'installDir'>,\n): Record<string, any> | undefined {\n const { installDir } = options;\n\n const composerPath = path.join(installDir, 'composer.json');\n try {\n const content = fs.readFileSync(composerPath, 'utf-8');\n return JSON.parse(content);\n } catch {\n return undefined;\n }\n}\n\n/**\n * Check if a package is installed (present in composer.json)\n */\nfunction hasComposerPackage(\n packageName: string,\n options: Pick<WizardRunOptions, 'installDir'>,\n): boolean {\n const composer = getComposerJson(options);\n if (!composer) return false;\n\n return !!(\n composer.require?.[packageName] || composer['require-dev']?.[packageName]\n );\n}\n\n/**\n * Extract version for a package from composer.json\n */\nfunction getComposerPackageVersion(\n packageName: string,\n options: Pick<WizardRunOptions, 'installDir'>,\n): string | undefined {\n const composer = getComposerJson(options);\n if (!composer) return undefined;\n\n const version =\n composer.require?.[packageName] || composer['require-dev']?.[packageName];\n if (version) {\n // Clean version string (remove ^, ~, >=, etc.)\n return version.replace(/^[\\^~>=<]+/, '');\n }\n\n return undefined;\n}\n\n/**\n * Check if a pattern exists in PHP source files\n */\nasync function hasLaravelCodePattern(\n pattern: RegExp | string,\n options: Pick<WizardRunOptions, 'installDir'>,\n filePatterns: string[] = ['**/*.php'],\n): Promise<boolean> {\n const { installDir } = options;\n\n const phpFiles = await boundedGlob(filePatterns, {\n cwd: installDir,\n extraIgnore: EXTRA_IGNORE,\n limit: SOURCE_PROBE_LIMIT,\n });\n\n const searchPattern =\n typeof pattern === 'string' ? new RegExp(pattern) : pattern;\n\n for (const phpFile of phpFiles) {\n const content = readProjectFile(path.join(installDir, phpFile));\n if (!content) continue;\n if (searchPattern.test(content)) return true;\n }\n\n return false;\n}\n\n/**\n * Get Laravel version from composer.json\n */\nexport function getLaravelVersion(\n options: Pick<WizardRunOptions, 'installDir'>,\n): string | undefined {\n return getComposerPackageVersion('laravel/framework', options);\n}\n\n/**\n * Get human-readable name for Laravel project type\n */\nexport function getLaravelProjectTypeName(\n projectType: LaravelProjectType,\n): string {\n switch (projectType) {\n case LaravelProjectType.STANDARD:\n return 'Standard Laravel';\n case LaravelProjectType.INERTIA:\n return 'Laravel with Inertia.js';\n case LaravelProjectType.LIVEWIRE:\n return 'Laravel with Livewire';\n default:\n return 'Laravel';\n }\n}\n\n/**\n * Check for Inertia.js\n */\nasync function hasInertia(\n options: Pick<WizardRunOptions, 'installDir'>,\n): Promise<boolean> {\n return (\n hasComposerPackage('inertiajs/inertia-laravel', options) ||\n (await hasLaravelCodePattern(/Inertia::render|inertia\\(/, options))\n );\n}\n\n/**\n * Check for Livewire\n */\nasync function hasLivewire(\n options: Pick<WizardRunOptions, 'installDir'>,\n): Promise<boolean> {\n return (\n hasComposerPackage('livewire/livewire', options) ||\n (await hasLaravelCodePattern(/extends\\s+Component|@livewire/, options))\n );\n}\n\n/**\n * Detect Laravel project type\n */\nexport async function getLaravelProjectType(\n options: WizardRunOptions,\n): Promise<LaravelProjectType> {\n // Check for SPA/Reactive frameworks (important to detect - affects SDK needs)\n if (await hasInertia(options)) {\n return LaravelProjectType.INERTIA;\n }\n if (await hasLivewire(options)) {\n return LaravelProjectType.LIVEWIRE;\n }\n\n // Default to standard\n return LaravelProjectType.STANDARD;\n}\n\n/**\n * Find the main service provider file\n */\nexport async function findLaravelServiceProvider(\n options: Pick<WizardRunOptions, 'installDir'>,\n): Promise<string | undefined> {\n const { installDir } = options;\n\n // Look for AppServiceProvider first (most common place for setup)\n const appServiceProvider = path.join(\n installDir,\n 'app/Providers/AppServiceProvider.php',\n );\n\n if (fs.existsSync(appServiceProvider)) {\n return 'app/Providers/AppServiceProvider.php';\n }\n\n // Fall back to searching for any service provider\n const providers = await boundedGlob(\n ['**/app/Providers/*ServiceProvider.php'],\n {\n cwd: installDir,\n extraIgnore: EXTRA_IGNORE,\n limit: 1,\n },\n );\n\n return providers[0];\n}\n\n/**\n * Find the bootstrap file (differs between Laravel versions)\n */\nexport function findLaravelBootstrapFile(\n options: Pick<WizardRunOptions, 'installDir'>,\n): string | undefined {\n const { installDir } = options;\n\n // Laravel 11+ uses bootstrap/app.php with new structure\n const bootstrapApp = path.join(installDir, 'bootstrap/app.php');\n if (fs.existsSync(bootstrapApp)) {\n return 'bootstrap/app.php';\n }\n\n // Older Laravel uses app/Http/Kernel.php\n const httpKernel = path.join(installDir, 'app/Http/Kernel.php');\n if (fs.existsSync(httpKernel)) {\n return 'app/Http/Kernel.php';\n }\n\n return undefined;\n}\n\n/**\n * Detect Laravel version structure for configuration guidance\n */\nexport function detectLaravelStructure(\n options: Pick<WizardRunOptions, 'installDir'>,\n): 'legacy' | 'modern' | 'latest' {\n const version = getLaravelVersion(options);\n if (!version) return 'modern';\n\n try {\n const majorVersion = parseInt(version.split('.')[0], 10);\n if (majorVersion >= 11) return 'latest'; // Laravel 11+ (new structure)\n if (majorVersion >= 9) return 'modern'; // Laravel 9-10\n return 'legacy'; // Laravel 8 and below\n } catch {\n return 'modern';\n }\n}\n","/* Laravel wizard using posthog-agent with PostHog MCP */\nimport type { WizardRunOptions } from '@utils/types';\nimport type { FrameworkConfig } from '../../framework-config';\nimport { composerPackageManager } from '../../detection/package-manager';\nimport { Integration } from '@shared/constants';\nimport { boundedGlob } from '@utils/bounded-fs';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport {\n getLaravelVersion,\n getLaravelProjectType,\n getLaravelProjectTypeName,\n getLaravelVersionBucket,\n LaravelProjectType,\n findLaravelServiceProvider,\n findLaravelBootstrapFile,\n detectLaravelStructure,\n} from './utils';\n\ntype LaravelContext = {\n projectType?: LaravelProjectType;\n serviceProvider?: string;\n bootstrapFile?: string;\n laravelStructure?: string;\n};\n\nexport const LARAVEL_AGENT_CONFIG: FrameworkConfig<LaravelContext> = {\n metadata: {\n name: 'Laravel',\n integration: Integration.laravel,\n docsUrl: 'https://posthog.com/docs/libraries/php',\n unsupportedVersionDocsUrl: 'https://posthog.com/docs/libraries/php',\n gatherContext: async (options: WizardRunOptions) => {\n const projectType = await getLaravelProjectType(options);\n const serviceProvider = await findLaravelServiceProvider(options);\n const bootstrapFile = findLaravelBootstrapFile(options);\n const laravelStructure = detectLaravelStructure(options);\n\n return {\n projectType,\n serviceProvider,\n bootstrapFile,\n laravelStructure,\n };\n },\n getDetectedFrameworkLabel: (context) =>\n context.projectType === LaravelProjectType.STANDARD\n ? 'Laravel'\n : context.projectType\n ? getLaravelProjectTypeName(context.projectType)\n : undefined,\n },\n\n detection: {\n packageName: 'laravel/framework',\n packageDisplayName: 'Laravel',\n usesPackageJson: false,\n getVersion: () => undefined,\n getVersionBucket: getLaravelVersionBucket,\n minimumVersion: '9.0.0',\n getInstalledVersion: (options: WizardRunOptions) =>\n Promise.resolve(getLaravelVersion(options)),\n detect: async (options) => {\n const { installDir } = options;\n\n const artisanPath = path.join(installDir, 'artisan');\n if (fs.existsSync(artisanPath)) {\n try {\n const content = fs.readFileSync(artisanPath, 'utf-8');\n if (content.includes('Laravel') || content.includes('Artisan')) {\n return true;\n }\n } catch {\n // Continue to other checks\n }\n }\n\n const composerPath = path.join(installDir, 'composer.json');\n if (fs.existsSync(composerPath)) {\n try {\n const content = fs.readFileSync(composerPath, 'utf-8');\n const composer = JSON.parse(content);\n if (\n composer.require?.['laravel/framework'] ||\n composer['require-dev']?.['laravel/framework']\n ) {\n return true;\n }\n } catch {\n // Continue to other checks\n }\n }\n\n const hasLaravelStructure = await boundedGlob(\n ['**/bootstrap/app.php', '**/app/Http/Kernel.php'],\n { cwd: installDir, limit: 1 },\n );\n\n return hasLaravelStructure.length > 0;\n },\n detectPackageManager: composerPackageManager,\n },\n\n environment: {\n uploadToHosting: false,\n getEnvVars: (apiKey: string, host: string) => ({\n POSTHOG_PROJECT_TOKEN: apiKey,\n POSTHOG_HOST: host,\n }),\n },\n\n analytics: {\n getTags: (context) => ({\n projectType: context.projectType || 'unknown',\n laravelStructure: context.laravelStructure || 'unknown',\n }),\n },\n\n prompts: {\n projectTypeDetection:\n 'This is a PHP/Laravel project. Look for composer.json, artisan CLI, and app/ directory structure to confirm. Check for Laravel-specific packages like laravel/framework.',\n packageInstallation:\n 'Use Composer to install packages. Run `composer require posthog/posthog-php` without pinning a specific version.',\n getAdditionalContextLines: (context) => {\n const projectTypeName = context.projectType\n ? getLaravelProjectTypeName(context.projectType)\n : 'unknown';\n\n const lines = [\n `Project type: ${projectTypeName}`,\n `Framework docs ID: php (use posthog://docs/frameworks/php for documentation)`,\n `Laravel structure: ${context.laravelStructure} (affects where to add configuration)`,\n ];\n\n if (context.serviceProvider) {\n lines.push(`Service provider: ${context.serviceProvider}`);\n }\n\n if (context.bootstrapFile) {\n lines.push(`Bootstrap file: ${context.bootstrapFile}`);\n }\n\n // Add Laravel-specific guidance based on version structure\n if (context.laravelStructure === 'latest') {\n lines.push(\n 'Note: Laravel 11+ uses simplified bootstrap/app.php for middleware and providers',\n );\n } else {\n lines.push(\n 'Note: Use app/Http/Kernel.php for middleware, app/Providers for service providers',\n );\n }\n\n return lines;\n },\n },\n\n ui: {\n successMessage: 'PostHog integration complete',\n estimatedDurationMinutes: 5,\n getOutroChanges: (context) => {\n const projectTypeName = context.projectType\n ? getLaravelProjectTypeName(context.projectType)\n : 'Laravel';\n\n const changes = [\n `Analyzed your ${projectTypeName} project structure`,\n `Installed the PostHog PHP package via Composer`,\n `Configured PostHog in your Laravel application`,\n ];\n\n if (context.laravelStructure === 'latest') {\n changes.push('Added PostHog initialization to bootstrap/app.php');\n } else {\n changes.push('Created a PostHog service provider for initialization');\n }\n\n if (context.projectType === LaravelProjectType.INERTIA) {\n changes.push('Configured PostHog to work with Inertia.js');\n }\n\n if (context.projectType === LaravelProjectType.LIVEWIRE) {\n changes.push('Configured PostHog to work with Livewire');\n }\n\n return changes;\n },\n getOutroNextSteps: () => [\n 'Start your Laravel development server with `php artisan serve`',\n 'Visit your PostHog dashboard to see incoming events',\n 'Use PostHog::capture() to track custom events',\n 'Use PostHog::identify() to associate events with users',\n ],\n },\n};\n","/* SvelteKit wizard using posthog-agent with PostHog MCP */\nimport type { FrameworkConfig } from '../../framework-config';\nimport { detectNodePackageManagers } from '../../detection/package-manager';\nimport { Integration } from '@shared/constants';\nimport {\n getDeclaredVersion,\n hasDeclaredDependency,\n type PackageJson,\n} from '@utils/package-json';\nimport { tryGetPackageJson } from '@utils/setup-utils';\n\ntype SvelteKitContext = Record<string, unknown>;\n\nexport const SVELTEKIT_AGENT_CONFIG: FrameworkConfig<SvelteKitContext> = {\n metadata: {\n name: 'SvelteKit',\n integration: Integration.sveltekit,\n docsUrl: 'https://posthog.com/docs/libraries/svelte',\n additionalMcpServers: {\n svelte: { url: 'https://mcp.svelte.dev/mcp' },\n },\n },\n\n detection: {\n packageName: '@sveltejs/kit',\n packageDisplayName: 'SvelteKit',\n getVersion: (packageJson: unknown) =>\n getDeclaredVersion('@sveltejs/kit', packageJson as PackageJson),\n detect: async (options) => {\n const packageJson = await tryGetPackageJson(options);\n return packageJson\n ? hasDeclaredDependency('@sveltejs/kit', packageJson)\n : false;\n },\n minimumVersion: '2.0.0',\n detectPackageManager: detectNodePackageManagers,\n },\n\n environment: {\n uploadToHosting: true,\n getEnvVars: (apiKey: string, host: string) => ({\n PUBLIC_POSTHOG_PROJECT_TOKEN: apiKey,\n PUBLIC_POSTHOG_HOST: host,\n }),\n },\n\n analytics: {\n getTags: () => ({}),\n },\n\n prompts: {\n projectTypeDetection:\n 'This is a JavaScript/TypeScript project using SvelteKit. Look for package.json, svelte.config.js, and lockfiles (package-lock.json, yarn.lock, pnpm-lock.yaml, bun.lockb) to confirm.',\n getAdditionalContextLines: () => [\n 'Framework docs ID: sveltekit (use posthog://docs/frameworks/sveltekit for documentation)',\n ],\n },\n\n ui: {\n successMessage: 'PostHog integration complete',\n estimatedDurationMinutes: 8,\n getOutroChanges: () => [\n 'Analyzed your SvelteKit project structure',\n 'Created and configured PostHog initializers',\n 'Integrated PostHog into your application',\n ],\n getOutroNextSteps: () => [\n 'Start your development server to see PostHog in action',\n 'Visit your PostHog dashboard to see incoming events',\n ],\n },\n};\n","/* Flutter wizard using posthog-agent with PostHog MCP */\nimport type { WizardRunOptions } from '@utils/types';\nimport type { FrameworkConfig } from '../../framework-config';\nimport { Integration } from '@shared/constants';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { pubPackageManager } from '../../detection/package-manager';\n\n/** Platform subtrees `flutter create` scaffolds; each needs its own setup notes. */\nconst FLUTTER_PLATFORM_DIRS = [\n 'android',\n 'ios',\n 'web',\n 'macos',\n 'linux',\n 'windows',\n] as const;\n\ntype FlutterContext = {\n platforms?: string[];\n};\n\nfunction readPubspec(installDir: string): string | undefined {\n const pubspecPath = path.join(installDir, 'pubspec.yaml');\n if (!fs.existsSync(pubspecPath)) return undefined;\n return fs.readFileSync(pubspecPath, 'utf-8');\n}\n\nexport const FLUTTER_AGENT_CONFIG: FrameworkConfig<FlutterContext> = {\n metadata: {\n name: 'Flutter',\n integration: Integration.flutter,\n docsUrl: 'https://posthog.com/docs/libraries/flutter',\n gatherContext: (options: WizardRunOptions) => {\n const platforms = FLUTTER_PLATFORM_DIRS.filter((dir) =>\n fs.existsSync(path.join(options.installDir, dir)),\n );\n return Promise.resolve({ platforms });\n },\n },\n\n detection: {\n packageName: 'posthog_flutter',\n packageDisplayName: 'Flutter',\n usesPackageJson: false,\n getVersion: () => undefined,\n detectPackageManager: pubPackageManager,\n // A pubspec.yaml alone is any Dart project; depending on the Flutter SDK\n // (`sdk: flutter`) is what makes it a Flutter app. Anchored to a key/value\n // line so comments (`# sdk: flutter`) don't match.\n detect: (options) => {\n const pubspec = readPubspec(options.installDir);\n return Promise.resolve(/^\\s*sdk:\\s*flutter\\s*$/m.test(pubspec ?? ''));\n },\n },\n\n environment: {\n uploadToHosting: false,\n getEnvVars: (apiKey: string, host: string) => ({\n POSTHOG_PROJECT_TOKEN: apiKey,\n POSTHOG_HOST: host,\n }),\n },\n\n analytics: {\n getTags: (context) => ({\n ...(context.platforms?.length\n ? { platforms: context.platforms.join(',') }\n : {}),\n }),\n },\n\n prompts: {\n projectTypeDetection:\n 'This is a Flutter project. Look for pubspec.yaml declaring a dependency on the Flutter SDK (flutter: sdk: flutter) and a lib/ directory with Dart source files to confirm.',\n packageInstallation:\n 'Add the PostHog Flutter SDK with `flutter pub add posthog_flutter`. Do not edit pubspec.yaml by hand; the pub tool updates it and resolves the version automatically.',\n getAdditionalContextLines: (context) => {\n const lines = [\n 'Framework docs ID: flutter (use posthog://docs/frameworks/flutter for documentation)',\n 'Prefer manual initialization in Dart (PostHogConfig + Posthog().setup) over the platform auto-init so configuration lives in one place; when doing so, disable auto-init in the Android manifest and iOS Info.plist per the docs.',\n ];\n\n if (context.platforms?.length) {\n lines.push(\n `Enabled target platforms: ${context.platforms.join(\n ', ',\n )}. Apply the platform-specific setup steps from the docs for each (e.g. AndroidManifest.xml on Android, Info.plist on iOS/macOS, the JS snippet in web/index.html for web).`,\n );\n }\n\n return lines;\n },\n },\n\n ui: {\n successMessage: 'PostHog integration complete',\n estimatedDurationMinutes: 5,\n getOutroChanges: () => [\n 'Analyzed your Flutter project structure',\n 'Added the posthog_flutter SDK to your pubspec',\n 'Configured PostHog initialization',\n 'Added event capture and user identification',\n ],\n getOutroNextSteps: () => [\n 'Run your app to see PostHog in action',\n 'Visit your PostHog dashboard to see incoming events',\n 'Check out the PostHog Flutter docs for session replay, feature flags, and more',\n ],\n },\n};\n","import type { WizardRunOptions } from '@utils/types';\nimport { boundedGlob, readProjectFile } from '@utils/bounded-fs';\nimport fg from 'fast-glob';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nconst EXTRA_IGNORE = ['**/.build/**', '**/*.xcodeproj/**'];\n\n/** Content probes read at most this many files, one in memory at a time. */\nconst SOURCE_PROBE_LIMIT = 200;\n\nexport enum SwiftProjectType {\n SWIFTUI = 'swiftui',\n UIKIT = 'uikit',\n SPM = 'spm',\n}\n\nexport function getSwiftProjectTypeName(projectType: SwiftProjectType): string {\n switch (projectType) {\n case SwiftProjectType.SWIFTUI:\n return 'SwiftUI';\n case SwiftProjectType.UIKIT:\n return 'UIKit';\n case SwiftProjectType.SPM:\n return 'Swift Package';\n }\n}\n\nexport async function detectSwiftProjectType(\n options: WizardRunOptions,\n): Promise<SwiftProjectType | undefined> {\n const { installDir } = options;\n\n // Pure SPM package: Package.swift with no Xcode project/workspace and no\n // XcodeGen spec (project.yml generates an app's .xcodeproj, often\n // uncommitted) — same app signals as the framework detect glob.\n const hasPackageSwift = fs.existsSync(path.join(installDir, 'Package.swift'));\n const hasXcodeGenSpec = fs.existsSync(path.join(installDir, 'project.yml'));\n const xcodeProjects = await fg('*.{xcodeproj,xcworkspace}', {\n cwd: installDir,\n onlyDirectories: true,\n });\n\n if (hasPackageSwift && xcodeProjects.length === 0 && !hasXcodeGenSpec) {\n return SwiftProjectType.SPM;\n }\n\n // Check Swift source files for SwiftUI vs UIKit imports\n const swiftFiles = await boundedGlob('**/*.swift', {\n cwd: installDir,\n extraIgnore: EXTRA_IGNORE,\n limit: SOURCE_PROBE_LIMIT,\n });\n\n let hasSwiftUI = false;\n let hasUIKit = false;\n\n for (const file of swiftFiles) {\n const content = readProjectFile(path.join(installDir, file));\n if (!content) continue;\n if (content.includes('import SwiftUI')) {\n hasSwiftUI = true;\n }\n if (content.includes('import UIKit')) {\n hasUIKit = true;\n }\n }\n\n if (hasSwiftUI) return SwiftProjectType.SWIFTUI;\n if (hasUIKit) return SwiftProjectType.UIKIT;\n\n return undefined;\n}\n","/* Swift wizard using posthog-agent with PostHog MCP */\nimport type { WizardRunOptions } from '@utils/types';\nimport type { FrameworkConfig } from '../../framework-config';\nimport { swiftPackageManager } from '../../detection/package-manager';\nimport { Integration } from '@shared/constants';\nimport { boundedGlob } from '@utils/bounded-fs';\nimport fg from 'fast-glob';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport {\n detectSwiftProjectType,\n getSwiftProjectTypeName,\n SwiftProjectType,\n} from './utils';\n\ntype SwiftContext = {\n projectType?: SwiftProjectType;\n};\n\nexport const SWIFT_AGENT_CONFIG: FrameworkConfig<SwiftContext> = {\n metadata: {\n name: 'Swift (iOS/macOS)',\n integration: Integration.swift,\n docsUrl: 'https://posthog.com/docs/libraries/ios',\n preRunNotice:\n 'Please close the Xcode project before proceeding. Xcode may overwrite changes the wizard makes to project files.',\n gatherContext: async (options: WizardRunOptions) => {\n const projectType = await detectSwiftProjectType(options);\n return { projectType };\n },\n },\n\n detection: {\n packageName: 'posthog-ios',\n packageDisplayName: 'Swift',\n usesPackageJson: false,\n getVersion: () => undefined,\n detect: async (options) => {\n const { installDir } = options;\n\n // Xcode project/workspace, or an XcodeGen `project.yml` (the generated\n // .xcodeproj is often uncommitted).\n const xcodeProjects = await fg('*.{xcodeproj,xcworkspace}', {\n cwd: installDir,\n onlyDirectories: true,\n });\n const hasXcodeGenSpec = fs.existsSync(\n path.join(installDir, 'project.yml'),\n );\n\n if (xcodeProjects.length > 0 || hasXcodeGenSpec) {\n // Verify it contains Swift source files\n const swiftFiles = await boundedGlob('**/*.swift', {\n cwd: installDir,\n extraIgnore: ['**/.build/**', '**/*.xcodeproj/**'],\n limit: 1,\n });\n if (swiftFiles.length > 0) {\n return true;\n }\n }\n\n // Check for Swift Package Manager project\n const packageSwiftPath = path.join(installDir, 'Package.swift');\n if (fs.existsSync(packageSwiftPath)) {\n return true;\n }\n\n return false;\n },\n detectPackageManager: swiftPackageManager,\n },\n\n environment: {\n uploadToHosting: false,\n getEnvVars: (apiKey: string, host: string) => ({\n POSTHOG_PROJECT_TOKEN: apiKey,\n POSTHOG_HOST: host,\n }),\n },\n\n analytics: {\n getTags: (context) => ({\n projectType: context.projectType || 'unknown',\n }),\n },\n\n prompts: {\n projectTypeDetection:\n 'This is a Swift project. Look for .xcodeproj directories, Package.swift, and .swift source files to confirm. Check for SwiftUI or UIKit imports to determine the UI framework.',\n packageInstallation:\n 'Add the posthog-ios package via Swift Package Manager. For Xcode projects, add XCRemoteSwiftPackageReference and XCSwiftPackageProductDependency to the .pbxproj file. For Swift packages, add the dependency to Package.swift.',\n getAdditionalContextLines: (context) => {\n const projectTypeName = context.projectType\n ? getSwiftProjectTypeName(context.projectType)\n : 'unknown';\n\n const lines = [\n `Project type: ${projectTypeName}`,\n `Framework docs ID: swift (use posthog://docs/frameworks/swift for documentation)`,\n ];\n\n return lines;\n },\n },\n\n ui: {\n successMessage: 'PostHog integration complete',\n estimatedDurationMinutes: 5,\n getOutroChanges: (context) => {\n const projectTypeName = context.projectType\n ? getSwiftProjectTypeName(context.projectType)\n : 'Swift';\n\n const changes = [\n `Analyzed your ${projectTypeName} project structure`,\n `Added the PostHog iOS SDK via Swift Package Manager`,\n `Configured PostHog initialization in your app entry point`,\n `Added event capture and user identification`,\n ];\n\n return changes;\n },\n getOutroNextSteps: () => [\n 'Set POSTHOG_PROJECT_TOKEN and POSTHOG_HOST in your Xcode scheme environment variables',\n 'Build and run your app to see PostHog in action',\n 'Visit your PostHog dashboard to see incoming events',\n ],\n },\n};\n","/* Kotlin Multiplatform (KMP) wizard using posthog-agent with PostHog MCP */\nimport type { FrameworkConfig } from '../../framework-config';\nimport { Integration } from '@shared/constants';\nimport { gradlePackageManager } from '../../detection/package-manager';\nimport { boundedGlob, readProjectFile } from '@utils/bounded-fs';\nimport * as path from 'node:path';\n\nexport const KMP_AGENT_CONFIG: FrameworkConfig = {\n metadata: {\n name: 'Kotlin Multiplatform',\n integration: Integration.kmp,\n beta: true,\n docsUrl: 'https://posthog.com/docs/libraries/kmp',\n preRunNotice:\n 'The PostHog Kotlin Multiplatform SDK is in early access (0.x pre-release). The API may change between minor versions.',\n },\n\n detection: {\n packageName: 'posthog-kmp',\n packageDisplayName: 'Kotlin Multiplatform',\n usesPackageJson: false,\n getVersion: () => undefined,\n detectPackageManager: gradlePackageManager,\n // KMP is detected before Android/Swift because a KMP project also looks like\n // an Android and/or Swift project. Detection therefore requires the Kotlin\n // Multiplatform Gradle plugin or a `commonMain` source set — signals that a\n // plain Android or Swift project does not have.\n detect: async (options) => {\n const { installDir } = options;\n\n // Strategy 1: a Gradle build file that applies the Kotlin Multiplatform plugin.\n const buildFiles = await boundedGlob(\n ['**/build.gradle', '**/build.gradle.kts'],\n { cwd: installDir },\n );\n\n for (const file of buildFiles) {\n const content = readProjectFile(path.join(installDir, file));\n if (!content) continue;\n if (\n content.includes('kotlin(\"multiplatform\")') ||\n content.includes('org.jetbrains.kotlin.multiplatform') ||\n content.includes('kotlin-multiplatform')\n ) {\n return true;\n }\n }\n\n // Strategy 2: a KMP `commonMain` source set exists.\n const commonMain = await boundedGlob('**/src/commonMain/**', {\n cwd: installDir,\n limit: 1,\n });\n\n return commonMain.length > 0;\n },\n },\n\n environment: {\n uploadToHosting: false,\n getEnvVars: (apiKey: string, host: string) => ({\n POSTHOG_PROJECT_TOKEN: apiKey,\n POSTHOG_HOST: host,\n }),\n },\n\n analytics: {\n getTags: () => ({}),\n },\n\n prompts: {\n projectTypeDetection:\n 'This is a Kotlin Multiplatform (KMP) project. Look for a build.gradle.kts (or build.gradle) that applies the Kotlin Multiplatform plugin (kotlin(\"multiplatform\") or org.jetbrains.kotlin.multiplatform) and a shared module with a src/commonMain source set.',\n packageInstallation:\n 'Add the PostHog KMP SDK to the shared module\\'s commonMain dependencies in build.gradle.kts: within the kotlin { sourceSets { ... } } block, add implementation(\"com.posthog:posthog-kmp:<VERSION>\") to commonMain.dependencies. Match the existing dependency format (Groovy vs Kotlin DSL).',\n getAdditionalContextLines: () => [\n 'Framework docs ID: kmp (use posthog://docs/frameworks/kmp for documentation)',\n 'Initialize once, early in the app lifecycle, from shared code. All PostHog APIs live in the com.posthog.kmp package.',\n 'Setup call: PostHog.setup(config = PostHogConfig(projectToken = \"<POSTHOG_PROJECT_TOKEN>\", host = \"<POSTHOG_HOST>\"), context = PostHogContext())',\n 'PostHogContext is platform-specific: on Android pass the Application via PostHogContext(application); on iOS and Web use the no-argument PostHogContext().',\n 'Imports: com.posthog.kmp.PostHog, com.posthog.kmp.PostHogConfig, com.posthog.kmp.PostHogContext.',\n ],\n },\n\n ui: {\n successMessage: 'PostHog integration complete',\n estimatedDurationMinutes: 5,\n getOutroChanges: () => [\n 'Analyzed your Kotlin Multiplatform project structure',\n 'Added the PostHog KMP SDK to your shared module',\n 'Configured PostHog initialization in your shared code',\n 'Added event capture and user identification',\n ],\n getOutroNextSteps: () => [\n 'Wire up the platform-specific PostHogContext for each target (Android/iOS/Web)',\n 'Build and run your app to see PostHog in action',\n 'Visit your PostHog dashboard to see incoming events',\n 'Check out the PostHog KMP docs for feature flags, session replay, and more',\n ],\n },\n};\n","import type { WizardRunOptions } from '@utils/types';\nimport { createVersionBucket } from '@utils/semver';\nimport { boundedGlob, readProjectFile } from '@utils/bounded-fs';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\n\n/**\n * Extract minSdk from the app-level build.gradle(.kts).\n * Returns the value as a semver-like string (e.g. \"24\" from minSdk = 24).\n */\nexport async function getMinSdkVersion(\n options: WizardRunOptions,\n): Promise<string | undefined> {\n const { installDir } = options;\n\n const buildFiles = await boundedGlob(\n ['**/build.gradle', '**/build.gradle.kts'],\n { cwd: installDir },\n );\n\n for (const file of buildFiles) {\n const content = readProjectFile(path.join(installDir, file));\n if (!content) continue;\n // Match: minSdk = 24, minSdkVersion 21, minSdkVersion = 21\n const match = content.match(/minSdk(?:Version)?\\s*=?\\s*(\\d+)/);\n if (match) return match[1];\n }\n\n return undefined;\n}\n\nexport const getKotlinVersionBucket = createVersionBucket();\n\n/**\n * Read the root or app-level build.gradle(.kts) and extract the Kotlin version.\n */\nexport function getKotlinVersion(\n options: WizardRunOptions,\n): string | undefined {\n const { installDir } = options;\n\n for (const name of [\n 'build.gradle',\n 'build.gradle.kts',\n 'gradle/libs.versions.toml',\n ]) {\n const filePath = path.join(installDir, name);\n if (!fs.existsSync(filePath)) continue;\n\n const content = fs.readFileSync(filePath, 'utf-8');\n\n // build.gradle: kotlinVersion = \"2.0.21\" or ext.kotlin_version = '1.9.0'\n const match = content.match(/kotlin[_-]?[Vv]ersion\\s*=\\s*[\"']([^\"']+)[\"']/);\n if (match) return match[1];\n\n // libs.versions.toml: kotlin = \"2.0.21\"\n const tomlMatch = content.match(/^kotlin\\s*=\\s*[\"']([^\"']+)[\"']/m);\n if (tomlMatch) return tomlMatch[1];\n }\n\n return undefined;\n}\n","/* Android (Kotlin) wizard using posthog-agent with PostHog MCP */\nimport type { WizardRunOptions } from '@utils/types';\nimport type { FrameworkConfig } from '../../framework-config';\nimport { Integration } from '@shared/constants';\nimport { boundedGlob } from '@utils/bounded-fs';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport {\n getKotlinVersion,\n getKotlinVersionBucket,\n getMinSdkVersion,\n} from './utils';\nimport { gradlePackageManager } from '../../detection/package-manager';\n\ntype AndroidContext = {\n kotlinVersion?: string;\n};\n\nexport const ANDROID_AGENT_CONFIG: FrameworkConfig<AndroidContext> = {\n metadata: {\n name: 'Android (Kotlin)',\n integration: Integration.android,\n docsUrl: 'https://posthog.com/docs/libraries/android',\n gatherContext: (options: WizardRunOptions) => {\n const kotlinVersion = getKotlinVersion(options);\n return Promise.resolve({ kotlinVersion });\n },\n },\n\n detection: {\n packageName: 'posthog-android',\n packageDisplayName: 'Android (Kotlin)',\n usesPackageJson: false,\n getVersion: () => undefined,\n getVersionBucket: (version: string) => getKotlinVersionBucket(version),\n // This is actually pretty high for a minimum, but android apis aren't super stable.\n minimumVersion: '21.0.0',\n getInstalledVersion: (options: WizardRunOptions) =>\n getMinSdkVersion(options),\n detectPackageManager: gradlePackageManager,\n detect: async (options) => {\n const { installDir } = options;\n\n // pubspec.yaml means Flutter — its android/ subtree would match below.\n if (fs.existsSync(path.join(installDir, 'pubspec.yaml'))) {\n return false;\n }\n\n // Strategy 1: Check for build.gradle(.kts) with Android plugin\n for (const name of ['build.gradle', 'build.gradle.kts']) {\n const buildGradlePath = path.join(installDir, name);\n if (fs.existsSync(buildGradlePath)) {\n const content = fs.readFileSync(buildGradlePath, 'utf-8');\n if (\n content.includes('com.android.application') ||\n content.includes('com.android.library') ||\n content.includes('com.android.tools.build:gradle')\n ) {\n return true;\n }\n }\n }\n\n // Strategy 2: Check for AndroidManifest.xml with Kotlin source files\n // This could be an issue if we have Flutter in the mix, but we'll figure that out later.\n const manifestFiles = await boundedGlob('**/AndroidManifest.xml', {\n cwd: installDir,\n limit: 1,\n });\n\n if (manifestFiles.length > 0) {\n const kotlinFiles = await boundedGlob('**/*.kt', {\n cwd: installDir,\n limit: 1,\n });\n if (kotlinFiles.length > 0) {\n return true;\n }\n }\n\n return false;\n },\n },\n\n environment: {\n uploadToHosting: false,\n getEnvVars: (apiKey: string, host: string) => ({\n POSTHOG_PROJECT_TOKEN: apiKey,\n POSTHOG_HOST: host,\n }),\n },\n\n analytics: {\n getTags: (context) => ({\n ...(context.kotlinVersion\n ? { kotlinVersion: getKotlinVersionBucket(context.kotlinVersion) }\n : {}),\n }),\n },\n\n prompts: {\n projectTypeDetection:\n 'This is an Android/Kotlin project. Look for build.gradle or build.gradle.kts files, AndroidManifest.xml, and Kotlin source files (.kt) to confirm.',\n packageInstallation:\n 'Add the PostHog Android SDK dependency to the app-level build.gradle(.kts) file. Use implementation(\"com.posthog:posthog-android:<VERSION>\"). Check the existing dependency format (Groovy vs Kotlin DSL) and match it.',\n getAdditionalContextLines: (context) => {\n const lines = [\n `Framework docs ID: android (use posthog://docs/frameworks/android for documentation)`,\n ];\n\n if (context.kotlinVersion) {\n lines.push(`Kotlin version: ${context.kotlinVersion}`);\n }\n\n return lines;\n },\n },\n\n ui: {\n successMessage: 'PostHog integration complete',\n estimatedDurationMinutes: 5,\n getOutroChanges: () => [\n `Analyzed your Android project structure`,\n `Added the PostHog Android SDK dependency`,\n `Configured PostHog initialization in your Application class`,\n `Added event capture and user identification`,\n ],\n getOutroNextSteps: () => [\n 'Build and run your app to see PostHog in action',\n 'Visit your PostHog dashboard to see incoming events',\n 'Check out the PostHog Android docs for advanced features like feature flags and session replay',\n ],\n },\n};\n","import fg from 'fast-glob';\nimport type { WizardRunOptions } from '@utils/types';\nimport { createVersionBucket } from '@utils/semver';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nexport enum RailsProjectType {\n STANDARD = 'standard', // Traditional Rails app (rails new)\n API = 'api', // Rails API-only (rails new --api)\n}\n\nconst IGNORE_PATTERNS = [\n '**/node_modules/**',\n '**/vendor/**',\n '**/vendor/bundle/**',\n '**/tmp/**',\n '**/log/**',\n '**/storage/**',\n];\n\n/**\n * Get Rails version bucket for analytics\n */\nexport const getRailsVersionBucket = createVersionBucket();\n\n/**\n * Read and parse Gemfile contents\n */\nfunction readGemfile(\n options: Pick<WizardRunOptions, 'installDir'>,\n): string | undefined {\n const { installDir } = options;\n\n const gemfilePath = path.join(installDir, 'Gemfile');\n try {\n return fs.readFileSync(gemfilePath, 'utf-8');\n } catch {\n return undefined;\n }\n}\n\n/**\n * Check if a gem is present in the Gemfile\n */\nexport function hasGem(\n gemName: string,\n options: Pick<WizardRunOptions, 'installDir'>,\n): boolean {\n const content = readGemfile(options);\n if (!content) return false;\n\n // Match gem declarations like: gem 'rails', gem \"rails\", gem 'rails', '~> 7.0'\n const gemPattern = new RegExp(`^\\\\s*gem\\\\s+['\"]${gemName}['\"]`, 'im');\n return gemPattern.test(content);\n}\n\n/**\n * Extract version for a gem from Gemfile\n */\nexport function getGemVersion(\n gemName: string,\n options: Pick<WizardRunOptions, 'installDir'>,\n): string | undefined {\n const content = readGemfile(options);\n if (!content) return undefined;\n\n const versionPattern = new RegExp(\n `^\\\\s*gem\\\\s+['\"]${gemName}['\"]\\\\s*,\\\\s*['\"][^0-9]*([0-9]+\\\\.[0-9]+(?:\\\\.[0-9]+)?)['\"]`,\n 'im',\n );\n const match = content.match(versionPattern);\n return match?.[1];\n}\n\n/**\n * Get Rails version from Gemfile\n */\nexport function getRailsVersion(\n options: Pick<WizardRunOptions, 'installDir'>,\n): string | undefined {\n return getGemVersion('rails', options);\n}\n\n/**\n * Detect Rails project type\n */\nexport function getRailsProjectType(\n options: WizardRunOptions,\n): RailsProjectType {\n const { installDir } = options;\n\n // Check for API-only mode in config/application.rb\n const appConfigPath = path.join(installDir, 'config/application.rb');\n if (fs.existsSync(appConfigPath)) {\n try {\n const content = fs.readFileSync(appConfigPath, 'utf-8');\n if (content.includes('config.api_only = true')) {\n return RailsProjectType.API;\n }\n } catch {\n // Continue to default\n }\n }\n\n return RailsProjectType.STANDARD;\n}\n\n/**\n * Get human-readable name for Rails project type\n */\nexport function getRailsProjectTypeName(projectType: RailsProjectType): string {\n switch (projectType) {\n case RailsProjectType.STANDARD:\n return 'Standard Rails';\n case RailsProjectType.API:\n return 'Rails API';\n }\n}\n\n/**\n * Find the Rails initializers directory\n */\nexport function findInitializersDir(\n options: Pick<WizardRunOptions, 'installDir'>,\n): string | undefined {\n const { installDir } = options;\n\n const initializersDir = path.join(installDir, 'config/initializers');\n if (fs.existsSync(initializersDir)) {\n return 'config/initializers';\n }\n\n return undefined;\n}\n\n/**\n * Detect if the project is a Rails project by looking for typical Rails files\n */\nexport async function isRailsProject(\n options: Pick<WizardRunOptions, 'installDir'>,\n): Promise<boolean> {\n const { installDir } = options;\n\n // Check for bin/rails\n const binRailsPath = path.join(installDir, 'bin/rails');\n if (fs.existsSync(binRailsPath)) {\n return true;\n }\n\n // Check for config/application.rb with Rails reference\n const appConfigPath = path.join(installDir, 'config/application.rb');\n if (fs.existsSync(appConfigPath)) {\n try {\n const content = fs.readFileSync(appConfigPath, 'utf-8');\n if (\n content.includes('Rails::Application') ||\n content.includes('require \"rails\"') ||\n content.includes(\"require 'rails'\")\n ) {\n return true;\n }\n } catch {\n // Continue to other checks\n }\n }\n\n // Check Gemfile for rails gem\n if (hasGem('rails', options)) {\n return true;\n }\n\n // Check for typical Rails directory structure\n const railsStructureFiles = await fg(\n ['config/routes.rb', 'config/environment.rb'],\n { cwd: installDir, ignore: IGNORE_PATTERNS },\n );\n\n return railsStructureFiles.length >= 2;\n}\n","/* Ruby on Rails wizard using posthog-agent with PostHog MCP */\nimport type { WizardRunOptions } from '@utils/types';\nimport type { FrameworkConfig } from '../../framework-config';\nimport { bundlerPackageManager } from '../../detection/package-manager';\nimport { Integration } from '@shared/constants';\nimport {\n getRailsVersion,\n getRailsProjectType,\n getRailsProjectTypeName,\n getRailsVersionBucket,\n RailsProjectType,\n findInitializersDir,\n isRailsProject,\n} from './utils';\n\ntype RailsContext = {\n projectType?: RailsProjectType;\n initializersDir?: string;\n};\n\nexport const RAILS_AGENT_CONFIG: FrameworkConfig<RailsContext> = {\n metadata: {\n name: 'Ruby on Rails',\n integration: Integration.rails,\n docsUrl: 'https://posthog.com/docs/libraries/ruby-on-rails',\n unsupportedVersionDocsUrl: 'https://posthog.com/docs/libraries/ruby',\n gatherContext: (options: WizardRunOptions) => {\n const projectType = getRailsProjectType(options);\n const initializersDir = findInitializersDir(options);\n return Promise.resolve({ projectType, initializersDir });\n },\n getDetectedFrameworkLabel: (context) =>\n context.projectType === RailsProjectType.API\n ? 'Rails API-only'\n : context.projectType === RailsProjectType.STANDARD\n ? 'Rails'\n : undefined,\n },\n\n detection: {\n packageName: 'rails',\n packageDisplayName: 'Ruby on Rails',\n usesPackageJson: false,\n getVersion: () => undefined,\n getVersionBucket: getRailsVersionBucket,\n minimumVersion: '6.0.0',\n getInstalledVersion: (options: WizardRunOptions) =>\n Promise.resolve(getRailsVersion(options)),\n detect: async (options) => isRailsProject(options),\n detectPackageManager: bundlerPackageManager,\n },\n\n environment: {\n uploadToHosting: false,\n getEnvVars: (apiKey: string, host: string) => ({\n POSTHOG_PROJECT_TOKEN: apiKey,\n POSTHOG_HOST: host,\n }),\n },\n\n analytics: {\n getTags: (context) => ({\n projectType: context.projectType || 'unknown',\n }),\n },\n\n prompts: {\n projectTypeDetection:\n 'This is a Ruby on Rails project. Look for Gemfile, config/application.rb, bin/rails, and config/routes.rb to confirm.',\n packageInstallation:\n \"Use Bundler to install gems. Add `gem 'posthog-ruby'` and `gem 'posthog-rails'` to the Gemfile and run `bundle install`. Do not pin specific versions.\",\n getAdditionalContextLines: (context) => {\n const projectTypeName = context.projectType\n ? getRailsProjectTypeName(context.projectType)\n : 'unknown';\n\n const lines = [\n `Project type: ${projectTypeName}`,\n `Framework docs ID: ruby-on-rails (use posthog://docs/frameworks/ruby-on-rails for documentation)`,\n ];\n\n if (context.initializersDir) {\n lines.push(`Initializers directory: ${context.initializersDir}`);\n }\n\n if (context.projectType === RailsProjectType.API) {\n lines.push(\n 'Note: This is an API-only Rails app — skip frontend posthog-js integration',\n );\n }\n\n return lines;\n },\n },\n\n ui: {\n successMessage: 'PostHog integration complete',\n estimatedDurationMinutes: 5,\n getOutroChanges: (context) => {\n const projectTypeName = context.projectType\n ? getRailsProjectTypeName(context.projectType)\n : 'Rails';\n\n const changes = [\n `Analyzed your ${projectTypeName} project structure`,\n `Installed the posthog-ruby and posthog-rails gems via Bundler`,\n `Created PostHog initializer in config/initializers/posthog.rb`,\n `Configured automatic exception capture and ActiveJob instrumentation`,\n ];\n\n if (context.projectType !== RailsProjectType.API) {\n changes.push(\n 'Added posthog-js snippet to the layout template for frontend tracking',\n );\n }\n\n return changes;\n },\n getOutroNextSteps: () => [\n 'Start your Rails development server with `bin/rails server`',\n 'Visit your PostHog dashboard to see incoming events',\n 'Use PostHog.capture() to track custom events',\n 'Use PostHog.identify() to associate events with users',\n 'Define posthog_distinct_id on your User model for automatic user association',\n ],\n },\n};\n","/* Elixir wizard using posthog-agent with PostHog MCP */\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport type { WizardRunOptions } from '@utils/types';\nimport type { FrameworkConfig } from '../../framework-config';\nimport { mixPackageManager } from '../../detection/package-manager';\nimport { Integration } from '@shared/constants';\n\ntype ElixirContext = {\n phoenix?: boolean;\n};\n\nfunction readMixExs(installDir: string): string | undefined {\n const mixExsPath = path.join(installDir, 'mix.exs');\n if (!fs.existsSync(mixExsPath)) {\n return undefined;\n }\n return fs.readFileSync(mixExsPath, 'utf-8');\n}\n\n/** Phoenix apps get the Plug integration; plain Elixir apps don't. */\nfunction isPhoenixProject(installDir: string): boolean {\n const mixExs = readMixExs(installDir);\n return !!mixExs && /\\{\\s*:phoenix\\s*,/.test(mixExs);\n}\n\nexport const ELIXIR_AGENT_CONFIG: FrameworkConfig<ElixirContext> = {\n metadata: {\n name: 'Elixir',\n integration: Integration.elixir,\n docsUrl: 'https://posthog.com/docs/libraries/elixir',\n gatherContext: (options: WizardRunOptions) => {\n const phoenix = isPhoenixProject(options.installDir);\n return Promise.resolve({ phoenix });\n },\n },\n\n detection: {\n packageName: 'posthog',\n packageDisplayName: 'Elixir',\n usesPackageJson: false,\n getVersion: () => undefined,\n // A mix.exs defining a project marks a Mix project root; the def project\n // check keeps stray files named mix.exs from claiming the directory.\n detect: (options) => {\n const mixExs = readMixExs(options.installDir);\n return Promise.resolve(!!mixExs && /def\\s+project\\b/.test(mixExs));\n },\n detectPackageManager: mixPackageManager,\n },\n\n environment: {\n uploadToHosting: false,\n getEnvVars: (apiKey: string, host: string) => ({\n POSTHOG_API_KEY: apiKey,\n POSTHOG_HOST: host,\n }),\n },\n\n analytics: {\n getTags: (context) => ({\n projectType: context.phoenix ? 'phoenix' : 'elixir',\n }),\n },\n\n prompts: {\n projectTypeDetection:\n 'This is an Elixir project. Look for mix.exs, mix.lock, config/, lib/, and application.ex to confirm; Phoenix apps also have endpoint and router modules.',\n packageInstallation:\n 'Mix has no single add command. Add `{:posthog, \"~> 2.0\"}` to the deps list in mix.exs, then run `mix deps.get` to fetch it.',\n getAdditionalContextLines: (context) => {\n const lines = [\n `Framework docs ID: elixir (use posthog://docs/frameworks/elixir for documentation)`,\n 'Configure PostHog in application config (api_key, api_host, in_app_otp_apps) reading from environment variables; set test_mode: true in the test environment.',\n ];\n if (context.phoenix) {\n lines.push(\n 'This is a Phoenix app — add PostHog.Integrations.Plug before the router so request context is attached to captured events.',\n );\n }\n return lines;\n },\n },\n\n ui: {\n successMessage: 'PostHog integration complete',\n estimatedDurationMinutes: 5,\n getOutroChanges: (context) => [\n `Analyzed your ${\n context.phoenix ? 'Phoenix' : 'Elixir'\n } project structure`,\n 'Added the posthog Hex package to mix.exs and fetched it with mix deps.get',\n 'Configured PostHog in application config from environment variables',\n 'Instrumented meaningful events with PostHog.capture',\n ],\n getOutroNextSteps: (context) => [\n context.phoenix\n ? 'Start your Phoenix server with `mix phx.server` and trigger the instrumented code paths'\n : 'Run your Elixir application and trigger the instrumented code paths',\n 'Visit your PostHog dashboard to see incoming events',\n 'Use PostHog.capture/2 to track custom events',\n 'Use PostHog.set_context/1 to set a distinct_id once per request or job process',\n ],\n },\n};\n","/* Go wizard using posthog-agent with PostHog MCP */\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport type { WizardRunOptions } from '@utils/types';\nimport type { FrameworkConfig } from '../../framework-config';\nimport { goModulesPackageManager } from '../../detection/package-manager';\nimport { Integration } from '@shared/constants';\n\ntype GoContext = {\n goVersion?: string;\n};\n\nfunction readGoMod(installDir: string): string | undefined {\n const goModPath = path.join(installDir, 'go.mod');\n if (!fs.existsSync(goModPath)) {\n return undefined;\n }\n return fs.readFileSync(goModPath, 'utf-8');\n}\n\n/** The `go 1.x` directive from go.mod (the toolchain floor, not a patch version). */\nfunction getGoVersion(installDir: string): string | undefined {\n const goMod = readGoMod(installDir);\n return goMod?.match(/^go\\s+([\\d.]+)/m)?.[1];\n}\n\nexport const GO_AGENT_CONFIG: FrameworkConfig<GoContext> = {\n metadata: {\n name: 'Go',\n integration: Integration.go,\n docsUrl: 'https://posthog.com/docs/libraries/go',\n gatherContext: (options: WizardRunOptions) => {\n const goVersion = getGoVersion(options.installDir);\n return Promise.resolve({ goVersion });\n },\n },\n\n detection: {\n packageName: 'posthog-go',\n packageDisplayName: 'Go',\n usesPackageJson: false,\n getVersion: () => undefined,\n // A go.mod with a module directive marks a Go module root; a bare\n // directory containing .go files without one is not integratable.\n detect: (options) => {\n const goMod = readGoMod(options.installDir);\n return Promise.resolve(!!goMod && /^module\\s+\\S+/m.test(goMod));\n },\n detectPackageManager: goModulesPackageManager,\n },\n\n environment: {\n uploadToHosting: false,\n getEnvVars: (apiKey: string, host: string) => ({\n POSTHOG_API_KEY: apiKey,\n POSTHOG_HOST: host,\n }),\n },\n\n analytics: {\n getTags: (context) => ({\n goVersion: context.goVersion || 'unknown',\n }),\n },\n\n prompts: {\n projectTypeDetection:\n 'This is a Go project. Look for go.mod, go.sum, cmd/, internal/, and main packages to confirm.',\n packageInstallation:\n 'Install the PostHog Go SDK with `go get github.com/posthog/posthog-go`. Do not manually edit go.mod or go.sum; the go tool updates them automatically. Run `go mod tidy` afterwards if imports change.',\n getAdditionalContextLines: (context) => {\n const lines = [\n `Framework docs ID: go (use posthog://docs/frameworks/go for documentation)`,\n ];\n if (context.goVersion) {\n lines.push(`Go version (go.mod directive): ${context.goVersion}`);\n }\n lines.push(\n 'Create one PostHog client per process and close it during graceful shutdown (`defer client.Close()`) so queued events flush.',\n );\n return lines;\n },\n },\n\n ui: {\n successMessage: 'PostHog integration complete',\n estimatedDurationMinutes: 5,\n getOutroChanges: () => [\n 'Analyzed your Go project structure',\n 'Installed the posthog-go SDK via go get',\n 'Initialized a shared PostHog client configured from environment variables',\n 'Instrumented meaningful server events with client.Enqueue(posthog.Capture{...})',\n ],\n getOutroNextSteps: () => [\n 'Run your Go service and trigger the instrumented code paths',\n 'Visit your PostHog dashboard to see incoming events',\n 'Use client.Enqueue(posthog.Capture{...}) to track custom events',\n 'Keep client.Close() in your graceful shutdown path so queued events flush',\n ],\n },\n};\n","/* Java (server) wizard using posthog-agent with PostHog MCP */\nimport fg from 'fast-glob';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport type { WizardRunOptions } from '@utils/types';\nimport type { FrameworkConfig } from '../../framework-config';\nimport { detectJavaPackageManagers } from '../../detection/package-manager';\nimport { Integration } from '@shared/constants';\n\ntype JavaContext = {\n buildTool?: 'maven' | 'gradle';\n};\n\nconst GRADLE_FILES = [\n 'build.gradle',\n 'build.gradle.kts',\n 'settings.gradle',\n 'settings.gradle.kts',\n];\n\nconst ANDROID_GRADLE_MARKERS = [\n 'com.android.application',\n 'com.android.library',\n 'com.android.tools.build:gradle',\n];\n\nconst KMP_GRADLE_MARKERS = [\n 'kotlin(\"multiplatform\")',\n 'org.jetbrains.kotlin.multiplatform',\n 'kotlin-multiplatform',\n];\n\nfunction readRootGradleFiles(installDir: string): string[] {\n return GRADLE_FILES.map((name) => path.join(installDir, name))\n .filter((p) => fs.existsSync(p))\n .map((p) => fs.readFileSync(p, 'utf-8'));\n}\n\nfunction getBuildTool(installDir: string): 'maven' | 'gradle' | undefined {\n if (fs.existsSync(path.join(installDir, 'pom.xml'))) {\n return 'maven';\n }\n if (readRootGradleFiles(installDir).length > 0) {\n return 'gradle';\n }\n return undefined;\n}\n\nexport const JAVA_AGENT_CONFIG: FrameworkConfig<JavaContext> = {\n metadata: {\n name: 'Java',\n integration: Integration.java,\n docsUrl: 'https://posthog.com/docs/libraries/java',\n gatherContext: (options: WizardRunOptions) => {\n const buildTool = getBuildTool(options.installDir);\n return Promise.resolve({ buildTool });\n },\n },\n\n detection: {\n packageName: 'posthog-server',\n packageDisplayName: 'Java',\n usesPackageJson: false,\n getVersion: () => undefined,\n // Maven projects (pom.xml) are unambiguously JVM backends. Gradle\n // projects are only claimed when they are neither Android nor KMP —\n // those detectors are ordered earlier, and this re-check keeps a\n // direct java detect() call from ever claiming their projects.\n detect: async (options) => {\n const { installDir } = options;\n\n // pubspec.yaml means Flutter — its gradle subtree is not a JVM backend.\n if (fs.existsSync(path.join(installDir, 'pubspec.yaml'))) {\n return false;\n }\n\n if (fs.existsSync(path.join(installDir, 'pom.xml'))) {\n return true;\n }\n\n const gradleContents = readRootGradleFiles(installDir);\n if (gradleContents.length === 0) {\n return false;\n }\n const combined = gradleContents.join('\\n');\n if (\n [...ANDROID_GRADLE_MARKERS, ...KMP_GRADLE_MARKERS].some((marker) =>\n combined.includes(marker),\n )\n ) {\n return false;\n }\n\n const manifestFiles = await fg('**/AndroidManifest.xml', {\n cwd: installDir,\n ignore: ['**/build/**', '**/node_modules/**', '**/.gradle/**'],\n });\n return manifestFiles.length === 0;\n },\n detectPackageManager: detectJavaPackageManagers,\n },\n\n environment: {\n uploadToHosting: false,\n getEnvVars: (apiKey: string, host: string) => ({\n POSTHOG_API_KEY: apiKey,\n POSTHOG_HOST: host,\n }),\n },\n\n analytics: {\n getTags: (context) => ({\n buildTool: context.buildTool || 'unknown',\n }),\n },\n\n prompts: {\n projectTypeDetection:\n 'This is a Java server project. Look for pom.xml (Maven) or build.gradle/build.gradle.kts (Gradle), src/main/java/, and the framework in use (Spring Boot, Quarkus, Micronaut, plain servlets) to confirm.',\n packageInstallation:\n 'Neither Maven nor Gradle has a single add command. Add the com.posthog:posthog-server dependency (pinned to the latest release on Maven Central) to pom.xml or build.gradle(.kts), matching the existing dependency format, then run `mvn install` or `gradle build` to resolve it.',\n getAdditionalContextLines: (context) => {\n const lines = [\n `Framework docs ID: java (use posthog://docs/frameworks/java for documentation)`,\n 'Use the posthog-server SDK (com.posthog:posthog-server) — posthog-android is a different library and must not be used on the server.',\n 'Create one PostHog client per process with PostHogConfig.builder(...) and PostHog.with(config); call close() during graceful shutdown, and flush() before returning in serverless handlers.',\n ];\n if (context.buildTool) {\n lines.push(`Build tool: ${context.buildTool}`);\n }\n return lines;\n },\n },\n\n ui: {\n successMessage: 'PostHog integration complete',\n estimatedDurationMinutes: 5,\n getOutroChanges: (context) => [\n 'Analyzed your Java project structure',\n `Added the posthog-server dependency to your ${\n context.buildTool === 'maven' ? 'pom.xml' : 'Gradle build'\n }`,\n 'Initialized a shared PostHog client configured from environment variables',\n 'Instrumented meaningful server events with posthog.capture',\n ],\n getOutroNextSteps: () => [\n 'Run your Java service and trigger the instrumented code paths',\n 'Visit your PostHog dashboard to see incoming events',\n 'Use posthog.capture(distinctId, eventName, options) to track custom events',\n 'Keep posthog.close() in your graceful shutdown path so queued events flush',\n ],\n },\n};\n","/* Rust wizard using posthog-agent with PostHog MCP */\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport type { WizardRunOptions } from '@utils/types';\nimport type { FrameworkConfig } from '../../framework-config';\nimport { cargoPackageManager } from '../../detection/package-manager';\nimport { Integration } from '@shared/constants';\n\ntype RustContext = {\n asyncRuntime?: boolean;\n};\n\nfunction readCargoToml(installDir: string): string | undefined {\n const cargoTomlPath = path.join(installDir, 'Cargo.toml');\n if (!fs.existsSync(cargoTomlPath)) {\n return undefined;\n }\n return fs.readFileSync(cargoTomlPath, 'utf-8');\n}\n\n/** posthog-rs defaults to its async client; projects without an async runtime need the blocking one. */\nfunction hasAsyncRuntime(installDir: string): boolean {\n const cargoToml = readCargoToml(installDir);\n return !!cargoToml && /^\\s*(tokio|async-std|smol)\\s*[=.]/m.test(cargoToml);\n}\n\nexport const RUST_AGENT_CONFIG: FrameworkConfig<RustContext> = {\n metadata: {\n name: 'Rust',\n integration: Integration.rust,\n docsUrl: 'https://posthog.com/docs/libraries/rust',\n gatherContext: (options: WizardRunOptions) => {\n const asyncRuntime = hasAsyncRuntime(options.installDir);\n return Promise.resolve({ asyncRuntime });\n },\n },\n\n detection: {\n packageName: 'posthog-rs',\n packageDisplayName: 'Rust',\n usesPackageJson: false,\n getVersion: () => undefined,\n // A Cargo.toml with a [package] section marks a crate root. A\n // workspace-root-only manifest ([workspace], no [package]) falls\n // through — the agentic monorepo scan finds the nested crates.\n detect: (options) => {\n const cargoToml = readCargoToml(options.installDir);\n return Promise.resolve(!!cargoToml && /^\\s*\\[package\\]/m.test(cargoToml));\n },\n detectPackageManager: cargoPackageManager,\n },\n\n environment: {\n uploadToHosting: false,\n getEnvVars: (apiKey: string, host: string) => ({\n POSTHOG_API_KEY: apiKey,\n POSTHOG_HOST: host,\n }),\n },\n\n analytics: {\n getTags: (context) => ({\n asyncRuntime: context.asyncRuntime ? 'true' : 'false',\n }),\n },\n\n prompts: {\n projectTypeDetection:\n 'This is a Rust project. Look for Cargo.toml with a [package] section, src/main.rs or src/lib.rs, and Cargo.lock to confirm.',\n packageInstallation:\n 'Install the PostHog Rust SDK with `cargo add posthog-rs`. Do not manually edit Cargo.toml; cargo updates it automatically.',\n getAdditionalContextLines: (context) => {\n const lines = [\n `Framework docs ID: rust (use posthog://docs/frameworks/rust for documentation)`,\n 'capture() hands events to a background worker — the client must flush() or shutdown() before the process exits or buffered events are lost.',\n ];\n if (context.asyncRuntime) {\n lines.push(\n 'An async runtime is present — use the default async posthog-rs client.',\n );\n } else {\n lines.push(\n 'No async runtime detected — install with `cargo add posthog-rs --no-default-features` and use the blocking client.',\n );\n }\n return lines;\n },\n },\n\n ui: {\n successMessage: 'PostHog integration complete',\n estimatedDurationMinutes: 5,\n getOutroChanges: () => [\n 'Analyzed your Rust project structure',\n 'Installed the posthog-rs crate via cargo add',\n 'Initialized a shared PostHog client configured from environment variables',\n 'Instrumented meaningful events with client.capture',\n ],\n getOutroNextSteps: () => [\n 'Run your Rust application and trigger the instrumented code paths',\n 'Visit your PostHog dashboard to see incoming events',\n 'Use Event::new(event_name, distinct_id) and client.capture to track custom events',\n 'Keep flush()/shutdown() in your exit path so queued events are sent',\n ],\n },\n};\n","/* Generic Python language wizard using posthog-agent with PostHog MCP */\nimport type { WizardRunOptions } from '@utils/types';\nimport type { FrameworkConfig } from '../../framework-config';\nimport { PYTHON_PACKAGE_INSTALLATION } from '../../framework-config';\nimport { detectPythonPackageManagers } from '../../detection/package-manager';\nimport { Integration } from '@shared/constants';\nimport fg from 'fast-glob';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport {\n getPythonVersion,\n getPythonVersionBucket,\n detectPackageManager,\n getPackageManagerName,\n PythonPackageManager,\n} from './utils';\n\ntype PythonContext = {\n packageManager?: PythonPackageManager;\n};\n\nexport const PYTHON_AGENT_CONFIG: FrameworkConfig<PythonContext> = {\n metadata: {\n name: 'Python Language',\n integration: Integration.python,\n docsUrl: 'https://posthog.com/docs/libraries/python',\n gatherContext: async (options: WizardRunOptions) => {\n const packageManager = await detectPackageManager(options);\n return { packageManager };\n },\n },\n\n detection: {\n packageName: 'python',\n packageDisplayName: 'Python',\n usesPackageJson: false,\n getVersion: () => undefined,\n getVersionBucket: getPythonVersionBucket,\n minimumVersion: '3.8.0',\n getInstalledVersion: (options: WizardRunOptions) =>\n Promise.resolve(getPythonVersion(options)),\n detect: async (options) => {\n const { installDir } = options;\n\n // Look for Python package management files\n const pythonConfigFiles = await fg(\n [\n '**/requirements*.txt',\n '**/pyproject.toml',\n '**/setup.py',\n '**/Pipfile',\n ],\n {\n cwd: installDir,\n ignore: ['**/venv/**', '**/.venv/**', '**/env/**', '**/.env/**'],\n },\n );\n\n if (pythonConfigFiles.length === 0) {\n return false;\n }\n\n // Make sure this isn't Django or Flask (those should be detected first)\n // Check for Django\n const managePyMatches = await fg('**/manage.py', {\n cwd: installDir,\n ignore: ['**/venv/**', '**/.venv/**', '**/env/**', '**/.env/**'],\n });\n\n for (const match of managePyMatches) {\n try {\n const content = fs.readFileSync(\n path.join(installDir, match),\n 'utf-8',\n );\n if (\n content.includes('django') ||\n content.includes('DJANGO_SETTINGS_MODULE')\n ) {\n return false; // Django detected, use django agent instead\n }\n } catch {\n continue;\n }\n }\n\n // Check for Flask\n for (const configFile of pythonConfigFiles) {\n try {\n const content = fs.readFileSync(\n path.join(installDir, configFile),\n 'utf-8',\n );\n if (\n /^flask([<>=~!]|$|\\s)/im.test(content) ||\n /[\"']flask[\"']/i.test(content)\n ) {\n return false; // Flask detected, use flask agent instead\n }\n } catch {\n continue;\n }\n }\n\n const pyFiles = await fg(\n ['**/app.py', '**/wsgi.py', '**/application.py', '**/__init__.py'],\n {\n cwd: installDir,\n ignore: [\n '**/venv/**',\n '**/.venv/**',\n '**/env/**',\n '**/.env/**',\n '**/__pycache__/**',\n ],\n },\n );\n\n for (const pyFile of pyFiles) {\n try {\n const content = fs.readFileSync(\n path.join(installDir, pyFile),\n 'utf-8',\n );\n if (\n content.includes('from flask import') ||\n content.includes('import flask') ||\n /Flask\\s*\\(/.test(content)\n ) {\n return false; // Flask detected, use flask agent instead\n }\n } catch {\n continue;\n }\n }\n\n // If we have Python config files but it's not Django or Flask, it's a generic Python project\n return true;\n },\n detectPackageManager: detectPythonPackageManagers,\n },\n\n environment: {\n uploadToHosting: false,\n getEnvVars: (apiKey: string, host: string) => ({\n POSTHOG_PROJECT_TOKEN: apiKey,\n POSTHOG_HOST: host,\n }),\n },\n\n analytics: {\n getTags: (context) => {\n const packageManagerName = context.packageManager\n ? getPackageManagerName(context.packageManager)\n : 'unknown';\n return {\n packageManager: packageManagerName,\n };\n },\n },\n\n prompts: {\n packageInstallation: PYTHON_PACKAGE_INSTALLATION,\n projectTypeDetection:\n 'This is a generic Python project. Look for requirements.txt, pyproject.toml, setup.py, or Pipfile to confirm.',\n getAdditionalContextLines: (context) => {\n const packageManagerName = context.packageManager\n ? getPackageManagerName(context.packageManager)\n : 'unknown';\n\n return [\n `Package manager: ${packageManagerName}`,\n `Framework docs ID: python (use posthog://docs/frameworks/python for documentation)`,\n `Project type: Generic Python application (CLI, script, worker, data pipeline, etc.)`,\n ];\n },\n },\n\n ui: {\n successMessage: 'PostHog integration complete',\n estimatedDurationMinutes: 5,\n getOutroChanges: (context) => {\n const packageManagerName = context.packageManager\n ? getPackageManagerName(context.packageManager)\n : 'package manager';\n return [\n `Analyzed your Python project structure`,\n `Installed the PostHog Python package using ${packageManagerName}`,\n `Created PostHog initialization using instance-based API (Posthog class)`,\n `Configured exception autocapture and graceful shutdown`,\n `Added example code for events, feature flags, and error capture (without PII)`,\n ];\n },\n getOutroNextSteps: () => [\n 'Use Posthog() class (not module-level posthog) with enable_exception_autocapture=True',\n 'Call posthog_client.shutdown() on application exit (use atexit.register)',\n 'NEVER send PII in event properties (no emails, names, or user content)',\n 'Use posthog_client.capture() for events and posthog_client.identify() for users',\n 'Visit your PostHog dashboard to see incoming events',\n ],\n },\n};\n","import { boundedGlob } from '@utils/bounded-fs';\nimport type { WizardRunOptions } from '@utils/types';\nimport { createVersionBucket } from '@utils/semver';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\n\nexport enum RubyPackageManager {\n BUNDLER = 'bundler',\n MANUAL = 'manual',\n}\n\nconst EXTRA_IGNORE = ['**/tmp/**', '**/log/**'];\n\n/**\n * Get Ruby version bucket for analytics\n */\nexport const getRubyVersionBucket = createVersionBucket();\n\n/**\n * Detect Ruby package manager\n */\nexport function detectPackageManager(\n options: Pick<WizardRunOptions, 'installDir'>,\n): RubyPackageManager {\n const { installDir } = options;\n\n const gemfilePath = path.join(installDir, 'Gemfile');\n if (fs.existsSync(gemfilePath)) {\n return RubyPackageManager.BUNDLER;\n }\n\n return RubyPackageManager.MANUAL;\n}\n\n/**\n * Get human-readable name for package manager\n */\nexport function getPackageManagerName(\n packageManager: RubyPackageManager,\n): string {\n switch (packageManager) {\n case RubyPackageManager.BUNDLER:\n return 'Bundler';\n case RubyPackageManager.MANUAL:\n return 'gem install';\n }\n}\n\n/**\n * Get Ruby version from .ruby-version file or Gemfile\n */\nexport function getRubyVersion(\n options: Pick<WizardRunOptions, 'installDir'>,\n): string | undefined {\n const { installDir } = options;\n\n // Check .ruby-version file\n const rubyVersionPath = path.join(installDir, '.ruby-version');\n try {\n const content = fs.readFileSync(rubyVersionPath, 'utf-8').trim();\n // Remove \"ruby-\" prefix if present\n const version = content.replace(/^ruby-/, '');\n if (/^[0-9]+\\.[0-9]+/.test(version)) {\n return version;\n }\n } catch {\n // Continue to other checks\n }\n\n // Check Gemfile for ruby version declaration\n const gemfilePath = path.join(installDir, 'Gemfile');\n try {\n const content = fs.readFileSync(gemfilePath, 'utf-8');\n const match = content.match(/ruby\\s+['\"]([0-9]+\\.[0-9]+(?:\\.[0-9]+)?)['\"]/);\n if (match) {\n return match[1];\n }\n } catch {\n // No Gemfile\n }\n\n return undefined;\n}\n\n/**\n * Check if the project is a Ruby project (but not Rails)\n */\nexport async function isRubyProject(\n options: Pick<WizardRunOptions, 'installDir'>,\n): Promise<boolean> {\n const { installDir } = options;\n\n // Check for Gemfile\n const gemfilePath = path.join(installDir, 'Gemfile');\n if (fs.existsSync(gemfilePath)) {\n // Make sure this isn't a Rails project (Rails should be detected first)\n try {\n const content = fs.readFileSync(gemfilePath, 'utf-8');\n if (/^\\s*gem\\s+['\"]rails['\"]/im.test(content)) {\n return false; // Rails project, use rails agent instead\n }\n } catch {\n // Continue checking\n }\n return true;\n }\n\n // Check for .ruby-version file\n const rubyVersionPath = path.join(installDir, '.ruby-version');\n if (fs.existsSync(rubyVersionPath)) {\n return true;\n }\n\n // Check for *.gemspec files\n const gemspecFiles = await boundedGlob('*.gemspec', {\n cwd: installDir,\n extraIgnore: EXTRA_IGNORE,\n limit: 1,\n });\n\n if (gemspecFiles.length > 0) {\n return true;\n }\n\n // Check for Ruby source files in the root\n const rubyFiles = await boundedGlob(['*.rb', 'lib/**/*.rb', 'bin/**/*.rb'], {\n cwd: installDir,\n extraIgnore: EXTRA_IGNORE,\n limit: 1,\n });\n\n return rubyFiles.length > 0;\n}\n","/* Generic Ruby language wizard using posthog-agent with PostHog MCP */\nimport type { WizardRunOptions } from '@utils/types';\nimport type { FrameworkConfig } from '../../framework-config';\nimport { bundlerPackageManager } from '../../detection/package-manager';\nimport { Integration } from '@shared/constants';\nimport {\n getRubyVersion,\n getRubyVersionBucket,\n detectPackageManager,\n getPackageManagerName,\n RubyPackageManager,\n isRubyProject,\n} from './utils';\n\ntype RubyContext = {\n packageManager?: RubyPackageManager;\n};\n\nexport const RUBY_AGENT_CONFIG: FrameworkConfig<RubyContext> = {\n metadata: {\n name: 'Ruby',\n integration: Integration.ruby,\n docsUrl: 'https://posthog.com/docs/libraries/ruby',\n gatherContext: (options: WizardRunOptions) => {\n const packageManager = detectPackageManager(options);\n return Promise.resolve({ packageManager });\n },\n },\n\n detection: {\n packageName: 'ruby',\n packageDisplayName: 'Ruby',\n usesPackageJson: false,\n getVersion: () => undefined,\n getVersionBucket: getRubyVersionBucket,\n minimumVersion: '2.7.0',\n getInstalledVersion: (options: WizardRunOptions) =>\n Promise.resolve(getRubyVersion(options)),\n detect: async (options) => isRubyProject(options),\n detectPackageManager: bundlerPackageManager,\n },\n\n environment: {\n uploadToHosting: false,\n getEnvVars: (apiKey: string, host: string) => ({\n POSTHOG_PROJECT_TOKEN: apiKey,\n POSTHOG_HOST: host,\n }),\n },\n\n analytics: {\n getTags: (context) => {\n const packageManagerName = context.packageManager\n ? getPackageManagerName(context.packageManager)\n : 'unknown';\n return {\n packageManager: packageManagerName,\n };\n },\n },\n\n prompts: {\n projectTypeDetection:\n 'This is a Ruby project. Look for Gemfile, *.gemspec, .ruby-version, or *.rb files to confirm.',\n packageInstallation:\n \"Use Bundler if a Gemfile is present (add `gem 'posthog-ruby'` and run `bundle install`). Otherwise use `gem install posthog-ruby`. Do not pin a specific version.\",\n getAdditionalContextLines: (context) => {\n const packageManagerName = context.packageManager\n ? getPackageManagerName(context.packageManager)\n : 'unknown';\n\n const lines = [\n `Package manager: ${packageManagerName}`,\n `Framework docs ID: ruby (use posthog://docs/frameworks/ruby for documentation)`,\n `Project type: Generic Ruby application (CLI, script, gem, worker, etc.)`,\n ``,\n `## CRITICAL: Ruby PostHog Best Practices`,\n ``,\n `### 1. Gem Name vs Require`,\n `The gem is named posthog-ruby but you require it as 'posthog':`,\n ` gem 'posthog-ruby' # in Gemfile`,\n ` require 'posthog' # in code (NOT require 'posthog-ruby')`,\n ``,\n `### 2. Use Instance-Based API (REQUIRED for scripts/CLIs)`,\n `Use PostHog::Client.new for scripts and standalone applications:`,\n ``,\n `client = PostHog::Client.new(`,\n ` api_key: ENV['POSTHOG_PROJECT_TOKEN'],`,\n ` host: ENV['POSTHOG_HOST'] || 'https://us.i.posthog.com'`,\n `)`,\n ``,\n `### 3. MUST Call shutdown Before Exit`,\n `In scripts and CLIs, you MUST call client.shutdown or events will be lost:`,\n ``,\n `begin`,\n ` client.capture(distinct_id: 'user_123', event: 'my_event')`,\n `ensure`,\n ` client.shutdown`,\n `end`,\n ``,\n `### 4. capture_exception Takes Positional Args`,\n `client.capture_exception(exception, distinct_id, additional_properties)`,\n `Do NOT use keyword arguments for capture_exception.`,\n ``,\n `### 5. NEVER Send PII`,\n `Do NOT include emails, names, phone numbers, or user content in event properties.`,\n ];\n\n return lines;\n },\n },\n\n ui: {\n successMessage: 'PostHog integration complete',\n estimatedDurationMinutes: 5,\n getOutroChanges: (context) => {\n const packageManagerName = context.packageManager\n ? getPackageManagerName(context.packageManager)\n : 'package manager';\n return [\n `Analyzed your Ruby project structure`,\n `Installed the posthog-ruby gem using ${packageManagerName}`,\n `Created PostHog initialization with instance-based API`,\n `Configured shutdown handler for proper event flushing`,\n ];\n },\n getOutroNextSteps: () => [\n 'Use client.capture() for events and client.identify() for users',\n 'Always call client.shutdown() before your application exits',\n 'Visit your PostHog dashboard to see incoming events',\n ],\n },\n};\n","/* Generic Node.js language wizard using posthog-agent with PostHog MCP */\nimport type { FrameworkConfig } from '../../framework-config';\nimport { Integration } from '@shared/constants';\nimport { tryGetPackageJson } from '@utils/setup-utils';\nimport { detectNodePackageManagers } from '../../detection/package-manager';\n\ntype JavaScriptNodeContext = Record<string, unknown>;\n\nexport const JAVASCRIPT_NODE_AGENT_CONFIG: FrameworkConfig<JavaScriptNodeContext> =\n {\n metadata: {\n name: 'Node.js',\n integration: Integration.javascriptNode,\n docsUrl: 'https://posthog.com/docs/libraries/node',\n },\n\n detection: {\n packageName: 'posthog-node',\n packageDisplayName: 'Node.js',\n usesPackageJson: false,\n getVersion: () => undefined,\n detectPackageManager: detectNodePackageManagers,\n detect: async (options) => {\n const packageJson = await tryGetPackageJson(options);\n return !!packageJson;\n },\n },\n\n environment: {\n uploadToHosting: false,\n getEnvVars: (apiKey: string, host: string) => ({\n POSTHOG_PROJECT_TOKEN: apiKey,\n POSTHOG_HOST: host,\n }),\n },\n\n analytics: {\n getTags: () => ({}),\n },\n\n prompts: {\n projectTypeDetection:\n 'This is a server-side Node.js project. Look for package.json and lockfiles to confirm.',\n packageInstallation:\n 'Use npm, yarn, pnpm, or bun based on the existing lockfile (package-lock.json, yarn.lock, pnpm-lock.yaml, bun.lockb). Install posthog-node as a regular dependency.',\n getAdditionalContextLines: () => [\n `Framework docs ID: javascript_node (use posthog://docs/frameworks/javascript_node for documentation)`,\n ],\n },\n\n ui: {\n successMessage: 'PostHog integration complete',\n estimatedDurationMinutes: 5,\n getOutroChanges: () => [\n `Analyzed your Node.js project structure`,\n `Installed the posthog-node package`,\n `Created PostHog initialization with proper configuration`,\n `Configured graceful shutdown for event flushing`,\n `Added example code for events, feature flags, and error capture`,\n ],\n getOutroNextSteps: () => [\n 'Use the PostHog client instance for all tracking calls',\n 'Call posthog.shutdown() on application exit to flush pending events',\n 'NEVER send PII in event properties (no emails, names, or user content)',\n 'Use posthog.capture() for events and posthog.identify() for users',\n 'Visit your PostHog dashboard to see incoming events',\n ],\n },\n };\n","import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { boundedGlob } from '@utils/bounded-fs';\nimport { detectAllPackageManagers } from '@utils/package-manager';\nimport type { WizardRunOptions } from '@utils/types';\n\nexport type JavaScriptContext = {\n packageManagerName?: string;\n hasTypeScript?: boolean;\n hasBundler?: string;\n};\n\nconst INDEX_HTML_MAX_DEPTH = 6;\n\n/**\n * Packages that indicate a specific framework integration exists.\n * If any of these are in package.json, we should NOT match as generic JavaScript.\n *\n * When adding a new JS framework integration to the wizard,\n * add its detection package here too.\n */\nexport const FRAMEWORK_PACKAGES = [\n 'next',\n 'nuxt',\n 'vue',\n 'react-router',\n '@tanstack/react-start',\n '@tanstack/react-router',\n 'react-native',\n '@angular/core',\n 'astro',\n '@sveltejs/kit',\n] as const;\n\n/**\n * Detect the JS package manager for the project by checking lockfiles.\n * Reuses the existing package manager detection infrastructure.\n */\nexport function detectJsPackageManager(\n options: Pick<WizardRunOptions, 'installDir'>,\n): string {\n const detected = detectAllPackageManagers(options);\n if (detected.length > 0) {\n return detected[0].label;\n }\n return 'unknown';\n}\n\n/**\n * Detect the bundler used in the project by checking package.json dependencies.\n */\nexport function detectBundler(\n options: Pick<WizardRunOptions, 'installDir'>,\n): string | undefined {\n try {\n const content = fs.readFileSync(\n path.join(options.installDir, 'package.json'),\n 'utf-8',\n );\n const pkg = JSON.parse(content);\n const allDeps: Record<string, string> = {\n ...pkg.dependencies,\n ...pkg.devDependencies,\n };\n\n if (allDeps['vite']) return 'vite';\n if (allDeps['webpack']) return 'webpack';\n if (allDeps['esbuild']) return 'esbuild';\n if (allDeps['parcel']) return 'parcel';\n if (allDeps['rollup']) return 'rollup';\n return undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Heuristic: check if there is an index.html anywhere in the project,\n * ignoring common build and dependency directories.\n */\nexport async function hasIndexHtml(\n options: Pick<WizardRunOptions, 'installDir'>,\n): Promise<boolean> {\n const matches = await boundedGlob('**/index.html', {\n cwd: options.installDir,\n deep: INDEX_HTML_MAX_DEPTH,\n limit: 1,\n });\n\n return matches.length > 0;\n}\n","/* Generic JavaScript Web (client-side) wizard using posthog-agent with PostHog MCP */\nimport type { WizardRunOptions } from '@utils/types';\nimport type { FrameworkConfig } from '../../framework-config';\nimport { Integration } from '@shared/constants';\nimport * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport { hasDeclaredDependency } from '@utils/package-json';\nimport { tryGetPackageJson } from '@utils/setup-utils';\nimport {\n FRAMEWORK_PACKAGES,\n detectJsPackageManager,\n detectBundler,\n hasIndexHtml,\n type JavaScriptContext,\n} from './utils';\nimport { detectNodePackageManagers } from '../../detection/package-manager';\n\nexport const JAVASCRIPT_WEB_AGENT_CONFIG: FrameworkConfig<JavaScriptContext> = {\n metadata: {\n name: 'JavaScript (Web)',\n integration: Integration.javascript_web,\n docsUrl: 'https://posthog.com/docs/libraries/js',\n gatherContext: (options: WizardRunOptions) => {\n const packageManagerName = detectJsPackageManager(options);\n const hasTypeScript = fs.existsSync(\n path.join(options.installDir, 'tsconfig.json'),\n );\n const hasBundler = detectBundler(options);\n return Promise.resolve({ packageManagerName, hasTypeScript, hasBundler });\n },\n },\n\n detection: {\n packageName: 'posthog-js',\n packageDisplayName: 'JavaScript (Web)',\n usesPackageJson: false,\n getVersion: () => undefined,\n detectPackageManager: detectNodePackageManagers,\n detect: async (options) => {\n const packageJson = await tryGetPackageJson(options);\n if (!packageJson) {\n return false;\n }\n\n // Exclude projects with known framework packages\n for (const frameworkPkg of FRAMEWORK_PACKAGES) {\n if (hasDeclaredDependency(frameworkPkg, packageJson)) {\n return false;\n }\n }\n\n const { installDir } = options;\n\n // Has (index.html OR has a bundler) AND is a JavaScript project\n const hasIndexHtmlFlag = await hasIndexHtml(options);\n\n const bundler = detectBundler(options);\n const hasBundler = !!bundler;\n\n const hasLockfile = [\n 'package-lock.json',\n 'yarn.lock',\n 'pnpm-lock.yaml',\n 'bun.lockb',\n 'bun.lock',\n 'deno.lock',\n ].some((lockfile) => fs.existsSync(path.join(installDir, lockfile)));\n\n // We only treat this as JS Web if there's BOTH:\n // - a lockfile, and\n // - at least one frontend signal (index.html or bundler)\n if (hasLockfile && (hasIndexHtmlFlag || hasBundler)) {\n return true;\n }\n\n // Otherwise → Node/Backend (handled by javascriptNode fallback)\n return false;\n },\n },\n\n environment: {\n uploadToHosting: false,\n getEnvVars: (apiKey: string, host: string) => ({\n POSTHOG_PROJECT_TOKEN: apiKey,\n POSTHOG_HOST: host,\n }),\n },\n\n analytics: {\n getTags: (context) => {\n const tags: Record<string, string> = {\n packageManager: context.packageManagerName ?? 'unknown',\n };\n if (context.hasBundler) {\n tags.bundler = context.hasBundler;\n }\n return tags;\n },\n },\n\n prompts: {\n projectTypeDetection:\n 'This is a JavaScript/TypeScript project. Look for package.json and lockfiles (package-lock.json, yarn.lock, pnpm-lock.yaml, bun.lockb) to confirm.',\n packageInstallation:\n 'Look for lockfiles to determine the package manager (npm, yarn, pnpm, bun). Do not manually edit package.json.',\n getAdditionalContextLines: (context) => {\n const lines = [\n `Package manager: ${context.packageManagerName ?? 'unknown'}`,\n `Has TypeScript: ${context.hasTypeScript ? 'yes' : 'no'}`,\n `Framework docs ID: js (use posthog://docs/frameworks/js for documentation if available)`,\n `Project type: Generic JavaScript/TypeScript application (no specific framework detected)`,\n ];\n\n if (context.hasBundler) {\n lines.unshift(`Bundler: ${context.hasBundler}`);\n }\n\n return lines;\n },\n },\n\n ui: {\n successMessage: 'PostHog integration complete',\n estimatedDurationMinutes: 5,\n getOutroChanges: (context) => {\n const packageManagerName =\n context.packageManagerName ?? 'package manager';\n return [\n `Analyzed your JavaScript project structure`,\n `Installed the posthog-js package using ${packageManagerName}`,\n `Created PostHog initialization code`,\n `Configured autocapture, error tracking, and event capture`,\n ];\n },\n getOutroNextSteps: () => [\n 'Ensure posthog.init() is called before any capture calls',\n 'Autocapture tracks clicks, form submissions, and pageviews automatically',\n 'Use posthog.capture() for custom events and posthog.identify() for users',\n 'NEVER send PII in event properties (no emails, names, or user content)',\n 'Visit your PostHog dashboard to see incoming events',\n ],\n },\n};\n","import type { FrameworkConfig } from '../framework-config';\nimport { Integration } from '@shared/constants';\nimport { NEXTJS_AGENT_CONFIG } from './nextjs/nextjs-wizard-agent';\nimport { NUXT_AGENT_CONFIG } from './nuxt/nuxt-wizard-agent';\nimport { VUE_AGENT_CONFIG } from './vue/vue-wizard-agent';\nimport { REACT_ROUTER_AGENT_CONFIG } from './react-router/react-router-wizard-agent';\nimport { TANSTACK_ROUTER_AGENT_CONFIG } from './tanstack-router/tanstack-router-wizard-agent';\nimport { TANSTACK_START_AGENT_CONFIG } from './tanstack-start/tanstack-start-wizard-agent';\nimport { REACT_NATIVE_AGENT_CONFIG } from './react-native/react-native-wizard-agent';\nimport { ANGULAR_AGENT_CONFIG } from './angular/angular-wizard-agent';\nimport { ASTRO_AGENT_CONFIG } from './astro/astro-wizard-agent';\nimport { DJANGO_AGENT_CONFIG } from './django/django-wizard-agent';\nimport { FLASK_AGENT_CONFIG } from './flask/flask-wizard-agent';\nimport { FASTAPI_AGENT_CONFIG } from './fastapi/fastapi-wizard-agent';\nimport { LARAVEL_AGENT_CONFIG } from './laravel/laravel-wizard-agent';\nimport { SVELTEKIT_AGENT_CONFIG } from './svelte/svelte-wizard-agent';\nimport { FLUTTER_AGENT_CONFIG } from './flutter/flutter-wizard-agent';\nimport { SWIFT_AGENT_CONFIG } from './swift/swift-wizard-agent';\nimport { KMP_AGENT_CONFIG } from './kmp/kmp-wizard-agent';\nimport { ANDROID_AGENT_CONFIG } from './android/android-wizard-agent';\nimport { RAILS_AGENT_CONFIG } from './rails/rails-wizard-agent';\nimport { ELIXIR_AGENT_CONFIG } from './elixir/elixir-wizard-agent';\nimport { GO_AGENT_CONFIG } from './go/go-wizard-agent';\nimport { JAVA_AGENT_CONFIG } from './java/java-wizard-agent';\nimport { RUST_AGENT_CONFIG } from './rust/rust-wizard-agent';\nimport { PYTHON_AGENT_CONFIG } from './python/python-wizard-agent';\nimport { RUBY_AGENT_CONFIG } from './ruby/ruby-wizard-agent';\nimport { JAVASCRIPT_NODE_AGENT_CONFIG } from './javascript-node/javascript-node-wizard-agent';\nimport { JAVASCRIPT_WEB_AGENT_CONFIG } from './javascript-web/javascript-web-wizard-agent';\n\nexport const FRAMEWORK_REGISTRY: Record<Integration, FrameworkConfig> = {\n [Integration.nextjs]: NEXTJS_AGENT_CONFIG,\n [Integration.nuxt]: NUXT_AGENT_CONFIG,\n [Integration.vue]: VUE_AGENT_CONFIG,\n [Integration.tanstackStart]: TANSTACK_START_AGENT_CONFIG,\n [Integration.reactRouter]: REACT_ROUTER_AGENT_CONFIG,\n [Integration.tanstackRouter]: TANSTACK_ROUTER_AGENT_CONFIG,\n [Integration.reactNative]: REACT_NATIVE_AGENT_CONFIG,\n [Integration.angular]: ANGULAR_AGENT_CONFIG,\n [Integration.astro]: ASTRO_AGENT_CONFIG,\n [Integration.django]: DJANGO_AGENT_CONFIG,\n [Integration.flask]: FLASK_AGENT_CONFIG,\n [Integration.fastapi]: FASTAPI_AGENT_CONFIG,\n [Integration.laravel]: LARAVEL_AGENT_CONFIG,\n [Integration.sveltekit]: SVELTEKIT_AGENT_CONFIG,\n [Integration.flutter]: FLUTTER_AGENT_CONFIG,\n [Integration.kmp]: KMP_AGENT_CONFIG,\n [Integration.swift]: SWIFT_AGENT_CONFIG,\n [Integration.android]: ANDROID_AGENT_CONFIG,\n [Integration.rails]: RAILS_AGENT_CONFIG,\n [Integration.elixir]: ELIXIR_AGENT_CONFIG,\n [Integration.go]: GO_AGENT_CONFIG,\n [Integration.rust]: RUST_AGENT_CONFIG,\n [Integration.java]: JAVA_AGENT_CONFIG,\n [Integration.python]: PYTHON_AGENT_CONFIG,\n [Integration.ruby]: RUBY_AGENT_CONFIG,\n [Integration.javascriptNode]: JAVASCRIPT_NODE_AGENT_CONFIG,\n [Integration.javascript_web]: JAVASCRIPT_WEB_AGENT_CONFIG,\n};\n","/**\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 '@shared/constants';\nimport { FRAMEWORK_REGISTRY } from '../frameworks/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 * 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 '@shared/constants';\nimport type { FrameworkConfig } from '../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","/** What a run does with the label a framework gives its gathered context (Django with Wagtail CMS, Next.js App Router). */\nimport type { FrameworkConfig } from '../framework-config';\nimport type { ProgramSession } from '../program-session';\nimport { analytics } from '@utils/analytics';\n\n/** A CI run prints the label, a TUI run keeps it on its session and the `detected_framework` tag. */\nexport function noteDetectedFramework(\n session: ProgramSession,\n config: FrameworkConfig,\n context: Record<string, unknown>,\n log: { info(message: string): void },\n): void {\n const label = config.metadata.getDetectedFrameworkLabel?.(context);\n if (!label) return;\n if (session.ci) {\n log.info(`Framework: ${label}`);\n return;\n }\n session.detectedFrameworkLabel = label;\n analytics.setTag('detected_framework', label);\n}\n","/** The wizard's feature flags as one snapshot, for a run's routing and prompts. */\nimport { analytics } from '@utils/analytics';\nimport type { WizardFlagSnapshot } from './program-input';\n\nexport async function loadWizardFlags(): Promise<WizardFlagSnapshot> {\n return {\n flags: await analytics.getAllFlagsForWizard(),\n payloads: analytics.getWizardFlagPayloads(),\n };\n}\n","/**\n * Agentic project detection.\n *\n * A reusable detection tool that drives an 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 goes through the same `runAgent` every\n * program uses, which needs credentials.\n */\n\nimport { DEFAULT_BINDING, runAgent, RunOutcome } from '@agent';\nimport type {\n AgentProgress,\n AgentRunDefinition,\n RunConfig,\n RunInput,\n} from '@agent/types';\nimport { isAbsolute, resolve, sep } from 'path';\nimport { z } from 'zod';\nimport { zodToJsonSchema } from 'zod-to-json-schema';\nimport { ErrorCodes } from '@shared/errors';\nimport { detectNodePackageManagers } from './package-manager.js';\nimport {\n AGENTIC_DETECTION_FIRST_ATTEMPT_TIMEOUT_MS,\n AGENTIC_DETECTION_RETRY_TIMEOUT_MS,\n CallType,\n getSkillsBaseUrl,\n POSTHOG_DOCS_URL,\n} from '@shared/constants';\nimport type { ProgramSession } from '../program-session';\nimport { loadWizardFlags } from '../wizard-flags';\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\nexport class AgenticDetectionTimeoutError extends Error {\n constructor(attempt: number, timeoutMs: number) {\n super(\n `Project scan attempt ${attempt} timed out after ${timeoutMs / 1000}s`,\n );\n this.name = 'AgenticDetectionTimeoutError';\n }\n}\n\n/** Streaming progress callback — one short activity line per agent step. */\nexport type DetectEvent = (line: string) => void;\n/** Agent progress a scan forwards to the caller's UI. */\nexport type DetectProgress = (event: AgentProgress) => 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 @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 /** The scan's warnings, tasks and usage, for the caller's UI. */\n onProgress?: DetectProgress;\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, return {\"repoType\":\"single\",\"projects\":[]}.',\n ].join('\\n');\n}\n\n/**\n * Build the detection report from the agent's output, or null when it holds\n * neither a project verdict nor a `projects` array. 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 let sawReport = false;\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 sawReport ||= Array.isArray(obj.projects);\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 && !sawReport) 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\nfunction detectionReportSchema(recommend: boolean) {\n return z\n .object({\n repoType: z.enum(['monorepo', 'single']),\n projects: z.array(\n z\n .object({\n path: z.string(),\n framework: z.string(),\n matchingTargets: z.array(z.string()),\n targetId: z.string().nullable(),\n hasPostHog: z.boolean(),\n evidence: z.string(),\n ...(recommend ? { recommended: z.boolean() } : {}),\n })\n .strict(),\n ),\n })\n .strict();\n}\n\n/** Read-only scan with a typed result and transcript recovery. */\nfunction detectionRunDefinition(prompt: string): AgentRunDefinition {\n return {\n integrationLabel: 'agentic-detect',\n readOnly: true,\n prompt: () => prompt,\n collectTranscript: true,\n requestRemark: false,\n detectPackageManager: detectNodePackageManagers,\n spinnerMessage: 'Scanning the repo...',\n successMessage: 'Detection complete',\n errorMessage: 'Detection failed',\n estimatedDurationMinutes: 1,\n reportFile: '',\n docsUrl: POSTHOG_DOCS_URL,\n };\n}\n\n/** What the UI saw before `runAgent`: no run lifecycle, spinner, outro, or setup logs below warn. */\nfunction reachesUi(event: AgentProgress): boolean {\n switch (event.kind) {\n case 'lifecycle':\n case 'completion':\n case 'spinner':\n return false;\n case 'log':\n return event.level === 'warn' || event.level === 'error';\n default:\n return true;\n }\n}\n\n/** Scan through `runAgent` with the bound triage model, then the SDK fallback. */\nexport async function detectProjectsWithAgent(\n session: ProgramSession,\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 onProgress,\n } = options;\n\n const flags = await loadWizardFlags();\n const reportSchema = detectionReportSchema(recommend);\n const schema = zodToJsonSchema(reportSchema);\n const config: RunConfig = {\n programId,\n run: detectionRunDefinition(\n buildPrompt(session.installDir, targets, purpose, recommend),\n ),\n composed: true,\n // Only the scan's harness comes from this routing, and every scanning program binds Pi, as DEFAULT_BINDING does.\n routing: {\n binding: DEFAULT_BINDING,\n overrides: { harness: session.harness },\n record: false,\n },\n skillsBaseUrl: getSkillsBaseUrl(),\n wizardFlags: flags.flags,\n wizardFlagPayloads: flags.payloads,\n tags: { call_type: CallType.detection },\n // The scan's scans count toward the program run's report.\n scanReport: 'defer',\n };\n const input: RunInput = {\n installDir: session.installDir,\n credentials: session.credentials,\n project: null,\n apiUser: null,\n // No benchmark pipeline and no AIO capture: the scan never had either.\n flags: {\n ci: session.ci,\n signup: session.signup,\n debug: session.debug,\n e2eAsk: false,\n localMcp: session.localMcp,\n captureAio: false,\n benchmark: false,\n yaraReport: session.yaraReport,\n },\n host: { projectId: session.projectId, apiKey: session.apiKey },\n };\n const forward = (event: AgentProgress): void => {\n if (event.kind === 'activity') onEvent?.(event.line);\n if (reachesUi(event)) onProgress?.(event);\n };\n\n for (let attempt = 0; attempt < 2; attempt++) {\n const timeoutMs =\n attempt === 0\n ? AGENTIC_DETECTION_FIRST_ATTEMPT_TIMEOUT_MS\n : AGENTIC_DETECTION_RETRY_TIMEOUT_MS;\n const result = await runAgent(\n {\n ...config,\n routing: {\n ...config.routing,\n scan: attempt === 0 ? 'first' : 'retry',\n },\n run: { ...config.run, structured: { schema, timeoutMs } },\n },\n input,\n { onProgress: forward },\n );\n\n if (\n result.outcome !== RunOutcome.Success &&\n result.failure.code === ErrorCodes.AgenticDetectionTimeout\n ) {\n if (attempt === 0) {\n onEvent?.('Project scan timed out; retrying...');\n continue;\n }\n throw new AgenticDetectionTimeoutError(attempt + 1, timeoutMs);\n }\n if (result.outcome !== RunOutcome.Success) {\n if (\n result.failure.code === ErrorCodes.AgentInvalidStructuredOutput &&\n attempt === 0\n ) {\n onEvent?.('Project scan returned invalid output; retrying...');\n continue;\n }\n throw result.failure.error ?? new Error(result.failure.message);\n }\n if (result.structuredOutput !== undefined) {\n const structured = reportSchema.safeParse(result.structuredOutput);\n if (structured.success) {\n return coerceAgenticReport(\n structured.data,\n targets.map((t) => t.id),\n { recommend, rerankIds },\n );\n }\n // A typed report that misses the schema is invalid output, not a transcript.\n if (attempt === 0) {\n onEvent?.('Project scan returned invalid output; retrying...');\n }\n continue;\n }\n\n // Transcript first, final message last — its verdicts win path conflicts.\n const output = result.snapshot.transcriptTail ?? '';\n const derived = deriveReportJson(output);\n if (derived !== null) {\n return coerceAgenticReport(\n derived,\n targets.map((t) => t.id),\n { recommend, rerankIds },\n );\n }\n if (attempt === 0) onEvent?.('Retrying project scan...');\n }\n throw new Error('Agent did not return a JSON object after retry');\n}\n","/** Non-interactive project scoping — scan the repo agentically and pick which project the run integrates. */\n\nimport {\n detectProjectsWithAgent,\n AgenticDetectionTimeoutError,\n resolveProjectDir,\n type AgenticDetectionReport,\n type AgenticProject,\n type DetectEvent,\n type DetectProgress,\n type DetectTarget,\n} from './agentic.js';\nimport type { CiRunnerContext } from '../runner-context';\nimport { FRAMEWORK_REGISTRY } from '../frameworks/registry';\nimport {\n Integration,\n WIZARD_BASIC_INTEGRATION_AGENTIC_DETECTION_FLAG_KEY,\n} from '@shared/constants';\nimport type { ProgramSession } from '../program-session';\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\nconst INTEGRATION_IDS = new Set<string>(Object.values(Integration));\n\n/** A scanned project matched to a wizard framework. Each program classifies it with its own rule. */\nexport type IntegrationCandidate = {\n /** Path relative to the repo root (\".\" for the root). */\n path: string;\n /** Human-readable framework the agent detected (e.g. \"Next.js\"). */\n framework: string;\n /** The wizard framework the project matches, else null. */\n integration: Integration | null;\n /** Whether a PostHog SDK is already installed in this project. */\n hasPostHog: boolean;\n /** The scan's pick for the main app. Always false unless the scan set `recommend`. */\n recommended: boolean;\n};\n\n/** Match each project of an integration scan to a wizard framework. */\nexport function toIntegrationCandidates(\n report: AgenticDetectionReport,\n): IntegrationCandidate[] {\n return report.projects.map((p) => ({\n path: p.path,\n framework: p.framework,\n integration:\n p.targetId && INTEGRATION_IDS.has(p.targetId)\n ? (p.targetId as Integration)\n : null,\n hasPostHog: p.hasPostHog,\n recommended: p.recommended === true,\n }));\n}\n\n/** Run the agentic detector for the wizard's integration frameworks — the single home of targets + purpose. */\nexport async function detectIntegrationProjects(\n session: ProgramSession,\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 onProgress?: DetectProgress;\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\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: ProgramSession,\n runner: CiRunnerContext,\n): Promise<void> {\n // Idempotent early auth: the detector needs credentials and the flag must evaluate as the logged-in user.\n await runner.authenticate('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 runner.log.info('Scanning the repo for projects...');\n const startedAt = Date.now();\n let report: AgenticDetectionReport;\n try {\n report = await 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 onProgress: (event) => runner.onProgress?.(event),\n });\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n if (error instanceof AgenticDetectionTimeoutError) {\n captureOutcome('timeout', { duration_ms: Date.now() - startedAt });\n runner.log.warn(\n `${error.message}; continuing with the install dir as-is.`,\n );\n return;\n }\n analytics.captureException(error, { step: 'agentic_detection' });\n captureOutcome('error', {\n duration_ms: Date.now() - startedAt,\n error_message: error.message,\n });\n runner.log.warn(\n `Project scan failed (${error.message}); 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 runner.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 runner.log.info(`Continuing with ${project.path} (${project.framework}).`);\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 '@shared/discovered-feature';\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 * Registry of data warehouse source detectors.\n *\n * Each entry maps a codebase footprint to a PostHog source `kind`. The `kind`\n * strings are validated against the MCP `external-data-sources-wizard` tool —\n * keep them in sync with PostHog's released source types.\n *\n * `in-cli` sources are created from the terminal (databases + API-key SaaS).\n * `deep-link` sources have no safe terminal credential path (OAuth) but a\n * codebase footprint worth nudging the user about — we open the app instead.\n */\n\nimport type { SourceDetector } from './types.js';\n\nconst CORE_SOURCE_DETECTORS: SourceDetector[] = [\n {\n kind: 'Postgres',\n label: 'PostgreSQL',\n mode: 'in-cli',\n signals: {\n npm: ['pg', 'postgres', 'postgres.js', 'knex', 'sequelize'],\n python: ['psycopg', 'psycopg2', 'psycopg2-binary', 'asyncpg'],\n ruby: ['pg'],\n envKeys: [\n // NOTE: DATABASE_URL is ambiguous — MySQL/SQLite projects (Prisma,\n // Rails) use it too. We only read key NAMES, not the scheme, so this\n // is a deliberate precision/recall tradeoff biased toward the most\n // common convention (DATABASE_URL → Postgres).\n /^DATABASE_URL$/,\n /^POSTGRES_/,\n /^PG(HOST|DATABASE|USER|PORT)$/,\n ],\n },\n // Neon and Supabase are hosted Postgres, and a project on either still\n // names its connection with the generic signals above. Two sources over\n // one database import the same tables twice.\n supersededBy: ['Neon', 'Supabase'],\n },\n {\n kind: 'MySQL',\n label: 'MySQL',\n mode: 'in-cli',\n signals: {\n npm: ['mysql', 'mysql2'],\n python: ['pymysql', 'mysqlclient', 'mysql-connector-python'],\n ruby: ['mysql2'],\n envKeys: [/^MYSQL_/],\n },\n },\n {\n kind: 'MongoDB',\n label: 'MongoDB',\n mode: 'in-cli',\n signals: {\n npm: ['mongodb', 'mongoose'],\n python: ['pymongo', 'motor'],\n ruby: ['mongo', 'mongoid'],\n // Matches both MONGO_* and MONGODB_* prefixes (e.g. MONGO_HOST,\n // MONGODB_URI) in one pattern.\n envKeys: [/^MONGO(DB)?_/],\n },\n },\n {\n kind: 'Snowflake',\n label: 'Snowflake',\n mode: 'in-cli',\n signals: {\n npm: ['snowflake-sdk'],\n python: ['snowflake-connector-python', 'snowflake-sqlalchemy'],\n envKeys: [/^SNOWFLAKE_/],\n },\n },\n {\n // BigQuery authenticates with a Google Cloud service-account JSON key\n // file, like Firebase above — the source's only required credential field\n // is a file upload, and the terminal prompt collects single-line text, so\n // there is no in-cli path that can accept it. Deep-link to the app's\n // new-source form instead of dead-ending on an unpasteable credential.\n kind: 'BigQuery',\n label: 'BigQuery',\n mode: 'deep-link',\n signals: {\n npm: ['@google-cloud/bigquery'],\n python: ['google-cloud-bigquery'],\n envKeys: [/^BIGQUERY_/],\n },\n },\n {\n kind: 'Redshift',\n label: 'Redshift',\n mode: 'in-cli',\n signals: {\n npm: ['node-redshift'],\n python: ['redshift-connector'],\n envKeys: [/^REDSHIFT_/],\n },\n },\n {\n kind: 'MSSQL',\n label: 'SQL Server',\n mode: 'in-cli',\n signals: {\n npm: ['mssql', 'tedious'],\n python: ['pyodbc', 'pymssql'],\n envKeys: [/^MSSQL_/],\n },\n },\n {\n kind: 'Supabase',\n label: 'Supabase',\n mode: 'in-cli',\n signals: {\n npm: ['@supabase/supabase-js'],\n python: ['supabase'],\n envKeys: [/^SUPABASE_/],\n },\n },\n {\n kind: 'ClickHouse',\n label: 'ClickHouse',\n mode: 'in-cli',\n signals: {\n npm: ['@clickhouse/client'],\n python: ['clickhouse-connect', 'clickhouse-driver'],\n envKeys: [/^CLICKHOUSE_/],\n },\n },\n {\n kind: 'Convex',\n label: 'Convex',\n mode: 'in-cli',\n signals: {\n npm: ['convex'],\n python: ['convex'],\n envKeys: [/^CONVEX_/, /^NEXT_PUBLIC_CONVEX_URL$/],\n },\n },\n {\n // Firebase authenticates with a service-account JSON key file, not a\n // pasteable string. The terminal credential prompt only collects\n // single-line text, so there is no safe in-cli path: the file upload lives\n // in the app's new-source form. Deep-link there instead of dead-ending on a\n // credential the CLI cannot accept.\n kind: 'Firebase',\n label: 'Firebase',\n mode: 'deep-link',\n signals: {\n // NOTE: the `firebase` client SDK also covers auth-only projects, which\n // have no Firestore data to import. We accept the false positives — the\n // package is a strong signal for the common case.\n npm: ['firebase-admin', 'firebase'],\n python: ['firebase-admin'],\n envKeys: [/^FIREBASE_/, /^NEXT_PUBLIC_FIREBASE_/],\n },\n },\n {\n kind: 'Neon',\n label: 'Neon',\n mode: 'in-cli',\n signals: {\n npm: ['@neondatabase/serverless'],\n envKeys: [/^NEON_/],\n },\n },\n {\n kind: 'PlanetScaleMySQL',\n label: 'PlanetScale MySQL',\n mode: 'in-cli',\n signals: {\n npm: ['@planetscale/database'],\n envKeys: [/^PLANETSCALE_/],\n },\n },\n {\n kind: 'DynamoDB',\n label: 'DynamoDB',\n mode: 'in-cli',\n signals: {\n npm: ['@aws-sdk/client-dynamodb', '@aws-sdk/lib-dynamodb'],\n python: ['pynamodb'],\n },\n },\n {\n kind: 'Motherduck',\n label: 'MotherDuck',\n mode: 'in-cli',\n signals: {\n npm: ['@motherduck/wasm-client'],\n envKeys: [/^MOTHERDUCK_/],\n },\n },\n {\n kind: 'Databricks',\n label: 'Databricks',\n mode: 'in-cli',\n signals: {\n npm: ['@databricks/sql'],\n python: ['databricks-sql-connector', 'databricks-sdk'],\n envKeys: [/^DATABRICKS_/],\n },\n },\n {\n kind: 'Singlestore',\n label: 'SingleStore',\n mode: 'in-cli',\n signals: {\n python: ['singlestoredb'],\n envKeys: [/^SINGLESTORE_/],\n },\n },\n {\n kind: 'Stripe',\n label: 'Stripe',\n mode: 'in-cli',\n signals: {\n npm: ['stripe', '@stripe/stripe-js', '@stripe/react-stripe-js'],\n python: ['stripe'],\n ruby: ['stripe'],\n envKeys: [/^STRIPE_(SECRET|API)_KEY$/],\n },\n },\n {\n kind: 'Clerk',\n label: 'Clerk',\n mode: 'in-cli',\n signals: {\n npm: [\n '@clerk/nextjs',\n '@clerk/clerk-react',\n '@clerk/backend',\n '@clerk/express',\n '@clerk/fastify',\n '@clerk/remix',\n ],\n envKeys: [/^CLERK_SECRET_KEY$/, /^NEXT_PUBLIC_CLERK_/],\n },\n },\n {\n kind: 'Resend',\n label: 'Resend',\n mode: 'in-cli',\n signals: {\n npm: ['resend'],\n python: ['resend'],\n envKeys: [/^RESEND_API_KEY$/],\n },\n },\n {\n kind: 'Shopify',\n label: 'Shopify',\n mode: 'in-cli',\n signals: {\n npm: ['@shopify/shopify-api', 'shopify-api-node'],\n python: ['shopifyapi'],\n envKeys: [/^SHOPIFY_/],\n },\n },\n {\n kind: 'Klaviyo',\n label: 'Klaviyo',\n mode: 'in-cli',\n signals: {\n npm: ['klaviyo-api'],\n python: ['klaviyo-api'],\n envKeys: [/^KLAVIYO_/],\n },\n },\n {\n kind: 'Chargebee',\n label: 'Chargebee',\n mode: 'in-cli',\n signals: {\n npm: ['chargebee'],\n python: ['chargebee'],\n envKeys: [/^CHARGEBEE_/],\n },\n },\n {\n kind: 'Paddle',\n label: 'Paddle',\n mode: 'in-cli',\n signals: {\n npm: ['@paddle/paddle-node-sdk', '@paddle/paddle-js'],\n envKeys: [/^PADDLE_/],\n },\n },\n {\n kind: 'Polar',\n label: 'Polar',\n mode: 'in-cli',\n signals: {\n npm: ['@polar-sh/sdk', '@polar-sh/nextjs'],\n envKeys: [/^POLAR_/],\n },\n },\n {\n kind: 'Mailchimp',\n label: 'Mailchimp',\n mode: 'in-cli',\n signals: {\n npm: ['@mailchimp/mailchimp_marketing'],\n python: ['mailchimp-marketing'],\n envKeys: [/^MAILCHIMP_/],\n },\n },\n {\n kind: 'CustomerIO',\n label: 'Customer.io',\n mode: 'in-cli',\n signals: {\n npm: ['customerio-node'],\n python: ['customerio'],\n envKeys: [/^CUSTOMER_?IO_/],\n },\n },\n {\n kind: 'Typeform',\n label: 'Typeform',\n mode: 'in-cli',\n signals: {\n npm: ['@typeform/api-client'],\n envKeys: [/^TYPEFORM_/],\n },\n },\n {\n kind: 'Sentry',\n label: 'Sentry',\n mode: 'in-cli',\n signals: {\n npm: [\n '@sentry/node',\n '@sentry/browser',\n '@sentry/react',\n '@sentry/nextjs',\n ],\n python: ['sentry-sdk'],\n ruby: ['sentry-ruby'],\n },\n },\n {\n kind: 'Plaid',\n label: 'Plaid',\n mode: 'in-cli',\n signals: {\n npm: ['plaid'],\n python: ['plaid-python', 'plaid'],\n ruby: ['plaid'],\n envKeys: [/^PLAID_/],\n },\n },\n {\n kind: 'Braintree',\n label: 'Braintree',\n mode: 'in-cli',\n signals: {\n npm: ['braintree'],\n python: ['braintree'],\n ruby: ['braintree'],\n envKeys: [/^BRAINTREE_/],\n },\n },\n {\n kind: 'Square',\n label: 'Square',\n mode: 'in-cli',\n signals: {\n npm: ['square'],\n python: ['squareup'],\n ruby: ['square'],\n envKeys: [/^SQUARE_/],\n },\n },\n {\n kind: 'GoCardless',\n label: 'GoCardless',\n mode: 'in-cli',\n signals: {\n npm: ['gocardless-nodejs'],\n python: ['gocardless-pro'],\n ruby: ['gocardless_pro'],\n envKeys: [/^GOCARDLESS_/],\n },\n },\n {\n kind: 'Mollie',\n label: 'Mollie',\n mode: 'in-cli',\n signals: {\n npm: ['@mollie/api-client'],\n python: ['mollie-api-python'],\n envKeys: [/^MOLLIE_/],\n },\n },\n {\n kind: 'CheckoutCom',\n label: 'Checkout.com',\n mode: 'in-cli',\n signals: {\n npm: ['checkout-sdk-node'],\n python: ['checkout-sdk'],\n // Checkout.com's own convention is the CKO_ prefix.\n envKeys: [/^CKO_/, /^CHECKOUT_COM_/],\n },\n },\n {\n kind: 'Recurly',\n label: 'Recurly',\n mode: 'in-cli',\n signals: {\n npm: ['recurly'],\n python: ['recurly'],\n ruby: ['recurly'],\n envKeys: [/^RECURLY_/],\n },\n },\n {\n kind: 'RevenueCat',\n label: 'RevenueCat',\n mode: 'in-cli',\n signals: {\n npm: [\n '@revenuecat/purchases-js',\n 'react-native-purchases',\n '@revenuecat/purchases-capacitor',\n ],\n envKeys: [/^REVENUE_?CAT_/],\n },\n },\n {\n kind: 'Twilio',\n label: 'Twilio',\n mode: 'in-cli',\n signals: {\n npm: ['twilio'],\n python: ['twilio'],\n ruby: ['twilio-ruby'],\n envKeys: [/^TWILIO_/],\n },\n },\n {\n kind: 'SendGrid',\n label: 'SendGrid',\n mode: 'in-cli',\n signals: {\n npm: ['@sendgrid/mail', '@sendgrid/client'],\n python: ['sendgrid'],\n ruby: ['sendgrid-ruby'],\n envKeys: [/^SENDGRID_/],\n },\n },\n {\n kind: 'Mailgun',\n label: 'Mailgun',\n mode: 'in-cli',\n signals: {\n npm: ['mailgun.js', 'mailgun-js'],\n python: ['mailgun'],\n ruby: ['mailgun-ruby'],\n envKeys: [/^MAILGUN_/],\n },\n },\n {\n kind: 'Postmark',\n label: 'Postmark',\n mode: 'in-cli',\n signals: {\n npm: ['postmark'],\n python: ['postmarker'],\n ruby: ['postmark'],\n envKeys: [/^POSTMARK_/],\n },\n },\n {\n kind: 'Brevo',\n label: 'Brevo',\n mode: 'in-cli',\n signals: {\n npm: ['@getbrevo/brevo', 'sib-api-v3-sdk'],\n python: ['sib-api-v3-sdk'],\n envKeys: [/^BREVO_/],\n },\n },\n {\n kind: 'MailerLite',\n label: 'MailerLite',\n mode: 'in-cli',\n signals: {\n npm: ['@mailerlite/mailerlite-nodejs'],\n python: ['mailerlite'],\n envKeys: [/^MAILERLITE_/],\n },\n },\n {\n kind: 'Mailjet',\n label: 'Mailjet',\n mode: 'in-cli',\n signals: {\n npm: ['node-mailjet'],\n python: ['mailjet-rest'],\n // Mailjet's documented env convention is MJ_APIKEY_PUBLIC / *_PRIVATE.\n envKeys: [/^MAILJET_/, /^MJ_APIKEY_/],\n },\n },\n {\n kind: 'LaunchDarkly',\n label: 'LaunchDarkly',\n mode: 'in-cli',\n signals: {\n npm: [\n 'launchdarkly-node-server-sdk',\n '@launchdarkly/node-server-sdk',\n 'launchdarkly-js-client-sdk',\n 'launchdarkly-react-client-sdk',\n ],\n python: ['launchdarkly-server-sdk'],\n ruby: ['launchdarkly-server-sdk'],\n envKeys: [/^LAUNCHDARKLY_/, /^LD_SDK_KEY$/],\n },\n },\n {\n kind: 'Optimizely',\n label: 'Optimizely',\n mode: 'in-cli',\n signals: {\n npm: ['@optimizely/optimizely-sdk'],\n python: ['optimizely-sdk'],\n envKeys: [/^OPTIMIZELY_/],\n },\n },\n {\n kind: 'Braze',\n label: 'Braze',\n mode: 'in-cli',\n signals: {\n npm: ['@braze/web-sdk', '@braze/react-native-sdk'],\n python: ['braze-client'],\n envKeys: [/^BRAZE_/],\n },\n },\n {\n kind: 'Rollbar',\n label: 'Rollbar',\n mode: 'in-cli',\n signals: {\n npm: ['rollbar'],\n python: ['rollbar', 'pyrollbar'],\n ruby: ['rollbar'],\n envKeys: [/^ROLLBAR_/],\n },\n },\n {\n kind: 'Okta',\n label: 'Okta',\n mode: 'in-cli',\n signals: {\n npm: ['@okta/okta-sdk-nodejs', '@okta/okta-auth-js', '@okta/okta-react'],\n python: ['okta'],\n envKeys: [/^OKTA_/],\n },\n },\n {\n kind: 'WorkOS',\n label: 'WorkOS',\n mode: 'in-cli',\n signals: {\n npm: ['@workos-inc/node'],\n python: ['workos'],\n envKeys: [/^WORKOS_/],\n },\n },\n {\n kind: 'Notion',\n label: 'Notion',\n mode: 'in-cli',\n signals: {\n npm: ['@notionhq/client'],\n python: ['notion-client'],\n envKeys: [/^NOTION_/],\n },\n },\n {\n kind: 'FullStory',\n label: 'FullStory',\n mode: 'in-cli',\n signals: {\n npm: ['@fullstory/browser', '@fullstory/react-native'],\n envKeys: [/^FULLSTORY_/],\n },\n },\n {\n kind: 'Amplitude',\n label: 'Amplitude',\n mode: 'in-cli',\n signals: {\n npm: [\n '@amplitude/analytics-browser',\n '@amplitude/analytics-node',\n '@amplitude/analytics-react-native',\n 'amplitude-js',\n ],\n python: ['amplitude-analytics'],\n envKeys: [/^AMPLITUDE_/],\n },\n },\n {\n kind: 'Mixpanel',\n label: 'Mixpanel',\n mode: 'in-cli',\n signals: {\n npm: ['mixpanel', 'mixpanel-browser'],\n python: ['mixpanel'],\n ruby: ['mixpanel-ruby'],\n envKeys: [/^MIXPANEL_/],\n },\n },\n {\n kind: 'Pendo',\n label: 'Pendo',\n mode: 'in-cli',\n signals: {\n npm: ['@pendo/agent'],\n envKeys: [/^PENDO_/],\n },\n },\n {\n kind: 'Salesforce',\n label: 'Salesforce',\n mode: 'deep-link',\n signals: {\n npm: ['jsforce'],\n python: ['simple-salesforce'],\n envKeys: [/^SALESFORCE_/],\n },\n },\n {\n kind: 'Hubspot',\n label: 'HubSpot',\n mode: 'deep-link',\n signals: {\n npm: ['@hubspot/api-client'],\n python: ['hubspot-api-client'],\n envKeys: [/^HUBSPOT_/],\n },\n },\n {\n kind: 'Zendesk',\n label: 'Zendesk',\n mode: 'deep-link',\n signals: {\n npm: ['node-zendesk'],\n python: ['zenpy'],\n envKeys: [/^ZENDESK_/],\n },\n },\n {\n kind: 'Intercom',\n label: 'Intercom',\n mode: 'deep-link',\n signals: {\n npm: ['intercom-client', '@intercom/messenger-js-sdk'],\n python: ['python-intercom'],\n envKeys: [/^INTERCOM_/],\n },\n },\n {\n kind: 'Linear',\n label: 'Linear',\n mode: 'deep-link',\n signals: {\n npm: ['@linear/sdk'],\n envKeys: [/^LINEAR_API_KEY$/],\n },\n },\n {\n // OAuth-only in PostHog (Slack app integration), so deep-link.\n kind: 'Slack',\n label: 'Slack',\n mode: 'deep-link',\n signals: {\n npm: ['@slack/web-api', '@slack/bolt'],\n python: ['slack-sdk', 'slack-bolt'],\n envKeys: [/^SLACK_(BOT|APP|SIGNING|CLIENT)_/],\n },\n },\n {\n // 'Github' (not 'GitHub') — matches the ExternalDataSourceType value.\n // Default auth is the GitHub App integration (OAuth), so deep-link.\n kind: 'Github',\n label: 'GitHub',\n mode: 'deep-link',\n signals: {\n npm: ['@octokit/rest', '@octokit/core', '@octokit/graphql', 'octokit'],\n python: ['pygithub'],\n ruby: ['octokit'],\n },\n },\n];\n\n// ============================================================\n// Additional released source types (see PostHog data-warehouse\n// source catalog). Detected by SDK package or .env key convention.\n// ============================================================\n// ---- LLM / AI ----\nconst LLM_SOURCE_DETECTORS: SourceDetector[] = [\n {\n kind: 'OpenAI',\n label: 'OpenAI',\n mode: 'in-cli',\n signals: {\n npm: ['openai'],\n python: ['openai'],\n envKeys: [/^OPENAI_/],\n },\n },\n {\n kind: 'Anthropic',\n label: 'Anthropic',\n mode: 'in-cli',\n signals: {\n npm: ['@anthropic-ai/sdk'],\n python: ['anthropic'],\n envKeys: [/^ANTHROPIC_/],\n },\n },\n {\n kind: 'Cohere',\n label: 'Cohere',\n mode: 'in-cli',\n signals: {\n npm: ['cohere-ai'],\n python: ['cohere'],\n envKeys: [/^COHERE_/],\n },\n },\n {\n kind: 'MistralAI',\n label: 'Mistral AI',\n mode: 'in-cli',\n signals: {\n npm: ['@mistralai/mistralai'],\n python: ['mistralai'],\n envKeys: [/^MISTRAL_/],\n },\n },\n {\n kind: 'Groq',\n label: 'Groq',\n mode: 'in-cli',\n signals: {\n npm: ['groq-sdk'],\n python: ['groq'],\n envKeys: [/^GROQ_/],\n },\n },\n {\n kind: 'TogetherAI',\n label: 'Together AI',\n mode: 'in-cli',\n signals: {\n npm: ['together-ai'],\n python: ['together'],\n envKeys: [/^TOGETHER_/],\n },\n },\n {\n kind: 'FireworksAI',\n label: 'Fireworks AI',\n mode: 'in-cli',\n signals: {\n python: ['fireworks-ai'],\n envKeys: [/^FIREWORKS_/],\n },\n },\n {\n kind: 'Replicate',\n label: 'Replicate',\n mode: 'in-cli',\n signals: {\n npm: ['replicate'],\n python: ['replicate'],\n envKeys: [/^REPLICATE_/],\n },\n },\n {\n kind: 'HuggingFace',\n label: 'Hugging Face',\n mode: 'in-cli',\n signals: {\n npm: ['@huggingface/inference'],\n python: ['huggingface-hub'],\n envKeys: [/^HUGGINGFACE_/, /^HF_TOKEN$/],\n },\n },\n {\n kind: 'ElevenLabs',\n label: 'ElevenLabs',\n mode: 'in-cli',\n signals: {\n npm: ['@elevenlabs/elevenlabs-js', 'elevenlabs'],\n python: ['elevenlabs'],\n envKeys: [/^ELEVENLABS_/, /^ELEVEN_LABS_/],\n },\n },\n {\n kind: 'Deepgram',\n label: 'Deepgram',\n mode: 'in-cli',\n signals: {\n npm: ['@deepgram/sdk'],\n python: ['deepgram-sdk'],\n envKeys: [/^DEEPGRAM_/],\n },\n },\n {\n kind: 'AssemblyAI',\n label: 'AssemblyAI',\n mode: 'in-cli',\n signals: {\n npm: ['assemblyai'],\n python: ['assemblyai'],\n envKeys: [/^ASSEMBLYAI_/],\n },\n },\n {\n kind: 'Langfuse',\n label: 'Langfuse',\n mode: 'in-cli',\n signals: {\n npm: ['langfuse'],\n python: ['langfuse'],\n envKeys: [/^LANGFUSE_/],\n },\n },\n {\n kind: 'LangSmith',\n label: 'LangSmith',\n mode: 'in-cli',\n signals: {\n npm: ['langsmith'],\n python: ['langsmith'],\n envKeys: [/^LANGSMITH_/, /^LANGCHAIN_API_KEY$/],\n },\n },\n {\n kind: 'Firecrawl',\n label: 'Firecrawl',\n mode: 'in-cli',\n signals: {\n npm: ['@mendable/firecrawl-js'],\n python: ['firecrawl-py'],\n envKeys: [/^FIRECRAWL_/],\n },\n },\n {\n kind: 'Mem0',\n label: 'Mem0',\n mode: 'in-cli',\n signals: {\n npm: ['mem0ai'],\n python: ['mem0ai'],\n envKeys: [/^MEM0_/],\n },\n },\n {\n kind: 'Vellum',\n label: 'Vellum',\n mode: 'in-cli',\n signals: {\n npm: ['vellum-ai'],\n python: ['vellum-ai'],\n envKeys: [/^VELLUM_/],\n },\n },\n {\n kind: 'Helicone',\n label: 'Helicone',\n mode: 'in-cli',\n signals: {\n npm: ['@helicone/helpers'],\n envKeys: [/^HELICONE_/],\n },\n },\n {\n kind: 'OpenRouter',\n label: 'OpenRouter',\n mode: 'in-cli',\n signals: {\n npm: ['@openrouter/ai-sdk-provider'],\n envKeys: [/^OPENROUTER_/],\n },\n },\n {\n kind: 'Browserbase',\n label: 'Browserbase',\n mode: 'in-cli',\n signals: {\n npm: ['@browserbasehq/sdk', '@browserbasehq/stagehand'],\n python: ['browserbase'],\n envKeys: [/^BROWSERBASE_/],\n },\n },\n {\n kind: 'E2B',\n label: 'E2B',\n mode: 'in-cli',\n signals: {\n npm: ['e2b', '@e2b/code-interpreter'],\n python: ['e2b', 'e2b-code-interpreter'],\n envKeys: [/^E2B_/],\n },\n },\n {\n kind: 'WeightsAndBiases',\n label: 'Weights & Biases',\n mode: 'in-cli',\n signals: {\n python: ['wandb'],\n envKeys: [/^WANDB_/],\n },\n },\n {\n kind: 'LlamaCloud',\n label: 'LlamaCloud',\n mode: 'in-cli',\n signals: {\n npm: ['llama-cloud-services'],\n python: ['llama-cloud-services'],\n envKeys: [/^LLAMA_CLOUD_/],\n },\n },\n {\n kind: 'Zep',\n label: 'Zep',\n mode: 'in-cli',\n signals: {\n npm: ['@getzep/zep-cloud'],\n python: ['zep-cloud'],\n envKeys: [/^ZEP_API_KEY$/],\n },\n },\n];\n\nconst OTHER_SOURCE_DETECTORS: SourceDetector[] = [\n // ---- Payments / billing ----\n {\n kind: 'Paystack',\n label: 'Paystack',\n mode: 'in-cli',\n signals: {\n python: ['paystackapi'],\n envKeys: [/^PAYSTACK_/],\n },\n },\n {\n kind: 'Orb',\n label: 'Orb',\n mode: 'in-cli',\n signals: {\n npm: ['orb-billing'],\n python: ['orb-billing'],\n envKeys: [/^ORB_/],\n },\n },\n {\n kind: 'Lago',\n label: 'Lago',\n mode: 'in-cli',\n signals: {\n npm: ['lago-javascript-client'],\n python: ['lago-python-client'],\n envKeys: [/^LAGO_/],\n },\n },\n {\n kind: 'Zuora',\n label: 'Zuora',\n mode: 'in-cli',\n signals: {\n envKeys: [/^ZUORA_/],\n },\n },\n {\n kind: 'Stigg',\n label: 'Stigg',\n mode: 'in-cli',\n signals: {\n npm: ['@stigg/node-server-sdk'],\n envKeys: [/^STIGG_/],\n },\n },\n {\n kind: 'Ramp',\n label: 'Ramp',\n mode: 'in-cli',\n signals: {\n envKeys: [/^RAMP_/],\n },\n },\n {\n kind: 'Brex',\n label: 'Brex',\n mode: 'in-cli',\n signals: {\n envKeys: [/^BREX_/],\n },\n },\n {\n kind: 'Tremendous',\n label: 'Tremendous',\n mode: 'in-cli',\n signals: {\n envKeys: [/^TREMENDOUS_/],\n },\n },\n {\n kind: 'Maxio',\n label: 'Maxio',\n mode: 'in-cli',\n signals: {\n envKeys: [/^MAXIO_/],\n },\n },\n {\n kind: 'Chargify',\n label: 'Chargify',\n mode: 'in-cli',\n signals: {\n envKeys: [/^CHARGIFY_/],\n },\n },\n {\n kind: 'Invoiced',\n label: 'Invoiced',\n mode: 'in-cli',\n signals: {\n npm: ['invoiced'],\n python: ['invoiced'],\n envKeys: [/^INVOICED_/],\n },\n },\n {\n kind: 'LemonSqueezy',\n label: 'Lemon Squeezy',\n mode: 'in-cli',\n signals: {\n npm: ['@lemonsqueezy/lemonsqueezy.js'],\n envKeys: [/^LEMONSQUEEZY_/, /^LEMON_SQUEEZY_/],\n },\n },\n {\n kind: 'Razorpay',\n label: 'Razorpay',\n mode: 'in-cli',\n signals: {\n npm: ['razorpay'],\n python: ['razorpay'],\n ruby: ['razorpay'],\n envKeys: [/^RAZORPAY_/],\n },\n },\n {\n kind: 'Adyen',\n label: 'Adyen',\n mode: 'in-cli',\n signals: {\n npm: ['@adyen/api-library'],\n python: ['adyen'],\n envKeys: [/^ADYEN_/],\n },\n },\n {\n kind: 'ChartMogul',\n label: 'ChartMogul',\n mode: 'in-cli',\n signals: {\n npm: ['chartmogul-node'],\n python: ['chartmogul'],\n envKeys: [/^CHARTMOGUL_/],\n },\n },\n {\n kind: 'Airwallex',\n label: 'Airwallex',\n mode: 'in-cli',\n signals: {\n npm: ['airwallex-payment-elements'],\n envKeys: [/^AIRWALLEX_/],\n },\n },\n {\n kind: 'Flutterwave',\n label: 'Flutterwave',\n mode: 'in-cli',\n signals: {\n npm: ['flutterwave-node-v3'],\n python: ['flutterwave'],\n envKeys: [/^FLUTTERWAVE_/, /^FLW_(PUBLIC|SECRET)_KEY$/],\n },\n },\n {\n kind: 'DodoPayments',\n label: 'Dodo Payments',\n mode: 'in-cli',\n signals: {\n npm: ['dodopayments'],\n python: ['dodopayments'],\n envKeys: [/^DODO_PAYMENTS_/],\n },\n },\n {\n kind: 'Whop',\n label: 'Whop',\n mode: 'in-cli',\n signals: {\n npm: ['@whop/api', '@whop-apps/sdk'],\n envKeys: [/^WHOP_/],\n },\n },\n // ---- Email / marketing ----\n {\n kind: 'SparkPost',\n label: 'SparkPost',\n mode: 'in-cli',\n signals: {\n npm: ['sparkpost'],\n python: ['sparkpost'],\n envKeys: [/^SPARKPOST_/],\n },\n },\n {\n kind: 'MailerSend',\n label: 'MailerSend',\n mode: 'in-cli',\n signals: {\n npm: ['mailersend'],\n python: ['mailersend'],\n envKeys: [/^MAILERSEND_/],\n },\n },\n {\n kind: 'Iterable',\n label: 'Iterable',\n mode: 'in-cli',\n signals: {\n envKeys: [/^ITERABLE_/],\n },\n },\n {\n kind: 'ConvertKit',\n label: 'ConvertKit',\n mode: 'in-cli',\n signals: {\n envKeys: [/^CONVERTKIT_/],\n },\n },\n {\n kind: 'Drip',\n label: 'Drip',\n mode: 'in-cli',\n signals: {\n npm: ['drip-nodejs'],\n envKeys: [/^DRIP_/],\n },\n },\n {\n kind: 'Omnisend',\n label: 'Omnisend',\n mode: 'in-cli',\n signals: {\n envKeys: [/^OMNISEND_/],\n },\n },\n {\n kind: 'EmailOctopus',\n label: 'EmailOctopus',\n mode: 'in-cli',\n signals: {\n envKeys: [/^EMAILOCTOPUS_/, /^EMAIL_OCTOPUS_/],\n },\n },\n {\n kind: 'Elasticemail',\n label: 'Elastic Email',\n mode: 'in-cli',\n signals: {\n envKeys: [/^ELASTICEMAIL_/, /^ELASTIC_EMAIL_/],\n },\n },\n {\n kind: 'CampaignMonitor',\n label: 'Campaign Monitor',\n mode: 'in-cli',\n signals: {\n npm: ['createsend-node'],\n envKeys: [/^CAMPAIGN_MONITOR_/, /^CREATESEND_/],\n },\n },\n {\n kind: 'Lemlist',\n label: 'Lemlist',\n mode: 'in-cli',\n signals: {\n envKeys: [/^LEMLIST_/],\n },\n },\n {\n kind: 'Loops',\n label: 'Loops',\n mode: 'in-cli',\n signals: {\n npm: ['loops'],\n envKeys: [/^LOOPS_/],\n },\n },\n {\n kind: 'Knock',\n label: 'Knock',\n mode: 'in-cli',\n signals: {\n npm: ['@knocklabs/node', '@knocklabs/client'],\n python: ['knockapi'],\n envKeys: [/^KNOCK_/],\n },\n },\n {\n kind: 'AwsSes',\n label: 'Amazon SES',\n mode: 'in-cli',\n signals: {\n npm: ['@aws-sdk/client-ses', '@aws-sdk/client-sesv2'],\n // A bare /^AWS_/ would fire on every AWS project, so we match only\n // the SES-specific prefix.\n envKeys: [/^AWS_SES_/],\n },\n },\n {\n kind: 'Beehiiv',\n label: 'beehiiv',\n mode: 'in-cli',\n signals: {\n envKeys: [/^BEEHIIV_/],\n },\n },\n {\n kind: 'Mailtrap',\n label: 'Mailtrap',\n mode: 'in-cli',\n signals: {\n npm: ['mailtrap'],\n python: ['mailtrap'],\n envKeys: [/^MAILTRAP_/],\n },\n },\n {\n kind: 'Plunk',\n label: 'Plunk',\n mode: 'in-cli',\n signals: {\n npm: ['@plunk/node'],\n envKeys: [/^PLUNK_/],\n },\n },\n {\n kind: 'Ortto',\n label: 'Ortto',\n mode: 'in-cli',\n signals: {\n envKeys: [/^ORTTO_/],\n },\n },\n {\n kind: 'Postscript',\n label: 'Postscript',\n mode: 'in-cli',\n signals: {\n envKeys: [/^POSTSCRIPT_/],\n },\n },\n {\n kind: 'Marketo',\n label: 'Marketo',\n mode: 'in-cli',\n signals: {\n python: ['marketorestpython'],\n envKeys: [/^MARKETO_/],\n },\n },\n {\n kind: 'Lob',\n label: 'Lob',\n mode: 'in-cli',\n signals: {\n npm: ['lob'],\n python: ['lob'],\n envKeys: [/^LOB_API_KEY$/],\n },\n },\n // ---- Product analytics / CDP ----\n {\n kind: 'Segment',\n label: 'Segment',\n mode: 'in-cli',\n signals: {\n npm: ['@segment/analytics-node', 'analytics-node'],\n python: ['segment-analytics-python', 'analytics-python'],\n envKeys: [/^SEGMENT_/],\n },\n },\n {\n kind: 'Snowplow',\n label: 'Snowplow Analytics',\n mode: 'in-cli',\n signals: {\n npm: ['@snowplow/node-tracker'],\n python: ['snowplow-tracker'],\n envKeys: [/^SNOWPLOW_/],\n },\n },\n {\n kind: 'Matomo',\n label: 'Matomo',\n mode: 'in-cli',\n signals: {\n npm: ['matomo-tracker'],\n envKeys: [/^MATOMO_/],\n },\n },\n {\n kind: 'Plausible',\n label: 'Plausible',\n mode: 'in-cli',\n signals: {\n npm: ['plausible-tracker'],\n envKeys: [/^PLAUSIBLE_/],\n },\n },\n // ---- Feature flags / experimentation ----\n {\n kind: 'ConfigCat',\n label: 'ConfigCat',\n mode: 'in-cli',\n signals: {\n npm: ['configcat-node', 'configcat-js'],\n python: ['configcat-client'],\n envKeys: [/^CONFIGCAT_/],\n },\n },\n {\n kind: 'Flagsmith',\n label: 'Flagsmith',\n mode: 'in-cli',\n signals: {\n npm: ['flagsmith-nodejs', 'flagsmith'],\n python: ['flagsmith'],\n envKeys: [/^FLAGSMITH_/],\n },\n },\n {\n kind: 'Unleash',\n label: 'Unleash',\n mode: 'in-cli',\n signals: {\n npm: ['unleash-client'],\n python: ['unleashclient'],\n envKeys: [/^UNLEASH_/],\n },\n },\n {\n kind: 'SplitIo',\n label: 'Split.io',\n mode: 'in-cli',\n signals: {\n npm: ['@splitsoftware/splitio'],\n python: ['splitio-client'],\n envKeys: [/^SPLITIO_/, /^SPLIT_IO_/],\n },\n },\n // ---- Auth / secrets ----\n {\n kind: 'Stytch',\n label: 'Stytch',\n mode: 'in-cli',\n signals: {\n npm: ['stytch'],\n python: ['stytch'],\n envKeys: [/^STYTCH_/],\n },\n },\n {\n kind: 'Doppler',\n label: 'Doppler',\n mode: 'in-cli',\n signals: {\n npm: ['@dopplerhq/node-sdk'],\n envKeys: [/^DOPPLER_/],\n },\n },\n {\n kind: 'Infisical',\n label: 'Infisical',\n mode: 'in-cli',\n signals: {\n npm: ['@infisical/sdk'],\n python: ['infisicalsdk'],\n envKeys: [/^INFISICAL_/],\n },\n },\n {\n kind: 'OnePassword',\n label: '1Password',\n mode: 'in-cli',\n signals: {\n npm: ['@1password/sdk'],\n python: ['onepassword-sdk'],\n envKeys: [/^ONEPASSWORD_/, /^OP_SERVICE_ACCOUNT_TOKEN$/],\n },\n },\n {\n kind: 'Persona',\n label: 'Persona',\n mode: 'in-cli',\n signals: {\n envKeys: [/^PERSONA_/],\n },\n },\n // ---- Comms / webhooks / voice ----\n {\n kind: 'Svix',\n label: 'Svix',\n mode: 'in-cli',\n signals: {\n npm: ['svix'],\n python: ['svix'],\n envKeys: [/^SVIX_/],\n },\n },\n {\n kind: 'Mux',\n label: 'Mux',\n mode: 'in-cli',\n signals: {\n npm: ['@mux/mux-node'],\n python: ['mux-python'],\n envKeys: [/^MUX_/],\n },\n },\n {\n kind: 'Vapi',\n label: 'Vapi',\n mode: 'in-cli',\n signals: {\n npm: ['@vapi-ai/server-sdk'],\n python: ['vapi-server-sdk'],\n envKeys: [/^VAPI_/],\n },\n },\n {\n kind: 'Aircall',\n label: 'Aircall',\n mode: 'in-cli',\n signals: {\n envKeys: [/^AIRCALL_/],\n },\n },\n {\n kind: 'JustCall',\n label: 'JustCall',\n mode: 'in-cli',\n signals: {\n envKeys: [/^JUSTCALL_/],\n },\n },\n {\n kind: 'Telnyx',\n label: 'Telnyx',\n mode: 'in-cli',\n signals: {\n npm: ['telnyx'],\n python: ['telnyx'],\n envKeys: [/^TELNYX_/],\n },\n },\n {\n kind: 'Plivo',\n label: 'Plivo',\n mode: 'in-cli',\n signals: {\n npm: ['plivo'],\n python: ['plivo'],\n envKeys: [/^PLIVO_/],\n },\n },\n {\n kind: 'Courier',\n label: 'Courier',\n mode: 'in-cli',\n signals: {\n npm: ['@trycourier/courier'],\n python: ['trycourier'],\n // COURIER_ is a generic shipping word, so we match the exact key.\n envKeys: [/^COURIER_AUTH_TOKEN$/],\n },\n },\n // ---- E-commerce / logistics ----\n {\n kind: 'WooCommerce',\n label: 'WooCommerce',\n mode: 'in-cli',\n signals: {\n npm: ['@woocommerce/woocommerce-rest-api'],\n python: ['woocommerce'],\n envKeys: [/^WOOCOMMERCE_/],\n },\n },\n {\n kind: 'Recharge',\n label: 'Recharge',\n mode: 'in-cli',\n signals: {\n envKeys: [/^RECHARGE_/],\n },\n },\n {\n kind: 'Commercetools',\n label: 'commercetools',\n mode: 'in-cli',\n signals: {\n npm: ['@commercetools/platform-sdk'],\n python: ['commercetools'],\n envKeys: [/^CTP_/, /^COMMERCETOOLS_/],\n },\n },\n {\n kind: 'Webflow',\n label: 'Webflow',\n mode: 'in-cli',\n signals: {\n npm: ['webflow-api'],\n envKeys: [/^WEBFLOW_/],\n },\n },\n {\n kind: 'Easypost',\n label: 'EasyPost',\n mode: 'in-cli',\n signals: {\n npm: ['@easypost/api'],\n python: ['easypost'],\n envKeys: [/^EASYPOST_/],\n },\n },\n {\n kind: 'Shippo',\n label: 'Shippo',\n mode: 'in-cli',\n signals: {\n npm: ['shippo'],\n python: ['shippo'],\n envKeys: [/^SHIPPO_/],\n },\n },\n {\n kind: 'ShipStation',\n label: 'ShipStation',\n mode: 'in-cli',\n signals: {\n envKeys: [/^SHIPSTATION_/],\n },\n },\n {\n kind: 'Squarespace',\n label: 'Squarespace',\n mode: 'in-cli',\n signals: {\n envKeys: [/^SQUARESPACE_/],\n },\n },\n {\n kind: 'Printify',\n label: 'Printify',\n mode: 'in-cli',\n signals: {\n envKeys: [/^PRINTIFY_/],\n },\n },\n {\n kind: 'BigCommerce',\n label: 'BigCommerce',\n mode: 'in-cli',\n signals: {\n npm: ['node-bigcommerce'],\n envKeys: [/^BIGCOMMERCE_/],\n },\n },\n // ---- Support / helpdesk ----\n {\n kind: 'Freshdesk',\n label: 'Freshdesk',\n mode: 'in-cli',\n signals: {\n python: ['python-freshdesk'],\n envKeys: [/^FRESHDESK_/],\n },\n },\n {\n kind: 'Front',\n label: 'Front',\n mode: 'in-cli',\n signals: {\n envKeys: [/^FRONTAPP_/, /^FRONT_API_/],\n },\n },\n {\n kind: 'Gorgias',\n label: 'Gorgias',\n mode: 'in-cli',\n signals: {\n envKeys: [/^GORGIAS_/],\n },\n },\n {\n kind: 'Chatwoot',\n label: 'Chatwoot',\n mode: 'in-cli',\n signals: {\n envKeys: [/^CHATWOOT_/],\n },\n },\n {\n kind: 'Kustomer',\n label: 'Kustomer',\n mode: 'in-cli',\n signals: {\n envKeys: [/^KUSTOMER_/],\n },\n },\n {\n kind: 'Plain',\n label: 'Plain',\n mode: 'in-cli',\n signals: {\n npm: ['@team-plain/typescript-sdk'],\n envKeys: [/^PLAIN_/],\n },\n },\n {\n kind: 'Canny',\n label: 'Canny',\n mode: 'in-cli',\n signals: {\n envKeys: [/^CANNY_/],\n },\n },\n {\n kind: 'Pylon',\n label: 'Pylon',\n mode: 'in-cli',\n signals: {\n envKeys: [/^PYLON_/],\n },\n },\n // ---- Dev / infra / observability ----\n {\n kind: 'GitLab',\n label: 'GitLab',\n mode: 'in-cli',\n signals: {\n npm: ['@gitbeaker/rest'],\n python: ['python-gitlab'],\n ruby: ['gitlab'],\n envKeys: [/^GITLAB_/],\n },\n },\n {\n kind: 'Bitbucket',\n label: 'Atlassian Bitbucket Cloud',\n mode: 'in-cli',\n signals: {\n npm: ['bitbucket'],\n envKeys: [/^BITBUCKET_/],\n },\n },\n {\n kind: 'Gitea',\n label: 'Gitea',\n mode: 'in-cli',\n signals: {\n npm: ['gitea-js'],\n envKeys: [/^GITEA_/],\n },\n },\n {\n kind: 'Datadog',\n label: 'Datadog',\n mode: 'in-cli',\n signals: {\n npm: ['@datadog/datadog-api-client', 'dd-trace'],\n python: ['datadog', 'datadog-api-client'],\n ruby: ['dogapi'],\n envKeys: [/^DATADOG_/, /^DD_API_KEY$/, /^DD_APP_KEY$/],\n },\n },\n {\n kind: 'NewRelic',\n label: 'New Relic',\n mode: 'in-cli',\n signals: {\n npm: ['newrelic'],\n python: ['newrelic'],\n ruby: ['newrelic_rpm'],\n envKeys: [/^NEW_RELIC_/, /^NEWRELIC_/],\n },\n },\n {\n kind: 'Cloudflare',\n label: 'Cloudflare',\n mode: 'in-cli',\n signals: {\n npm: ['cloudflare'],\n python: ['cloudflare'],\n envKeys: [/^CLOUDFLARE_/, /^CF_API_TOKEN$/],\n },\n },\n {\n kind: 'Elasticsearch',\n label: 'Elasticsearch',\n mode: 'in-cli',\n signals: {\n npm: ['@elastic/elasticsearch'],\n python: ['elasticsearch'],\n ruby: ['elasticsearch'],\n envKeys: [/^ELASTICSEARCH_/],\n },\n },\n {\n kind: 'Snyk',\n label: 'Snyk',\n mode: 'in-cli',\n signals: {\n npm: ['snyk'],\n python: ['pysnyk'],\n envKeys: [/^SNYK_/],\n },\n },\n {\n kind: 'PagerDuty',\n label: 'PagerDuty',\n mode: 'in-cli',\n signals: {\n npm: ['@pagerduty/pdjs'],\n python: ['pdpyras'],\n envKeys: [/^PAGERDUTY_/, /^PD_API_KEY$/],\n },\n },\n {\n kind: 'Opsgenie',\n label: 'Opsgenie',\n mode: 'in-cli',\n signals: {\n envKeys: [/^OPSGENIE_/],\n },\n },\n {\n kind: 'IncidentIo',\n label: 'incident.io',\n mode: 'in-cli',\n signals: {\n envKeys: [/^INCIDENT_IO_/, /^INCIDENTIO_/],\n },\n },\n {\n kind: 'Bugsnag',\n label: 'Bugsnag',\n mode: 'in-cli',\n signals: {\n npm: ['@bugsnag/js'],\n python: ['bugsnag'],\n ruby: ['bugsnag'],\n envKeys: [/^BUGSNAG_/],\n },\n },\n {\n kind: 'Honeybadger',\n label: 'Honeybadger',\n mode: 'in-cli',\n signals: {\n npm: ['@honeybadger-io/js'],\n python: ['honeybadger'],\n ruby: ['honeybadger'],\n envKeys: [/^HONEYBADGER_/],\n },\n },\n {\n kind: 'Raygun',\n label: 'Raygun',\n mode: 'in-cli',\n signals: {\n npm: ['raygun'],\n python: ['raygun4py'],\n ruby: ['raygun4ruby'],\n envKeys: [/^RAYGUN_/],\n },\n },\n {\n kind: 'CircleCI',\n label: 'CircleCI',\n mode: 'in-cli',\n signals: {\n envKeys: [/^CIRCLECI_/, /^CIRCLE_TOKEN$/],\n },\n },\n {\n kind: 'Upstash',\n label: 'Upstash',\n mode: 'in-cli',\n signals: {\n npm: ['@upstash/redis'],\n python: ['upstash-redis'],\n envKeys: [/^UPSTASH_/],\n },\n },\n {\n kind: 'Vercel',\n label: 'Vercel',\n mode: 'in-cli',\n signals: {\n npm: ['@vercel/sdk'],\n envKeys: [/^VERCEL_API_TOKEN$/],\n },\n },\n {\n kind: 'Algolia',\n label: 'Algolia',\n mode: 'in-cli',\n signals: {\n npm: ['algoliasearch'],\n python: ['algoliasearch'],\n ruby: ['algolia'],\n envKeys: [/^ALGOLIA_/],\n },\n },\n {\n kind: 'Inngest',\n label: 'Inngest',\n mode: 'in-cli',\n signals: {\n npm: ['inngest'],\n python: ['inngest'],\n envKeys: [/^INNGEST_/],\n },\n },\n {\n kind: 'TriggerDev',\n label: 'Trigger.dev',\n mode: 'in-cli',\n signals: {\n npm: ['@trigger.dev/sdk'],\n // TRIGGER_ alone is a common app-domain prefix, so we match only the\n // three keys Trigger.dev actually documents.\n envKeys: [/^TRIGGER_(SECRET_KEY|API_KEY|PROJECT_ID)$/],\n },\n },\n {\n kind: 'Ably',\n label: 'Ably',\n mode: 'in-cli',\n signals: {\n npm: ['ably'],\n python: ['ably'],\n envKeys: [/^ABLY_/],\n },\n },\n {\n kind: 'Netlify',\n label: 'Netlify',\n mode: 'in-cli',\n signals: {\n npm: ['@netlify/functions'],\n envKeys: [/^NETLIFY_/],\n },\n },\n {\n kind: 'Railway',\n label: 'Railway',\n mode: 'in-cli',\n signals: {\n envKeys: [/^RAILWAY_/],\n },\n },\n {\n kind: 'Render',\n label: 'Render',\n mode: 'in-cli',\n signals: {\n // RENDER_ is a generic word in front-end code — exact key only.\n envKeys: [/^RENDER_API_KEY$/],\n },\n },\n {\n kind: 'FlyIo',\n label: 'Fly.io',\n mode: 'in-cli',\n signals: {\n // `fly.toml` is not one of the manifests we read, so env keys are the\n // only signal available.\n envKeys: [/^FLY_API_TOKEN$/, /^FLY_APP_NAME$/],\n },\n },\n {\n kind: 'Heroku',\n label: 'Heroku',\n mode: 'in-cli',\n signals: {\n envKeys: [/^HEROKU_/],\n },\n },\n {\n kind: 'DigitalOcean',\n label: 'DigitalOcean',\n mode: 'in-cli',\n signals: {\n // DO_ is too short to be safe, so we match the full product name.\n envKeys: [/^DIGITALOCEAN_/],\n },\n },\n {\n kind: 'Grafana',\n label: 'Grafana',\n mode: 'in-cli',\n signals: {\n python: ['grafana-client'],\n envKeys: [/^GRAFANA_/],\n },\n },\n {\n kind: 'BetterStack',\n label: 'Better Stack',\n mode: 'in-cli',\n signals: {\n // Logtail is Better Stack's log product — same account, same source.\n npm: ['@logtail/node', '@logtail/js'],\n envKeys: [/^BETTERSTACK_/, /^BETTER_STACK_/, /^LOGTAIL_/],\n },\n },\n {\n kind: 'Honeycomb',\n label: 'Honeycomb',\n mode: 'in-cli',\n signals: {\n npm: ['@honeycombio/opentelemetry-node', 'honeycomb-beeline'],\n python: ['honeycomb-beeline', 'libhoney'],\n envKeys: [/^HONEYCOMB_/],\n },\n },\n {\n kind: 'Descope',\n label: 'Descope',\n mode: 'in-cli',\n signals: {\n npm: ['@descope/node-sdk', '@descope/nextjs-sdk', '@descope/react-sdk'],\n python: ['descope'],\n envKeys: [/^DESCOPE_/],\n },\n },\n {\n kind: 'FusionAuth',\n label: 'FusionAuth',\n mode: 'in-cli',\n signals: {\n npm: ['@fusionauth/typescript-client'],\n python: ['fusionauth-client'],\n envKeys: [/^FUSIONAUTH_/, /^FUSION_AUTH_/],\n },\n },\n {\n kind: 'Hookdeck',\n label: 'Hookdeck',\n mode: 'in-cli',\n signals: {\n npm: ['@hookdeck/sdk'],\n envKeys: [/^HOOKDECK_/],\n },\n },\n {\n kind: 'N8n',\n label: 'n8n',\n mode: 'in-cli',\n signals: {\n npm: ['n8n'],\n envKeys: [/^N8N_/],\n },\n },\n {\n kind: 'Dbt',\n label: 'dbt',\n mode: 'in-cli',\n signals: {\n // NOTE: these signals prove the project uses dbt, not that it uses dbt\n // Cloud — the source needs dbt Cloud credentials. Local-only dbt users\n // are a known false positive.\n python: [\n 'dbt-core',\n 'dbt-snowflake',\n 'dbt-postgres',\n 'dbt-bigquery',\n 'dbt-redshift',\n 'dbt-databricks',\n ],\n envKeys: [/^DBT_/],\n },\n },\n {\n kind: 'Fastly',\n label: 'Fastly',\n mode: 'in-cli',\n signals: {\n npm: ['fastly'],\n python: ['fastly'],\n envKeys: [/^FASTLY_/],\n },\n },\n {\n kind: 'Bunny',\n label: 'Bunny.net',\n mode: 'in-cli',\n signals: {\n envKeys: [/^BUNNY_/],\n },\n },\n {\n kind: 'Codecov',\n label: 'Codecov',\n mode: 'in-cli',\n signals: {\n npm: ['codecov'],\n envKeys: [/^CODECOV_/],\n },\n },\n {\n kind: 'Sourcegraph',\n label: 'Sourcegraph',\n mode: 'in-cli',\n signals: {\n envKeys: [/^SOURCEGRAPH_/, /^SRC_ACCESS_TOKEN$/],\n },\n },\n {\n kind: 'TemporalIO',\n label: 'Temporal.io',\n mode: 'in-cli',\n signals: {\n // NOTE: these signals also match a self-hosted Temporal cluster, but the\n // source wants Temporal Cloud mTLS certificates.\n npm: ['@temporalio/client', '@temporalio/worker'],\n python: ['temporalio'],\n envKeys: [/^TEMPORAL_/],\n },\n },\n {\n kind: 'Hatchet',\n label: 'Hatchet',\n mode: 'in-cli',\n signals: {\n npm: ['@hatchet-dev/typescript-sdk'],\n python: ['hatchet-sdk'],\n envKeys: [/^HATCHET_/],\n },\n },\n // ---- CRM / sales ----\n {\n kind: 'Pipedrive',\n label: 'Pipedrive',\n mode: 'in-cli',\n signals: {\n npm: ['pipedrive'],\n envKeys: [/^PIPEDRIVE_/],\n },\n },\n {\n kind: 'Close',\n label: 'Close',\n mode: 'in-cli',\n signals: {\n python: ['closeio'],\n envKeys: [/^CLOSE_API_KEY$/],\n },\n },\n {\n kind: 'Copper',\n label: 'Copper',\n mode: 'in-cli',\n signals: {\n envKeys: [/^COPPER_/],\n },\n },\n {\n kind: 'Insightly',\n label: 'Insightly',\n mode: 'in-cli',\n signals: {\n envKeys: [/^INSIGHTLY_/],\n },\n },\n {\n kind: 'Salesflare',\n label: 'Salesflare',\n mode: 'in-cli',\n signals: {\n envKeys: [/^SALESFLARE_/],\n },\n },\n {\n kind: 'SalesLoft',\n label: 'Salesloft',\n mode: 'in-cli',\n signals: {\n envKeys: [/^SALESLOFT_/],\n },\n },\n {\n kind: 'Attio',\n label: 'Attio',\n mode: 'in-cli',\n signals: {\n npm: ['attio'],\n envKeys: [/^ATTIO_/],\n },\n },\n {\n kind: 'ActiveCampaign',\n label: 'ActiveCampaign',\n mode: 'in-cli',\n signals: {\n envKeys: [/^ACTIVECAMPAIGN_/, /^ACTIVE_CAMPAIGN_/],\n },\n },\n {\n kind: 'Vitally',\n label: 'Vitally',\n mode: 'in-cli',\n signals: {\n envKeys: [/^VITALLY_/],\n },\n },\n {\n kind: 'Docusign',\n label: 'DocuSign',\n mode: 'in-cli',\n signals: {\n npm: ['docusign-esign'],\n python: ['docusign-esign'],\n envKeys: [/^DOCUSIGN_/],\n },\n },\n {\n kind: 'PandaDoc',\n label: 'PandaDoc',\n mode: 'in-cli',\n signals: {\n envKeys: [/^PANDADOC_/],\n },\n },\n {\n kind: 'Gong',\n label: 'Gong',\n mode: 'in-cli',\n signals: {\n envKeys: [/^GONG_/],\n },\n },\n // ---- PM / productivity ----\n {\n kind: 'Asana',\n label: 'Asana',\n mode: 'in-cli',\n signals: {\n npm: ['asana'],\n python: ['asana'],\n envKeys: [/^ASANA_/],\n },\n },\n {\n kind: 'Trello',\n label: 'Trello',\n mode: 'in-cli',\n signals: {\n npm: ['trello'],\n envKeys: [/^TRELLO_/],\n },\n },\n {\n kind: 'Todoist',\n label: 'Todoist',\n mode: 'in-cli',\n signals: {\n npm: ['@doist/todoist-api-typescript'],\n python: ['todoist-api-python'],\n envKeys: [/^TODOIST_/],\n },\n },\n {\n kind: 'Monday',\n label: 'monday.com',\n mode: 'in-cli',\n signals: {\n npm: ['@mondaydotcomorg/api'],\n envKeys: [/^MONDAY_/],\n },\n },\n {\n kind: 'ClickUp',\n label: 'ClickUp',\n mode: 'in-cli',\n signals: {\n envKeys: [/^CLICKUP_/],\n },\n },\n {\n kind: 'Height',\n label: 'Height',\n mode: 'in-cli',\n signals: {\n envKeys: [/^HEIGHT_API_KEY$/],\n },\n },\n {\n kind: 'Shortcut',\n label: 'Shortcut',\n mode: 'in-cli',\n signals: {\n npm: ['@shortcut/client'],\n envKeys: [/^SHORTCUT_/],\n },\n },\n {\n kind: 'Jira',\n label: 'Jira',\n mode: 'in-cli',\n signals: {\n npm: ['jira-client'],\n python: ['jira', 'atlassian-python-api'],\n envKeys: [/^JIRA_/],\n },\n },\n {\n kind: 'Confluence',\n label: 'Confluence',\n mode: 'in-cli',\n signals: {\n envKeys: [/^CONFLUENCE_/],\n },\n },\n {\n kind: 'Airtable',\n label: 'Airtable',\n mode: 'in-cli',\n signals: {\n npm: ['airtable'],\n python: ['pyairtable'],\n envKeys: [/^AIRTABLE_/],\n },\n },\n {\n kind: 'Smartsheet',\n label: 'Smartsheet',\n mode: 'in-cli',\n signals: {\n npm: ['smartsheet'],\n python: ['smartsheet-python-sdk'],\n envKeys: [/^SMARTSHEET_/],\n },\n },\n {\n kind: 'Coda',\n label: 'Coda',\n mode: 'in-cli',\n signals: {\n envKeys: [/^CODA_API_/],\n },\n },\n {\n kind: 'Productboard',\n label: 'Productboard',\n mode: 'in-cli',\n signals: {\n envKeys: [/^PRODUCTBOARD_/],\n },\n },\n {\n kind: 'GoogleSheets',\n label: 'Google Sheets',\n mode: 'in-cli',\n signals: {\n npm: ['google-spreadsheet'],\n python: ['gspread'],\n envKeys: [/^GOOGLE_SHEETS_/],\n },\n },\n {\n kind: 'Formbricks',\n label: 'Formbricks',\n mode: 'in-cli',\n signals: {\n npm: ['@formbricks/js'],\n envKeys: [/^FORMBRICKS_/],\n },\n },\n {\n kind: 'Tally',\n label: 'Tally',\n mode: 'in-cli',\n signals: {\n // Tally is also an accounting product, so we match the exact key.\n envKeys: [/^TALLY_API_KEY$/],\n },\n },\n {\n kind: 'Jotform',\n label: 'Jotform',\n mode: 'in-cli',\n signals: {\n python: ['jotform'],\n envKeys: [/^JOTFORM_/],\n },\n },\n {\n kind: 'GitBook',\n label: 'GitBook',\n mode: 'in-cli',\n signals: {\n npm: ['@gitbook/api'],\n envKeys: [/^GITBOOK_/],\n },\n },\n {\n kind: 'Wordpress',\n label: 'WordPress',\n mode: 'in-cli',\n signals: {\n // NOTE: recall is low here. Most WordPress projects are PHP, and\n // `composer.json` is not one of the manifests we read.\n npm: ['wpapi'],\n envKeys: [/^WORDPRESS_/],\n },\n },\n {\n kind: 'Clockify',\n label: 'Clockify',\n mode: 'in-cli',\n signals: {\n envKeys: [/^CLOCKIFY_/],\n },\n },\n // ---- Scheduling / events ----\n {\n kind: 'Calendly',\n label: 'Calendly',\n mode: 'in-cli',\n signals: {\n envKeys: [/^CALENDLY_/],\n },\n },\n {\n kind: 'CalCom',\n label: 'Cal.com',\n mode: 'in-cli',\n signals: {\n envKeys: [/^CALCOM_/, /^CAL_API_KEY$/],\n },\n },\n {\n kind: 'Eventbrite',\n label: 'Eventbrite',\n mode: 'in-cli',\n signals: {\n python: ['eventbrite'],\n envKeys: [/^EVENTBRITE_/],\n },\n },\n // ---- HR / people ----\n {\n kind: 'BambooHR',\n label: 'BambooHR',\n mode: 'in-cli',\n signals: {\n python: ['pybamboohr'],\n envKeys: [/^BAMBOOHR_/, /^BAMBOO_HR_/],\n },\n },\n {\n kind: 'Personio',\n label: 'Personio',\n mode: 'in-cli',\n signals: {\n envKeys: [/^PERSONIO_/],\n },\n },\n {\n kind: 'Rippling',\n label: 'Rippling',\n mode: 'in-cli',\n signals: {\n envKeys: [/^RIPPLING_/],\n },\n },\n {\n kind: 'Greenhouse',\n label: 'Greenhouse',\n mode: 'in-cli',\n signals: {\n envKeys: [/^GREENHOUSE_/],\n },\n },\n {\n kind: 'Ashby',\n label: 'Ashby',\n mode: 'in-cli',\n signals: {\n envKeys: [/^ASHBY_/],\n },\n },\n {\n kind: 'Workable',\n label: 'Workable',\n mode: 'in-cli',\n signals: {\n envKeys: [/^WORKABLE_/],\n },\n },\n // ---- Ads / marketing analytics (OAuth-first -> deep-link) ----\n {\n kind: 'GoogleAds',\n label: 'Google Ads',\n mode: 'deep-link',\n signals: {\n npm: ['google-ads-api'],\n python: ['google-ads'],\n envKeys: [/^GOOGLE_ADS_/],\n },\n },\n {\n kind: 'MetaAds',\n label: 'Meta Ads',\n mode: 'deep-link',\n signals: {\n npm: ['facebook-nodejs-business-sdk'],\n python: ['facebook-business'],\n envKeys: [/^META_ADS_/, /^FACEBOOK_ADS_/],\n },\n },\n {\n kind: 'LinkedinAds',\n label: 'LinkedIn Ads',\n mode: 'deep-link',\n signals: {\n envKeys: [/^LINKEDIN_ADS_/],\n },\n },\n {\n kind: 'TikTokAds',\n label: 'TikTok Ads',\n mode: 'deep-link',\n signals: {\n envKeys: [/^TIKTOK_ADS_/],\n },\n },\n {\n kind: 'RedditAds',\n label: 'Reddit Ads',\n mode: 'deep-link',\n signals: {\n envKeys: [/^REDDIT_ADS_/],\n },\n },\n {\n kind: 'PinterestAds',\n label: 'Pinterest Ads',\n mode: 'deep-link',\n signals: {\n envKeys: [/^PINTEREST_ADS_/],\n },\n },\n {\n kind: 'BingAds',\n label: 'Bing Ads',\n mode: 'deep-link',\n signals: {\n python: ['bingads'],\n envKeys: [/^BING_ADS_/, /^MICROSOFT_ADS_/],\n },\n },\n {\n kind: 'AmazonAds',\n label: 'Amazon Ads',\n mode: 'deep-link',\n signals: {\n envKeys: [/^AMAZON_ADS_/],\n },\n },\n {\n kind: 'GoogleAnalytics',\n label: 'Google Analytics',\n mode: 'deep-link',\n signals: {\n npm: ['react-ga4'],\n python: ['google-analytics-data'],\n envKeys: [/^GOOGLE_ANALYTICS_/, /^GA4_/],\n },\n },\n {\n kind: 'GoogleSearchConsole',\n label: 'Google Search Console',\n mode: 'deep-link',\n signals: {\n envKeys: [/^SEARCH_CONSOLE_/, /^GSC_/],\n },\n },\n {\n kind: 'AppsFlyer',\n label: 'AppsFlyer',\n mode: 'in-cli',\n signals: {\n npm: ['react-native-appsflyer'],\n envKeys: [/^APPSFLYER_/],\n },\n },\n {\n kind: 'Dub',\n label: 'Dub',\n mode: 'in-cli',\n signals: {\n npm: ['dub'],\n python: ['dub'],\n envKeys: [/^DUB_API_KEY$/],\n },\n },\n];\n\nexport const SOURCE_DETECTORS: SourceDetector[] = [\n ...CORE_SOURCE_DETECTORS,\n ...LLM_SOURCE_DETECTORS,\n ...OTHER_SOURCE_DETECTORS,\n];\n\n/** Kinds from the LLM / AI section above — the only ones that may set `wizard_ai_sdk_detected`. */\nexport const AI_SOURCE_KINDS: ReadonlySet<string> = new Set(\n LLM_SOURCE_DETECTORS.map((detector) => detector.kind),\n);\n","/**\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 type { ProgramSession } from '../program-session';\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 '../detection/features';\nimport { SOURCE_DETECTORS } from './registry.js';\nimport type { DetectedSource, SourceDetector } from './types.js';\n\ninterface ProjectSignals {\n npm: Set<string>;\n python: Set<string>;\n ruby: Set<string>;\n /**\n * Key NAME → the project-relative `.env*` file that first defined it. The\n * path is sanitised on the way in, so nothing here can reach a prompt raw.\n */\n envKeys: Map<string, string>;\n}\n\n// Shared with `check_env_keys` so the tool scans exactly what the detector\n// scanned — see `@utils/env-scan`.\nconst MAX_DEPTH = ENV_SCAN_MAX_DEPTH;\n\n// Each signal Set retains at most this many entries.\nconst MAX_SIGNAL_SET = MAX_ENV_KEY_SET;\n\nfunction addCapped(set: Set<string>, value: string): void {\n if (set.size < MAX_SIGNAL_SET) set.add(value);\n}\n\n/**\n * Detect which warehouse sources the project at `installDir` appears to use.\n * Returns one `DetectedSource` per matched registry entry (kinds are unique,\n * so the result is naturally deduped), minus the entries a more specific\n * match supersedes.\n */\nexport function detectWarehouseSources(installDir: string): DetectedSource[] {\n // No directory guard here: walkProjectFiles is best-effort and yields no\n // signals for a missing/unreadable dir (→ []). The program-level detect\n // step is responsible for surfacing a structured `bad-directory` error.\n const signals = collectSignals(installDir);\n\n const matched: { detector: SourceDetector; signal: string }[] = [];\n for (const detector of SOURCE_DETECTORS) {\n const signal = matchDetector(detector, signals);\n if (signal) matched.push({ detector, signal });\n }\n\n const kinds = new Set(matched.map((m) => m.detector.kind));\n return matched\n .filter(({ detector }) => !isSuperseded(detector, kinds))\n .map(({ detector, signal }) => ({\n kind: detector.kind,\n label: detector.label,\n mode: detector.mode,\n matchedSignal: signal,\n }));\n}\n\n/**\n * Whether a more specific match covers this detector's data. Every consumer\n * treats a detected kind as a source to create, so a project whose Postgres\n * lives on Neon or Supabase would otherwise be offered both and end up with\n * the same tables imported twice.\n */\nfunction isSuperseded(\n detector: SourceDetector,\n detectedKinds: ReadonlySet<string>,\n): boolean {\n return (detector.supersededBy ?? []).some((kind) => detectedKinds.has(kind));\n}\n\n/** Returns a human-readable description of the first matching signal, or null. */\nfunction matchDetector(\n detector: SourceDetector,\n signals: ProjectSignals,\n): string | null {\n const { npm, python, ruby, envKeys } = detector.signals;\n\n const npmHit = npm?.find((dep) => signals.npm.has(dep));\n if (npmHit) return `found \\`${npmHit}\\` in package.json`;\n\n const pyHit = python?.find((dep) => signals.python.has(dep));\n if (pyHit) return `found \\`${pyHit}\\` in Python dependencies`;\n\n const rubyHit = ruby?.find((gem) => signals.ruby.has(gem));\n if (rubyHit) return `found \\`${rubyHit}\\` in Gemfile`;\n\n if (envKeys) {\n // Name the file that actually matched. The agent acts on this string, so\n // pointing it at `.env` when the key lives in `apps/api/.env.local` sends\n // it to look in the wrong place and conclude the credential is absent.\n //\n // Both interpolated parts are repository-derived, so both are quoted as\n // code and both are constrained. `parseEnvKeyNames` limits the key to\n // `[A-Za-z_][A-Za-z0-9_]*`. The path is the unconstrained part: the\n // repository names its own directories, so it arrives already sanitised\n // from `toPromptSafeRelativePath` and cannot break out of the code span.\n for (const [key, file] of signals.envKeys) {\n if (envKeys.some((re) => re.test(key))) {\n return `found \\`${key}\\` in \\`${file}\\``;\n }\n }\n }\n\n return null;\n}\n\nfunction collectSignals(installDir: string): ProjectSignals {\n const signals: ProjectSignals = {\n npm: new Set(),\n python: new Set(),\n ruby: new Set(),\n envKeys: new Map(),\n };\n\n walkProjectFiles(\n installDir,\n (name, fullPath) => ingestFile(installDir, name, fullPath, signals),\n MAX_DEPTH,\n );\n\n return signals;\n}\n\n/**\n * Route a file to the right parser BY NAME, reading its contents only when the\n * name matches one of the ~6 manifests we care about. Checking the name first\n * avoids slurping every file in the tree (lockfiles, binaries, assets) into\n * memory just to discard it.\n */\nfunction ingestFile(\n installDir: string,\n name: string,\n fullPath: string,\n signals: ProjectSignals,\n): void {\n const ingest = ingestorFor(name);\n if (!ingest) return;\n\n const content = safeReadFile(fullPath);\n if (content === null) return;\n\n ingest(content, signals, toPromptSafeRelativePath(installDir, fullPath));\n}\n\ntype Ingestor = (\n content: string,\n signals: ProjectSignals,\n relativePath: string,\n) => void;\n\n/** Pick the parser for a manifest filename, or null if it's not one we read. */\nfunction ingestorFor(name: string): Ingestor | null {\n if (name === 'package.json') return addNpmDeps;\n if (name === 'requirements.txt')\n return (c, s) =>\n parseRequirementsTxt(c).forEach((d) => addCapped(s.python, d));\n if (name === 'pyproject.toml')\n return (c, s) =>\n parsePyprojectToml(c).forEach((d) => addCapped(s.python, d));\n if (name === 'Pipfile')\n return (c, s) => parsePipfile(c).forEach((d) => addCapped(s.python, d));\n if (name === 'Gemfile')\n return (c, s) => parseGemfile(c).forEach((g) => addCapped(s.ruby, g));\n if (isEnvFileName(name))\n return (c, s, relativePath) => addEnvKeys(c, s, relativePath);\n return null;\n}\n\n/**\n * Record each key NAME against the file that defined it. The first file wins,\n * so the reported signal stays stable when several `.env*` files repeat a key.\n * Values are never read.\n */\nfunction addEnvKeys(\n content: string,\n signals: ProjectSignals,\n relativePath: string,\n): void {\n for (const key of parseEnvKeyNames(content)) {\n if (signals.envKeys.has(key)) continue;\n if (signals.envKeys.size >= MAX_SIGNAL_SET) return;\n signals.envKeys.set(key, relativePath);\n }\n}\n\nfunction addNpmDeps(content: string, signals: ProjectSignals): void {\n try {\n const pkg = JSON.parse(content) as PackageJson;\n for (const dep of Object.keys({\n ...pkg.dependencies,\n ...pkg.devDependencies,\n })) {\n addCapped(signals.npm, dep);\n }\n } catch (error) {\n // Malformed package.json — skip it, but record that we hit it.\n analytics.captureException(\n error instanceof Error ? error : new Error(String(error)),\n { step: 'detectWarehouseSources.parsePackageJson' },\n );\n }\n}\n\n/** Extract gem names from `gem 'name'` declarations. */\nexport function parseGemfile(content: string): string[] {\n const gems: string[] = [];\n for (const match of content.matchAll(/^\\s*gem\\s+['\"]([^'\"]+)['\"]/gm)) {\n gems.push(match[1]);\n }\n return gems;\n}\n\n/**\n * Extract KEY NAMES from a dotenv file. Values are intentionally discarded.\n * Re-exported from `@utils/env-scan`, which `check_env_keys` shares, so the\n * detector and the tool cannot disagree about what counts as a key.\n */\nexport { parseEnvKeyNames as parseEnvKeys } from '@utils/env-scan';\n\n/** 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: ProgramSession,\n): DetectedSource[] {\n return (\n (session.frameworkContext[DETECTED_WAREHOUSE_SOURCES_KEY] as\n | DetectedSource[]\n | undefined) ?? []\n );\n}\n","import { relative } from 'path';\nimport { safeReadFile, walkProjectFiles } from '@utils/bounded-fs';\n\nexport const POSTHOG_SDKS = new Set([\n 'posthog-js',\n 'posthog-node',\n 'posthog-react-native',\n 'posthog-android',\n 'posthog-ios',\n]);\n\nexport const STRIPE_SDKS = new Set([\n 'stripe',\n '@stripe/stripe-js',\n '@stripe/react-stripe-js',\n]);\n\nexport interface PackageMatch {\n /** Path to the package.json relative to installDir */\n path: string;\n posthogSdks: string[];\n stripeSdks: string[];\n}\n\n// At most this many matches retained, regardless of monorepo package count.\nconst MAX_PACKAGE_MATCHES = 500;\n\n/**\n * Find all package.json files under installDir via the shared bounded walk\n * (depth cap, ignored dirs, symlink-loop protection, per-dir entry cap).\n * Returns matches with detected SDKs.\n */\nexport function findPackageJsons(\n installDir: string,\n maxDepth = 3,\n): PackageMatch[] {\n const matches: PackageMatch[] = [];\n\n walkProjectFiles(\n installDir,\n (name, fullPath) => {\n if (name !== 'package.json' || matches.length >= MAX_PACKAGE_MATCHES) {\n return;\n }\n const content = safeReadFile(fullPath);\n if (content === null) return;\n try {\n const pkg = JSON.parse(content) as {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n };\n const depNames = [\n ...Object.keys(pkg.dependencies ?? {}),\n ...Object.keys(pkg.devDependencies ?? {}),\n ];\n const posthogSdks = depNames.filter((d) => POSTHOG_SDKS.has(d));\n const stripeSdks = depNames.filter((d) => STRIPE_SDKS.has(d));\n matches.push({\n path: relative(installDir, fullPath) || 'package.json',\n posthogSdks,\n stripeSdks,\n });\n } catch {\n // Skip malformed package.json\n }\n },\n maxDepth,\n );\n\n return matches;\n}\n","/** The AI SDK org stamp. Session-free, so runProgram can load it without the session. */\n\nimport type { ApiUser } from '@shared/api';\nimport { DiscoveredFeature } from '@shared/discovered-feature';\nimport { analytics } from '@utils/analytics';\nimport { AI_SOURCE_KINDS } from '../warehouse-sources/registry';\nimport type { DetectedSource } from '../warehouse-sources/types';\n\n/** What the org stamp reads, with no session. */\nexport type AiSdkStampEvidence = {\n apiUser: Pick<ApiUser, 'organization'> | null;\n discoveredFeatures: readonly DiscoveredFeature[];\n warehouseSources: readonly DetectedSource[];\n /** Scan consent was granted, so local detection results may be reported. */\n mayReportScanResults: boolean;\n};\n\nfunction hasAiSdkEvidence(evidence: AiSdkStampEvidence): boolean {\n return (\n evidence.warehouseSources.some((s) => AI_SOURCE_KINDS.has(s.kind)) ||\n evidence.discoveredFeatures.includes(DiscoveredFeature.LLM)\n );\n}\n\n/**\n * Boolean only, on the org, never the list of kinds or any non-AI tool: a\n * decline must not leak even the shape of what local detection saw.\n */\nexport function stampAiSdkDetected(evidence: AiSdkStampEvidence): void {\n if (!evidence.mayReportScanResults) return;\n const organizationId = evidence.apiUser?.organization?.id;\n if (!organizationId) return;\n if (!hasAiSdkEvidence(evidence)) return;\n\n analytics.groupIdentify('organization', organizationId, {\n wizard_ai_sdk_detected: true,\n });\n}\n","/**\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 '../program-step';\nimport { mayReportScanResults, ScanConsent } from '@shared/run-state';\nimport type { ProgramSession } from '../program-session';\nimport { FRAMEWORK_REGISTRY } from '../frameworks/registry';\nimport { detectFramework } from './framework';\nimport { discoverFeatures } from './features';\nimport { checkFrameworkVersion, gatherFrameworkContext } from './context';\nimport { analytics } from '@utils/analytics';\nimport { detectWarehouseSources } from '../warehouse-sources/detect';\nimport {\n DETECTED_WAREHOUSE_SOURCES_KEY,\n getDetectedWarehouseSources,\n} from '../warehouse-sources/detect';\nimport { findPackageJsons } from '../shared/package-scanning';\n\n// Session-free, so runProgram can stamp without loading the session.\nexport { stampAiSdkDetected, type AiSdkStampEvidence } from './ai-sdk-stamp';\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 const detectedLabel = config.metadata.getDetectedFrameworkLabel?.(context);\n if (detectedLabel) {\n ctx.setDetectedFramework(detectedLabel);\n } else 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 detectExistingPostHog(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 end the run 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\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 * The org stamp is a separate concern: `runProgram` makes it once, after the\n * first login, rather than at consent resolution.\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: ProgramSession,\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\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/** Dependency-level signal, not a verified install. A failed scan reports false. */\nexport function detectExistingPostHog(\n ctx: Pick<ProgramReadyContext, 'setPosthogSdkDetected'>,\n installDir: string,\n): void {\n try {\n const pkgJsons = findPackageJsons(installDir);\n ctx.setPosthogSdkDetected(pkgJsons.some((p) => p.posthogSdks.length > 0));\n } catch (error) {\n analytics.captureException(\n error instanceof Error ? error : new Error(String(error)),\n { step: 'detectExistingPosthog' },\n );\n ctx.setPosthogSdkDetected(false);\n }\n}\n","import type { ErrorCode } from '@shared/errors';\nimport type { OutroData } from '@shared/outro';\n\n/**\n * A decided stop, such as an unsupported platform. A program throws it rather\n * than exiting: `runProgram` settles it as an aborted outcome from detection\n * and a failed one from a run definition, and the CLI turns that into its exit.\n * `outroData` is the structured outro for hosts that render one; `message` is\n * the plain text for every other host.\n */\nexport class ProgramAbort extends Error {\n readonly code: ErrorCode;\n readonly outroData?: OutroData;\n\n constructor(failure: {\n code: ErrorCode;\n message: string;\n outroData?: OutroData;\n }) {\n super(failure.message);\n this.name = 'ProgramAbort';\n this.code = failure.code;\n this.outroData = failure.outroData;\n }\n}\n","import { ErrorCodes } from '@shared/errors';\nimport { OutroKind, type OutroData } from '@shared/outro';\nimport { ProgramAbort } from '../program-abort';\n\ntype NoFrameworkGuidance = Pick<OutroData, 'message' | 'docsLabel' | 'docsUrl'>;\n\nexport function abortNoFrameworkDetected(\n overrides: NoFrameworkGuidance = {},\n): never {\n const message = overrides.message ?? 'Could not detect a framework';\n const outroData: OutroData = {\n kind: OutroKind.Error,\n message,\n instruction: 'Run the wizard from an app root directory.',\n body: \"That's the folder containing package.json or an equivalent project file.\",\n docsLabel: 'Supported frameworks and manual setup:',\n docsUrl: 'https://posthog.com/docs/libraries',\n ...overrides,\n };\n // Hosts without an outro screen (CI) only see the message, so it carries the\n // recovery guidance too.\n throw new ProgramAbort({\n code: ErrorCodes.DetectNoFramework,\n message: [\n message,\n outroData.instruction,\n outroData.body,\n `${outroData.docsLabel} ${outroData.docsUrl}`,\n ].join('\\n\\n'),\n outroData,\n });\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","/**\n * Scope additions more than one program asks for. A program widens the base\n * set with its config's `oauthScopeAdditions`, merged by `withScopeAdditions`\n * (`@shared/oauth-scopes`); `getOAuthScopesForProgram` in\n * `program-registry.ts` looks a program's additions up. A program's own\n * additions live in its folder.\n */\n\n/**\n * Extra scopes the warehouse-source program needs on top of\n * `WIZARD_OAUTH_SCOPES`. The agent creates data warehouse sources directly\n * (`external-data-sources-create`) and lists what's connected\n * (`external-data-sources-list`) to verify the result. Both are already within\n * the wizard OAuth app's scope ceiling — the self-driving program requests the\n * same pair.\n */\nexport const WAREHOUSE_SOURCE_SCOPE_ADDITIONS = [\n 'external_data_source:read',\n 'external_data_source:write',\n] as const;\n","import { detectPostHogIntegration } from '../detection/integration.js';\nimport type { ProgramConfig } from '../program-step';\nimport type { ProgramRun } from '../program-run';\nimport { AgentSignals, WIZARD_TOOL_NAMES } from '@agent';\nimport { shouldDisableAsk } from '@shared/ask-policy';\nimport type { ProgramSession } from '../program-session';\nimport { mayReportScanResults } from '@shared/run-state';\nimport { OutroKind } from '@shared/outro';\nimport {\n DEFAULT_PACKAGE_INSTALLATION,\n SPINNER_MESSAGE,\n} from '../framework-config';\nimport { tryGetPackageJson, isUsingTypeScript } from '@utils/setup-utils';\nimport { analytics } from '@utils/analytics';\nimport { detectFramework } from '../detection/framework';\nimport { gatherFrameworkContext } from '../detection/context';\nimport { noteDetectedFramework } from '../detection/detected-framework';\nimport { scopeInstallDirToProject } from '../detection/project-scope';\nimport type { CiRunnerContext, RunnerContext } from '../runner-context';\nimport { FRAMEWORK_REGISTRY } from '../frameworks/registry';\nimport { abortNoFrameworkDetected } from '../shared/abort-no-framework';\nimport {\n SETUP_REPORT_FILE,\n WIZARD_DEFAULT_AIO_LOGS_FLAG_KEY,\n WIZARD_INTERACTION_EVENT_NAME,\n} from '@shared/constants';\nimport { requestDeepLink } from '@utils/provisioning';\nimport { openTrackedLink, withUtm } from '@utils/links';\nimport type { HostResolution } from '@shared/host-resolution';\nimport { getDetectedWarehouseSources } from '../warehouse-sources/detect';\nimport { buildCodingAgentPrompt } from './handoff.js';\nimport { EVENT_PLAN_FILE } from './constants.js';\nimport { WAREHOUSE_SOURCE_SCOPE_ADDITIONS } from '../oauth/program-scopes';\n\nconst DASHBOARD_DEEP_LINK_KEY = 'dashboardDeepLink';\n\nconst WAREHOUSE_SOURCES_DOCS_URL =\n 'https://posthog.com/docs/data-warehouse/sources';\n\n/** Task type of the seeded step below, matched against the drain's result. */\nconst WAREHOUSE_SEED_TASK_TYPE = 'warehouse';\n\nfunction resolveContinueUrl(\n sess: ProgramSession,\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 * How many detected sources the seeded step is allowed to collect credentials\n * for.\n *\n * The step's cost to the user is one credential prompt per source, and the\n * wizard knows the count at seed time: detection keys off dependency and\n * `.env` key names, so an ordinary app can match a dozen sources it has no\n * intention of importing. Offering all of them asks a person to agree, up\n * front, to an interrogation whose length they cannot see — and the runs\n * offered more than a handful answer none of the prompts at all, while the\n * short ones are where every connected source comes from.\n *\n * So the step takes the first few and the outro carries them all as links,\n * which is the same trade {@link WAREHOUSE_LINK_LIMIT} already makes for a\n * list too long to read. Ordering is the registry's, which groups databases\n * ahead of the API-key SaaS that inflates the tail.\n */\nconst WAREHOUSE_SEED_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 end the run\n * — costing the user the success outro and the post-outro MCP step 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. Every detected source is listed,\n * including the ones the run's own warehouse step was given: that step reports\n * success once it has handled each source somehow, and handing the user a link\n * for one whose credentials never arrived is one of those outcomes. Nothing in\n * the run records which sources ended up connected, so the deterministic list\n * stays complete rather than dropping a source on the step's status.\n */\nfunction buildWarehouseNextSteps(\n sess: ProgramSession,\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: ProgramSession): 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. Capped at\n * {@link WAREHOUSE_SEED_LIMIT} sources; {@link buildWarehouseNextSteps} hands\n * every detected source over as an outro link.\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 const offered = sources.slice(0, WAREHOUSE_SEED_LIMIT);\n const deferred = sources.length - offered.length;\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 // What the step was actually given, which is what its outcome is a rate\n // of. The two counts above stay the detection totals they have always\n // been, so the detection trend reads across this change.\n warehouse_offered_count: offered.length,\n });\n }\n return [\n {\n type: WAREHOUSE_SEED_TASK_TYPE,\n inputs: {\n sources: offered.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 ...(deferred > 0\n ? [\n `We found ${deferred} more we can connect. Those are listed with a link each at the end, so this step stays short.`,\n ]\n : []),\n \"You can select [Skip] if you'd like to do this later in PostHog.\",\n ],\n items: offered.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 { EVENT_PLAN_FILE } from './constants.js';\n\nexport const config: ProgramConfig = {\n description: 'Set up PostHog SDK integration',\n id: 'posthog-integration',\n agentFlow: 'integration-v2',\n handoffNotebook: true,\n eventPlanFile: EVENT_PLAN_FILE,\n onReady: (ctx) => detectPostHogIntegration(ctx),\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 // When detection finds data sources, the orchestrator's warehouse task\n // creates them through `external-data-sources-create`. Without the\n // warehouse pair that call 403s on a token the user already granted.\n oauthScopeAdditions: [...WAREHOUSE_SOURCE_SCOPE_ADDITIONS],\n\n seedTasks: warehouseSeedTasks,\n\n // Kill switch over the shipped default: only an explicit 'false' excludes,\n // so a failed flag fetch keeps AI Observability and Logs in the run.\n excludedTaskTypes: (flags) =>\n flags[WIZARD_DEFAULT_AIO_LOGS_FLAG_KEY] === 'false'\n ? ['ai-observability', 'logs']\n : [],\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 (\n session: ProgramSession,\n runner: CiRunnerContext,\n ): Promise<void> => {\n await scopeInstallDirToProject(session, runner);\n\n const integration = await detectFramework(session.installDir);\n if (!integration) {\n abortNoFrameworkDetected();\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 noteDetectedFramework(session, frameworkConfig, context, runner.log);\n },\n\n run: async (\n session: ProgramSession,\n runner: RunnerContext,\n ): Promise<ProgramRun> => {\n const config = session.frameworkConfig;\n if (!config) {\n abortNoFrameworkDetected();\n }\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 runner.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 runner.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 // The same kill switch the orchestrator applies via excludedTaskTypes,\n // gated here for linear/composed runs, which assemble their own prompt —\n // without this, disabling the flag would not reach this path and the\n // prompt would still instruct installing the AIO and Logs skills. Only an\n // explicit 'false' excludes, so a failed flag fetch keeps the default.\n const wizardFlags = await analytics.getAllFlagsForWizard();\n const skillCategoryInstruction =\n wizardFlags[WIZARD_DEFAULT_AIO_LOGS_FLAG_KEY] !== 'false'\n ? `Choose a skill from the \\`integration\\` category that matches this project's framework. Start with this framework skill; load the AI Observability and Logs skills when its workflow calls for them, and follow each installed skill's own steps to completion — framework first, then AI Observability, then Logs — before verification and the setup report. Both are included by default where applicable; the skills define applicability and how to report skipped work. These three categories — \\`integration\\`, \\`ai-observability\\`, \\`logs\\` — are the only ones this run uses. Do NOT load or install skills from any other category (llm-analytics, error-tracking, feature-flags, audit, etc.) — those are handled separately. In particular, \\`ai-observability\\` is the category for AI Observability; do not substitute \\`llm-analytics\\`.`\n : `Choose a skill from the \\`integration\\` category that matches this project's framework. The \\`integration\\` category is the ONLY one this run uses. Do NOT load or install skills from any other category (ai-observability, logs, llm-analytics, error-tracking, feature-flags, audit, etc.) — those are handled separately. If the installed skill's workflow contains an \"AI Observability and Logs\" section, skip that entire section: this run excludes both products.`;\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 // 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) with category: \"integration\" to see available framework skills.\n If the tool fails, emit: ${\n AgentSignals.ERROR_MCP_MISSING\n } Could not load skill menu and halt.\n\n ${skillCategoryInstruction}\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 './upload-environment-variables/upload-step'\n );\n const uploadedEnvVars = await uploadEnvironmentVariablesStep(\n envVars,\n {\n integration: config.metadata.integration,\n installDir: sess.installDir,\n runner,\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 buildOutroNextSteps: (sess, credentials) =>\n buildWarehouseNextSteps(sess, credentials.host, credentials.projectId),\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 // `buildOutroNextSteps` carries the orchestrated case.\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"],"mappings":"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,GAC7C,WAGH;IAEJ;CAED,SAAS;EACP,sBACE;EACF,qBACE;EACF,4BAA4B,YAAY;AA0CtC,UArCc;IACZ,oBALyB,QAAQ,iBAC/B,sBAAsB,QAAQ,eAAe,GAC7C;IAIF;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACD;;EAIJ;CAED,IAAI;EACF,gBAAgB;EAChB,0BAA0B;EAC1B,kBAAkB,YAAY;AAI5B,UAAO;IACL;IACA,wCALyB,QAAQ,iBAC/B,sBAAsB,QAAQ,eAAe,GAC7C;IAIF;IACA;IACD;;EAEH,yBAAyB;GACvB;GACA;GACA;GACD;EACF;CACF;;;AC5HD,MAAa,+BACX;CACE,UAAU;EACR,MAAM;EACN,aAAA;EACA,SAAS;EACV;CAED,WAAW;EACT,aAAa;EACb,oBAAoB;EACpB,iBAAiB;EACjB,kBAAkB,KAAA;EAClB,sBAAsB;EACtB,QAAQ,OAAO,YAAY;AAEzB,UAAO,CAAC,CADY,MAAM,kBAAkB,QAAQ;;EAGvD;CAED,aAAa;EACX,iBAAiB;EACjB,aAAa,QAAgB,UAAkB;GAC7C,uBAAuB;GACvB,cAAc;GACf;EACF;CAED,WAAW,EACT,gBAAgB,EAAE,GACnB;CAED,SAAS;EACP,sBACE;EACF,qBACE;EACF,iCAAiC,CAC/B,uGACD;EACF;CAED,IAAI;EACF,gBAAgB;EAChB,0BAA0B;EAC1B,uBAAuB;GACrB;GACA;GACA;GACA;GACA;GACD;EACD,yBAAyB;GACvB;GACA;GACA;GACA;GACA;GACD;EACF;CACF;;;ACxDH,MAAM,uBAAuB;;;;;;;;AAS7B,MAAa,qBAAqB;CAChC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;;;;;AAMD,SAAgB,uBACd,SACQ;CACR,MAAM,WAAW,yBAAyB,QAAQ;AAClD,KAAI,SAAS,SAAS,EACpB,QAAO,SAAS,GAAG;AAErB,QAAO;;;;;A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"}
|