@posthog/wizard 2.14.3 → 2.15.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 (90) hide show
  1. package/README.md +43 -1
  2. package/dist/{TextBlock-DEHERFec.js → TextBlock-B_8bXLLs.js} +2 -2
  3. package/dist/{TextBlock-DEHERFec.js.map → TextBlock-B_8bXLLs.js.map} +1 -1
  4. package/dist/{add-mcp-server-to-clients-B48J7VVO.js → add-mcp-server-to-clients-Dq0n2yzq.js} +5 -5
  5. package/dist/{add-mcp-server-to-clients-B48J7VVO.js.map → add-mcp-server-to-clients-Dq0n2yzq.js.map} +1 -1
  6. package/dist/{agent-interface-cEdS_bNo.js → agent-interface-yB_27jG8.js} +106 -21
  7. package/dist/agent-interface-yB_27jG8.js.map +1 -0
  8. package/dist/{agent-runner-CK5r-zQF.js → agent-runner-C9sSudE0.js} +7 -8
  9. package/dist/agent-runner-C9sSudE0.js.map +1 -0
  10. package/dist/analytics-BnR9904x.js +2 -0
  11. package/dist/{analytics-DaDpDus8.js → analytics-Da4QHjMw.js} +2 -2
  12. package/dist/{analytics-DaDpDus8.js.map → analytics-Da4QHjMw.js.map} +1 -1
  13. package/dist/bin.js +896 -80
  14. package/dist/bin.js.map +1 -1
  15. package/dist/{debug-B_PK52GI.js → debug-D5kt4fxB.js} +1 -1
  16. package/dist/{debug-BOogNcWX.js → debug-DRKLej5r.js} +55 -46
  17. package/dist/debug-DRKLej5r.js.map +1 -0
  18. package/dist/{defaults-DgKAzsD1.js → defaults-CPH6eWhN.js} +1 -1
  19. package/dist/{defaults-DgKAzsD1.js.map → defaults-CPH6eWhN.js.map} +1 -1
  20. package/dist/{detection-OCF8fpfp.js → detection-0Pz2NncX.js} +3 -3
  21. package/dist/{detection-OCF8fpfp.js.map → detection-0Pz2NncX.js.map} +1 -1
  22. package/dist/{env-api-key-D5G2PrXW.js → env-api-key-HFqv1l-z.js} +1 -1
  23. package/dist/{env-api-key-D5G2PrXW.js.map → env-api-key-HFqv1l-z.js.map} +1 -1
  24. package/dist/{file-utils-DPmgn9Vm.js → file-utils-DnTSiTJw.js} +1 -1
  25. package/dist/file-utils-DnTSiTJw.js.map +1 -0
  26. package/dist/package-json-Cttzi3C8.js +2 -0
  27. package/dist/package-json-v_g2YlN1.js +35 -0
  28. package/dist/package-json-v_g2YlN1.js.map +1 -0
  29. package/dist/{package-manager-CmMJAD-V.js → package-manager-DlTISyej.js} +2 -2
  30. package/dist/package-manager-DlTISyej.js.map +1 -0
  31. package/dist/posthog-B1G0raJU.js +120 -0
  32. package/dist/posthog-B1G0raJU.js.map +1 -0
  33. package/dist/{posthog-integration-By5930Gz.js → posthog-integration-D-DyEJvz.js} +13 -12
  34. package/dist/{posthog-integration-By5930Gz.js.map → posthog-integration-D-DyEJvz.js.map} +1 -1
  35. package/dist/provisioning-COeHnCVG.js +2 -0
  36. package/dist/{provisioning-BHa8VWaa.js → provisioning-DmN8ZDbE.js} +3 -3
  37. package/dist/{provisioning-BHa8VWaa.js.map → provisioning-DmN8ZDbE.js.map} +1 -1
  38. package/dist/{registry-DpROZPnl.js → registry-CofBzIdU.js} +31 -31
  39. package/dist/registry-CofBzIdU.js.map +1 -0
  40. package/dist/setup-utils-C5iSJ3eg.js +2 -0
  41. package/dist/{setup-utils-Mzpk1vqG.js → setup-utils-_P-or31U.js} +91 -51
  42. package/dist/setup-utils-_P-or31U.js.map +1 -0
  43. package/dist/{slides-BtDXEXdn.js → slides-D3I6JzlG.js} +41 -8
  44. package/dist/slides-D3I6JzlG.js.map +1 -0
  45. package/dist/smoke-test-ci.sh +5 -2
  46. package/dist/smoke-test.sh +43 -0
  47. package/dist/{start-playground-zZL5y9id.js → start-playground-Bxd2KG2L.js} +5 -6
  48. package/dist/{start-playground-zZL5y9id.js.map → start-playground-Bxd2KG2L.js.map} +1 -1
  49. package/dist/{start-tui-Cz7RZSn_.js → start-tui-Bl8fCbp_.js} +576 -23
  50. package/dist/start-tui-Bl8fCbp_.js.map +1 -0
  51. package/dist/{steps-C2XEzN79.js → steps-B-vmvb2V.js} +6 -6
  52. package/dist/{steps-C2XEzN79.js.map → steps-B-vmvb2V.js.map} +1 -1
  53. package/dist/task-stream-z6QFZtpC.js +195 -0
  54. package/dist/task-stream-z6QFZtpC.js.map +1 -0
  55. package/dist/{telemetry-BG2bOwCp.js → telemetry-XO0SlTFs.js} +2 -2
  56. package/dist/{telemetry-BG2bOwCp.js.map → telemetry-XO0SlTFs.js.map} +1 -1
  57. package/dist/{wizard-abort-CYW83OG5.js → wizard-abort-CuaS1eXn.js} +1 -1
  58. package/dist/{wizard-abort-BmT-F0Vr.js → wizard-abort-uolun8Q3.js} +3 -3
  59. package/dist/{wizard-abort-BmT-F0Vr.js.map → wizard-abort-uolun8Q3.js.map} +1 -1
  60. package/dist/{wizard-session-CsI33S4_.js → wizard-session-BlgiX-5d.js} +16 -2
  61. package/dist/wizard-session-BlgiX-5d.js.map +1 -0
  62. package/dist/wizard-session-DxU5ZMBN.js +2 -0
  63. package/dist/wizard-ui-YdGFRyu_.js.map +1 -1
  64. package/package.json +3 -2
  65. package/dist/agent-interface-cEdS_bNo.js.map +0 -1
  66. package/dist/agent-runner-CK5r-zQF.js.map +0 -1
  67. package/dist/analytics-Bw8E-yhX.js +0 -2
  68. package/dist/craft-pre-release.sh +0 -10
  69. package/dist/debug-BOogNcWX.js.map +0 -1
  70. package/dist/file-BKbKreWF.js +0 -16
  71. package/dist/file-BKbKreWF.js.map +0 -1
  72. package/dist/file-utils-DPmgn9Vm.js.map +0 -1
  73. package/dist/package-json-DZpnf6vU.js +0 -23
  74. package/dist/package-json-DZpnf6vU.js.map +0 -1
  75. package/dist/package-json-_4PEss19.js +0 -2
  76. package/dist/package-manager-CmMJAD-V.js.map +0 -1
  77. package/dist/paths-DJS47p5x.js +0 -26
  78. package/dist/paths-DJS47p5x.js.map +0 -1
  79. package/dist/posthog-BbQf_Hzq.js +0 -11
  80. package/dist/posthog-BbQf_Hzq.js.map +0 -1
  81. package/dist/provisioning-gHqu_MXL.js +0 -2
  82. package/dist/registry-DpROZPnl.js.map +0 -1
  83. package/dist/setup-utils-Mzpk1vqG.js.map +0 -1
  84. package/dist/setup-utils-ptemIB6g.js +0 -2
  85. package/dist/slides-BtDXEXdn.js.map +0 -1
  86. package/dist/start-tui-Cz7RZSn_.js.map +0 -1
  87. package/dist/task-stream-DUpUZmFQ.js +0 -61
  88. package/dist/task-stream-DUpUZmFQ.js.map +0 -1
  89. package/dist/wizard-session-CPhhll4P.js +0 -2
  90. package/dist/wizard-session-CsI33S4_.js.map +0 -1
