@posthog/wizard 2.34.0 → 2.36.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/dist/{add-mcp-server-to-clients-BjH4z7gH.js → add-mcp-server-to-clients-D5e3JbUC.js} +6 -6
  2. package/dist/{add-mcp-server-to-clients-BjH4z7gH.js.map → add-mcp-server-to-clients-D5e3JbUC.js.map} +1 -1
  3. package/dist/{agent-interface-BcUv1qeh.js → agent-interface-CPn9pZ8j.js} +204 -175
  4. package/dist/agent-interface-CPn9pZ8j.js.map +1 -0
  5. package/dist/{agent-runner-8g_pDAVs.js → agent-runner-Cic1uZZ8.js} +58 -41
  6. package/dist/agent-runner-Cic1uZZ8.js.map +1 -0
  7. package/dist/{analytics-DQ8IS1Hu.js → analytics-Be_wRgxD.js} +2 -2
  8. package/dist/{analytics-DQ8IS1Hu.js.map → analytics-Be_wRgxD.js.map} +1 -1
  9. package/dist/{api-EghEV_u9.js → api-C_R_ybiA.js} +3 -3
  10. package/dist/{api-EghEV_u9.js.map → api-C_R_ybiA.js.map} +1 -1
  11. package/dist/bin.js +297 -68
  12. package/dist/bin.js.map +1 -1
  13. package/dist/{ci-install-ouGSf4zp.js → ci-install-B0BHTkGI.js} +5 -5
  14. package/dist/ci-install-B0BHTkGI.js.map +1 -0
  15. package/dist/{debug-Cn4L5Ype.js → debug-BpWrz3hX.js} +3 -4
  16. package/dist/debug-BpWrz3hX.js.map +1 -0
  17. package/dist/{debug-BM7yop-T.js → debug-DJS2KPGb.js} +1 -1
  18. package/dist/{defaults-DII5CAog.js → defaults-UswXMiTx.js} +1 -1
  19. package/dist/{defaults-DII5CAog.js.map → defaults-UswXMiTx.js.map} +1 -1
  20. package/dist/{env-api-key-MlzJYAvt.js → env-api-key-Db-mNPK2.js} +1 -1
  21. package/dist/{env-api-key-MlzJYAvt.js.map → env-api-key-Db-mNPK2.js.map} +1 -1
  22. package/dist/{environment-D2WUIm8o.js → environment-Dc6VTWyK.js} +3 -3
  23. package/dist/{environment-D2WUIm8o.js.map → environment-Dc6VTWyK.js.map} +1 -1
  24. package/dist/{file-utils-CdQn6073.js → file-utils-Buj9-umf.js} +2 -2
  25. package/dist/{file-utils-CdQn6073.js.map → file-utils-Buj9-umf.js.map} +1 -1
  26. package/dist/{headless-ui-CSqtmW-d.js → headless-ui-BplqZRcO.js} +2 -2
  27. package/dist/{headless-ui-CSqtmW-d.js.map → headless-ui-BplqZRcO.js.map} +1 -1
  28. package/dist/host-resolution-BD6TcZG0.js +115 -0
  29. package/dist/host-resolution-BD6TcZG0.js.map +1 -0
  30. package/dist/{interactive-CFGcWw43.js → interactive-BspTioP_.js} +2 -2
  31. package/dist/{interactive-CFGcWw43.js.map → interactive-BspTioP_.js.map} +1 -1
  32. package/dist/{mcp-prompt-streaming-XZSpcXkG.js → mcp-prompt-streaming-BCNzyL12.js} +5 -5
  33. package/dist/mcp-prompt-streaming-BCNzyL12.js.map +1 -0
  34. package/dist/{non-interactive-D6eksWIw.js → non-interactive-CFikUAzO.js} +2 -2
  35. package/dist/{non-interactive-D6eksWIw.js.map → non-interactive-CFikUAzO.js.map} +1 -1
  36. package/dist/{package-manager-Dozr4x6K.js → package-manager-L7gsAbE0.js} +2 -2
  37. package/dist/{package-manager-Dozr4x6K.js.map → package-manager-L7gsAbE0.js.map} +1 -1
  38. package/dist/{playground-BB2O8GyY.js → playground-Bl2iPxdt.js} +7 -7
  39. package/dist/{playground-BB2O8GyY.js.map → playground-Bl2iPxdt.js.map} +1 -1
  40. package/dist/{posthog-DU6JXG00.js → posthog-BrLFkaji.js} +1 -1
  41. package/dist/{posthog-DU6JXG00.js.map → posthog-BrLFkaji.js.map} +1 -1
  42. package/dist/{posthog-integration-C3m_uR5A.js → posthog-integration-B6pTHVcn.js} +32 -17
  43. package/dist/posthog-integration-B6pTHVcn.js.map +1 -0
  44. package/dist/{provisioning-wMzPfaaP.js → provisioning-C9ts56R5.js} +28 -9
  45. package/dist/provisioning-C9ts56R5.js.map +1 -0
  46. package/dist/{registry-BfTeAX2z.js → registry-DFazVUSE.js} +4 -4
  47. package/dist/{registry-BfTeAX2z.js.map → registry-DFazVUSE.js.map} +1 -1
  48. package/dist/{setup-utils-B0oz3raQ.js → setup-utils-BxdW2R0r.js} +56 -29
  49. package/dist/setup-utils-BxdW2R0r.js.map +1 -0
  50. package/dist/{start-tui-B9qDcoGA.js → start-tui-oGWfxdTd.js} +404 -35
  51. package/dist/start-tui-oGWfxdTd.js.map +1 -0
  52. package/dist/{steps-BhERMRRI.js → steps-O0v5UU1G.js} +7 -7
  53. package/dist/{steps-BhERMRRI.js.map → steps-O0v5UU1G.js.map} +1 -1
  54. package/dist/{store-J2Rv955W.js → store-Di9OvMql.js} +55 -4
  55. package/dist/store-Di9OvMql.js.map +1 -0
  56. package/dist/{task-stream-CPjpHFhI.js → task-stream-DkbGqxZv.js} +3 -3
  57. package/dist/{task-stream-CPjpHFhI.js.map → task-stream-DkbGqxZv.js.map} +1 -1
  58. package/dist/{telemetry-BTLJ-YnG.js → telemetry-D5WQ4-Ic.js} +3 -3
  59. package/dist/{telemetry-BTLJ-YnG.js.map → telemetry-D5WQ4-Ic.js.map} +1 -1
  60. package/dist/{terminal-UwqFnPrL.js → terminal-Bd-k7pCi.js} +14 -14
  61. package/dist/{terminal-UwqFnPrL.js.map → terminal-Bd-k7pCi.js.map} +1 -1
  62. package/dist/urls-DpTCPWLD.js +67 -0
  63. package/dist/urls-DpTCPWLD.js.map +1 -0
  64. package/dist/{wizard-abort-BAB8yvGF.js → wizard-abort-C1t9M-JN.js} +1 -1
  65. package/dist/{wizard-abort-DqeMgCVr.js → wizard-abort-t41wO4Bh.js} +4 -4
  66. package/dist/{wizard-abort-DqeMgCVr.js.map → wizard-abort-t41wO4Bh.js.map} +1 -1
  67. package/dist/{wizard-session-CN55LYyZ.js → wizard-session-CqihOtk3.js} +7 -1
  68. package/dist/wizard-session-CqihOtk3.js.map +1 -0
  69. package/dist/{wizard-session-BKEdX9mO.js → wizard-session-xzqycI7i.js} +1 -1
  70. package/package.json +1 -1
  71. package/dist/agent-interface-BcUv1qeh.js.map +0 -1
  72. package/dist/agent-runner-8g_pDAVs.js.map +0 -1
  73. package/dist/ci-install-ouGSf4zp.js.map +0 -1
  74. package/dist/debug-Cn4L5Ype.js.map +0 -1
  75. package/dist/mcp-prompt-streaming-XZSpcXkG.js.map +0 -1
  76. package/dist/posthog-integration-C3m_uR5A.js.map +0 -1
  77. package/dist/provisioning-wMzPfaaP.js.map +0 -1
  78. package/dist/setup-utils-B0oz3raQ.js.map +0 -1
  79. package/dist/start-tui-B9qDcoGA.js.map +0 -1
  80. package/dist/store-J2Rv955W.js.map +0 -1
  81. package/dist/urls-DAVzgHGZ.js +0 -35
  82. package/dist/urls-DAVzgHGZ.js.map +0 -1
  83. package/dist/wizard-session-CN55LYyZ.js.map +0 -1