package/dist/bin.js CHANGED
@@ -1,13 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import { t as __exportAll } from "./rolldown-runtime-B_-DWIq7.js";
3
- import { D as POSTHOG_DOCS_URL, G as VERSION, W as runtimeEnv, c as getUI, l as setUI, s as logToFile, u as LoggingUI, z as WIZARD_USER_AGENT } from "./debug-BOogNcWX.js";
4
- import { n as analytics } from "./analytics-DaDpDus8.js";
5
- import { a as isUsingTypeScript, d as getCloudUrlFromRegion, u as handleApiError } from "./setup-utils-Mzpk1vqG.js";
6
- import { g as AUDIT_REPORT_FILE, h as AUDIT_CHECKS_KEY, m as AUDIT_CHECKS_FILE, u as WIZARD_TOOL_NAMES } from "./agent-interface-cEdS_bNo.js";
7
- import { i as SPINNER_MESSAGE } from "./registry-DpROZPnl.js";
8
- import { c as HEALTH_CHECK_STEP, o as Colors } from "./TextBlock-DEHERFec.js";
9
- import { a as LINE_CHART_BLOCK, i as FUNNEL_BLOCK, n as posthogIntegrationConfig, o as PRODUCT_SUITE_BLOCK, s as StatusPeekTrigger } from "./posthog-integration-By5930Gz.js";
10
- import { t as IGNORED_DIRS } from "./file-utils-DPmgn9Vm.js";
3
+ import { M as POSTHOG_DOCS_URL, W as WIZARD_USER_AGENT, X as VERSION, Y as runtimeEnv, _ as SIGNUP_WIZARD_READINESS_CONFIG, h as LoggingUI, m as setUI, p as getUI, s as logToFile, v as evaluateWizardReadiness, y as getBlockingServiceKeys } from "./debug-DRKLej5r.js";
4
+ import { n as analytics } from "./analytics-Da4QHjMw.js";
5
+ import { a as isUsingTypeScript, f as getCloudUrlFromRegion, m as getUiHostFromHost, u as handleApiError } from "./setup-utils-_P-or31U.js";
6
+ import "./wizard-session-BlgiX-5d.js";
7
+ import { g as AUDIT_REPORT_FILE, h as AUDIT_CHECKS_KEY, m as AUDIT_CHECKS_FILE, t as AgentSignals, u as WIZARD_TOOL_NAMES } from "./agent-interface-yB_27jG8.js";
8
+ import { i as SPINNER_MESSAGE } from "./registry-CofBzIdU.js";
9
+ import { c as HEALTH_CHECK_STEP, o as Colors, r as isClearBlock } from "./TextBlock-B_8bXLLs.js";
10
+ import { a as LINE_CHART_BLOCK, i as FUNNEL_BLOCK, n as posthogIntegrationConfig, o as PRODUCT_SUITE_BLOCK, s as StatusPeekTrigger } from "./posthog-integration-D-DyEJvz.js";
11
+ import { t as IGNORED_DIRS } from "./file-utils-DnTSiTJw.js";
11
12
  import { satisfies } from "semver";
12
13
  import yargs from "yargs";
13
14
  import { hideBin } from "yargs/helpers";
@@ -34,7 +35,7 @@ function readEnvironment() {
34
35
  }
35
36
  //#endregion
36
37
  //#region src/lib/programs/revenue-analytics/detect.ts