package/dist/bin.js CHANGED
@@ -1,23 +1,25 @@
1
1
  #!/usr/bin/env node
2
- import { I as POSTHOG_DOCS_URL, Q as WIZARD_USER_AGENT, a as getLogFilePath, et as getSkillsBaseUrl, h as LoggingUI, m as setUI, p as getUI, r as debug, s as logToFile, tt as VERSION } from "./debug-Cn4L5Ype.js";
3
- import { t as analytics } from "./analytics-DQ8IS1Hu.js";
4
- import { r as setEntryCommand } from "./telemetry-BTLJ-YnG.js";
5
- import { n as isUsingTypeScript } from "./setup-utils-B0oz3raQ.js";
6
- import { a as getUiHostFromHost, n as getCloudUrlFromRegion } from "./urls-DAVzgHGZ.js";
7
- import { o as handleApiError } from "./api-EghEV_u9.js";
8
- import "./wizard-session-CN55LYyZ.js";
9
- import { r as runCleanups } from "./wizard-abort-DqeMgCVr.js";
10
- import { n as isNonInteractiveEnvironment } from "./environment-D2WUIm8o.js";
11
- import { D as AUDIT_REPORT_FILE, E as AUDIT_CHECKS_KEY, T as AUDIT_CHECKS_FILE, _ as SETUP_REPORT_FILE, b as fetchSkillMenu, f as AgentSignals, l as recoverOrphanedSettingsBackups, v as WIZARD_TOOL_NAMES } from "./agent-interface-BcUv1qeh.js";
12
- import { i as SPINNER_MESSAGE } from "./registry-BfTeAX2z.js";
13
- import { _ as parseRequirementsTxt, a as StatusPeekTrigger, c as isClearBlock, d as Colors, f as Icons, g as parsePyprojectToml, h as parsePipfile, i as PRODUCT_SUITE_BLOCK, n as FUNNEL_BLOCK, p as HEALTH_CHECK_STEP, r as LINE_CHART_BLOCK, t as posthogIntegrationConfig } from "./posthog-integration-C3m_uR5A.js";
14
- import { n as safeReadFile, r as walkProjectFiles, t as IGNORED_DIRS } from "./file-utils-CdQn6073.js";
15
- import { n as readApiKeyFromEnv } from "./env-api-key-MlzJYAvt.js";
2
+ import { $ as getSkillsBaseUrl, I as POSTHOG_DOCS_URL, Z as WIZARD_USER_AGENT, a as getLogFilePath, et as VERSION, h as LoggingUI, j as Integration, m as setUI, p as getUI, r as debug, s as logToFile } from "./debug-BpWrz3hX.js";
3
+ import { t as analytics } from "./analytics-Be_wRgxD.js";
4
+ import { r as setEntryCommand } from "./telemetry-D5WQ4-Ic.js";
5
+ import { n as isUsingTypeScript } from "./setup-utils-BxdW2R0r.js";
6
+ import { o as getUiHostFromHost } from "./urls-DpTCPWLD.js";
7
+ import { t as HostResolution } from "./host-resolution-BD6TcZG0.js";
8
+ import { o as handleApiError } from "./api-C_R_ybiA.js";
9
+ import "./wizard-session-CqihOtk3.js";
10
+ import { r as runCleanups } from "./wizard-abort-t41wO4Bh.js";
11
+ import { n as isNonInteractiveEnvironment } from "./environment-Dc6VTWyK.js";
12
+ import { D as AUDIT_CHECKS_KEY, E as AUDIT_CHECKS_FILE, O as AUDIT_REPORT_FILE, f as AgentSignals, l as recoverOrphanedSettingsBackups, v as SETUP_REPORT_FILE, x as fetchSkillMenu, y as WIZARD_TOOL_NAMES } from "./agent-interface-CPn9pZ8j.js";
13
+ import { n as runAgent, r as authenticate } from "./agent-runner-Cic1uZZ8.js";
14
+ import { i as SPINNER_MESSAGE, t as FRAMEWORK_REGISTRY } from "./registry-DFazVUSE.js";
15
+ import { _ as gatherFrameworkContext, a as LINE_CHART_BLOCK, b as parseRequirementsTxt, g as detectProjectsWithAgent, h as HEALTH_CHECK_STEP, i as FUNNEL_BLOCK, m as Icons, n as integrationRunStep, o as PRODUCT_SUITE_BLOCK, p as Colors, r as posthogIntegrationConfig, s as StatusPeekTrigger, u as isClearBlock, v as parsePipfile, y as parsePyprojectToml } from "./posthog-integration-B6pTHVcn.js";
16
+ import { n as safeReadFile, r as walkProjectFiles, t as IGNORED_DIRS } from "./file-utils-Buj9-umf.js";
17
+ import { n as readApiKeyFromEnv } from "./env-api-key-Db-mNPK2.js";
16
18
  import { satisfies } from "semver";
17
19
  import yargs from "yargs";
18
20
  import { hideBin } from "yargs/helpers";
19
21
  import fs, { existsSync, readFileSync, readdirSync, statSync } from "fs";
20
- import path, { join, relative } from "path";
22
+ import path, { join, relative, resolve } from "path";
21
23
  import * as os from "node:os";
22
24
  import * as path$1 from "node:path";
23
25
  import { spawnSync } from "node:child_process";
@@ -141,6 +143,11 @@ const GLOBAL_OPTIONS = {
141
143
  type: "boolean",
142
144
  hidden: true
143
145
  },
146
+ "base-url": {
147
+ describe: "Override the PostHog base URL (e.g. http://localhost:8010), bypassing region resolution. Pins the API host, cloud URL, and OAuth server.\nenv: POSTHOG_WIZARD_BASE_URL",
148
+ type: "string",
149
+ hidden: true
150
+ },
144
151
  benchmark: {
145
152
  default: false,
146
153
  describe: "Run in benchmark mode with per-phase token tracking\nenv: POSTHOG_WIZARD_BENCHMARK",
@@ -222,14 +229,15 @@ function runProvision(argv) {
222
229
  email: argv.email,
223
230
  region: argv.region.toUpperCase(),
224
231
  name: argv.name ?? "",
232
+ baseUrl: argv.baseUrl,
225
233
  jsonMode
226
234
  });
227
235
  }