37
- const POSTHOG_SDKS = [
38
+ const POSTHOG_SDKS$1 = [
38
39
  "posthog-js",
39
40
  "posthog-node",
40
41
  "posthog-react-native",
@@ -79,7 +80,7 @@ function findPackageJsons(installDir, maxDepth = 3) {
79
80
  if (entry.isFile() && entry.name === "package.json") try {
80
81
  const pkg = JSON.parse(readFileSync(fullPath, "utf-8"));
81
82
  const depNames = [...Object.keys(pkg.dependencies ?? {}), ...Object.keys(pkg.devDependencies ?? {})];
82
- const posthogSdks = depNames.filter((d) => POSTHOG_SDKS.includes(d));
83
+ const posthogSdks = depNames.filter((d) => POSTHOG_SDKS$1.includes(d));
83
84
  const stripeSdks = depNames.filter((d) => STRIPE_SDKS.includes(d));
84
85
  matches.push({
85
86
  path: relative(installDir, fullPath) || "package.json",
@@ -212,7 +213,7 @@ const REVENUE_ANALYTICS_PROGRAM = [
212
213
  * skill-based program (audit, revenue-analytics, agent-skill, etc.)
213
214
  * runs. Skill programs don't need the full PostHog onboarding narrative.
214
215
  */
215
- const getContentBlocks$1 = (store) => {
216
+ const getContentBlocks$2 = (store) => {
216
217
  return [
217
218
  {
218
219
  content: "Welcome.",
@@ -244,7 +245,7 @@ const revenueAnalyticsConfig = {
244
245
  description: "Set up PostHog revenue analytics (e.g. Stripe integration)",
245
246
  id: "revenue-analytics-setup",
246
247
  steps: REVENUE_ANALYTICS_PROGRAM,
247
- getContentBlocks: getContentBlocks$1,
248
+ getContentBlocks: getContentBlocks$2,
248
249
  allowedTools: ["Agent"],
249
250
  disallowedTools: [WIZARD_TOOL_NAMES.wizardAsk],
250
251
  run: {
@@ -305,7 +306,7 @@ function createSkillProgram(opts) {
305
306
  skillId: opts.skillId,
306
307
  steps: AGENT_SKILL_STEPS,
307
308
  reportFile: opts.reportFile,
308
- getContentBlocks: getContentBlocks$1,
309
+ getContentBlocks: getContentBlocks$2,
309
310
  run: {
310
311
  skillId: opts.skillId,
311
312
  integrationLabel: opts.integrationLabel,
@@ -506,7 +507,7 @@ const EVENTS_AUDIT_PROGRAM = [
506
507
  //#endregion
507
508
  //#region src/lib/programs/events-audit/index.ts
508
509
  const SETUP_REPORT_FILE = "posthog-events-audit-report.md";
509
- const DOCS_URL = "https://posthog.com/docs/product-analytics/best-practices";
510
+ const DOCS_URL$1 = "https://posthog.com/docs/product-analytics/best-practices";
510
511
  const eventsAuditConfig = {
511
512
  command: "events-audit",
512
513
  description: "Audit PostHog event tracking in this project",
@@ -528,7 +529,7 @@ const eventsAuditConfig = {
528
529
  successMessage: "Events audit complete! You can view the report at ./posthog-events-audit-report.md",
529
530
  estimatedDurationMinutes: 5,
530
531
  reportFile: SETUP_REPORT_FILE,
531
- docsUrl: DOCS_URL,
532
+ docsUrl: DOCS_URL$1,
532
533
  errorMessage: "Events audit failed",
533
534
  additionalFeatureQueue: session.additionalFeatureQueue,
534
535
  customPrompt: (ctx) => `Audit PostHog event capture in this project. Do not modify any project files — produce a read-only report only.
@@ -546,7 +547,7 @@ Project context:
546
547
  message: "Your events audit was successful",
547
548
  reportFile: SETUP_REPORT_FILE,
548
549
  changes: [],
549
- docsUrl: DOCS_URL,
550
+ docsUrl: DOCS_URL$1,
550
551
  continueUrl: sess.signup && cloudUrl ? `${cloudUrl}/products?source=wizard` : void 0,
551
552
  dashboardUrl: sess.dashboardUrl ?? (cloudUrl ? `${cloudUrl}/dashboard` : void 0)
552
553
  };
@@ -1188,7 +1189,7 @@ const PRICING_STRUCTURE_BLOCK = {
1188
1189
  * - posthog.com/docs/feature-flags/common-questions
1189
1190
  * - posthog.com/docs/experiments/best-practices
1190
1191
  */
1191
- const getContentBlocks = (store) => [
1192
+ const getContentBlocks$1 = (store) => [
1192
1193
  {
1193
1194
  content: "Hello.",
1194
1195
  pause: 3e3,
@@ -1440,7 +1441,7 @@ const migrationConfig = {
1440
1441
  skillId: PRODUCT_TO_SKILL_ID.statsig,
1441
1442
  steps: MIGRATION_PROGRAM,
1442
1443
  reportFile: MIGRATION_REPORT_FILE,
1443
- getContentBlocks,
1444
+ getContentBlocks: getContentBlocks$1,
1444
1445
  allowedTools: ["Agent"],
1445
1446
  disallowedTools: [WIZARD_TOOL_NAMES.wizardAsk],
1446
1447
  cliOptions: { product: {
@@ -1464,6 +1465,753 @@ const migrationConfig = {
1464
1465
  requires: ["posthog-integration"]
1465
1466
  };
1466
1467
  //#endregion
1468
+ //#region src/lib/programs/error-tracking-upload-source-maps/detect.ts
1469
+ const DISPLAY_NAME = {
1470
+ web: "Web (JavaScript)",
1471
+ nextjs: "Next.js",
1472
+ node: "Node.js",
1473
+ react: "React",
1474
+ angular: "Angular",
1475
+ nuxt: "Nuxt",
1476
+ "react-native": "React Native",
1477
+ android: "Android",
1478
+ flutter: "Flutter",
1479
+ ios: "iOS",
1480
+ vite: "Vite",
1481
+ webpack: "Webpack",
1482
+ rollup: "Rollup"
1483
+ };
1484
+ const POSTHOG_SDKS = [
1485
+ "posthog-js",
1486
+ "posthog-node",
1487
+ "posthog-react-native",
1488
+ "posthog-android",
1489
+ "posthog-ios"
1490
+ ];
1491
+ /** `[ABORT] <reason>` cases the source maps skill can emit. */
1492
+ const SOURCE_MAPS_ABORT_CASES = [{
1493
+ match: /^no posthog sdk detected$/i,
1494
+ message: "No PostHog SDK detected",
1495
+ body: "The agent could not find a PostHog SDK in your project. Source map upload requires the SDK to already be installed so it can report errors. Run `npx @posthog/wizard` first to install the SDK.",
1496
+ docsUrl: "https://posthog.com/docs/error-tracking"
1497
+ }, {
1498
+ match: /^build command not found$/i,
1499
+ message: "Build command not found",
1500
+ body: "The agent could not identify how to build your project. Source map upload runs as part of the production build. Add a build script to your project and run this wizard again.",
1501
+ docsUrl: "https://posthog.com/docs/error-tracking/upload-source-maps"
1502
+ }];
1503
+ function collectSignals(installDir, maxDepth = 3) {
1504
+ const signals = {
1505
+ packageJsons: [],
1506
+ hasXcodeProject: false,
1507
+ hasPodfile: false,
1508
+ hasSwiftPackage: false,
1509
+ hasGradle: false,
1510
+ hasPubspec: false,
1511
+ scannedFileCount: 0
1512
+ };
1513
+ function scan(dir, depth) {
1514
+ if (depth > maxDepth) return;
1515
+ let entries;
1516
+ try {
1517
+ entries = readdirSync(dir, { withFileTypes: true });
1518
+ } catch {
1519
+ return;
1520
+ }
1521
+ for (const entry of entries) {
1522
+ if (entry.name.startsWith(".") && entry.name !== ".") continue;
1523
+ if (IGNORED_DIRS.has(entry.name)) continue;
1524
+ const fullPath = join(dir, entry.name);
1525
+ if (entry.isFile()) {
1526
+ signals.scannedFileCount += 1;
1527
+ if (entry.name === "package.json") try {
1528
+ const pkg = JSON.parse(readFileSync(fullPath, "utf-8"));
1529
+ const deps = new Set([...Object.keys(pkg.dependencies ?? {}), ...Object.keys(pkg.devDependencies ?? {})]);
1530
+ signals.packageJsons.push({
1531
+ path: relative(installDir, fullPath) || "package.json",
1532
+ deps
1533
+ });
1534
+ } catch {}
1535
+ else if (entry.name === "Podfile") signals.hasPodfile = true;
1536
+ else if (entry.name === "Package.swift") signals.hasSwiftPackage = true;
1537
+ else if (entry.name === "pubspec.yaml") signals.hasPubspec = true;
1538
+ else if (entry.name === "build.gradle" || entry.name === "build.gradle.kts" || entry.name === "settings.gradle" || entry.name === "settings.gradle.kts") signals.hasGradle = true;
1539
+ } else if (entry.isDirectory()) if (entry.name.endsWith(".xcodeproj")) signals.hasXcodeProject = true;
1540
+ else scan(fullPath, depth + 1);
1541
+ }
1542
+ }
1543
+ scan(installDir, 0);
1544
+ return signals;
1545
+ }
1546
+ function pickJsVariant(deps) {
1547
+ if (deps.has("react-native")) return "react-native";
1548
+ if (deps.has("nuxt")) return "nuxt";
1549
+ if (deps.has("next")) return "nextjs";
1550
+ if (deps.has("@angular/core")) return "angular";
1551
+ if (deps.has("vite")) return "vite";
1552
+ if (deps.has("webpack")) return "webpack";
1553
+ if (deps.has("rollup")) return "rollup";
1554
+ if (deps.has("react")) return "react";
1555
+ if (deps.has("posthog-node")) return "node";
1556
+ return "web";
1557
+ }
1558
+ function selectVariant(signals) {
1559
+ if (signals.hasPubspec) return "flutter";
1560
+ if (signals.hasXcodeProject || signals.hasPodfile || signals.hasSwiftPackage) return "ios";
1561
+ if (signals.hasGradle) return "android";
1562
+ if (signals.packageJsons.length > 0) {
1563
+ const allDeps = /* @__PURE__ */ new Set();
1564
+ for (const pkg of signals.packageJsons) for (const dep of pkg.deps) allDeps.add(dep);
1565
+ return pickJsVariant(allDeps);
1566
+ }
1567
+ return null;
1568
+ }
1569
+ function hasPostHogSdk(signals) {
1570
+ for (const pkg of signals.packageJsons) for (const sdk of POSTHOG_SDKS) if (pkg.deps.has(sdk)) return true;
1571
+ return signals.hasXcodeProject || signals.hasPodfile || signals.hasSwiftPackage || signals.hasGradle || signals.hasPubspec;
1572
+ }
1573
+ const SOURCE_MAPS_CONTEXT_KEYS = {
1574
+ skillVariant: "sourceMapsSkillVariant",
1575
+ displayName: "sourceMapsDisplayName",
1576
+ packagePaths: "sourceMapsPackagePaths",
1577
+ detectError: "detectError"
1578
+ };
1579
+ /**
1580
+ * Scan `session.installDir` for platform / build-system signals. Writes
1581
+ * detection results into frameworkContext via the callback — either the
1582
+ * picked skill variant + display name, or a `SourceMapsDetectError`.
1583
+ *
1584
+ * The skill install happens later in the agent run, not here. This step
1585
+ * only picks which variant the prompt should ask the agent to load.
1586
+ */
1587
+ function detectSourceMapsPrerequisites(session, setFrameworkContext) {
1588
+ const fail = (error) => setFrameworkContext(SOURCE_MAPS_CONTEXT_KEYS.detectError, error);
1589
+ const installDir = session.installDir;
1590
+ if (!existsSync(installDir)) {
1591
+ fail({
1592
+ kind: "bad-directory",
1593
+ path: installDir,
1594
+ reason: "missing"
1595
+ });
1596
+ return;
1597
+ }
1598
+ try {
1599
+ if (!statSync(installDir).isDirectory()) {
1600
+ fail({
1601
+ kind: "bad-directory",
1602
+ path: installDir,
1603
+ reason: "not-dir"
1604
+ });
1605
+ return;
1606
+ }
1607
+ } catch {
1608
+ fail({
1609
+ kind: "bad-directory",
1610
+ path: installDir,
1611
+ reason: "unreadable"
1612
+ });
1613
+ return;
1614
+ }
1615
+ const signals = collectSignals(installDir);
1616
+ const variant = selectVariant(signals);
1617
+ if (variant && [
1618
+ "react-native",
1619
+ "flutter",
1620
+ "ios",
1621
+ "android"
1622
+ ].includes(variant)) {
1623
+ fail({
1624
+ kind: "unsupported-platform",
1625
+ detected: variant
1626
+ });
1627
+ return;
1628
+ }
1629
+ if (!variant) {
1630
+ if (signals.scannedFileCount === 0) fail({ kind: "no-project-files" });
1631
+ else fail({
1632
+ kind: "unsupported-platform",
1633
+ detected: "unknown"
1634
+ });
1635
+ return;
1636
+ }
1637
+ if (!hasPostHogSdk(signals)) {
1638
+ fail({
1639
+ kind: "no-posthog-sdk",
1640
+ platform: variant
1641
+ });
1642
+ return;
1643
+ }
1644
+ setFrameworkContext(SOURCE_MAPS_CONTEXT_KEYS.skillVariant, variant);
1645
+ setFrameworkContext(SOURCE_MAPS_CONTEXT_KEYS.displayName, DISPLAY_NAME[variant]);
1646
+ setFrameworkContext(SOURCE_MAPS_CONTEXT_KEYS.packagePaths, signals.packageJsons.map((p) => p.path));
1647
+ }
1648
+ //#endregion
1649
+ //#region src/lib/programs/error-tracking-upload-source-maps/steps.ts
1650
+ function healthCheckReady(session) {
1651
+ if (!session.readinessResult) return false;
1652
+ if (session.signup) {
1653
+ const hardBlocking = getBlockingServiceKeys(session.readinessResult.health, SIGNUP_WIZARD_READINESS_CONFIG);
1654
+ const defaultBlocking = getBlockingServiceKeys(session.readinessResult.health);
1655
+ if (hardBlocking.length === 0 && defaultBlocking.length === 0) return true;
1656
+ return session.outageDismissed;
1657
+ }
1658
+ if (session.readinessResult.decision === "no") return session.outageDismissed;
1659
+ return true;
1660
+ }
1661
+ const ERROR_TRACKING_UPLOAD_SOURCE_MAPS_PROGRAM = [
1662
+ {
1663
+ id: "detect",
1664
+ label: "Detecting platform",
1665
+ onReady: (ctx) => detectSourceMapsPrerequisites(ctx.session, ctx.setFrameworkContext)
1666
+ },
1667
+ {
1668
+ id: "intro",
1669
+ label: "Welcome",
1670
+ screenId: "source-maps-intro",
1671
+ gate: (session) => session.setupConfirmed
1672
+ },
1673
+ {
1674
+ id: "health-check",
1675
+ label: "Health check",
1676
+ screenId: "health-check",
1677
+ gate: healthCheckReady,
1678
+ onInit: (ctx) => {
1679
+ evaluateWizardReadiness().then((readiness) => {
1680
+ ctx.setReadinessResult(readiness);
1681
+ }).catch(() => {
1682
+ ctx.setReadinessResult({
1683
+ decision: "yes",
1684
+ health: {},
1685
+ reasons: []
1686
+ });
1687
+ });
1688
+ }
1689
+ },
1690
+ {
1691
+ id: "auth",
1692
+ label: "Authentication",
1693
+ screenId: "auth",
1694
+ isComplete: (session) => session.credentials !== null
1695
+ },
1696
+ {
1697
+ id: "run",
1698
+ label: "Upload source maps",
1699
+ screenId: "run",
1700
+ isComplete: (session) => session.runPhase === "completed" || session.runPhase === "error"
1701
+ },
1702
+ {
1703
+ id: "outro",
1704
+ label: "Done",
1705
+ screenId: "source-maps-outro",
1706
+ isComplete: (session) => session.outroDismissed
1707
+ },
1708
+ {
1709
+ id: "skills",
1710
+ label: "Skills",
1711
+ screenId: "keep-skills"
1712
+ }
1713
+ ];
1714
+ //#endregion
1715
+ //#region src/lib/programs/error-tracking-upload-source-maps/prompt.ts
1716
+ const SOURCE_MAPS_DETECTION_FAILED_PROMPT = `Detection did not pick a source maps skill variant for this project.
1717
+ Emit: ${AgentSignals.ABORT} unsupported-platform
1718
+ Then halt.`;
1719
+ function buildSourceMapsUploadPrompt(params) {
1720
+ const { displayName, variant, skillId, projectId, host, settingsUrl, uiHost } = params;
1721
+ const platformLabel = displayName ?? variant;
1722
+ return `You are wiring up PostHog Error Tracking source map upload for this ${platformLabel} project.
1723
+
1724
+ Project context:
1725
+ - PostHog Project ID: ${projectId}
1726
+ - PostHog Host: ${host}
1727
+ - Detected platform: ${platformLabel}
1728
+ - Skill to use: ${skillId}
1729
+ - Personal API keys settings page: ${settingsUrl}
1730
+
1731
+ The skill you install in STEP 2 is the source of truth for the HOW of every
1732
+ step: its "## Steps" section has an overview, tips and per-technology
1733
+ examples for each named step, and its reference files carry the exact
1734
+ per-framework API. The STEPS below give the order, the conditionals, and the
1735
+ wizard-specific mechanics (which MCP tool to call, signals to emit) — read
1736
+ the matching skill step (named in parentheses) before doing the work, and do
1737
+ not invent steps the skill doesn't describe.
1738
+
1739
+ Follow these steps IN ORDER. Do not skip or reorder.
1740
+
1741
+ Before doing any work, create your FULL task list in a single TaskCreate
1742
+ call so the user can follow your progress in the TUI. Use exactly these
1743
+ tasks, in this order — do not collapse, rename, or omit any of them:
1744
+ 1. Get personal API key
1745
+ 2. Install source maps skill
1746
+ 3. Apply build-config changes (per skill)
1747
+ 4. Make credentials readable at build time
1748
+ 5. Write keys to .env
1749
+ 6. Identify build & run commands
1750
+ 7. Test the local setup
1751
+ 8. Summarise & hand off
1752
+ Drive the list with TaskUpdate — mark a task in_progress when you start it
1753
+ and completed when done. ALWAYS keep task 7 ("Test the local setup") in the
1754
+ list even if the user declines testing in STEP 7: mark it completed rather
1755
+ than deleting it, so the user can see testing was offered.
1756
+
1757
+ STEP 1 — Get a personal API key from the user. (skill: "Get a personal API key")
1758
+ The wizard cannot mint keys — never call the PostHog API or any tool to
1759
+ create one. Ask the user with the wizard_ask MCP tool; you receive the
1760
+ answer as a vaulted secretRef (never the raw value), which you reuse in
1761
+ STEP 5:
1762
+ {
1763
+ id: "api-key",
1764
+ prompt: "Paste your PostHog personal API key below.\\n\\nDon't have one yet? Create one here:\\n${settingsUrl}\\n\\nWhen creating the key, choose the 'Source map upload' preset, then come back and paste it here.",
1765
+ kind: "text",
1766
+ sensitive: true
1767
+ }
1768
+ Keep the \\n line breaks exactly as written — Ink's <Text> renders them
1769
+ as separate lines. The answer is { secretRef: "secret:..." }.
1770
+ If wizard_ask is unavailable (CI / non-interactive), emit
1771
+ ${AgentSignals.ABORT} requires-interactive-mode and halt.
1772
+
1773
+ STEP 2 — Install the skill.
1774
+ Call install_skill (wizard-tools MCP server) with skillId "${skillId}".
1775
+ Do NOT run shell commands to install skills. Then read the installed
1776
+ SKILL.md and its reference files — they drive STEPS 3-8.
1777
+ If install fails, emit ${AgentSignals.ERROR_RESOURCE_MISSING} skill ${skillId} could not be installed.
1778
+
1779
+ STEP 3 — Apply build-config changes. (skill: "Apply build-config changes")
1780
+ Make the bundler / build-config changes the skill's step instructs. The
1781
+ skill and its reference are the source of truth for this platform.
1782
+
1783
+ STEP 4 — Make the credentials readable at build time. (skill: "Make credentials available at build time")
1784
+ Follow the skill's step. Wizard-specific: if it calls for a loader (e.g.
1785
+ \`dotenv\`), install it SILENTLY — do NOT ask the user or call wizard_ask.
1786
+ Skip this step entirely if the platform already auto-loads .env.
1787
+
1788
+ STEP 5 — Write the credentials to the env file. (skill: "Write credentials to the env file")
1789
+ Use the wizard-tools MCP server. Reuse the env file the skill tells you to
1790
+ pick — the prerequisite PostHog integration usually already wrote
1791
+ POSTHOG_* vars to one, so seed your keys alongside them.
1792
+ - First call check_env_keys on that file (returns present/absent, never
1793
+ values — don't read the file directly).
1794
+ - Then call set_env_values, passing the STEP 1 secretRef as a value
1795
+ object, not a literal string:
1796
+ values: {
1797
+ "POSTHOG_CLI_API_KEY": { secretRef: "<the ref from STEP 1>" },
1798
+ "POSTHOG_CLI_PROJECT_ID": "${projectId}",
1799
+ "POSTHOG_CLI_HOST": "${host}"
1800
+ }
1801
+ Variable names follow the skill's per-uploader conventions. The wizard
1802
+ resolves the ref locally before writing, so you never see the key value.
1803
+
1804
+ STEP 6 — Identify the build AND run commands. (skill: "Identify the build and run commands")
1805
+ Per the skill, resolve the production BUILD command and the RUN command
1806
+ for THIS project (use detect_package_manager for the package manager). Do
1807
+ NOT run either yourself — the user runs them. If you cannot identify a
1808
+ build command, emit ${AgentSignals.ABORT} build command not found.
1809
+
1810
+ STEP 7 — Offer to test the local setup. (skill: "Test the local setup")
1811
+ Call wizard_ask:
1812
+ {
1813
+ id: "test-affordance",
1814
+ prompt: "Want me to help you test your local setup? I'll add a temporary test button (or route) to your app so you can confirm errors show up in Error Tracking with readable stack traces after your next build. I'll remove it once you've confirmed it works.",
1815
+ kind: "single",
1816
+ options: [
1817
+ { label: "Yes, help me test it", value: "yes" },
1818
+ { label: "No, I'll test on my own later", value: "no" }
1819
+ ]
1820
+ }
1821
+
1822
+ If "no", skip to STEP 8.
1823
+
1824
+ If "yes", follow the skill's "Test the local setup" step for the
1825
+ platform-appropriate affordance, the captureException shape, the
1826
+ placement, and the read-before-edit / always-revert rules. Then pause for
1827
+ the user with wizard_ask, baking the EXACT build and run commands from
1828
+ STEP 6 (and the exact button label / route) into the prompt as literal,
1829
+ copy-pasteable steps. Separate each numbered step with \\n\\n so the TUI
1830
+ renders them as distinct lines:
1831
+ {
1832
+ id: "test-done",
1833
+ prompt: "1) Run \`<your detected build command>\` to upload source maps and build the app with the test affordance.\\n\\n2) Start the app with \`<your detected run command>\`, then click the \\"<your test button label>\\" button (or hit \`<your test route>\`).\\n\\n3) Open Error Tracking in PostHog (${uiHost}/project/${projectId}/error_tracking) and confirm the test error appears with a source-resolved stack trace pointing at real source files (not minified bundle paths).\\n\\nWhen you're done, select Continue and I'll revert the test code.",
1834
+ kind: "single",
1835
+ options: [{ label: "Continue (revert test code)", value: "continue" }]
1836
+ }
1837
+ After the user continues, revert the test code per the skill's rules and
1838
+ surface any failure in STEP 8.
1839
+
1840
+ STEP 8 — Summarise and hand off. (skill: "Verify and hand off")
1841
+ Follow the skill's "Verify and hand off" step. The Symbol sets page for
1842
+ this project — where the user confirms the upload landed — is:
1843
+ ${uiHost}/project/${projectId}/error_tracking/configuration
1844
+ `;
1845
+ }
1846
+ //#endregion
1847
+ //#region src/lib/programs/error-tracking-upload-source-maps/content/index.tsx
1848
+ /**
1849
+ * Source-maps learn-deck — the narrative played in the run screen's left
1850
+ * pane (LearnCard) while the agent wires source-map upload into the build.
1851
+ *
1852
+ * It educates the user on what source maps are and why uploading them
1853
+ * matters, built around a before/after stack-trace contrast: a minified
1854
+ * production trace nobody can read, then the same trace resolved back to
1855
+ * real source. Program-owned; wired onto the program's getContentBlocks.
1856
+ *
1857
+ * Lines stay narrow (~36 cols) because this renders in the left half of a
1858
+ * split pane — see LearnCard's paneWidth math.
1859
+ */
1860
+ /**
1861
+ * Per-slide dwell multiplier. Each block stays on screen for `pause * SLIDE_PACE`
1862
+ * ms after it finishes animating, before the deck advances. Bump this single
1863
+ * knob to give every slide more reading time. Clear (page-break) blocks are
1864
+ * left untouched so the blank gap between slides stays snappy.
1865
+ */
1866
+ const SLIDE_PACE = 1.5;
1867
+ const withPace = (block) => {
1868
+ if (typeof block === "string" || isClearBlock(block) || block.pause == null) return block;
1869
+ return {
1870
+ ...block,
1871
+ pause: Math.round(block.pause * SLIDE_PACE)
1872
+ };
1873
+ };
1874
+ /** Apply the dwell multiplier to every block in a deck. */
1875
+ const pace = (blocks) => blocks.map(withPace);
1876
+ /** A minified production stack trace — the problem source maps solve. */
1877
+ const MINIFIED_TRACE = {
1878
+ type: "lines",
1879
+ interval: 400,
1880
+ pause: 7e3,
1881
+ lines: [
1882
+ /* @__PURE__ */ jsx(Text, {
1883
+ color: Colors.error,
1884
+ children: "✘ TypeError: cart is undefined"
1885
+ }),
1886
+ /* @__PURE__ */ jsx(Text, {
1887
+ dimColor: true,
1888
+ children: " at t.min.js:1:48213"
1889
+ }),
1890
+ /* @__PURE__ */ jsx(Text, {
1891
+ dimColor: true,
1892
+ children: " at t.min.js:1:9402"
1893
+ }),
1894
+ /* @__PURE__ */ jsx(Text, {
1895
+ dimColor: true,
1896
+ children: " at t.min.js:1:71150"
1897
+ })
1898
+ ]
1899
+ };
1900
+ /** The same trace, resolved through uploaded source maps. */
1901
+ const RESOLVED_TRACE = {
1902
+ type: "lines",
1903
+ interval: 400,
1904
+ pause: 8e3,
1905
+ lines: [
1906
+ /* @__PURE__ */ jsx(Text, {
1907
+ color: Colors.success,
1908
+ children: "✔ TypeError: cart is undefined"
1909
+ }),
1910
+ /* @__PURE__ */ jsxs(Text, { children: [
1911
+ /* @__PURE__ */ jsx(Text, {
1912
+ dimColor: true,
1913
+ children: " at "
1914
+ }),
1915
+ /* @__PURE__ */ jsx(Text, {
1916
+ color: "cyan",
1917
+ children: "Cart.tsx:42"
1918
+ }),
1919
+ /* @__PURE__ */ jsx(Text, {
1920
+ dimColor: true,
1921
+ children: " loadCart"
1922
+ })
1923
+ ] }),
1924
+ /* @__PURE__ */ jsxs(Text, { children: [
1925
+ /* @__PURE__ */ jsx(Text, {
1926
+ dimColor: true,
1927
+ children: " at "
1928
+ }),
1929
+ /* @__PURE__ */ jsx(Text, {
1930
+ color: "cyan",
1931
+ children: "App.tsx:88"
1932
+ }),
1933
+ /* @__PURE__ */ jsx(Text, {
1934
+ dimColor: true,
1935
+ children: " render"
1936
+ })
1937
+ ] }),
1938
+ /* @__PURE__ */ jsxs(Text, { children: [
1939
+ /* @__PURE__ */ jsx(Text, {
1940
+ dimColor: true,
1941
+ children: " at "
1942
+ }),
1943
+ /* @__PURE__ */ jsx(Text, {
1944
+ color: "cyan",
1945
+ children: "index.tsx:5"
1946
+ }),
1947
+ /* @__PURE__ */ jsx(Text, {
1948
+ dimColor: true,
1949
+ children: " main"
1950
+ })
1951
+ ] })
1952
+ ]
1953
+ };
1954
+ /**
1955
+ * How a bundle is tied to its map: PostHog injects a chunk-ID marker into the
1956
+ * built JS and stamps the matching source map with the same ID.
1957
+ */
1958
+ const CHUNK_ID_LINK = {
1959
+ type: "lines",
1960
+ interval: 450,
1961
+ pause: 7500,
1962
+ lines: [
1963
+ /* @__PURE__ */ jsx(Text, {
1964
+ dimColor: true,
1965
+ children: "app.min.js"
1966
+ }),
1967
+ /* @__PURE__ */ jsx(Text, {
1968
+ dimColor: true,
1969
+ children: " …minified code…"
1970
+ }),
1971
+ /* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
1972
+ color: "cyan",
1973
+ children: " //# chunkId=a1b2c3d4"
1974
+ }), /* @__PURE__ */ jsx(Text, {
1975
+ dimColor: true,
1976
+ children: " ← injected"
1977
+ })] }),
1978
+ /* @__PURE__ */ jsx(Text, {
1979
+ dimColor: true,
1980
+ children: " ↕ matched by id"
1981
+ }),
1982
+ /* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
1983
+ dimColor: true,
1984
+ children: "app.min.js.map"
1985
+ }), /* @__PURE__ */ jsx(Text, {
1986
+ dimColor: true,
1987
+ children: " ← uploaded"
1988
+ })] })
1989
+ ]
1990
+ };
1991
+ /** Many similar exceptions collapse into a single issue. */
1992
+ const GROUPING = {
1993
+ type: "lines",
1994
+ interval: 450,
1995
+ pause: 7e3,
1996
+ lines: [
1997
+ /* @__PURE__ */ jsx(Text, {
1998
+ dimColor: true,
1999
+ children: "exception ─┐"
2000
+ }),
2001
+ /* @__PURE__ */ jsxs(Text, { children: [/* @__PURE__ */ jsx(Text, {
2002
+ dimColor: true,
2003
+ children: "exception ─┼──→ "
2004
+ }), /* @__PURE__ */ jsx(Text, {
2005
+ color: Colors.accent,
2006
+ bold: true,
2007
+ children: "1 issue"
2008
+ })] }),
2009
+ /* @__PURE__ */ jsx(Text, {
2010
+ dimColor: true,
2011
+ children: "exception ─┘"
2012
+ })
2013
+ ]
2014
+ };
2015
+ const getContentBlocks = (store) => pace([
2016
+ {
2017
+ content: "Welcome.",
2018
+ pause: 3e3,
2019
+ mode: 0,
2020
+ animationInterval: 160
2021
+ },
2022
+ {
2023
+ content: "I'm wiring PostHog Error Tracking into your build.",
2024
+ pause: 5e3
2025
+ },
2026
+ {
2027
+ type: "clear",
2028
+ pause: 1500
2029
+ },
2030
+ {
2031
+ content: "When you ship to production, your code gets minified.",
2032
+ pause: 5e3
2033
+ },
2034
+ {
2035
+ content: "Thousands of readable lines collapse into one dense bundle.",
2036
+ pause: 5e3
2037
+ },
2038
+ {
2039
+ content: "So a thrown error gives you a stack trace like this:",
2040
+ pause: 2e3
2041
+ },
2042
+ MINIFIED_TRACE,
2043
+ {
2044
+ content: "Just offsets into a file no human can read.",
2045
+ pause: 5e3
2046
+ },
2047
+ {
2048
+ type: "clear",
2049
+ pause: 1500
2050
+ },
2051
+ {
2052
+ content: "Source maps are the key.",
2053
+ pause: 3500
2054
+ },
2055
+ {
2056
+ content: "They map every position in that bundle back to your original source — the real file, line, and function.",
2057
+ pause: 6e3
2058
+ },
2059
+ {
2060
+ content: "Right now I'm hooking source-map generation and upload into your build, tied to each release you ship.",
2061
+ pause: 6e3
2062
+ },
2063
+ {
2064
+ type: "clear",
2065
+ pause: 1500
2066
+ },
2067
+ {
2068
+ content: "But how does PostHog know which map belongs to which build?",
2069
+ pause: 4500
2070
+ },
2071
+ {
2072
+ content: "During the build, it injects a unique chunk ID into each bundle:",
2073
+ pause: 2500
2074
+ },
2075
+ CHUNK_ID_LINK,
2076
+ {
2077
+ content: "The matching source map is stamped with that same ID before it ships to PostHog.",
2078
+ pause: 6e3
2079
+ },
2080
+ {
2081
+ content: "When an error comes in, PostHog reads the chunk ID off the bundle, finds the map with the exact same ID, and uses it to map each frame back to your source — even for a release you shipped weeks ago.",
2082
+ pause: 8e3
2083
+ },
2084
+ {
2085
+ type: "clear",
2086
+ pause: 1500
2087
+ },
2088
+ {
2089
+ content: "So that same error becomes:",
2090
+ pause: 2e3
2091
+ },
2092
+ RESOLVED_TRACE,
2093
+ {
2094
+ content: "Readable stack traces, straight from production.",
2095
+ pause: 5e3
2096
+ },
2097
+ {
2098
+ content: "You debug a live error like it happened on your own machine.",
2099
+ pause: 6e3
2100
+ },
2101
+ {
2102
+ type: "clear",
2103
+ pause: 1500
2104
+ },
2105
+ {
2106
+ content: "Zooming out — this is how Error Tracking works.",
2107
+ pause: 4e3
2108
+ },
2109
+ {
2110
+ content: "Every error your app throws is captured as an exception.",
2111
+ pause: 5e3
2112
+ },
2113
+ {
2114
+ content: "PostHog groups similar exceptions into a single issue:",
2115
+ pause: 2500
2116
+ },
2117
+ GROUPING,
2118
+ {
2119
+ content: "So a bug that fires ten thousand times is one issue to triage — not ten thousand alerts.",
2120
+ pause: 6500
2121
+ },
2122
+ {
2123
+ type: "clear",
2124
+ pause: 1500
2125
+ },
2126
+ {
2127
+ content: "And this is where source maps earn their keep again.",
2128
+ pause: 4500
2129
+ },
2130
+ {
2131
+ content: "Grouping reads the stack trace. Minified frames all look alike — so unrelated crashes get merged, and one real bug scatters across many issues.",
2132
+ pause: 8e3
2133
+ },
2134
+ {
2135
+ content: "With source maps, PostHog groups on your real frames — so each distinct bug lands as one clean issue.",
2136
+ pause: 7e3
2137
+ },
2138
+ {
2139
+ type: "clear",
2140
+ pause: 1500
2141
+ },
2142
+ {
2143
+ pause: 5e3,
2144
+ persist: true,
2145
+ content: /* @__PURE__ */ jsx(StatusPeekTrigger, { store })
2146
+ },
2147
+ {
2148
+ pause: 9e4,
2149
+ content: /* @__PURE__ */ jsxs(Text, { children: [
2150
+ "Press",
2151
+ " ",
2152
+ /* @__PURE__ */ jsx(Text, {
2153
+ color: Colors.accent,
2154
+ bold: true,
2155
+ children: "S"
2156
+ }),
2157
+ " ",
2158
+ "to follow along — or sit tight, I'll let you know when it's done."
2159
+ ] })
2160
+ }
2161
+ ]);
2162
+ //#endregion
2163
+ //#region src/lib/programs/error-tracking-upload-source-maps/index.ts
2164
+ const REPORT_FILE = "posthog-source-maps-report.md";
2165
+ const DOCS_URL = "https://posthog.com/docs/error-tracking/upload-source-maps";
2166
+ const errorTrackingUploadSourceMapsConfig = {
2167
+ command: "upload-sourcemaps",
2168
+ description: "Upload source maps to PostHog Error Tracking",
2169
+ id: "error-tracking-upload-source-maps",
2170
+ steps: ERROR_TRACKING_UPLOAD_SOURCE_MAPS_PROGRAM,
2171
+ reportFile: REPORT_FILE,
2172
+ getContentBlocks,
2173
+ requires: ["posthog-integration"],
2174
+ run: (session) => {
2175
+ const variant = session.frameworkContext[SOURCE_MAPS_CONTEXT_KEYS.skillVariant];
2176
+ const displayName = session.frameworkContext[SOURCE_MAPS_CONTEXT_KEYS.displayName];
2177
+ const skillId = variant ? `error-tracking-upload-source-maps-${variant}` : void 0;
2178
+ return Promise.resolve({
2179
+ integrationLabel: "error-tracking-upload-source-maps",
2180
+ successMessage: "Source maps wired up!",
2181
+ reportFile: REPORT_FILE,
2182
+ docsUrl: DOCS_URL,
2183
+ spinnerMessage: "Wiring up source maps...",
2184
+ estimatedDurationMinutes: 3,
2185
+ abortCases: SOURCE_MAPS_ABORT_CASES,
2186
+ customPrompt: (ctx) => {
2187
+ if (!skillId || !variant) return SOURCE_MAPS_DETECTION_FAILED_PROMPT;
2188
+ const uiHost = getUiHostFromHost(ctx.host).replace(/\/$/, "");
2189
+ return buildSourceMapsUploadPrompt({
2190
+ displayName,
2191
+ variant,
2192
+ skillId,
2193
+ projectId: ctx.projectId,
2194
+ host: ctx.host,
2195
+ settingsUrl: `${uiHost}/project/${ctx.projectId}/settings/user-api-keys`,
2196
+ uiHost
2197
+ });
2198
+ },
2199
+ postRun: (sess) => {
2200
+ if (variant) sess.frameworkContext["sourceMapsCompletedVariant"] = variant;
2201
+ return Promise.resolve();
2202
+ },
2203
+ buildOutroData: () => {
2204
+ return {
2205
+ kind: "success",
2206
+ message: "Source maps wired up!",
2207
+ reportFile: REPORT_FILE,
2208
+ docsUrl: DOCS_URL
2209
+ };
2210
+ }
2211
+ });
2212
+ }
2213
+ };
2214
+ //#endregion
1467
2215
  //#region src/lib/programs/mcp/index.ts
1468
2216
  const mcpAddConfig = {
1469
2217
  id: "mcp-add",
@@ -1491,12 +2239,13 @@ const agentSkillConfig = {
1491
2239
  id: "agent-skill",
1492
2240
  description: "Run an arbitrary context-mill skill",
1493
2241
  steps: AGENT_SKILL_STEPS,
1494
- getContentBlocks: getContentBlocks$1,
2242
+ getContentBlocks: getContentBlocks$2,
1495
2243
  allowedTools: ["Agent"]
1496
2244
  };
1497
2245
  const PROGRAM_REGISTRY = [
1498
2246
  posthogIntegrationConfig,
1499
2247
  revenueAnalyticsConfig,
2248
+ errorTrackingUploadSourceMapsConfig,
1500
2249
  auditConfig,
1501
2250
  eventsAuditConfig,
1502
2251
  audit3000Config,
@@ -1514,6 +2263,7 @@ const PROGRAM_REGISTRY = [
1514
2263
  const Program = {
1515
2264
  PostHogIntegration: posthogIntegrationConfig.id,
1516
2265
  RevenueAnalyticsSetup: revenueAnalyticsConfig.id,
2266
+ ErrorTrackingUploadSourceMaps: errorTrackingUploadSourceMapsConfig.id,
1517
2267
  Migration: migrationConfig.id,
1518
2268
  Audit: auditConfig.id,
1519
2269
  EventsAudit: eventsAuditConfig.id,
@@ -1537,12 +2287,12 @@ function getSubcommandPrograms() {
1537
2287
  }
1538
2288
  //#endregion
1539
2289
  //#region bin.ts
1540
- const WIZARD_VERSION = VERSION;
1541
- const NODE_VERSION_RANGE = ">=18.17.0";
1542
- if (!satisfies(process.version, NODE_VERSION_RANGE)) {
1543
- console.log(`PostHog wizard requires Node.js ${NODE_VERSION_RANGE}. You are using Node.js ${process.version}. Please upgrade your Node.js version.`);
2290
+ const MIN_NODE_VERSION = ">=18.17.0";
2291
+ if (!satisfies(process.version, MIN_NODE_VERSION)) {
2292
+ console.log(`PostHog wizard needs Node.js ${MIN_NODE_VERSION}. Detected ${process.version} — please upgrade Node and re-run.`);
1544
2293
  process.exit(1);
1545
2294
  }
2295
+ const WIZARD_VERSION = VERSION;
1546
2296
  /** Shared yargs options for skill-based program subcommands. */
1547
2297
  const skillSubcommandOptions = {
1548
2298
  debug: {
@@ -1597,11 +2347,6 @@ const cli = yargs(hideBin(process.argv)).env("POSTHOG_WIZARD").options({
1597
2347
  describe: "Use local MCP server at http://localhost:8787/mcp\nenv: POSTHOG_WIZARD_LOCAL_MCP",
1598
2348
  type: "boolean"
1599
2349
  },
1600
- ci: {
1601
- default: false,
1602
- describe: "Enable CI mode for non-interactive execution\nenv: POSTHOG_WIZARD_CI",
1603
- type: "boolean"
1604
- },
1605
2350
  "api-key": {
1606
2351
  describe: "PostHog personal API key (phx_xxx) for authentication\nenv: POSTHOG_WIZARD_API_KEY",
1607
2352
  type: "string"
@@ -1613,6 +2358,11 @@ const cli = yargs(hideBin(process.argv)).env("POSTHOG_WIZARD").options({
1613
2358
  email: {
1614
2359
  describe: "Email address for signup (used with --signup)\nenv: POSTHOG_WIZARD_EMAIL",
1615
2360
  type: "string"
2361
+ },
2362
+ telemetry: {
2363
+ default: true,
2364
+ describe: "Send wizard run state to PostHog (pass --no-telemetry to disable)\nenv: POSTHOG_WIZARD_TELEMETRY",
2365
+ type: "boolean"
1616
2366
  }
1617
2367
  }).command(["$0"], "Run the PostHog setup wizard", (yargs) => {
1618
2368
  return yargs.options({
@@ -1710,7 +2460,7 @@ const cli = yargs(hideBin(process.argv)).env("POSTHOG_WIZARD").options({
1710
2460
  setUI(new LoggingUI());
1711
2461
  getUI().intro("PostHog Wizard");
1712
2462
  try {
1713
- const { provisionNewAccount } = await import("./provisioning-gHqu_MXL.js");
2463
+ const { provisionNewAccount } = await import("./provisioning-COeHnCVG.js");
1714
2464
  const signupRegion = options.region.toUpperCase();
1715
2465
  getUI().log.info(`Provisioning new PostHog account for ${String(options.email)} in ${signupRegion}...`);
1716
2466
  const result = await provisionNewAccount(options.email, options.name ?? "", signupRegion);
@@ -1732,11 +2482,11 @@ const cli = yargs(hideBin(process.argv)).env("POSTHOG_WIZARD").options({
1732
2482
  return;
1733
2483
  }
1734
2484
  }
1735
- const { posthogIntegrationConfig } = await import("./posthog-integration-By5930Gz.js").then((n) => n.r);
1736
- const { FRAMEWORK_REGISTRY } = await import("./registry-DpROZPnl.js").then((n) => n.n);
1737
- const { detectFramework, gatherFrameworkContext } = await import("./detection-OCF8fpfp.js").then((n) => n.t);
1738
- const { analytics } = await import("./analytics-Bw8E-yhX.js");
1739
- const { wizardAbort } = await import("./wizard-abort-CYW83OG5.js");
2485
+ const { posthogIntegrationConfig } = await import("./posthog-integration-D-DyEJvz.js").then((n) => n.r);
2486
+ const { FRAMEWORK_REGISTRY } = await import("./registry-CofBzIdU.js").then((n) => n.n);
2487
+ const { detectFramework, gatherFrameworkContext } = await import("./detection-0Pz2NncX.js").then((n) => n.t);
2488
+ const { analytics } = await import("./analytics-BnR9904x.js");
2489
+ const { wizardAbort } = await import("./wizard-abort-CuaS1eXn.js");
1740
2490
  runWizardCI(posthogIntegrationConfig, options, async (session) => {
1741
2491
  const integration = session.integration ?? await detectFramework(session.installDir);
1742
2492
  if (!integration) {
@@ -1766,10 +2516,10 @@ const cli = yargs(hideBin(process.argv)).env("POSTHOG_WIZARD").options({
1766
2516
  });
1767
2517
  } else if (isNonInteractiveEnvironment()) {
1768
2518
  getUI().intro(`PostHog Wizard`);
1769
- getUI().log.error("This installer requires an interactive terminal (TTY) to run.\nIt appears you are running in a non-interactive environment.\nPlease run the wizard in an interactive terminal.\n\nFor CI/CD environments, use --ci mode:\n npx @posthog/wizard --ci --region us --api-key phx_xxx");
2519
+ getUI().log.error("This installer requires an interactive terminal (TTY) to run.\nIt appears you are running in a non-interactive environment.\n\nNon-interactive (CI) mode is not supported in published builds.\n");
1770
2520
  process.exit(1);
1771
2521
  } else if (options.playground) (async () => {
1772
- const { startPlayground } = await import("./start-playground-zZL5y9id.js");
2522
+ const { startPlayground } = await import("./start-playground-Bxd2KG2L.js");
1773
2523
  startPlayground(WIZARD_VERSION);
1774
2524
  })();
1775
2525
  else if (options.skill) (async () => {
@@ -1792,7 +2542,7 @@ const cli = yargs(hideBin(process.argv)).env("POSTHOG_WIZARD").options({
1792
2542
  });
1793
2543
  })();
1794
2544
  else (async () => {
1795
- const { posthogIntegrationConfig } = await import("./posthog-integration-By5930Gz.js").then((n) => n.r);
2545
+ const { posthogIntegrationConfig } = await import("./posthog-integration-D-DyEJvz.js").then((n) => n.r);
1796
2546
  runWizard(posthogIntegrationConfig, options);
1797
2547
  })();
1798
2548
  }).command("mcp <command>", "MCP server management commands", (yargs) => {
@@ -1816,11 +2566,11 @@ const cli = yargs(hideBin(process.argv)).env("POSTHOG_WIZARD").options({
1816
2566
  const options = { ...argv };
1817
2567
  const mcpFeatures = options.features?.split(",").map((s) => s.trim()).filter(Boolean);
1818
2568
  (async () => {
1819
- const { readApiKeyFromEnv } = await import("./env-api-key-D5G2PrXW.js");
2569
+ const { readApiKeyFromEnv } = await import("./env-api-key-HFqv1l-z.js");
1820
2570
  const apiKey = options.apiKey || readApiKeyFromEnv();
1821
2571
  try {
1822
- const { startTUI } = await import("./start-tui-Cz7RZSn_.js");
1823
- const { buildSession } = await import("./wizard-session-CPhhll4P.js");
2572
+ const { startTUI } = await import("./start-tui-Bl8fCbp_.js");
2573
+ const { buildSession } = await import("./wizard-session-DxU5ZMBN.js");
1824
2574
  const tui = startTUI(WIZARD_VERSION, Program.McpAdd);
1825
2575
  const session = buildSession({
1826
2576
  debug: options.debug,
@@ -1831,7 +2581,7 @@ const cli = yargs(hideBin(process.argv)).env("POSTHOG_WIZARD").options({
1831
2581
  tui.store.session = session;
1832
2582
  } catch {
1833
2583
  setUI(new LoggingUI());
1834
- const { addMCPServerToClientsStep } = await import("./add-mcp-server-to-clients-B48J7VVO.js").then((n) => n.r);
2584
+ const { addMCPServerToClientsStep } = await import("./add-mcp-server-to-clients-Dq0n2yzq.js").then((n) => n.r);
1835
2585
  await addMCPServerToClientsStep({
1836
2586
  local: options.local,
1837
2587
  features: mcpFeatures,
@@ -1849,8 +2599,8 @@ const cli = yargs(hideBin(process.argv)).env("POSTHOG_WIZARD").options({
1849
2599
  const options = { ...argv };
1850
2600
  (async () => {
1851
2601
  try {
1852
- const { startTUI } = await import("./start-tui-Cz7RZSn_.js");
1853
- const { buildSession } = await import("./wizard-session-CPhhll4P.js");
2602
+ const { startTUI } = await import("./start-tui-Bl8fCbp_.js");
2603
+ const { buildSession } = await import("./wizard-session-DxU5ZMBN.js");
1854
2604
  const tui = startTUI(WIZARD_VERSION, Program.McpRemove);
1855
2605
  const session = buildSession({
1856
2606
  debug: options.debug,
@@ -1859,7 +2609,7 @@ const cli = yargs(hideBin(process.argv)).env("POSTHOG_WIZARD").options({
1859
2609
  tui.store.session = session;
1860
2610
  } catch {
1861
2611
  setUI(new LoggingUI());
1862
- const { removeMCPServerFromClientsStep } = await import("./add-mcp-server-to-clients-B48J7VVO.js").then((n) => n.r);
2612
+ const { removeMCPServerFromClientsStep } = await import("./add-mcp-server-to-clients-Dq0n2yzq.js").then((n) => n.r);
1863
2613
  await removeMCPServerFromClientsStep({ local: options.local });
1864
2614
  }
1865
2615
  })();
@@ -1895,7 +2645,7 @@ cli.command("provision", "Create a new PostHog account (headless, no TUI)", (yar
1895
2645
  if (!jsonMode) setUI(new LoggingUI());
1896
2646
  (async () => {
1897
2647
  try {
1898
- const { provisionNewAccount } = await import("./provisioning-gHqu_MXL.js");
2648
+ const { provisionNewAccount } = await import("./provisioning-COeHnCVG.js");
1899
2649
  if (!jsonMode) getUI().log.info(`Provisioning account for ${email} in ${region}...`);
1900
2650
  const result = await provisionNewAccount(email, name, region);
1901
2651
  if (jsonMode) process.stdout.write(`${JSON.stringify(result)}\n`);
@@ -1934,23 +2684,56 @@ for (const programConfig of getSubcommandPrograms()) cli.command(programConfig.c
1934
2684
  if (options.ci) runWizardCI(programConfig, options);
1935
2685
  else runWizard(programConfig, options);
1936
2686
  });
1937
- cli.help().alias("help", "h").version().alias("version", "v").wrap(process.stdout.isTTY ? cli.terminalWidth() : 80).argv;
2687
+ cli.strictOptions().fail((msg, err) => {
2688
+ throw err || new Error(msg);
2689
+ }).help().alias("help", "h").version().alias("version", "v").wrap(process.stdout.isTTY ? cli.terminalWidth() : 80);
2690
+ {
2691
+ const argvHasCI = process.argv.slice(2).some((a) => a === "--ci" || a === "--no-ci" || a.startsWith("--ci="));
2692
+ const envHasCI = process.env.POSTHOG_WIZARD_CI != null && process.env.POSTHOG_WIZARD_CI !== "";
2693
+ if (argvHasCI || envHasCI) exitWithProductionCIError();
2694
+ }
2695
+ try {
2696
+ cli.parse();
2697
+ } catch (err) {
2698
+ const RED = "\x1B[31m";
2699
+ const BOLD = "\x1B[1m";
2700
+ const RESET = "\x1B[0m";
2701
+ const message = err instanceof Error ? err.message : String(err);
2702
+ process.stderr.write(`${RED}${BOLD}✖ ${message}${RESET}\n`);
2703
+ process.stderr.write("Run with --help to see available options.\n");
2704
+ process.exit(1);
2705
+ }
2706
+ function exitWithProductionCIError() {
2707
+ process.stderr.write(`✖ CI mode is not currently supported in published builds.\n`);
2708
+ process.exit(1);
2709
+ }
2710
+ function resolveNoTelemetry(options) {
2711
+ if (options.telemetry === false) return true;
2712
+ const env = process.env.POSTHOG_WIZARD_NO_TELEMETRY;
2713
+ if (env == null || env === "") return false;
2714
+ const norm = env.toLowerCase();
2715
+ return norm !== "0" && norm !== "false";
2716
+ }
1938
2717
  /**
1939
2718
  * Run a full wizard program in the TUI. Handles the full lifecycle: start TUI,
1940
2719
  * build session, run detection, wait for intro gate, execute the
1941
2720
  * agent pipeline, wait for outro dismissal, then exit.
1942
2721
  */
1943
2722
  function runWizard(config, options) {
2723
+ let tui = null;
2724
+ let taskStream = null;
2725
+ let onSignal = null;
2726
+ let exitInProgress = false;
1944
2727
  (async () => {
1945
2728
  try {
1946
2729
  const installDir = options.installDir || process.cwd();
1947
- const { startTUI } = await import("./start-tui-Cz7RZSn_.js");
1948
- const { buildSession } = await import("./wizard-session-CPhhll4P.js");
1949
- const { TaskStreamPush } = await import("./task-stream-DUpUZmFQ.js");
1950
- const { FileDestination } = await import("./file-BKbKreWF.js");
1951
- const { PostHogDestination } = await import("./posthog-BbQf_Hzq.js");
1952
- const { analytics } = await import("./analytics-Bw8E-yhX.js");
1953
- const tui = startTUI(WIZARD_VERSION, config.id);
2730
+ const { startTUI } = await import("./start-tui-Bl8fCbp_.js");
2731
+ const { buildSession, RunPhase } = await import("./wizard-session-DxU5ZMBN.js");
2732
+ const { TaskStreamPush } = await import("./task-stream-z6QFZtpC.js");
2733
+ const { PostHogDestination } = await import("./posthog-B1G0raJU.js");
2734
+ const { logToFile } = await import("./debug-D5kt4fxB.js");
2735
+ tui = startTUI(WIZARD_VERSION, config.id);
2736
+ const activeTui = tui;
1954
2737
  const session = buildSession({
1955
2738
  debug: options.debug,
1956
2739
  forceInstall: options.forceInstall,
@@ -1964,43 +2747,64 @@ function runWizard(config, options) {
1964
2747
  menu: options.menu,
1965
2748
  integration: options.integration,
1966
2749
  benchmark: options.benchmark,
1967
- yaraReport: options.yaraReport
2750
+ yaraReport: options.yaraReport,
2751
+ noTelemetry: resolveNoTelemetry(options)
1968
2752
  });
1969
2753
  session.programLabel = config.id;
1970
2754
  if (options.skillId) session.skillId = options.skillId;
1971
2755
  else if (config.skillId) session.skillId = config.skillId;
1972
- tui.store.session = session;
1973
- const taskStream = new TaskStreamPush({
1974
- store: tui.store,
2756
+ activeTui.store.session = session;
2757
+ const taskStreamEnabled = !session.noTelemetry;
2758
+ taskStream = new TaskStreamPush({
2759
+ store: activeTui.store,
1975
2760
  programId: config.id,
1976
- destinations: [new FileDestination(), new PostHogDestination()]
2761
+ destinations: [new PostHogDestination({
2762
+ getCredentials: () => activeTui.store.session.credentials,
2763
+ onError: (err) => logToFile("[task-stream-push]", err.message)
2764
+ })],
2765
+ enabled: taskStreamEnabled
1977
2766
  });
1978
- tui.store.onTasksChanged = () => void taskStream.push();
1979
- await tui.store.runReadyHooks();
1980
- await tui.store.getGate("intro");
1981
- await tui.store.getGate("health-check");
2767
+ const activeStream = taskStream;
2768
+ activeStream.attach();
2769
+ let signalled = false;
2770
+ onSignal = () => {
2771
+ if (signalled || exitInProgress) return;
2772
+ signalled = true;
2773
+ if (activeTui.store.session.runPhase === RunPhase.Running) activeTui.store.setRunPhase(RunPhase.Error);
2774
+ activeStream.shutdown(2e3).finally(() => {
2775
+ try {
2776
+ activeTui.unmount();
2777
+ } catch {}
2778
+ process.exit(130);
2779
+ });
2780
+ };
2781
+ process.on("SIGINT", onSignal);
2782
+ process.on("SIGTERM", onSignal);
2783
+ await activeTui.store.runReadyHooks();
2784
+ await activeTui.store.getGate("intro");
2785
+ await activeTui.store.getGate("health-check");
1982
2786
  const skipAgent = config.run == null;
1983
2787
  if (skipAgent) {
1984
- const { getOrAskForProjectData } = await import("./setup-utils-ptemIB6g.js");
2788
+ const { getOrAskForProjectData } = await import("./setup-utils-C5iSJ3eg.js");
1985
2789
  const { projectApiKey, host, accessToken, projectId } = await getOrAskForProjectData({
1986
2790
  signup: session.signup,
1987
2791
  ci: session.ci,
1988
2792
  apiKey: session.apiKey,
1989
2793
  projectId: session.projectId
1990
2794
  });
1991
- tui.store.setCredentials({
2795
+ activeTui.store.setCredentials({
1992
2796
  accessToken,
1993
2797
  projectApiKey,
1994
2798
  host,
1995
2799
  projectId
1996
2800
  });
1997
2801
  } else {
1998
- const { runAgent } = await import("./agent-runner-CK5r-zQF.js");
1999
- await runAgent(config, tui.store.session);
2802
+ const { runAgent } = await import("./agent-runner-C9sSudE0.js");
2803
+ await runAgent(config, activeTui.store.session);
2000
2804
  }
2001
- const isDone = () => skipAgent ? tui.store.session.outroDismissed : tui.store.session.skillsComplete;
2805
+ const isDone = () => skipAgent ? activeTui.store.session.outroDismissed : activeTui.store.session.skillsComplete;
2002
2806
  await new Promise((resolve) => {
2003
- const unsub = tui.store.subscribe(() => {
2807
+ const unsub = activeTui.store.subscribe(() => {
2004
2808
  if (isDone()) {
2005
2809
  unsub();
2006
2810
  resolve();
@@ -2011,15 +2815,26 @@ function runWizard(config, options) {
2011
2815
  resolve();
2012
2816
  }
2013
2817
  });
2014
- try {
2015
- await taskStream.dispose();
2016
- } catch (error) {
2017
- analytics.captureException(error);
2018
- }
2019
- tui.unmount();
2818
+ exitInProgress = true;
2819
+ await activeStream.shutdown(2e3);
2820
+ process.off("SIGINT", onSignal);
2821
+ process.off("SIGTERM", onSignal);
2822
+ activeTui.unmount();
2020
2823
  process.exit(0);
2021
2824
  } catch (err) {
2022
2825
  if (runtimeEnv("DEBUG") || runtimeEnv("POSTHOG_WIZARD_DEBUG")) console.error("TUI init failed:", err);
2826
+ exitInProgress = true;
2827
+ if (onSignal) {
2828
+ process.off("SIGINT", onSignal);
2829
+ process.off("SIGTERM", onSignal);
2830
+ }
2831
+ if (taskStream) try {
2832
+ await taskStream.shutdown(2e3);
2833
+ } catch {}
2834
+ if (tui) try {
2835
+ tui.unmount();
2836
+ } catch {}
2837
+ process.exit(1);
2023
2838
  }
2024
2839
  })();
2025
2840
  }
@@ -2046,11 +2861,11 @@ function runWizardCI(config, options, preRun) {
2046
2861
  }
2047
2862
  (async () => {
2048
2863
  const path = await import("path");
2049
- const { buildSession } = await import("./wizard-session-CPhhll4P.js");
2864
+ const { buildSession } = await import("./wizard-session-DxU5ZMBN.js");
2050
2865
  const { readEnvironment } = await Promise.resolve().then(() => environment_exports);
2051
- const { readApiKeyFromEnv } = await import("./env-api-key-D5G2PrXW.js");
2052
- const { configureLogFileFromEnvironment, logToFile } = await import("./debug-B_PK52GI.js");
2053
- const { wizardAbort, WizardError } = await import("./wizard-abort-CYW83OG5.js");
2866
+ const { readApiKeyFromEnv } = await import("./env-api-key-HFqv1l-z.js");
2867
+ const { configureLogFileFromEnvironment, logToFile } = await import("./debug-D5kt4fxB.js");
2868
+ const { wizardAbort, WizardError } = await import("./wizard-abort-CuaS1eXn.js");
2054
2869
  configureLogFileFromEnvironment();
2055
2870
  const env = readEnvironment();
2056
2871
  const apiKey = options.apiKey ?? readApiKeyFromEnv() ?? void 0;
@@ -2069,6 +2884,7 @@ function runWizardCI(config, options, preRun) {
2069
2884
  projectId: options.projectId,
2070
2885
  benchmark: options.benchmark,
2071
2886
  yaraReport: options.yaraReport,
2887
+ noTelemetry: resolveNoTelemetry(options),
2072
2888
  ...env
2073
2889
  });
2074
2890
  session.programLabel = config.id;
@@ -2100,7 +2916,7 @@ function runWizardCI(config, options, preRun) {
2100
2916
  })
2101
2917
  });
2102
2918
  }
2103
- const { runAgent } = await import("./agent-runner-CK5r-zQF.js");
2919
+ const { runAgent } = await import("./agent-runner-C9sSudE0.js");
2104
2920
  await runAgent(config, session);
2105
2921
  } catch (error) {
2106
2922
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -2118,6 +2934,6 @@ function runWizardCI(config, options, preRun) {
2118
2934
  });
2119
2935
  }
2120
2936
  //#endregion
2121
- export { getKindMeta as a, POSTHOG_SDKS as c, getContentBlocks as i, STRIPE_SDKS as l, Program as n, fetchHealthIssues as o, getProgramConfig as r, getContentBlocks$1 as s, PROGRAM_REGISTRY as t };
2937
+ export { SOURCE_MAPS_CONTEXT_KEYS as a, fetchHealthIssues as c, STRIPE_SDKS as d, DISPLAY_NAME as i, getContentBlocks$2 as l, Program as n, getContentBlocks$1 as o, getProgramConfig as r, getKindMeta as s, PROGRAM_REGISTRY as t, POSTHOG_SDKS$1 as u };
2122
2938
 
2123
2939
  //# sourceMappingURL=bin.js.map