228
- async function provision({ email, region, name, jsonMode }) {
236
+ async function provision({ email, region, name, baseUrl, jsonMode }) {
229
237
  try {
230
- const { provisionNewAccount } = await import("./provisioning-wMzPfaaP.js").then((n) => n.n);
238
+ const { provisionNewAccount } = await import("./provisioning-C9ts56R5.js").then((n) => n.n);
231
239
  if (!jsonMode) getUI().log.info(`Provisioning account for ${email} in ${region}...`);
232
- emitResult(await provisionNewAccount(email, name, region), jsonMode);
240
+ emitResult(await provisionNewAccount(email, name, region, { baseUrl }), jsonMode);
233
241
  process.exit(0);
234
242
  } catch (error) {
235
243
  emitError(error, jsonMode);
@@ -292,22 +300,22 @@ const basicIntegrationCommand = {
292
300
  setEntryCommand("integrate");
293
301
  (async () => {
294
302
  if (isHeadless(argv)) {
295
- const { runHeadlessInstall } = await import("./ci-install-ouGSf4zp.js");
303
+ const { runHeadlessInstall } = await import("./ci-install-B0BHTkGI.js");
296
304
  return runHeadlessInstall(argv);
297
305
  }
298
306
  if (argv.ci) {
299
- const { runCIInstall } = await import("./ci-install-ouGSf4zp.js");
307
+ const { runCIInstall } = await import("./ci-install-B0BHTkGI.js");
300
308
  return runCIInstall(argv);
301
309
  }
302
310
  if (isNonInteractiveEnvironment()) {
303
- const { failNonInteractive } = await import("./non-interactive-D6eksWIw.js");
311
+ const { failNonInteractive } = await import("./non-interactive-CFikUAzO.js");
304
312
  return failNonInteractive();
305
313
  }
306
314
  if (argv.playground) {
307
- const { runPlayground } = await import("./playground-BB2O8GyY.js");
315
+ const { runPlayground } = await import("./playground-Bl2iPxdt.js");
308
316
  return runPlayground();
309
317
  }
310
- const { runInteractive } = await import("./interactive-CFGcWw43.js");
318
+ const { runInteractive } = await import("./interactive-BspTioP_.js");
311
319
  runInteractive(argv);
312
320
  })();
313
321
  }
@@ -1632,17 +1640,17 @@ const auditRun = async (session) => {
1632
1640
  const baseRun = typeof baseConfig.run === "function" ? await baseConfig.run(session) : baseConfig.run;
1633
1641
  return {
1634
1642
  ...baseRun,
1635
- buildOutroData: (sess, _credentials, cloudRegion) => {
1636
- const cloudUrl = cloudRegion ? getCloudUrlFromRegion(cloudRegion) : void 0;
1637
- const continueUrl = sess.signup && cloudUrl ? `${cloudUrl}/products?source=wizard` : void 0;
1643
+ buildOutroData: (session, _credentials, cloudRegion) => {
1644
+ const cloudUrl = cloudRegion ? HostResolution.fromRegion(cloudRegion, { baseUrl: session.baseUrl }).appHost : void 0;
1645
+ const continueUrl = session.signup && cloudUrl ? `${cloudUrl}/products?source=wizard` : void 0;
1638
1646
  return {
1639
1647
  kind: "success",
1640
1648
  message: baseRun.successMessage,
1641
1649
  reportFile: baseRun.reportFile,
1642
1650
  docsUrl: baseRun.docsUrl,
1643
1651
  continueUrl,
1644
- dashboardUrl: sess.dashboardUrl ?? void 0,
1645
- notebookUrl: sess.notebookUrl ?? void 0
1652
+ dashboardUrl: session.dashboardUrl ?? void 0,
1653
+ notebookUrl: session.notebookUrl ?? void 0
1646
1654
  };
1647
1655
  }
1648
1656
  };
@@ -1798,7 +1806,7 @@ Project context:
1798
1806
  - PostHog Host: ${ctx.host}
1799
1807
  `,
1800
1808
  buildOutroData: (sess, _credentials, cloudRegion) => {
1801
- const cloudUrl = cloudRegion ? getCloudUrlFromRegion(cloudRegion) : void 0;
1809
+ const cloudUrl = cloudRegion ? HostResolution.fromRegion(cloudRegion, { baseUrl: sess.baseUrl }).appHost : void 0;
1802
1810
  return {
1803
1811
  kind: "success",
1804
1812
  message: "Your events audit was successful",
@@ -3270,6 +3278,48 @@ const errorTrackingUploadSourceMapsConfig = {
3270
3278
  * PostHog-side flags (`product-autonomy`, `signals-scout`) are unchanged by
3271
3279
  * the wizard-side "self-driving" rename.
3272
3280
  */
3281
+ /** frameworkContext key holding the deterministic PostHog-presence result. */
3282
+ const POSTHOG_PRESENT_KEY = "postHogPresent";
3283
+ /**
3284
+ * frameworkContext key holding the repo-relative path of the project the user
3285
+ * picked on the integration-detect screen ("." for the repo root). The
3286
+ * integrate-run phase scopes its install dir to this so a monorepo integrates
3287
+ * into the chosen sub-app, not the root.
3288
+ */
3289
+ const SELF_DRIVING_INTEGRATE_PATH_KEY = "selfDrivingIntegratePath";
3290
+ const POSTHOG_PACKAGE_RE = /(^|["'\s/=])posthog/im;
3291
+ /**
3292
+ * Deterministic, offline check: does the project already have a PostHog SDK?
3293
+ * Scans the common dependency manifests at the install dir for a `posthog`
3294
+ * package — the same signal the agentic detector reports as `hasPostHog`, but
3295
+ * instant and credential-free. Drives whether self-driving asks to integrate
3296
+ * first ("not found") or proceeds straight to setup ("found").
3297
+ */
3298
+ function detectPostHogPresent(installDir) {
3299
+ const manifests = [
3300
+ "package.json",
3301
+ "requirements.txt",
3302
+ "pyproject.toml",
3303
+ "Pipfile",
3304
+ "Gemfile",
3305
+ "go.mod",
3306
+ "composer.json",
3307
+ "pubspec.yaml"
3308
+ ];
3309
+ for (const dir of [
3310
+ ".",
3311
+ "app",
3312
+ "frontend",
3313
+ "backend"
3314
+ ]) for (const name of manifests) {
3315
+ const path = join(installDir, dir, name);
3316
+ if (!existsSync(path)) continue;
3317
+ try {
3318
+ if (POSTHOG_PACKAGE_RE.test(readFileSync(path, "utf8"))) return true;
3319
+ } catch {}
3320
+ }
3321
+ return false;
3322
+ }
3273
3323
  /**
3274
3324
  * `[ABORT] <reason>` cases the self-driving skill can emit. The
3275
3325
  * reason strings are part of the skill contract — the context-mill
@@ -3330,9 +3380,110 @@ function detectSelfDrivingPrerequisites(session, setFrameworkContext) {
3330
3380
  });
3331
3381
  return;
3332
3382
  }
3383
+ setFrameworkContext(POSTHOG_PRESENT_KEY, detectPostHogPresent(installDir));
3384
+ }
3385
+ //#endregion
3386
+ //#region src/lib/programs/self-driving/detect-agentic.ts
3387
+ /**
3388
+ * Agentic (Haiku) detection for self-driving's integration phase.
3389
+ *
3390
+ * Mirrors source-maps: the integration-detect screen runs `detectSelfDriving-
3391
+ * IntegrationProjects` (the shared Haiku detector with the integration framework
3392
+ * targets), shows a project map, and the user picks one. This file supplies the
3393
+ * targets, maps the result back to `Integration`s, and classifies each project
3394
+ * as instrumentable (a framework the wizard supports that doesn't already have
3395
+ * PostHog). The screen writes the choice to the session; `prepSelfDriving-
3396
+ * Integration` then gathers the chosen project's framework context before the
3397
+ * integration agent runs (the runner scopes the install dir).
3398
+ */
3399
+ /** Integration framework targets for the agentic detector (id → display name). */
3400
+ const INTEGRATION_TARGETS = Object.entries(FRAMEWORK_REGISTRY).map(([id, config]) => ({
3401
+ id,
3402
+ name: config.metadata.name
3403
+ }));
3404
+ const INTEGRATION_IDS = new Set(Object.values(Integration));
3405
+ function classify(integration, hasPostHog) {
3406
+ if (integration == null) return {
3407
+ instrumentable: false,
3408
+ reason: "Not a framework the wizard can set up yet"
3409
+ };
3410
+ if (hasPostHog) return {
3411
+ instrumentable: false,
3412
+ reason: "Already has the PostHog SDK"
3413
+ };
3414
+ return { instrumentable: true };
3415
+ }
3416
+ /** Map a generic detection report into classified integration projects. */
3417
+ function toIntegrationReport(report) {
3418
+ return {
3419
+ repoType: report.repoType,
3420
+ projects: report.projects.map((p) => {
3421
+ const integration = p.targetId && INTEGRATION_IDS.has(p.targetId) ? p.targetId : null;
3422
+ return {
3423
+ path: p.path,
3424
+ framework: p.framework,
3425
+ integration,
3426
+ hasPostHog: p.hasPostHog,
3427
+ ...classify(integration, p.hasPostHog)
3428
+ };
3429
+ })
3430
+ };
3431
+ }
3432
+ /** Run the Haiku detector over the repo and classify projects for integration. */
3433
+ async function detectSelfDrivingIntegrationProjects(session, onEvent) {
3434
+ return toIntegrationReport(await detectProjectsWithAgent(session, {
3435
+ targets: INTEGRATION_TARGETS,
3436
+ purpose: "set up a PostHog SDK integration",
3437
+ onEvent
3438
+ }));
3439
+ }
3440
+ /**
3441
+ * Prepare the integration phase after the user picked a project on the
3442
+ * integration-detect screen (which set `session.integration`, `frameworkConfig`,
3443
+ * and the chosen path). Scopes `installDir` to the chosen project — so a
3444
+ * monorepo integrates into the picked sub-app — and gathers that project's
3445
+ * framework context, mirroring posthog-integration's `ciPreRun`. Used as the
3446
+ * integrate-run step's `onRunPrep`.
3447
+ */
3448
+ async function prepSelfDrivingIntegration(session) {
3449
+ const frameworkConfig = session.frameworkConfig;
3450
+ if (!frameworkConfig) return;
3451
+ const context = await gatherFrameworkContext(frameworkConfig, {
3452
+ installDir: session.installDir,
3453
+ debug: session.debug,
3454
+ default: false,
3455
+ signup: session.signup,
3456
+ localMcp: session.localMcp,
3457
+ ci: session.ci,
3458
+ benchmark: session.benchmark,
3459
+ yaraReport: session.yaraReport
3460
+ });
3461
+ for (const [key, value] of Object.entries(context)) if (!(key in session.frameworkContext)) session.frameworkContext[key] = value;
3333
3462
  }
3334
3463
  //#endregion
3335
3464
  //#region src/lib/programs/self-driving/steps.ts
3465
+ /**
3466
+ * Self-driving program step list.
3467
+ *
3468
+ * detect → intro → integration-check → health-check → auth → integrate-detect →
3469
+ * integrate-run → self-driving-handoff → run → outro. A deterministic check in
3470
+ * `detect` decides whether PostHog is already in the project: found → the
3471
+ * integration screens are skipped and the integrate-run phase never shows; not
3472
+ * found → integration-check reports it and the only action sets up PostHog.
3473
+ * After auth, `integrate-detect` runs the Haiku detector and has the user pick
3474
+ * which project to set PostHog up in (a monorepo can have several);
3475
+ * `integrate-run` then runs the real integration program's agent (its own task
3476
+ * list) in that project. `self-driving-handoff` then bridges to Self-driving
3477
+ * ("PostHog is installed — now set up Self-driving") before the Self-driving
3478
+ * run. No keep-skills step: the setup skill is transient, so postRun removes it.
3479
+ */
3480
+ /** True once detection found PostHog already present in the project. */
3481
+ const postHogPresent = (session) => session.frameworkContext[POSTHOG_PRESENT_KEY] === true;
3482
+ /** Absolute dir to integrate into: the picked sub-app, else the repo root. */
3483
+ const integrationDir = (session) => {
3484
+ const rel = session.frameworkContext[SELF_DRIVING_INTEGRATE_PATH_KEY];
3485
+ return typeof rel === "string" && rel !== "." ? resolve(session.installDir, rel) : session.installDir;
3486
+ };
3336
3487
  const SELF_DRIVING_PROGRAM = [
3337
3488
  {
3338
3489
  id: "detect",
@@ -3345,6 +3496,14 @@ const SELF_DRIVING_PROGRAM = [
3345
3496
  screenId: "self-driving-intro",
3346
3497
  gate: (session) => session.setupConfirmed
3347
3498
  },
3499
+ {
3500
+ id: "integration-check",
3501
+ label: "Integration",
3502
+ screenId: "self-driving-integration-check",
3503
+ show: (session) => !postHogPresent(session) && session.integrate === null,
3504
+ isComplete: (session) => postHogPresent(session) || session.integrate !== null,
3505
+ gate: (session) => postHogPresent(session) || session.integrate !== null
3506
+ },
3348
3507
  HEALTH_CHECK_STEP,
3349
3508
  {
3350
3509
  id: "auth",
@@ -3352,6 +3511,28 @@ const SELF_DRIVING_PROGRAM = [
3352
3511
  screenId: "auth",
3353
3512
  isComplete: (session) => session.credentials !== null
3354
3513
  },
3514
+ {
3515
+ id: "integrate-detect",
3516
+ label: "Detecting",
3517
+ screenId: "self-driving-integration-detect",
3518
+ show: (session) => session.integrate === true && session.integration == null,
3519
+ isComplete: (session) => session.integration != null
3520
+ },
3521
+ {
3522
+ ...integrationRunStep,
3523
+ id: "integrate-run",
3524
+ onRunPrep: prepSelfDrivingIntegration,
3525
+ targetDir: integrationDir,
3526
+ show: (session) => session.integrate === true,
3527
+ isComplete: (session) => session.completedRuns.includes("integrate-run")
3528
+ },
3529
+ {
3530
+ id: "self-driving-handoff",
3531
+ label: "Ready",
3532
+ screenId: "self-driving-handoff",
3533
+ show: (session) => session.integrate === true,
3534
+ isComplete: (session) => session.selfDrivingHandoffConfirmed
3535
+ },
3355
3536
  {
3356
3537
  id: "run",
3357
3538
  label: "Self-driving",
@@ -3373,6 +3554,10 @@ const SELF_DRIVING_PROGRAM = [
3373
3554
  * every step (which MCP tools to call, which sources/scouts apply, how
3374
3555
  * to verify); this prompt carries the order, the wizard-specific
3375
3556
  * mechanics (wizard_ask, abort signals), and the project URLs.
3557
+ *
3558
+ * Integration (when the project has no PostHog yet) runs as a separate phase
3559
+ * before this — the real integration program, with its own screens and task
3560
+ * list — so this prompt only covers the Self-driving steps.
3376
3561
  */
3377
3562
  function buildSelfDrivingPrompt(ctx) {
3378
3563
  const uiHost = getUiHostFromHost(ctx.host).replace(/\/$/, "");
@@ -3836,24 +4021,25 @@ const mcpAddCommand = {
3836
4021
  function runMcpAdd(argv) {
3837
4022
  const features = parseFeatures(argv.features);
3838
4023
  (async () => {
3839
- const { readApiKeyFromEnv } = await import("./env-api-key-MlzJYAvt.js").then((n) => n.t);
4024
+ const { readApiKeyFromEnv } = await import("./env-api-key-Db-mNPK2.js").then((n) => n.t);
3840
4025
  const apiKey = argv.apiKey || readApiKeyFromEnv();
3841
4026
  const debug = argv.debug;
3842
4027
  const localMcp = argv.local;
3843
4028
  try {
3844
- const { startTUI } = await import("./start-tui-B9qDcoGA.js");
3845
- const { buildSession } = await import("./wizard-session-BKEdX9mO.js");
4029
+ const { startTUI } = await import("./start-tui-oGWfxdTd.js");
4030
+ const { buildSession } = await import("./wizard-session-xzqycI7i.js");
3846
4031
  const tui = startTUI(VERSION, Program.McpAdd);
3847
4032
  tui.store.session = buildSession({
3848
4033
  debug,
3849
4034
  localMcp,
3850
4035
  mcpFeatures: features,
3851
- apiKey
4036
+ apiKey,
4037
+ baseUrl: argv.baseUrl
3852
4038
  });
3853
4039
  } catch (error) {
3854
4040
  if (!isTUIUnavailable(error)) throw error;
3855
4041
  setUI(new LoggingUI());
3856
- const { addMCPServerToClientsStep } = await import("./add-mcp-server-to-clients-BjH4z7gH.js").then((n) => n.r);
4042
+ const { addMCPServerToClientsStep } = await import("./add-mcp-server-to-clients-D5e3JbUC.js").then((n) => n.r);
3857
4043
  await addMCPServerToClientsStep({
3858
4044
  local: localMcp,
3859
4045
  features,
@@ -3892,16 +4078,17 @@ function runMcpRemove(argv) {
3892
4078
  const debug = argv.debug;
3893
4079
  const localMcp = argv.local;
3894
4080
  try {
3895
- const { startTUI } = await import("./start-tui-B9qDcoGA.js");
3896
- const { buildSession } = await import("./wizard-session-BKEdX9mO.js");
4081
+ const { startTUI } = await import("./start-tui-oGWfxdTd.js");
4082
+ const { buildSession } = await import("./wizard-session-xzqycI7i.js");
3897
4083
  const tui = startTUI(VERSION, Program.McpRemove);
3898
4084
  tui.store.session = buildSession({
3899
4085
  debug,
3900
- localMcp
4086
+ localMcp,
4087
+ baseUrl: argv.baseUrl
3901
4088
  });
3902
4089
  } catch {
3903
4090
  setUI(new LoggingUI());
3904
- const { removeMCPServerFromClientsStep } = await import("./add-mcp-server-to-clients-BjH4z7gH.js").then((n) => n.r);
4091
+ const { removeMCPServerFromClientsStep } = await import("./add-mcp-server-to-clients-D5e3JbUC.js").then((n) => n.r);
3905
4092
  await removeMCPServerFromClientsStep({ local: localMcp });
3906
4093
  }
3907
4094
  })();
@@ -3923,12 +4110,13 @@ function runMcpTutorial(argv) {
3923
4110
  const debug = argv.debug;
3924
4111
  const localMcp = argv.local;
3925
4112
  try {
3926
- const { startTUI } = await import("./start-tui-B9qDcoGA.js");
3927
- const { buildSession } = await import("./wizard-session-BKEdX9mO.js");
4113
+ const { startTUI } = await import("./start-tui-oGWfxdTd.js");
4114
+ const { buildSession } = await import("./wizard-session-xzqycI7i.js");
3928
4115
  const tui = startTUI(VERSION, Program.McpTutorial);
3929
4116
  tui.store.session = buildSession({
3930
4117
  debug,
3931
- localMcp
4118
+ localMcp,
4119
+ baseUrl: argv.baseUrl
3932
4120
  });
3933
4121
  } catch (err) {
3934
4122
  setUI(new LoggingUI());
@@ -3965,6 +4153,31 @@ function resolveNoTelemetry(options) {
3965
4153
  //#endregion
3966
4154
  //#region src/lib/runners/run-wizard.ts
3967
4155
  const WIZARD_VERSION = VERSION;
4156
+ /** The session a run step's agent runs in: scoped to the step's target dir
4157
+ * (e.g. a monorepo sub-app) with its own framework context, after any prep.
4158
+ * A step without `targetDir` runs in the live session, unchanged. */
4159
+ async function prepareRunSession(step, live) {
4160
+ const session = step.targetDir ? {
4161
+ ...live,
4162
+ installDir: step.targetDir(live),
4163
+ frameworkContext: { ...live.frameworkContext }
4164
+ } : live;
4165
+ if (step.onRunPrep) await step.onRunPrep(session);
4166
+ return session;
4167
+ }
4168
+ /** Advance one step of a composed run to completion: the auth screen
4169
+ * authenticates (every later run reuses it); a step carrying its own `run`
4170
+ * thunk runs that agent in its dir and is recorded in `completedRuns`; the
4171
+ * host program's own run screen runs `config.run`; any other screen waits for
4172
+ * the user to satisfy `isComplete`. */
4173
+ async function advanceStep(step, store, config) {
4174
+ if (step.screenId === "auth") await authenticate(store.session, config.id);
4175
+ else if (step.run) {
4176
+ await step.run(await prepareRunSession(step, store.session));
4177
+ store.completeRunStep(step.id);
4178
+ } else if (step.screenId === "run") await runAgent(config, await prepareRunSession(step, store.session));
4179
+ else if (step.isComplete) await store.waitUntil(step.isComplete);
4180
+ }
3968
4181
  /**
3969
4182
  * Run a full wizard program in the TUI. Handles the full lifecycle: start TUI,
3970
4183
  * build session, run detection, wait for intro gate, execute the
@@ -3978,10 +4191,10 @@ function runWizard(config, options) {
3978
4191
  (async () => {
3979
4192
  try {
3980
4193
  const installDir = options.installDir || process.cwd();
3981
- const { startTUI } = await import("./start-tui-B9qDcoGA.js");
3982
- const { buildSession, RunPhase } = await import("./wizard-session-BKEdX9mO.js");
3983
- const { TaskStreamPush } = await import("./task-stream-CPjpHFhI.js");
3984
- const { PostHogDestination } = await import("./posthog-DU6JXG00.js");
4194
+ const { startTUI } = await import("./start-tui-oGWfxdTd.js");
4195
+ const { buildSession, RunPhase } = await import("./wizard-session-xzqycI7i.js");
4196
+ const { TaskStreamPush } = await import("./task-stream-DkbGqxZv.js");
4197
+ const { PostHogDestination } = await import("./posthog-BrLFkaji.js");
3985
4198
  tui = startTUI(WIZARD_VERSION, config.id);
3986
4199
  const activeTui = tui;
3987
4200
  const session = buildSession({
@@ -3993,9 +4206,11 @@ function runWizard(config, options) {
3993
4206
  apiKey: options.apiKey,
3994
4207
  projectId: options.projectId,
3995
4208
  email: options.email,
4209
+ baseUrl: options.baseUrl,
3996
4210
  benchmark: options.benchmark,
3997
4211
  yaraReport: options.yaraReport,
3998
- noTelemetry: resolveNoTelemetry(options)
4212
+ noTelemetry: resolveNoTelemetry(options),
4213
+ integrate: options.integrate
3999
4214
  });
4000
4215
  session.programLabel = config.id;
4001
4216
  if (options.skillId) session.skillId = options.skillId;
@@ -4031,15 +4246,22 @@ function runWizard(config, options) {
4031
4246
  process.on("SIGTERM", onSignal);
4032
4247
  await activeTui.store.runReadyHooks();
4033
4248
  await activeTui.store.getGate("intro");
4249
+ await activeTui.store.getGate("integration-check");
4034
4250
  await activeTui.store.getGate("health-check");
4035
4251
  const skipAgent = config.run == null;
4036
- if (skipAgent) {
4037
- const { getOrAskForProjectData } = await import("./setup-utils-B0oz3raQ.js").then((n) => n.r);
4252
+ const shown = (s) => !s.show || s.show(activeTui.store.session);
4253
+ if (config.steps.some((s) => s.run)) for (const step of config.steps) {
4254
+ if (step.screenId === "outro") break;
4255
+ if (shown(step)) await advanceStep(step, activeTui.store, config);
4256
+ }
4257
+ else if (skipAgent) {
4258
+ const { getOrAskForProjectData } = await import("./setup-utils-BxdW2R0r.js").then((n) => n.r);
4038
4259
  const { projectApiKey, host, accessToken, projectId } = await getOrAskForProjectData({
4039
4260
  signup: session.signup,
4040
4261
  ci: session.ci,
4041
4262
  apiKey: session.apiKey,
4042
4263
  projectId: session.projectId,
4264
+ baseUrl: session.baseUrl,
4043
4265
  programId: config.id
4044
4266
  });
4045
4267
  activeTui.store.setCredentials({
@@ -4048,10 +4270,7 @@ function runWizard(config, options) {
4048
4270
  host,
4049
4271
  projectId
4050
4272
  });
4051
- } else {
4052
- const { runAgent } = await import("./agent-runner-8g_pDAVs.js");
4053
- await runAgent(config, activeTui.store.session);
4054
- }
4273
+ } else await runAgent(config, activeTui.store.session);
4055
4274
  const isDone = () => skipAgent ? activeTui.store.session.outroDismissed : activeTui.store.session.skillsComplete;
4056
4275
  await new Promise((resolve) => {
4057
4276
  const unsub = activeTui.store.subscribe(() => {
@@ -4138,11 +4357,11 @@ function runNonInteractive(config, options, mode) {
4138
4357
  analytics.setTag("build", mode);
4139
4358
  (async () => {
4140
4359
  const path = await import("path");
4141
- const { buildSession, RunPhase, OutroKind } = await import("./wizard-session-BKEdX9mO.js");
4142
- const { readEnvironment } = await import("./environment-D2WUIm8o.js").then((n) => n.t);
4143
- const { readApiKeyFromEnv } = await import("./env-api-key-MlzJYAvt.js").then((n) => n.t);
4144
- const { configureLogFileFromEnvironment, logToFile } = await import("./debug-BM7yop-T.js");
4145
- const { wizardAbort, WizardError } = await import("./wizard-abort-BAB8yvGF.js");
4360
+ const { buildSession, RunPhase, OutroKind } = await import("./wizard-session-xzqycI7i.js");
4361
+ const { readEnvironment } = await import("./environment-Dc6VTWyK.js").then((n) => n.t);
4362
+ const { readApiKeyFromEnv } = await import("./env-api-key-Db-mNPK2.js").then((n) => n.t);
4363
+ const { configureLogFileFromEnvironment, logToFile } = await import("./debug-DJS2KPGb.js");
4364
+ const { wizardAbort, WizardError } = await import("./wizard-abort-C1t9M-JN.js");
4146
4365
  configureLogFileFromEnvironment();
4147
4366
  const env = readEnvironment();
4148
4367
  const apiKey = options.apiKey ?? readApiKeyFromEnv() ?? void 0;
@@ -4156,6 +4375,7 @@ function runNonInteractive(config, options, mode) {
4156
4375
  apiKey,
4157
4376
  email: options.email,
4158
4377
  projectId: options.projectId,
4378
+ baseUrl: options.baseUrl,
4159
4379
  benchmark: options.benchmark,
4160
4380
  yaraReport: options.yaraReport,
4161
4381
  noTelemetry: resolveNoTelemetry(options),
@@ -4169,9 +4389,9 @@ function runNonInteractive(config, options, mode) {
4169
4389
  let store = null;
4170
4390
  let taskStream = null;
4171
4391
  if (mode === "headless") {
4172
- const { WizardStore } = await import("./store-J2Rv955W.js").then((n) => n.n);
4173
- const { HeadlessUI } = await import("./headless-ui-CSqtmW-d.js");
4174
- const { TaskStreamPush, PostHogDestination } = await import("./task-stream-CPjpHFhI.js");
4392
+ const { WizardStore } = await import("./store-Di9OvMql.js").then((n) => n.n);
4393
+ const { HeadlessUI } = await import("./headless-ui-BplqZRcO.js");
4394
+ const { TaskStreamPush, PostHogDestination } = await import("./task-stream-DkbGqxZv.js");
4175
4395
  store = new WizardStore(config.id);
4176
4396
  store.session = session;
4177
4397
  setUI(new HeadlessUI(store));
@@ -4226,7 +4446,7 @@ function runNonInteractive(config, options, mode) {
4226
4446
  });
4227
4447
  }
4228
4448
  }
4229
- const { runAgent } = await import("./agent-runner-8g_pDAVs.js");
4449
+ const { runAgent } = await import("./agent-runner-Cic1uZZ8.js").then((n) => n.t);
4230
4450
  await runAgent(config, session);
4231
4451
  await settleStream(RunPhase.Completed);
4232
4452
  } catch (error) {
@@ -5153,12 +5373,13 @@ async function runDoctorCI(options) {
5153
5373
  getUI().intro("Welcome to the PostHog setup wizard");
5154
5374
  getUI().log.info("Running posthog-doctor in CI mode");
5155
5375
  try {
5156
- const { getOrAskForProjectData } = await import("./setup-utils-B0oz3raQ.js").then((n) => n.r);
5376
+ const { getOrAskForProjectData } = await import("./setup-utils-BxdW2R0r.js").then((n) => n.r);
5157
5377
  const { host, accessToken, projectId } = await getOrAskForProjectData({
5158
5378
  signup: false,
5159
5379
  ci: true,
5160
5380
  apiKey,
5161
- projectId: options.projectId ? Number(options.projectId) : void 0
5381
+ projectId: options.projectId ? Number(options.projectId) : void 0,
5382
+ baseUrl: options.baseUrl
5162
5383
  });
5163
5384
  const issues = await fetchHealthIssues(accessToken, host, projectId);
5164
5385
  if (issues.length === 0) {
@@ -5170,7 +5391,7 @@ async function runDoctorCI(options) {
5170
5391
  for (const issue of sorted) getUI().log.info(` • [${issue.severity}] ${getKindMeta(issue.kind).title}`);
5171
5392
  process.exit(1);
5172
5393
  } catch (error) {
5173
- const { ApiError } = await import("./api-EghEV_u9.js").then((n) => n.n);
5394
+ const { ApiError } = await import("./api-C_R_ybiA.js").then((n) => n.n);
5174
5395
  const message = error instanceof ApiError && error.statusCode === 401 ? "Your PostHog API key is invalid or expired." : error instanceof Error ? error.message : String(error);
5175
5396
  getUI().log.error(`Doctor failed: ${message}`);
5176
5397
  process.exit(1);
@@ -5214,6 +5435,11 @@ const selfDrivingCommand = {
5214
5435
  description: selfDrivingConfig.description,
5215
5436
  options: {
5216
5437
  ...skillProgramOptions,
5438
+ integrate: {
5439
+ describe: "Integrate the PostHog SDK first, then set up Self-driving — skips the \"do you already have PostHog?\" question. Use when the project isn't set up yet.",
5440
+ type: "boolean",
5441
+ default: false
5442
+ },
5217
5443
  ...selfDrivingConfig.cliOptions ?? {}
5218
5444
  },
5219
5445
  check: (argv) => {
@@ -5247,10 +5473,13 @@ function runSlackConnect(argv) {
5247
5473
  (async () => {
5248
5474
  const debug = argv.debug;
5249
5475
  try {
5250
- const { startTUI } = await import("./start-tui-B9qDcoGA.js");
5251
- const { buildSession } = await import("./wizard-session-BKEdX9mO.js");
5476
+ const { startTUI } = await import("./start-tui-oGWfxdTd.js");
5477
+ const { buildSession } = await import("./wizard-session-xzqycI7i.js");
5252
5478
  const tui = startTUI(VERSION, Program.SlackConnect);
5253
- tui.store.session = buildSession({ debug });
5479
+ tui.store.session = buildSession({
5480
+ debug,
5481
+ baseUrl: argv.baseUrl
5482
+ });
5254
5483
  } catch (err) {
5255
5484
  setUI(new LoggingUI());
5256
5485
  getUI().log.error(`Connecting Slack requires an interactive terminal. ${err instanceof Error ? err.message : String(err)}`);
@@ -5626,6 +5855,6 @@ function resolveInstallDir() {
5626
5855
  }
5627
5856
  Wizard.use(basicIntegrationCommand).use(mcpCommand).use(mcpAnalyticsCommand).use(cliCommand).use(auditCommand).use(doctorCommand).use(migrateCommand).use(revenueCommand).use(warehouseCommand).use(selfDrivingCommand).use(slackCommand).use(uploadSourcemapsCommand).use(skillCommand).init();
5628
5857
  //#endregion
5629
- export { fetchHealthIssues as _, ConfirmButton as a, POSTHOG_SDKS as b, runWizardCI as c, Program as d, getProgramConfig as f, getKindMeta as g, SOURCE_MAPS_CONTEXT_KEYS as h, useKeyboardHintsContext as i, runWizard as l, DISPLAY_NAME as m, useKeyBindings as n, PromptLabel as o, AUTOMATABLE_VARIANTS as p, KeyboardHintsProvider as r, runWizardHeadless as s, PickerMenu as t, PROGRAM_REGISTRY as u, getDetectedWarehouseSources as v, STRIPE_SDKS as x, getContentBlocks$2 as y };
5858
+ export { STRIPE_SDKS as C, POSTHOG_SDKS as S, SOURCE_MAPS_CONTEXT_KEYS as _, ConfirmButton as a, getDetectedWarehouseSources as b, runWizardCI as c, Program as d, getProgramConfig as f, DISPLAY_NAME as g, AUTOMATABLE_VARIANTS as h, useKeyboardHintsContext as i, runWizard as l, SELF_DRIVING_INTEGRATE_PATH_KEY as m, useKeyBindings as n, PromptLabel as o, detectSelfDrivingIntegrationProjects as p, KeyboardHintsProvider as r, runWizardHeadless as s, PickerMenu as t, PROGRAM_REGISTRY as u, getKindMeta as v, getContentBlocks$2 as x, fetchHealthIssues as y };
5630
5859
 
5631
5860
  //# sourceMappingURL=bin.js.map