@posthog/wizard 2.14.3 → 2.16.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 (94) hide show
  1. package/README.md +43 -1
  2. package/dist/{TextBlock-DEHERFec.js → TextBlock-DJVhBkr3.js} +4 -4
  3. package/dist/TextBlock-DJVhBkr3.js.map +1 -0
  4. package/dist/{add-mcp-server-to-clients-B48J7VVO.js → add-mcp-server-to-clients-9jQjc-CO.js} +5 -5
  5. package/dist/{add-mcp-server-to-clients-B48J7VVO.js.map → add-mcp-server-to-clients-9jQjc-CO.js.map} +1 -1
  6. package/dist/{agent-interface-cEdS_bNo.js → agent-interface-pBnqJL8P.js} +106 -21
  7. package/dist/agent-interface-pBnqJL8P.js.map +1 -0
  8. package/dist/{agent-runner-CK5r-zQF.js → agent-runner-H1FP6XTc.js} +12 -9
  9. package/dist/agent-runner-H1FP6XTc.js.map +1 -0
  10. package/dist/{analytics-DaDpDus8.js → analytics-DZaUgJte.js} +2 -2
  11. package/dist/{analytics-DaDpDus8.js.map → analytics-DZaUgJte.js.map} +1 -1
  12. package/dist/analytics-DqeW7XYt.js +2 -0
  13. package/dist/bin.js +965 -83
  14. package/dist/bin.js.map +1 -1
  15. package/dist/{debug-B_PK52GI.js → debug-B6rX6xye.js} +1 -1
  16. package/dist/{debug-BOogNcWX.js → debug-C4jRuzny.js} +57 -46
  17. package/dist/debug-C4jRuzny.js.map +1 -0
  18. package/dist/{defaults-DgKAzsD1.js → defaults-GbLPuHxj.js} +1 -1
  19. package/dist/{defaults-DgKAzsD1.js.map → defaults-GbLPuHxj.js.map} +1 -1
  20. package/dist/{detection-OCF8fpfp.js → detection-4eukp9HD.js} +3 -3
  21. package/dist/{detection-OCF8fpfp.js.map → detection-4eukp9HD.js.map} +1 -1
  22. package/dist/{env-api-key-D5G2PrXW.js → env-api-key-DU8uIEvo.js} +1 -1
  23. package/dist/{env-api-key-D5G2PrXW.js.map → env-api-key-DU8uIEvo.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/mcp-prompt-streaming-DKiaymMt.js +200 -0
  27. package/dist/mcp-prompt-streaming-DKiaymMt.js.map +1 -0
  28. package/dist/package-json-Cttzi3C8.js +2 -0
  29. package/dist/package-json-v_g2YlN1.js +35 -0
  30. package/dist/package-json-v_g2YlN1.js.map +1 -0
  31. package/dist/{package-manager-CmMJAD-V.js → package-manager-DLt75bit.js} +2 -2
  32. package/dist/package-manager-DLt75bit.js.map +1 -0
  33. package/dist/posthog-7B92c2Ed.js +120 -0
  34. package/dist/posthog-7B92c2Ed.js.map +1 -0
  35. package/dist/{posthog-integration-By5930Gz.js → posthog-integration-CukaeYil.js} +13 -12
  36. package/dist/{posthog-integration-By5930Gz.js.map → posthog-integration-CukaeYil.js.map} +1 -1
  37. package/dist/{provisioning-BHa8VWaa.js → provisioning-C_ETLiZE.js} +3 -3
  38. package/dist/{provisioning-BHa8VWaa.js.map → provisioning-C_ETLiZE.js.map} +1 -1
  39. package/dist/provisioning-Ch6i8dRV.js +2 -0
  40. package/dist/{registry-DpROZPnl.js → registry-DqbwO5EL.js} +31 -31
  41. package/dist/registry-DqbwO5EL.js.map +1 -0
  42. package/dist/setup-utils-C5uZ9g60.js +2 -0
  43. package/dist/{setup-utils-Mzpk1vqG.js → setup-utils-DdAdxUTV.js} +170 -60
  44. package/dist/setup-utils-DdAdxUTV.js.map +1 -0
  45. package/dist/{slides-BtDXEXdn.js → slides-Dpj4j0w_.js} +580 -27
  46. package/dist/slides-Dpj4j0w_.js.map +1 -0
  47. package/dist/smoke-test-ci.sh +5 -2
  48. package/dist/smoke-test.sh +43 -0
  49. package/dist/{start-playground-zZL5y9id.js → start-playground-B40O4tye.js} +288 -6
  50. package/dist/start-playground-B40O4tye.js.map +1 -0
  51. package/dist/{start-tui-Cz7RZSn_.js → start-tui-CH_ZzQXx.js} +628 -26
  52. package/dist/start-tui-CH_ZzQXx.js.map +1 -0
  53. package/dist/{steps-C2XEzN79.js → steps-0d9XqvI6.js} +6 -6
  54. package/dist/{steps-C2XEzN79.js.map → steps-0d9XqvI6.js.map} +1 -1
  55. package/dist/task-stream-CoEsidgG.js +195 -0
  56. package/dist/task-stream-CoEsidgG.js.map +1 -0
  57. package/dist/{telemetry-BG2bOwCp.js → telemetry-jn2Daxl2.js} +2 -2
  58. package/dist/{telemetry-BG2bOwCp.js.map → telemetry-jn2Daxl2.js.map} +1 -1
  59. package/dist/{wizard-abort-BmT-F0Vr.js → wizard-abort-BjLIgu2s.js} +3 -3
  60. package/dist/{wizard-abort-BmT-F0Vr.js.map → wizard-abort-BjLIgu2s.js.map} +1 -1
  61. package/dist/{wizard-abort-CYW83OG5.js → wizard-abort-BlYGA1Jk.js} +1 -1
  62. package/dist/{wizard-session-CsI33S4_.js → wizard-session-Bi95IYca.js} +19 -2
  63. package/dist/wizard-session-Bi95IYca.js.map +1 -0
  64. package/dist/wizard-session-DPGTaJ4W.js +2 -0
  65. package/dist/wizard-ui-YdGFRyu_.js.map +1 -1
  66. package/package.json +3 -2
  67. package/dist/TextBlock-DEHERFec.js.map +0 -1
  68. package/dist/agent-interface-cEdS_bNo.js.map +0 -1
  69. package/dist/agent-runner-CK5r-zQF.js.map +0 -1
  70. package/dist/analytics-Bw8E-yhX.js +0 -2
  71. package/dist/craft-pre-release.sh +0 -10
  72. package/dist/debug-BOogNcWX.js.map +0 -1
  73. package/dist/file-BKbKreWF.js +0 -16
  74. package/dist/file-BKbKreWF.js.map +0 -1
  75. package/dist/file-utils-DPmgn9Vm.js.map +0 -1
  76. package/dist/package-json-DZpnf6vU.js +0 -23
  77. package/dist/package-json-DZpnf6vU.js.map +0 -1
  78. package/dist/package-json-_4PEss19.js +0 -2
  79. package/dist/package-manager-CmMJAD-V.js.map +0 -1
  80. package/dist/paths-DJS47p5x.js +0 -26
  81. package/dist/paths-DJS47p5x.js.map +0 -1
  82. package/dist/posthog-BbQf_Hzq.js +0 -11
  83. package/dist/posthog-BbQf_Hzq.js.map +0 -1
  84. package/dist/provisioning-gHqu_MXL.js +0 -2
  85. package/dist/registry-DpROZPnl.js.map +0 -1
  86. package/dist/setup-utils-Mzpk1vqG.js.map +0 -1
  87. package/dist/setup-utils-ptemIB6g.js +0 -2
  88. package/dist/slides-BtDXEXdn.js.map +0 -1
  89. package/dist/start-playground-zZL5y9id.js.map +0 -1
  90. package/dist/start-tui-Cz7RZSn_.js.map +0 -1
  91. package/dist/task-stream-DUpUZmFQ.js +0 -61
  92. package/dist/task-stream-DUpUZmFQ.js.map +0 -1
  93. package/dist/wizard-session-CPhhll4P.js +0 -2
  94. package/dist/wizard-session-CsI33S4_.js.map +0 -1
@@ -1,2 +1,2 @@
1
- import { n as configureLogFileFromEnvironment, s as logToFile } from "./debug-BOogNcWX.js";
1
+ import { n as configureLogFileFromEnvironment, s as logToFile } from "./debug-C4jRuzny.js";
2
2
  export { configureLogFileFromEnvironment, logToFile };
@@ -1,9 +1,10 @@
1
1
  import "./wizard-ui-YdGFRyu_.js";
2
- import { n as WIZARD_LOG_FILE } from "./paths-DJS47p5x.js";
2
+ import { tmpdir } from "node:os";
3
+ import { join, sep } from "node:path";
3
4
  import { appendFileSync } from "fs";
4
5
  import path from "path";
5
6
  //#region src/lib/version.ts
6
- const VERSION = "2.14.3";
7
+ const VERSION = "2.16.0";
7
8
  //#endregion
8
9
  //#region src/env.ts
9
10
  /**
@@ -116,15 +117,17 @@ const WIZARD_PROVISIONING_SCOPES = [
116
117
  ];
117
118
  /**
118
119
  * Scopes the wizard requests during the OAuth login flow. Superset of
119
- * `WIZARD_PROVISIONING_SCOPES` with two scopes that only apply to the login
120
+ * `WIZARD_PROVISIONING_SCOPES` with scopes that only apply to the login
120
121
  * path and are not in the provisioning allowlist:
121
- * - introspection lets the wizard introspect its own token
122
- * - health_issue:read used by `wizard doctor`
122
+ * - health_issue:read used by `wizard doctor`
123
+ * - wizard_session:read list / retrieve / stream sessions
124
+ * - wizard_session:write stream run state to /api/projects/{id}/wizard/sessions/
123
125
  */
124
126
  const WIZARD_OAUTH_SCOPES = [
125
127
  ...WIZARD_PROVISIONING_SCOPES,
126
- "introspection",
127
- "health_issue:read"
128
+ "health_issue:read",
129
+ "wizard_session:read",
130
+ "wizard_session:write"
128
131
  ];
129
132
  const WIZARD_INTERACTION_EVENT_NAME = "wizard interaction";
130
133
  const WIZARD_REMARK_EVENT_NAME = "wizard remark";
@@ -556,6 +559,7 @@ var LoggingUI = class {
556
559
  console.log(`│ ${url}`);
557
560
  }
558
561
  }
562
+ setAuthorizeUrl(_url) {}
559
563
  showBlockingOutage(result) {
560
564
  console.log(`▲ Service health issues detected — blocking outage.`);
561
565
  const blockingKeys = getBlockingServiceKeys(result.health);
@@ -582,6 +586,9 @@ var LoggingUI = class {
582
586
  showPortConflict(_processInfo) {
583
587
  return Promise.resolve();
584
588
  }
589
+ waitForManualAuthCode() {
590
+ return new Promise(() => {});
591
+ }
585
592
  showSettingsOverride(_conflicts, _backupAndFix) {
586
593
  return Promise.resolve();
587
594
  }
@@ -604,6 +611,8 @@ var LoggingUI = class {
604
611
  }
605
612
  startRun() {}
606
613
  setCredentials(_credentials) {}
614
+ setRoleAtOrganization(_role) {}
615
+ setApiUser(_user) {}
607
616
  syncTodos(todos) {
608
617
  const completed = todos.filter((t) => t.status === "completed").length;
609
618
  const inProgress = todos.find((t) => t.status === "in_progress");
@@ -623,69 +632,71 @@ function setUI(ui) {
623
632
  currentUI = ui;
624
633
  }
625
634
  //#endregion
635
+ //#region src/utils/paths.ts
636
+ const TMP = process.platform === "win32" ? tmpdir() : "/tmp";
637
+ const WIZARD_LOG_FILE = join(TMP, "posthog-wizard.log");
638
+ const WIZARD_BENCHMARK_FILE = join(TMP, "posthog-wizard-benchmark.json");
639
+ const WIZARD_YARA_REPORT_FILE = join(TMP, "posthog-wizard-yara-report.json");
640
+ /** Temp path for a skill download zip. */
641
+ function skillTmpPath(skillId) {
642
+ return join(TMP, `posthog-skill-${skillId}.zip`);
643
+ }
644
+ /**
645
+ * Strip an absolute installDir prefix off a project file path so the UI
646
+ * renders `index.js:12` instead of `/Users/.../index.js:12`. Defends
647
+ * against false matches like `/Users/foo` ⊂ `/Users/foobar/x.js` by
648
+ * normalizing to a trailing path separator before the prefix check.
649
+ */
650
+ function relativeToInstallDir(file, installDir) {
651
+ const prefix = installDir.endsWith(sep) ? installDir : installDir + sep;
652
+ return file.startsWith(prefix) ? file.slice(prefix.length) : file;
653
+ }
654
+ //#endregion
626
655
  //#region src/utils/debug.ts
627
- function formatLogValue(value) {
656
+ let logFilePath = WIZARD_LOG_FILE;
657
+ let fileLoggingEnabled = true;
658
+ let consoleLoggingEnabled = false;
659
+ function stringify(value) {
628
660
  if (typeof value === "string") return value;
629
661
  if (value instanceof Error) return value.stack ?? "";
630
662
  return JSON.stringify(value, null, 2);
631
663
  }
632
- let debugEnabled = false;
633
- let logFilePath = WIZARD_LOG_FILE;
634
- let logEnabled = true;
664
+ function renderLine(args) {
665
+ return args.map(stringify).join(" ");
666
+ }
635
667
  function getLogFilePath() {
636
668
  return logFilePath;
637
669
  }
638
- /**
639
- * Configure the log file path and enable/disable state.
640
- * Call before initLogFile() to override defaults.
641
- */
642
670
  function configureLogFile(opts) {
643
671
  if (opts.path !== void 0) logFilePath = opts.path;
644
- if (opts.enabled !== void 0) logEnabled = opts.enabled;
672
+ if (opts.enabled !== void 0) fileLoggingEnabled = opts.enabled;
645
673
  }
646
- /**
647
- * Configure log path from environment variables.
648
- *
649
- * Uses POSTHOG_WIZARD_LOG_DIR when set, joined with posthog-wizard.log.
650
- */
651
674
  function configureLogFileFromEnvironment() {
652
- const envLogDir = runtimeEnv("POSTHOG_WIZARD_LOG_DIR");
653
- if (envLogDir) configureLogFile({ path: path.join(envLogDir, "posthog-wizard.log") });
675
+ const dir = runtimeEnv("POSTHOG_WIZARD_LOG_DIR");
676
+ if (dir) configureLogFile({ path: path.join(dir, "posthog-wizard.log") });
654
677
  }
655
- /**
656
- * Initialize the log file with a run header.
657
- * Call this at the start of each wizard run.
658
- * Fails silently to avoid crashing the wizard.
659
- */
660
678
  function initLogFile() {
661
- if (!logEnabled) return;
679
+ if (!fileLoggingEnabled) return;
662
680
  try {
663
- const header = `\n${"=".repeat(60)}\nPostHog Wizard Run: ${(/* @__PURE__ */ new Date()).toISOString()}\n${"=".repeat(60)}\n`;
664
- appendFileSync(logFilePath, header);
681
+ const divider = "=".repeat(60);
682
+ appendFileSync(logFilePath, `\n${divider}\nPostHog Wizard Run: ${(/* @__PURE__ */ new Date()).toISOString()}\n${divider}\n`);
665
683
  } catch {}
666
684
  }
667
- /**
668
- * Log a message to the log file.
669
- * Always writes regardless of debug flag (when logging is enabled).
670
- * Fails silently to avoid masking errors in catch blocks.
671
- */
672
685
  function logToFile(...args) {
673
- if (!logEnabled) return;
686
+ if (!fileLoggingEnabled) return;
674
687
  try {
675
- const timestamp = (/* @__PURE__ */ new Date()).toISOString();
676
- const msg = args.map((a) => formatLogValue(a)).join(" ");
677
- appendFileSync(logFilePath, `[${timestamp}] ${msg}\n`);
688
+ const ts = (/* @__PURE__ */ new Date()).toISOString();
689
+ appendFileSync(logFilePath, `[${ts}] ${renderLine(args)}\n`);
678
690
  } catch {}
679
691
  }
680
692
  function debug(...args) {
681
- if (!debugEnabled) return;
682
- const msg = args.map((a) => formatLogValue(a)).join(" ");
683
- getUI().log.info(msg);
693
+ if (!consoleLoggingEnabled) return;
694
+ getUI().log.info(renderLine(args));
684
695
  }
685
696
  function enableDebugLogs() {
686
- debugEnabled = true;
697
+ consoleLoggingEnabled = true;
687
698
  }
688
699
  //#endregion
689
- export { POSTHOG_PROPERTY_HEADER_PREFIX as A, WIZARD_VARIANTS as B, Integration as C, POSTHOG_DOCS_URL as D, POSTHOG_DEV_CLIENT_ID as E, WIZARD_OAUTH_SCOPES as F, VERSION as G, getSkillsBaseUrl as H, WIZARD_PROVISIONING_SCOPES as I, WIZARD_REMARK_EVENT_NAME as L, POSTHOG_US_CLIENT_ID as M, REMOTE_SKILLS_BASE_URL as N, POSTHOG_FLAG_HEADER_PREFIX as O, WIZARD_INTERACTION_EVENT_NAME as P, WIZARD_TOOLS_MENU_FLAG_KEY as R, ISSUES_URL as S, OAUTH_TIMEOUT_MS as T, NODE_ENV as U, WIZARD_VARIANT_FLAG_KEY as V, runtimeEnv as W, ANALYTICS_TEAM_TAG as _, getLogFilePath as a, DETECTION_TIMEOUT_MS as b, getUI as c, SERVICE_LABELS as d, SIGNUP_WIZARD_READINESS_CONFIG as f, ANALYTICS_POSTHOG_PUBLIC_PROJECT_WRITE_KEY as g, ANALYTICS_HOST_URL as h, enableDebugLogs as i, POSTHOG_PROXY_CLIENT_ID as j, POSTHOG_OAUTH_URL as k, setUI as l, getBlockingServiceKeys as m, configureLogFileFromEnvironment as n, initLogFile as o, evaluateWizardReadiness as p, debug as r, logToFile as s, configureLogFile as t, LoggingUI as u, CONTEXT_MILL_URL as v, OAUTH_PORTS as w, DUMMY_PROJECT_API_KEY as x, DEFAULT_HOST_URL as y, WIZARD_USER_AGENT as z };
700
+ export { OAUTH_TIMEOUT_MS as A, WIZARD_OAUTH_SCOPES as B, CONTEXT_MILL_URL as C, ISSUES_URL as D, DUMMY_PROJECT_API_KEY as E, POSTHOG_PROPERTY_HEADER_PREFIX as F, WIZARD_VARIANTS as G, WIZARD_REMARK_EVENT_NAME as H, POSTHOG_PROXY_CLIENT_ID as I, NODE_ENV as J, WIZARD_VARIANT_FLAG_KEY as K, POSTHOG_US_CLIENT_ID as L, POSTHOG_DOCS_URL as M, POSTHOG_FLAG_HEADER_PREFIX as N, Integration as O, POSTHOG_OAUTH_URL as P, REMOTE_SKILLS_BASE_URL as R, ANALYTICS_TEAM_TAG as S, DETECTION_TIMEOUT_MS as T, WIZARD_TOOLS_MENU_FLAG_KEY as U, WIZARD_PROVISIONING_SCOPES as V, WIZARD_USER_AGENT as W, VERSION as X, runtimeEnv as Y, SIGNUP_WIZARD_READINESS_CONFIG as _, getLogFilePath as a, ANALYTICS_HOST_URL as b, WIZARD_BENCHMARK_FILE as c, relativeToInstallDir as d, skillTmpPath as f, SERVICE_LABELS as g, LoggingUI as h, enableDebugLogs as i, POSTHOG_DEV_CLIENT_ID as j, OAUTH_PORTS as k, WIZARD_LOG_FILE as l, setUI as m, configureLogFileFromEnvironment as n, initLogFile as o, getUI as p, getSkillsBaseUrl as q, debug as r, logToFile as s, configureLogFile as t, WIZARD_YARA_REPORT_FILE as u, evaluateWizardReadiness as v, DEFAULT_HOST_URL as w, ANALYTICS_POSTHOG_PUBLIC_PROJECT_WRITE_KEY as x, getBlockingServiceKeys as y, WIZARD_INTERACTION_EVENT_NAME as z };
690
701
 
691
- //# sourceMappingURL=debug-BOogNcWX.js.map
702
+ //# sourceMappingURL=debug-C4jRuzny.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debug-C4jRuzny.js","names":["errResult"],"sources":["../src/lib/version.ts","../src/env.ts","../src/lib/constants.ts","../src/lib/health-checks/statuspage.ts","../src/lib/health-checks/incidentio.ts","../src/lib/health-checks/endpoints.ts","../src/lib/health-checks/readiness.ts","../src/ui/logging-ui.ts","../src/ui/index.ts","../src/utils/paths.ts","../src/utils/debug.ts"],"sourcesContent":["// Auto-generated by scripts/generate-version.js — do not edit\nexport const VERSION = '2.16.0';\n","/**\n * Central environment variable access for the PostHog wizard.\n *\n * ── Build-time constants ────────────────────────────────────────────\n * Inlined by tsdown's `env` option at compile time. After build, the\n * runtime value of these env vars has zero effect on the wizard.\n *\n * ── Runtime variables ───────────────────────────────────────────────\n * Read through `runtimeEnv()` with a typed allowlist. This makes every\n * runtime dependency on the environment explicit and grep-able.\n *\n * ── Direct process.env access ───────────────────────────────────────\n * Reserved for subprocess environment configuration (writes) and\n * vendored code. Production source outside those cases should use\n * this module instead.\n */\n\n// ── Build-time constants ─────────────────────────────────────────────\n// tsdown replaces `process.env.NODE_ENV` with a string literal.\n// After build these are just `\"production\"`, `false`, etc.\n\nexport const NODE_ENV = process.env.NODE_ENV as string;\nexport const IS_DEV =\n process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test';\n\n/**\n * True only in published/production builds. tsdown inlines\n * `process.env.NODE_ENV` as the literal `\"production\"` at build time, so this\n * collapses to `true` in `dist/` and stays `false` for `tsx`/dev/test runs\n * (where NODE_ENV is unset, `development`, or `test`). Used to gate features\n * that aren't supported in the shipped package — e.g. `--ci` mode.\n */\nexport const IS_PRODUCTION_BUILD = process.env.NODE_ENV === 'production';\n\n// ── Runtime environment ──────────────────────────────────────────────\n\n/**\n * Exhaustive allowlist of env vars the wizard reads at runtime.\n * Add new keys here when a new runtime dependency is needed.\n */\ntype RuntimeEnvKey =\n // Wizard CLI configuration (yargs POSTHOG_WIZARD_ prefix)\n | 'POSTHOG_WIZARD_BENCHMARK_CONFIG'\n | 'POSTHOG_WIZARD_BENCHMARK_FILE'\n | 'POSTHOG_WIZARD_LOG_DIR'\n | 'POSTHOG_WIZARD_DEBUG'\n | 'DEBUG'\n // Agent / MCP\n | 'MCP_URL'\n | 'POSTHOG_API_KEY'\n // Platform: terminal detection\n | 'TERM'\n | 'TERM_PROGRAM'\n | 'TERMINAL_EMULATOR'\n | 'CI'\n | 'WT_SESSION'\n | 'TERMINUS_SUBLIME'\n | 'ConEmuTask'\n // Platform: paths\n | 'APPDATA'\n | 'XDG_CONFIG_HOME';\n\n/** Read a runtime environment variable. Only allowlisted keys compile. */\nexport function runtimeEnv(key: RuntimeEnvKey): string | undefined {\n return process.env[key];\n}\n","/**\n * Shared constants for the PostHog wizard.\n */\n\nimport { VERSION } from './version';\n\n// ── Integration / CLI ───────────────────────────────────────────────\n\n/**\n * Detection order matters: put framework-specific integrations BEFORE basic language fallbacks.\n */\nexport enum Integration {\n // Frameworks\n nextjs = 'nextjs',\n nuxt = 'nuxt',\n vue = 'vue',\n reactRouter = 'react-router',\n tanstackStart = 'tanstack-start',\n tanstackRouter = 'tanstack-router',\n reactNative = 'react-native',\n angular = 'angular',\n astro = 'astro',\n django = 'django',\n flask = 'flask',\n fastapi = 'fastapi',\n laravel = 'laravel',\n sveltekit = 'sveltekit',\n swift = 'swift',\n android = 'android',\n rails = 'rails',\n\n // Language fallbacks\n python = 'python',\n ruby = 'ruby',\n javascriptNode = 'javascript_node',\n javascript_web = 'javascript_web',\n}\n\nexport interface Args {\n debug: boolean;\n integration: Integration;\n}\n\n// ── Environment ──────────────────────────────────────────────────────\n\nimport { IS_DEV } from '@env';\nexport { IS_DEV };\nexport const DEBUG = false;\n\n// ── URLs ─────────────────────────────────────────────────────────────\n\nexport const DEFAULT_URL = IS_DEV\n ? 'http://localhost:8010'\n : 'https://us.posthog.com';\nexport const DEFAULT_HOST_URL = IS_DEV\n ? 'http://localhost:8010'\n : 'https://us.i.posthog.com';\nexport const ISSUES_URL = 'https://github.com/posthog/wizard/issues';\nexport const CONTEXT_MILL_URL = 'https://github.com/PostHog/context-mill';\nexport const POSTHOG_DOCS_URL = 'https://posthog.com/docs';\n\n/** Remote base URL for fetching the skill menu + downloading skills. */\nexport const REMOTE_SKILLS_BASE_URL =\n 'https://github.com/PostHog/context-mill/releases/latest/download';\n/** Local base URL when `--local-mcp` is set (served by context-mill dev server). */\nexport const LOCAL_SKILLS_BASE_URL = 'http://localhost:8765';\n\n/**\n * Pick the skills base URL based on the session's localMcp flag.\n * Single source of truth — do not inline this ternary anywhere.\n */\nexport function getSkillsBaseUrl(localMcp: boolean): string {\n return localMcp ? LOCAL_SKILLS_BASE_URL : REMOTE_SKILLS_BASE_URL;\n}\n\n// ── Analytics (internal) ──────────────────────────────────────────────\n\nexport const ANALYTICS_POSTHOG_PUBLIC_PROJECT_WRITE_KEY = 'sTMFPsFhdP1Ssg';\nexport const ANALYTICS_HOST_URL = 'https://internal-j.posthog.com';\nexport const ANALYTICS_TEAM_TAG = 'docs-and-wizard';\n\n// ── OAuth / Auth ────────────────────────────────────────────────────\n\nexport const POSTHOG_OAUTH_URL = IS_DEV\n ? 'http://localhost:8010'\n : 'https://oauth.posthog.com';\nexport const OAUTH_PORTS = [8239, 8238, 8240, 8237, 8236, 8235] as const;\nexport const POSTHOG_US_CLIENT_ID = 'c4Rdw8DIxgtQfA80IiSnGKlNX8QN00cFWF00QQhM';\nexport const POSTHOG_EU_CLIENT_ID = 'bx2C5sZRN03TkdjraCcetvQFPGH6N2Y9vRLkcKEy';\nexport const POSTHOG_DEV_CLIENT_ID = 'DC5uRLVbGI02YQ82grxgnK6Qn12SXWpCqdPb60oZ';\nexport const POSTHOG_PROXY_CLIENT_ID = POSTHOG_US_CLIENT_ID;\nexport const DUMMY_PROJECT_API_KEY = '_YOUR_POSTHOG_PROJECT_TOKEN_';\n\n/**\n * Scopes the wizard requests during the agentic provisioning signup flow.\n *\n * Each entry is justified by what the wizard's agent step does after signup:\n * - user:read identify the user for analytics + agent context\n * - project:read look up the freshly-provisioned project\n * - llm_gateway:read authenticate to gateway.{us,eu}.posthog.com/wizard\n * (the agent's LLM calls — without this scope, every\n * agent message returns 401)\n * - query:read run HogQL queries when the agent needs data\n * - dashboard:write create the onboarding dashboard during setup\n * - insight:write create the onboarding insights during setup\n *\n * Must be a subset of `ALLOWED_PROVISIONING_SCOPES` in\n * `ee/api/agentic_provisioning/views.py` on the backend.\n */\nexport const WIZARD_PROVISIONING_SCOPES = [\n 'user:read',\n 'project:read',\n 'llm_gateway:read',\n 'dashboard:write',\n 'insight:write',\n 'query:read',\n] as const;\n\n/**\n * Scopes the wizard requests during the OAuth login flow. Superset of\n * `WIZARD_PROVISIONING_SCOPES` with scopes that only apply to the login\n * path and are not in the provisioning allowlist:\n * - health_issue:read used by `wizard doctor`\n * - wizard_session:read list / retrieve / stream sessions\n * - wizard_session:write stream run state to /api/projects/{id}/wizard/sessions/\n */\nexport const WIZARD_OAUTH_SCOPES = [\n ...WIZARD_PROVISIONING_SCOPES,\n 'health_issue:read',\n 'wizard_session:read',\n 'wizard_session:write',\n] as const;\n\n// ── Wizard run / variants ───────────────────────────────────────────\n\nexport const WIZARD_INTERACTION_EVENT_NAME = 'wizard interaction';\nexport const WIZARD_REMARK_EVENT_NAME = 'wizard remark';\n/** Feature flag key whose value selects a variant from WIZARD_VARIANTS. */\nexport const WIZARD_VARIANT_FLAG_KEY = 'wizard-variant';\n/** Feature flag key that gates the intro-screen \"Tools\" menu. */\nexport const WIZARD_TOOLS_MENU_FLAG_KEY = 'wizard-tools-menu';\n/** Variant key -> metadata for wizard run (VARIANT flag selects which entry to use). */\nexport const WIZARD_VARIANTS: Record<string, Record<string, string>> = {\n base: { VARIANT: 'base' },\n subagents: { VARIANT: 'subagents' },\n};\n/** User-Agent for wizard HTTP requests and MCP server identification. */\nexport const WIZARD_USER_AGENT = `posthog/wizard; version: ${VERSION}`;\n\n// ── HTTP headers ─────────────────────────────────────────────────────\n\n/** Header prefix for PostHog properties (e.g. X-POSTHOG-PROPERTY-VARIANT). */\nexport const POSTHOG_PROPERTY_HEADER_PREFIX = 'X-POSTHOG-PROPERTY-';\n/** Header prefix for PostHog feature flags. */\nexport const POSTHOG_FLAG_HEADER_PREFIX = 'X-POSTHOG-FLAG-';\n\n// ── Timeouts ─────────────────────────────────────────────────────────\n\n/** Timeout for framework / project detection probes (ms). */\nexport const DETECTION_TIMEOUT_MS = 10_000;\n\n/** Timeout for the OAuth authorization flow (ms). */\nexport const OAUTH_TIMEOUT_MS = 360_000;\n","import {\n ServiceHealthStatus,\n type BaseHealthResult,\n type ComponentHealthResult,\n} from './types';\n\n// ---------------------------------------------------------------------------\n// Statuspage.io v2 API helpers\n// https://metastatuspage.com/api\n//\n// status.json – page-level rollup; indicator is one of: none | minor | major | critical\n// summary.json – same rollup + component list; component status is one of:\n// operational | degraded_performance | partial_outage | major_outage | under_maintenance\n// https://support.atlassian.com/statuspage/docs/show-service-status-with-components\n// ---------------------------------------------------------------------------\n\ninterface StatuspageStatusResponse {\n status?: { indicator?: string; description?: string };\n}\n\ninterface StatuspageSummaryResponse extends StatuspageStatusResponse {\n components?: { id: string; name: string; status: string }[];\n}\n\nfunction mapIndicator(v: string | null | undefined): ServiceHealthStatus {\n switch (v) {\n case 'none':\n return ServiceHealthStatus.Healthy;\n case 'minor':\n return ServiceHealthStatus.Degraded;\n case 'major':\n case 'critical':\n return ServiceHealthStatus.Down;\n default:\n return ServiceHealthStatus.Degraded;\n }\n}\n\nfunction mapComponentRaw(v: string | null | undefined): ServiceHealthStatus {\n switch (v) {\n case 'operational':\n return ServiceHealthStatus.Healthy;\n case 'degraded_performance':\n case 'under_maintenance':\n return ServiceHealthStatus.Degraded;\n case 'partial_outage':\n case 'major_outage':\n return ServiceHealthStatus.Down;\n default:\n return ServiceHealthStatus.Degraded;\n }\n}\n\nfunction errResult(error: string): BaseHealthResult {\n return { status: ServiceHealthStatus.Degraded, error };\n}\n\nasync function fetchStatuspageIndicator(\n url: string,\n timeoutMs = 5000,\n): Promise<BaseHealthResult> {\n try {\n const controller = new AbortController();\n const tid = setTimeout(() => controller.abort(), timeoutMs);\n const res = await fetch(url, { signal: controller.signal });\n clearTimeout(tid);\n\n if (!res.ok) return errResult(`HTTP ${res.status}`);\n\n const data = (await res.json()) as StatuspageStatusResponse;\n const indicator = data.status?.indicator ?? null;\n return {\n status: mapIndicator(indicator),\n rawIndicator: indicator ?? undefined,\n };\n } catch (e) {\n if (e instanceof Error && e.name === 'AbortError')\n return errResult('Request timed out');\n return errResult(e instanceof Error ? e.message : 'Unknown error');\n }\n}\n\nasync function fetchStatuspageSummary(\n url: string,\n timeoutMs = 5000,\n): Promise<ComponentHealthResult> {\n try {\n const controller = new AbortController();\n const tid = setTimeout(() => controller.abort(), timeoutMs);\n const res = await fetch(url, { signal: controller.signal });\n clearTimeout(tid);\n\n if (!res.ok) return errResult(`HTTP ${res.status}`);\n\n const data = (await res.json()) as StatuspageSummaryResponse;\n const indicator = data.status?.indicator ?? null;\n const overall = mapIndicator(indicator);\n\n const affected = (data.components ?? [])\n .map((c) => ({\n name: c.name,\n status: mapComponentRaw(c.status),\n rawStatus: c.status,\n }))\n .filter((c) => c.status !== ServiceHealthStatus.Healthy);\n\n return {\n status: affected.length > 0 ? ServiceHealthStatus.Degraded : overall,\n rawIndicator: indicator ?? undefined,\n degradedOrDownComponents: affected.length > 0 ? affected : undefined,\n };\n } catch (e) {\n if (e instanceof Error && e.name === 'AbortError')\n return errResult('Request timed out');\n return errResult(e instanceof Error ? e.message : 'Unknown error');\n }\n}\n\n// ---------------------------------------------------------------------------\n// Individual statuspage-backed checks\n// ---------------------------------------------------------------------------\n\nexport const checkAnthropicHealth = (): Promise<BaseHealthResult> =>\n fetchStatuspageIndicator('https://status.claude.com/api/v2/status.json');\n\nexport const checkGithubHealth = (): Promise<BaseHealthResult> =>\n fetchStatuspageIndicator('https://www.githubstatus.com/api/v2/status.json');\n\nexport const checkNpmOverallHealth = (): Promise<BaseHealthResult> =>\n fetchStatuspageIndicator('https://status.npmjs.org/api/v2/status.json');\n\nexport const checkNpmComponentHealth = (): Promise<ComponentHealthResult> =>\n fetchStatuspageSummary('https://status.npmjs.org/api/v2/summary.json');\n\nexport const checkCloudflareOverallHealth = (): Promise<BaseHealthResult> =>\n fetchStatuspageIndicator(\n 'https://www.cloudflarestatus.com/api/v2/status.json',\n );\n\nexport const checkCloudflareComponentHealth =\n (): Promise<ComponentHealthResult> =>\n fetchStatuspageSummary(\n 'https://www.cloudflarestatus.com/api/v2/summary.json',\n );\n","import {\n ServiceHealthStatus,\n type BaseHealthResult,\n type ComponentHealthResult,\n type ComponentStatus,\n} from './types';\n\ninterface IncidentIoAffectedComponent {\n id: string;\n name: string;\n group_name?: string;\n current_status: string;\n}\n\ninterface IncidentIoIncident {\n id: string;\n name: string;\n status: string;\n current_worst_impact: string;\n affected_components: IncidentIoAffectedComponent[];\n}\n\ninterface IncidentIoSummary {\n ongoing_incidents: IncidentIoIncident[];\n in_progress_maintenances: unknown[];\n}\n\nfunction mapIncidentImpact(impact: string): ServiceHealthStatus {\n switch (impact) {\n case 'full_outage':\n return ServiceHealthStatus.Down;\n case 'partial_outage':\n case 'degraded_performance':\n return ServiceHealthStatus.Degraded;\n default:\n return ServiceHealthStatus.Degraded;\n }\n}\n\nfunction mapComponentStatus(status: string): ServiceHealthStatus {\n switch (status) {\n case 'operational':\n return ServiceHealthStatus.Healthy;\n case 'full_outage':\n return ServiceHealthStatus.Down;\n case 'partial_outage':\n case 'degraded_performance':\n return ServiceHealthStatus.Degraded;\n default:\n return ServiceHealthStatus.Degraded;\n }\n}\n\nfunction errResult(error: string): BaseHealthResult {\n return { status: ServiceHealthStatus.Degraded, error };\n}\n\nconst POSTHOG_STATUS_URL = 'https://www.posthogstatus.com/api/v1/summary';\n\nasync function fetchPosthogStatus(\n timeoutMs = 5000,\n): Promise<{ overall: BaseHealthResult; components: ComponentHealthResult }> {\n try {\n const controller = new AbortController();\n const tid = setTimeout(() => controller.abort(), timeoutMs);\n const res = await fetch(POSTHOG_STATUS_URL, { signal: controller.signal });\n clearTimeout(tid);\n\n if (!res.ok) {\n const err = errResult(`HTTP ${res.status}`);\n return { overall: err, components: err };\n }\n\n const data = (await res.json()) as IncidentIoSummary;\n const incidents = data.ongoing_incidents ?? [];\n\n if (incidents.length === 0) {\n return {\n overall: { status: ServiceHealthStatus.Healthy },\n components: { status: ServiceHealthStatus.Healthy },\n };\n }\n\n let worstOverall = ServiceHealthStatus.Degraded;\n const affected: ComponentStatus[] = [];\n\n for (const incident of incidents) {\n const impact = mapIncidentImpact(incident.current_worst_impact);\n if (impact === ServiceHealthStatus.Down) {\n worstOverall = ServiceHealthStatus.Down;\n }\n\n for (const comp of incident.affected_components ?? []) {\n const compStatus = mapComponentStatus(comp.current_status);\n if (compStatus !== ServiceHealthStatus.Healthy) {\n affected.push({\n name: comp.group_name\n ? `${comp.group_name} — ${comp.name}`\n : comp.name,\n status: compStatus,\n rawStatus: comp.current_status,\n });\n }\n }\n }\n\n return {\n overall: { status: worstOverall },\n components: {\n status:\n affected.length > 0 ? ServiceHealthStatus.Degraded : worstOverall,\n degradedOrDownComponents: affected.length > 0 ? affected : undefined,\n },\n };\n } catch (e) {\n if (e instanceof Error && e.name === 'AbortError') {\n const err = errResult('Request timed out');\n return { overall: err, components: err };\n }\n const err = errResult(e instanceof Error ? e.message : 'Unknown error');\n return { overall: err, components: err };\n }\n}\n\nlet _cache: Promise<{\n overall: BaseHealthResult;\n components: ComponentHealthResult;\n}> | null = null;\n\nfunction getPosthogHealth() {\n if (!_cache) _cache = fetchPosthogStatus();\n return _cache;\n}\n\nexport function resetPosthogHealthCache(): void {\n _cache = null;\n}\n\nexport const checkPosthogOverallHealth = async (): Promise<BaseHealthResult> =>\n (await getPosthogHealth()).overall;\n\nexport const checkPosthogComponentHealth =\n async (): Promise<ComponentHealthResult> =>\n (await getPosthogHealth()).components;\n","import { REMOTE_SKILLS_BASE_URL } from '@lib/constants';\nimport { ServiceHealthStatus, type BaseHealthResult } from './types';\n\n// ---------------------------------------------------------------------------\n// Direct endpoint health checks\n//\n// These ping PostHog-owned services directly (no Statuspage intermediary).\n// A non-expected HTTP status or any network error is treated as Down.\n//\n// LLM Gateway – FastAPI service\n// Source: posthog/services/llm-gateway/src/llm_gateway/api/health.py\n// GET /_liveness → 200 {\"status\":\"alive\"}\n//\n// MCP – Cloudflare Worker\n// Source: posthog/services/mcp/src/index.ts\n// GET / → 200 (HTML landing page)\n// ---------------------------------------------------------------------------\n\nfunction downResult(error: string): BaseHealthResult {\n return { status: ServiceHealthStatus.Down, error };\n}\n\nasync function fetchEndpointHealth(\n url: string,\n timeoutMs = 5000,\n expectedStatus = 200,\n): Promise<BaseHealthResult> {\n try {\n const controller = new AbortController();\n const tid = setTimeout(() => controller.abort(), timeoutMs);\n const res = await fetch(url, { signal: controller.signal });\n clearTimeout(tid);\n\n if (res.status === expectedStatus) {\n return {\n status: ServiceHealthStatus.Healthy,\n rawIndicator: `HTTP ${res.status}`,\n };\n }\n return downResult(`HTTP ${res.status}`);\n } catch (e) {\n if (e instanceof Error && e.name === 'AbortError')\n return downResult('Request timed out');\n return downResult(e instanceof Error ? e.message : 'Unknown error');\n }\n}\n\nexport const checkLlmGatewayHealth = (): Promise<BaseHealthResult> =>\n fetchEndpointHealth('https://gateway.us.posthog.com/_liveness');\n\nexport const checkMcpHealth = (): Promise<BaseHealthResult> =>\n fetchEndpointHealth('https://mcp.posthog.com/');\n\nexport const checkGithubReleasesHealth = (): Promise<BaseHealthResult> =>\n fetchEndpointHealth(`${REMOTE_SKILLS_BASE_URL}/skill-menu.json`);\n","import {\n ServiceHealthStatus,\n type AllServicesHealth,\n type BaseHealthResult,\n type ComponentHealthResult,\n type HealthCheckKey,\n} from './types';\nimport {\n checkAnthropicHealth,\n checkGithubHealth,\n checkNpmOverallHealth,\n checkNpmComponentHealth,\n checkCloudflareOverallHealth,\n checkCloudflareComponentHealth,\n} from './statuspage';\nimport {\n checkPosthogOverallHealth,\n checkPosthogComponentHealth,\n} from './incidentio';\nimport {\n checkLlmGatewayHealth,\n checkMcpHealth,\n checkGithubReleasesHealth,\n} from './endpoints';\nimport { logToFile } from '@utils/debug';\n\n// ---------------------------------------------------------------------------\n// Service labels (used in human-readable reason strings)\n// ---------------------------------------------------------------------------\n\nexport const SERVICE_LABELS: Record<HealthCheckKey, string> = {\n anthropic: 'Anthropic',\n posthogOverall: 'PostHog',\n posthogComponents: 'PostHog (components)',\n github: 'GitHub',\n npmOverall: 'npm',\n npmComponents: 'npm (components)',\n cloudflareOverall: 'Cloudflare',\n cloudflareComponents: 'Cloudflare (components)',\n llmGateway: 'LLM Gateway',\n mcp: 'MCP',\n githubReleases: 'GitHub Releases',\n};\n\n// ---------------------------------------------------------------------------\n// Readiness config\n// ---------------------------------------------------------------------------\n\nexport interface WizardReadinessConfig {\n /** Services where status=Down blocks the run (readiness=No). */\n downBlocksRun: HealthCheckKey[];\n /** Services where status=Degraded (or worse) blocks the run (readiness=No). */\n degradedBlocksRun?: HealthCheckKey[];\n}\n\n/**\n * See README section \"Health checks\" for the full rationale.\n * Adjust these arrays to change what blocks a wizard run.\n */\nexport const DEFAULT_WIZARD_READINESS_CONFIG: WizardReadinessConfig = {\n downBlocksRun: [\n 'anthropic',\n 'npmOverall',\n 'llmGateway',\n 'mcp',\n 'githubReleases',\n ],\n degradedBlocksRun: ['anthropic'],\n};\n\n/**\n * Reduced readiness config for --signup provisioning flows.\n *\n * Provisioning only needs PostHog and the LLM Gateway - it doesn't\n * use Anthropic directly, npm, GitHub Releases, or MCP.\n */\nexport const SIGNUP_WIZARD_READINESS_CONFIG: WizardReadinessConfig = {\n downBlocksRun: ['posthogOverall', 'llmGateway'],\n};\n\n// ---------------------------------------------------------------------------\n// Aggregate check\n// ---------------------------------------------------------------------------\n\nexport async function checkAllExternalServices(): Promise<AllServicesHealth> {\n const [\n anthropic,\n posthogOverall,\n posthogComponents,\n github,\n npmOverall,\n npmComponents,\n cloudflareOverall,\n cloudflareComponents,\n llmGateway,\n mcp,\n githubReleases,\n ] = await Promise.all([\n checkAnthropicHealth(),\n checkPosthogOverallHealth(),\n checkPosthogComponentHealth(),\n checkGithubHealth(),\n checkNpmOverallHealth(),\n checkNpmComponentHealth(),\n checkCloudflareOverallHealth(),\n checkCloudflareComponentHealth(),\n checkLlmGatewayHealth(),\n checkMcpHealth(),\n checkGithubReleasesHealth(),\n ]);\n\n return {\n anthropic,\n posthogOverall,\n posthogComponents,\n github,\n npmOverall,\n npmComponents,\n cloudflareOverall,\n cloudflareComponents,\n llmGateway,\n mcp,\n githubReleases,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Wizard readiness evaluation\n// ---------------------------------------------------------------------------\n\nexport enum WizardReadiness {\n Yes = 'yes',\n No = 'no',\n YesWithWarnings = 'yes_with_warnings',\n}\n\nexport interface WizardReadinessResult {\n decision: WizardReadiness;\n health: AllServicesHealth;\n reasons: string[];\n}\n\nfunction describeResult(label: string, h: BaseHealthResult): string {\n const parts = [`${label}: ${h.status}`];\n if (h.rawIndicator) parts.push(`indicator=${h.rawIndicator}`);\n if (h.error) parts.push(h.error);\n return parts.join(' — ');\n}\n\nconst MAX_COMPONENT_NAMES = 8;\n\nfunction describeComponents(label: string, h: ComponentHealthResult): string {\n const affected = h.degradedOrDownComponents;\n if (!affected || affected.length === 0)\n return `${label} components: all operational`;\n const shown = affected\n .slice(0, MAX_COMPONENT_NAMES)\n .map((c) => `${c.name} (${c.status})`);\n const suffix =\n affected.length > MAX_COMPONENT_NAMES\n ? `, +${affected.length - MAX_COMPONENT_NAMES} more`\n : '';\n return `${label} components impacted: ${shown.join(', ')}${suffix}`;\n}\n\nconst READINESS_TIMEOUT_MS = 10_000;\n\nexport async function evaluateWizardReadiness(\n config: WizardReadinessConfig = DEFAULT_WIZARD_READINESS_CONFIG,\n): Promise<WizardReadinessResult> {\n try {\n const health = await Promise.race([\n checkAllExternalServices(),\n new Promise<AllServicesHealth>((resolve) =>\n setTimeout(\n () => resolve(allUnknown('Health check timed out')),\n READINESS_TIMEOUT_MS,\n ),\n ),\n ]);\n\n const reasons: string[] = [];\n\n for (const key of Object.keys(health) as HealthCheckKey[]) {\n const result = health[key];\n const label = SERVICE_LABELS[key];\n\n reasons.push(describeResult(label, result));\n\n if ('degradedOrDownComponents' in result) {\n reasons.push(describeComponents(label, result));\n }\n }\n\n const blockingKeys = getBlockingServiceKeys(health, config);\n if (blockingKeys.length > 0) {\n logToFile(`[health-checks] blocked by: ${blockingKeys.join(', ')}`);\n return { decision: WizardReadiness.No, health, reasons };\n }\n\n const hasWarnings = Object.values(health).some(\n (h) => h.status !== ServiceHealthStatus.Healthy,\n );\n\n if (hasWarnings) {\n return { decision: WizardReadiness.YesWithWarnings, health, reasons };\n }\n\n return { decision: WizardReadiness.Yes, health, reasons };\n } catch (err) {\n logToFile(\n `[health-checks] error: ${err instanceof Error ? err.message : err}`,\n );\n // Health checks must never block the wizard run\n return {\n decision: WizardReadiness.Yes,\n health: allUnknown('Unexpected error'),\n reasons: ['Health check failed unexpectedly — proceeding anyway'],\n };\n }\n}\n\n// ---------------------------------------------------------------------------\n// Blocking service detection\n// ---------------------------------------------------------------------------\n\n/** Keys that are component-level detail, not top-level services. */\nconst COMPONENT_KEYS: HealthCheckKey[] = [\n 'posthogComponents',\n 'npmComponents',\n 'cloudflareComponents',\n];\n\n/**\n * Get the keys of services that would block a wizard run per the given config.\n */\nexport function getBlockingServiceKeys(\n health: AllServicesHealth,\n config: WizardReadinessConfig = DEFAULT_WIZARD_READINESS_CONFIG,\n): HealthCheckKey[] {\n return (Object.keys(health) as HealthCheckKey[]).filter((key) => {\n if (COMPONENT_KEYS.includes(key)) return false;\n const result = health[key];\n if (\n config.downBlocksRun.includes(key) &&\n result.status === ServiceHealthStatus.Down\n ) {\n return true;\n }\n if (\n (config.degradedBlocksRun ?? []).includes(key) &&\n result.status !== ServiceHealthStatus.Healthy\n ) {\n return true;\n }\n return false;\n });\n}\n\n/** Build an AllServicesHealth where every service is Degraded with the given error. */\nfunction allUnknown(error: string): AllServicesHealth {\n const base: BaseHealthResult = {\n status: ServiceHealthStatus.Degraded,\n error,\n };\n return {\n anthropic: base,\n posthogOverall: base,\n posthogComponents: { ...base },\n github: base,\n npmOverall: base,\n npmComponents: { ...base },\n cloudflareOverall: base,\n cloudflareComponents: { ...base },\n llmGateway: base,\n mcp: base,\n githubReleases: base,\n };\n}\n","/* eslint-disable no-console */\n/**\n * LoggingUI — Logging-only implementation for CI mode.\n * No prompts, no TUI, no interactivity. Just console output.\n */\n\nimport {\n TaskStatus,\n type WizardUI,\n type SpinnerHandle,\n type AuthErrorDetail,\n} from './wizard-ui';\nimport type { SettingsConflict } from '@lib/agent/agent-interface';\nimport type { ApiUser } from '@lib/api';\nimport {\n type WizardReadinessResult,\n getBlockingServiceKeys,\n SERVICE_LABELS,\n} from '@lib/health-checks/readiness';\nimport type {\n AskAnswers,\n OutroData,\n PendingQuestion,\n} from '@lib/wizard-session';\n\nexport class LoggingUI implements WizardUI {\n intro(message: string): void {\n console.log(`┌ ${message}`);\n }\n\n outro(message: string): void {\n console.log(`└ ${message}`);\n }\n\n outroError(data: OutroData): void {\n console.log(`✖ ${data.message ?? 'Wizard aborted'}`);\n if (data.body) console.log(`│ ${data.body}`);\n if (data.docsUrl) console.log(`│ Docs: ${data.docsUrl}`);\n }\n\n waitForOutroDismissed(): Promise<void> {\n return Promise.resolve();\n }\n\n cancel(message: string): void {\n console.log(`■ ${message}`);\n }\n\n log = {\n info(message: string): void {\n console.log(`│ ${message}`);\n },\n warn(message: string): void {\n console.log(`▲ ${message}`);\n },\n error(message: string): void {\n console.log(`✖ ${message}`);\n },\n success(message: string): void {\n console.log(`✔ ${message}`);\n },\n step(message: string): void {\n console.log(`◇ ${message}`);\n },\n };\n\n note(message: string): void {\n console.log(`│ ${message}`);\n }\n\n spinner(): SpinnerHandle {\n return {\n start(message?: string) {\n if (message) console.log(`◌ ${message}`);\n },\n stop(message?: string) {\n if (message) console.log(`● ${message}`);\n },\n message(msg?: string) {\n if (msg) console.log(`◌ ${msg}`);\n },\n };\n }\n\n pushStatus(message: string): void {\n console.log(`◇ ${message}`);\n }\n\n setDetectedFramework(label: string): void {\n console.log(`✔ Framework: ${label}`);\n }\n\n onEnterScreen(_screen: string, _fn: () => void): void {\n // No screen transitions in CI\n }\n\n setLoginUrl(url: string | null): void {\n if (url) {\n console.log(\n `│ If the browser didn't open automatically, use this link:`,\n );\n console.log(`│ ${url}`);\n }\n }\n\n setAuthorizeUrl(_url: string | null): void {\n // Manual-paste modal is TUI-only; CI/non-interactive runs don't use it.\n }\n\n showBlockingOutage(result: WizardReadinessResult): Promise<void> {\n console.log(`▲ Service health issues detected — blocking outage.`);\n const blockingKeys = getBlockingServiceKeys(result.health);\n if (blockingKeys.length > 0) {\n console.log(`│`);\n console.log(`│ Blocking services:`);\n for (const key of blockingKeys) {\n const status = result.health[key].status;\n const error = result.health[key].error;\n const label = SERVICE_LABELS[key];\n const detail = error ? ` — ${error}` : '';\n console.log(`│ ✖ ${label}: ${status}${detail}`);\n }\n console.log(`│`);\n }\n for (const reason of result.reasons) {\n console.log(`│ ${reason}`);\n }\n console.log(`│ The wizard cannot start while these services are down.`);\n return Promise.resolve();\n }\n\n setReadinessWarnings(result: WizardReadinessResult): void {\n console.log(`▲ Service health warnings detected.`);\n for (const reason of result.reasons) {\n console.log(`│ ${reason}`);\n }\n }\n\n showPortConflict(_processInfo: {\n command: string;\n pid: string;\n port: number;\n user: string;\n }): Promise<void> {\n return Promise.resolve();\n }\n\n waitForManualAuthCode(): Promise<string> {\n // No interactive prompt in CI/logging mode — never resolves. CI bypasses\n // OAuth entirely, so this is only here to satisfy the interface.\n return new Promise<string>(() => {\n /* intentionally never resolves */\n });\n }\n\n showSettingsOverride(\n _conflicts: SettingsConflict[],\n _backupAndFix: () => boolean,\n ): Promise<void> {\n return Promise.resolve();\n }\n\n requestQuestion(_question: PendingQuestion): Promise<AskAnswers> {\n return Promise.reject(\n new Error(\n 'wizard_ask is not available in CI / non-interactive mode. ' +\n 'Re-run the wizard without --ci to answer interactively.',\n ),\n );\n }\n\n showAuthError(detail?: AuthErrorDetail): void {\n console.log(`✖ Authentication failed (401)`);\n if (detail?.hasSettingsConflict) {\n console.log(\n `│ Claude Code auth is conflicting with the wizard. Please try again after logging out:`,\n );\n console.log(`│ claude auth logout`);\n } else {\n console.log(\n `│ The PostHog LLM Gateway rejected the API key. Common causes:`,\n );\n console.log(\n `│ - Wrong key type: pass a personal API key (phx_xxx). pha_ is an OAuth access token, phc_ is a project key.`,\n );\n console.log(\n `│ - Missing scope: the personal API key needs the \"llm_gateway:read\" scope.`,\n );\n console.log(`│ - Expired or revoked key.`);\n console.log(\n `│ - Region mismatch: --region must match the region the key was issued in (us vs eu).`,\n );\n }\n if (detail?.logFilePath) {\n console.log(`│ Verbose log: ${detail.logFilePath}`);\n }\n }\n\n startRun(): void {\n // No-op in CI mode\n }\n\n setCredentials(_credentials: {\n accessToken: string;\n projectApiKey: string;\n host: string;\n projectId: number;\n }): void {\n // No-op in CI mode — credentials are handled directly\n }\n\n setRoleAtOrganization(_role: string | null): void {\n // No-op in CI mode — there's no TUI to render role-tailored prompts\n }\n\n setApiUser(_user: ApiUser | null): void {\n // No-op in CI mode — there's no TUI to read account context from\n // the session.\n }\n\n syncTodos(\n todos: Array<{ content: string; status: string; activeForm?: string }>,\n ): void {\n const completed = todos.filter(\n (t) => t.status === TaskStatus.Completed,\n ).length;\n const inProgress = todos.find((t) => t.status === TaskStatus.InProgress);\n if (inProgress) {\n console.log(\n `◌ [${completed}/${todos.length}] ${\n inProgress.activeForm || inProgress.content\n }`,\n );\n }\n }\n\n setEventPlan(_events: Array<{ name: string; description: string }>): void {\n // No-op in CI mode\n }\n\n setDashboardUrl(_url: string): void {\n // No-op in CI mode\n }\n\n setFrameworkContext(_key: string, _value: unknown): void {\n // No-op in CI mode\n }\n}\n","/**\n * UI singleton — provides getUI() and setUI() for the wizard.\n * Default: LoggingUI. Swap to InkUI at startup for TUI mode.\n */\n\nimport type { WizardUI } from './wizard-ui';\nimport { LoggingUI } from './logging-ui';\n\nlet currentUI: WizardUI = new LoggingUI();\n\nexport function getUI(): WizardUI {\n return currentUI;\n}\n\nexport function setUI(ui: WizardUI): void {\n currentUI = ui;\n}\n\nexport type { WizardUI, SpinnerHandle } from './wizard-ui';\n","import { tmpdir } from 'node:os';\nimport { join, sep } from 'node:path';\n\n// /tmp is stable and discoverable on macOS/Linux; Windows needs os.tmpdir()\nconst TMP = process.platform === 'win32' ? tmpdir() : '/tmp';\n\nexport const WIZARD_LOG_FILE = join(TMP, 'posthog-wizard.log');\nexport const WIZARD_BENCHMARK_FILE = join(TMP, 'posthog-wizard-benchmark.json');\nexport const WIZARD_YARA_REPORT_FILE = join(\n TMP,\n 'posthog-wizard-yara-report.json',\n);\n/** Temp path for a skill download zip. */\nexport function skillTmpPath(skillId: string): string {\n return join(TMP, `posthog-skill-${skillId}.zip`);\n}\n\n/**\n * Strip an absolute installDir prefix off a project file path so the UI\n * renders `index.js:12` instead of `/Users/.../index.js:12`. Defends\n * against false matches like `/Users/foo` ⊂ `/Users/foobar/x.js` by\n * normalizing to a trailing path separator before the prefix check.\n */\nexport function relativeToInstallDir(file: string, installDir: string): string {\n const prefix = installDir.endsWith(sep) ? installDir : installDir + sep;\n return file.startsWith(prefix) ? file.slice(prefix.length) : file;\n}\n","import { appendFileSync } from 'fs';\nimport path from 'path';\nimport { getUI } from '@ui';\nimport { runtimeEnv } from '@env';\nimport { WIZARD_LOG_FILE } from './paths';\n\nlet logFilePath = WIZARD_LOG_FILE;\nlet fileLoggingEnabled = true;\nlet consoleLoggingEnabled = false;\n\nfunction stringify(value: unknown): string {\n if (typeof value === 'string') return value;\n if (value instanceof Error) return value.stack ?? '';\n return JSON.stringify(value, null, 2);\n}\n\nfunction renderLine(args: readonly unknown[]): string {\n return args.map(stringify).join(' ');\n}\n\nexport function getLogFilePath(): string {\n return logFilePath;\n}\n\nexport function configureLogFile(opts: {\n path?: string;\n enabled?: boolean;\n}): void {\n if (opts.path !== undefined) logFilePath = opts.path;\n if (opts.enabled !== undefined) fileLoggingEnabled = opts.enabled;\n}\n\nexport function configureLogFileFromEnvironment(): void {\n const dir = runtimeEnv('POSTHOG_WIZARD_LOG_DIR');\n if (dir) {\n configureLogFile({ path: path.join(dir, 'posthog-wizard.log') });\n }\n}\n\nexport function initLogFile(): void {\n if (!fileLoggingEnabled) return;\n try {\n const divider = '='.repeat(60);\n appendFileSync(\n logFilePath,\n `\\n${divider}\\nPostHog Wizard Run: ${new Date().toISOString()}\\n${divider}\\n`,\n );\n } catch {\n // Logging must never crash the wizard.\n }\n}\n\nexport function logToFile(...args: unknown[]): void {\n if (!fileLoggingEnabled) return;\n try {\n const ts = new Date().toISOString();\n appendFileSync(logFilePath, `[${ts}] ${renderLine(args)}\\n`);\n } catch {\n // Logging must never crash the wizard.\n }\n}\n\nexport function debug(...args: unknown[]): void {\n if (!consoleLoggingEnabled) return;\n getUI().log.info(renderLine(args));\n}\n\nexport function enableDebugLogs(): void {\n consoleLoggingEnabled = true;\n}\n"],"mappings":"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"}
@@ -231,4 +231,4 @@ const getDefaultServerConfig = (apiKey, selectedFeatures, local) => {
231
231
  //#endregion
232
232
  export { getNativeHTTPServerConfig as i, AVAILABLE_FEATURES as n, getDefaultServerConfig as r, ALL_FEATURE_VALUES as t };
233
233
 
234
- //# sourceMappingURL=defaults-DgKAzsD1.js.map
234
+ //# sourceMappingURL=defaults-GbLPuHxj.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"defaults-DgKAzsD1.js","names":["z"],"sources":["../src/steps/add-mcp-server-to-clients/defaults.ts"],"sourcesContent":["import z from 'zod';\n\nexport const DefaultMCPClientConfig = z\n .object({\n mcpServers: z.record(\n z.string(),\n z.union([\n z.object({\n command: z.string().optional(),\n args: z.array(z.string()).optional(),\n env: z.record(z.string(), z.string()).optional(),\n }),\n z.object({\n url: z.string(),\n headers: z.record(z.string(), z.string()).optional(),\n }),\n ]),\n ),\n })\n .passthrough();\n\nexport const AVAILABLE_FEATURES = {\n 'Data & Analytics': [\n {\n value: 'dashboards',\n label: 'Dashboards',\n hint: 'Dashboard creation and management',\n },\n {\n value: 'insights',\n label: 'Insights',\n hint: 'Analytics insights',\n },\n {\n value: 'product_analytics',\n label: 'Product Analytics',\n hint: 'Insight CRUD management',\n },\n {\n value: 'experiments',\n label: 'Experiments',\n hint: 'A/B testing experiments',\n },\n {\n value: 'surveys',\n label: 'Surveys',\n hint: 'Survey management',\n },\n {\n value: 'annotations',\n label: 'Annotations',\n hint: 'Annotation management',\n },\n {\n value: 'replay',\n label: 'Session Replay',\n hint: 'Session recording management',\n },\n {\n value: 'sql',\n label: 'SQL',\n hint: 'SQL query execution',\n },\n ],\n 'AI Engineering': [\n {\n value: 'llm_analytics',\n label: 'LLM Analytics',\n hint: 'LLM usage and cost tracking',\n },\n {\n value: 'prompts',\n label: 'Prompts',\n hint: 'LLM prompt management',\n },\n ],\n 'Development Tools': [\n {\n value: 'error_tracking',\n label: 'Error Tracking',\n hint: 'Error monitoring and debugging',\n },\n {\n value: 'logs',\n label: 'Logs',\n hint: 'Log querying',\n },\n {\n value: 'flags',\n label: 'Feature Flags',\n hint: 'Feature flag management',\n },\n {\n value: 'early_access_features',\n label: 'Early Access Features',\n hint: 'Early access feature management',\n },\n {\n value: 'cohorts',\n label: 'Cohorts',\n hint: 'Cohort management',\n },\n ],\n 'Data Management': [\n {\n value: 'events',\n label: 'Events',\n hint: 'Event and property definitions',\n },\n {\n value: 'persons',\n label: 'Persons',\n hint: 'Person and group management',\n },\n {\n value: 'actions',\n label: 'Actions',\n hint: 'Action definitions',\n },\n {\n value: 'data_warehouse',\n label: 'Data Warehouse',\n hint: 'Data warehouse management',\n },\n {\n value: 'endpoints',\n label: 'Endpoints',\n hint: 'Data warehouse endpoint management',\n },\n {\n value: 'data_schema',\n label: 'Data Schema',\n hint: 'Data schema exploration',\n },\n ],\n 'CDP & Automation': [\n {\n value: 'hog_functions',\n label: 'Hog Functions',\n hint: 'CDP function management',\n },\n {\n value: 'hog_function_templates',\n label: 'Hog Function Templates',\n hint: 'CDP function template browsing',\n },\n {\n value: 'workflows',\n label: 'Workflows',\n hint: 'Workflow management',\n },\n ],\n 'Platform & Management': [\n {\n value: 'workspace',\n label: 'Workspace',\n hint: 'Organization and project management',\n },\n {\n value: 'docs',\n label: 'Documentation',\n hint: 'PostHog documentation search',\n },\n {\n value: 'notebooks',\n label: 'Notebooks',\n hint: 'Notebook management',\n },\n {\n value: 'alerts',\n label: 'Alerts',\n hint: 'Alert management',\n },\n {\n value: 'platform_features',\n label: 'Platform Features',\n hint: 'Activity logs, approvals, comments, and roles',\n },\n {\n value: 'integrations',\n label: 'Integrations',\n hint: 'Connected integration management',\n },\n {\n value: 'conversations',\n label: 'Conversations',\n hint: 'Support ticket management',\n },\n {\n value: 'core',\n label: 'Subscriptions',\n hint: 'Scheduled insight and dashboard deliveries',\n },\n {\n value: 'search',\n label: 'Search',\n hint: 'Entity search across the project',\n },\n {\n value: 'reverse_proxy',\n label: 'Reverse Proxy',\n hint: 'Reverse proxy record management',\n },\n {\n value: 'debug',\n label: 'Debug',\n hint: 'Debug and diagnostic tools',\n },\n ],\n};\n\nexport const ALL_FEATURE_VALUES = Object.values(AVAILABLE_FEATURES)\n .flat()\n .map((feature) => feature.value);\n\nexport const buildMCPUrl = (selectedFeatures?: string[], local?: boolean) => {\n const host = local ? 'http://localhost:8787' : 'https://mcp.posthog.com';\n const baseUrl = `${host}/mcp`;\n\n const isAllFeaturesSelected =\n selectedFeatures &&\n selectedFeatures.length === ALL_FEATURE_VALUES.length &&\n ALL_FEATURE_VALUES.every((feature) => selectedFeatures.includes(feature));\n\n const params: string[] = [];\n\n // Add features param if not all features selected\n if (\n selectedFeatures &&\n selectedFeatures.length > 0 &&\n !isAllFeaturesSelected\n ) {\n params.push(`features=${selectedFeatures.join(',')}`);\n }\n\n return params.length > 0 ? `${baseUrl}?${params.join('&')}` : baseUrl;\n};\n\nexport const getNativeHTTPServerConfig = (\n apiKey: string | undefined,\n selectedFeatures?: string[],\n local?: boolean,\n) => {\n const config: Record<string, unknown> = {\n url: buildMCPUrl(selectedFeatures, local),\n };\n\n // Only add auth header if API key is provided (not OAuth mode)\n if (apiKey) {\n config.headers = {\n Authorization: `Bearer ${apiKey}`,\n };\n }\n\n return config;\n};\n\nexport const getDefaultServerConfig = (\n apiKey: string | undefined,\n selectedFeatures?: string[],\n local?: boolean,\n) => {\n const urlWithFeatures = buildMCPUrl(selectedFeatures, local);\n\n // OAuth mode: no auth header, let MCP handle OAuth\n if (!apiKey) {\n return {\n command: 'npx',\n args: ['-y', 'mcp-remote@latest', urlWithFeatures],\n };\n }\n\n // API key mode: include auth header\n return {\n command: 'npx',\n args: [\n '-y',\n 'mcp-remote@latest',\n urlWithFeatures,\n '--header',\n `Authorization:\\${POSTHOG_AUTH_HEADER}`,\n ],\n env: {\n POSTHOG_AUTH_HEADER: `Bearer ${apiKey}`,\n },\n };\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"defaults-GbLPuHxj.js","names":["z"],"sources":["../src/steps/add-mcp-server-to-clients/defaults.ts"],"sourcesContent":["import z from 'zod';\n\nexport const DefaultMCPClientConfig = z\n .object({\n mcpServers: z.record(\n z.string(),\n z.union([\n z.object({\n command: z.string().optional(),\n args: z.array(z.string()).optional(),\n env: z.record(z.string(), z.string()).optional(),\n }),\n z.object({\n url: z.string(),\n headers: z.record(z.string(), z.string()).optional(),\n }),\n ]),\n ),\n })\n .passthrough();\n\nexport const AVAILABLE_FEATURES = {\n 'Data & Analytics': [\n {\n value: 'dashboards',\n label: 'Dashboards',\n hint: 'Dashboard creation and management',\n },\n {\n value: 'insights',\n label: 'Insights',\n hint: 'Analytics insights',\n },\n {\n value: 'product_analytics',\n label: 'Product Analytics',\n hint: 'Insight CRUD management',\n },\n {\n value: 'experiments',\n label: 'Experiments',\n hint: 'A/B testing experiments',\n },\n {\n value: 'surveys',\n label: 'Surveys',\n hint: 'Survey management',\n },\n {\n value: 'annotations',\n label: 'Annotations',\n hint: 'Annotation management',\n },\n {\n value: 'replay',\n label: 'Session Replay',\n hint: 'Session recording management',\n },\n {\n value: 'sql',\n label: 'SQL',\n hint: 'SQL query execution',\n },\n ],\n 'AI Engineering': [\n {\n value: 'llm_analytics',\n label: 'LLM Analytics',\n hint: 'LLM usage and cost tracking',\n },\n {\n value: 'prompts',\n label: 'Prompts',\n hint: 'LLM prompt management',\n },\n ],\n 'Development Tools': [\n {\n value: 'error_tracking',\n label: 'Error Tracking',\n hint: 'Error monitoring and debugging',\n },\n {\n value: 'logs',\n label: 'Logs',\n hint: 'Log querying',\n },\n {\n value: 'flags',\n label: 'Feature Flags',\n hint: 'Feature flag management',\n },\n {\n value: 'early_access_features',\n label: 'Early Access Features',\n hint: 'Early access feature management',\n },\n {\n value: 'cohorts',\n label: 'Cohorts',\n hint: 'Cohort management',\n },\n ],\n 'Data Management': [\n {\n value: 'events',\n label: 'Events',\n hint: 'Event and property definitions',\n },\n {\n value: 'persons',\n label: 'Persons',\n hint: 'Person and group management',\n },\n {\n value: 'actions',\n label: 'Actions',\n hint: 'Action definitions',\n },\n {\n value: 'data_warehouse',\n label: 'Data Warehouse',\n hint: 'Data warehouse management',\n },\n {\n value: 'endpoints',\n label: 'Endpoints',\n hint: 'Data warehouse endpoint management',\n },\n {\n value: 'data_schema',\n label: 'Data Schema',\n hint: 'Data schema exploration',\n },\n ],\n 'CDP & Automation': [\n {\n value: 'hog_functions',\n label: 'Hog Functions',\n hint: 'CDP function management',\n },\n {\n value: 'hog_function_templates',\n label: 'Hog Function Templates',\n hint: 'CDP function template browsing',\n },\n {\n value: 'workflows',\n label: 'Workflows',\n hint: 'Workflow management',\n },\n ],\n 'Platform & Management': [\n {\n value: 'workspace',\n label: 'Workspace',\n hint: 'Organization and project management',\n },\n {\n value: 'docs',\n label: 'Documentation',\n hint: 'PostHog documentation search',\n },\n {\n value: 'notebooks',\n label: 'Notebooks',\n hint: 'Notebook management',\n },\n {\n value: 'alerts',\n label: 'Alerts',\n hint: 'Alert management',\n },\n {\n value: 'platform_features',\n label: 'Platform Features',\n hint: 'Activity logs, approvals, comments, and roles',\n },\n {\n value: 'integrations',\n label: 'Integrations',\n hint: 'Connected integration management',\n },\n {\n value: 'conversations',\n label: 'Conversations',\n hint: 'Support ticket management',\n },\n {\n value: 'core',\n label: 'Subscriptions',\n hint: 'Scheduled insight and dashboard deliveries',\n },\n {\n value: 'search',\n label: 'Search',\n hint: 'Entity search across the project',\n },\n {\n value: 'reverse_proxy',\n label: 'Reverse Proxy',\n hint: 'Reverse proxy record management',\n },\n {\n value: 'debug',\n label: 'Debug',\n hint: 'Debug and diagnostic tools',\n },\n ],\n};\n\nexport const ALL_FEATURE_VALUES = Object.values(AVAILABLE_FEATURES)\n .flat()\n .map((feature) => feature.value);\n\nexport const buildMCPUrl = (selectedFeatures?: string[], local?: boolean) => {\n const host = local ? 'http://localhost:8787' : 'https://mcp.posthog.com';\n const baseUrl = `${host}/mcp`;\n\n const isAllFeaturesSelected =\n selectedFeatures &&\n selectedFeatures.length === ALL_FEATURE_VALUES.length &&\n ALL_FEATURE_VALUES.every((feature) => selectedFeatures.includes(feature));\n\n const params: string[] = [];\n\n // Add features param if not all features selected\n if (\n selectedFeatures &&\n selectedFeatures.length > 0 &&\n !isAllFeaturesSelected\n ) {\n params.push(`features=${selectedFeatures.join(',')}`);\n }\n\n return params.length > 0 ? `${baseUrl}?${params.join('&')}` : baseUrl;\n};\n\nexport const getNativeHTTPServerConfig = (\n apiKey: string | undefined,\n selectedFeatures?: string[],\n local?: boolean,\n) => {\n const config: Record<string, unknown> = {\n url: buildMCPUrl(selectedFeatures, local),\n };\n\n // Only add auth header if API key is provided (not OAuth mode)\n if (apiKey) {\n config.headers = {\n Authorization: `Bearer ${apiKey}`,\n };\n }\n\n return config;\n};\n\nexport const getDefaultServerConfig = (\n apiKey: string | undefined,\n selectedFeatures?: string[],\n local?: boolean,\n) => {\n const urlWithFeatures = buildMCPUrl(selectedFeatures, local);\n\n // OAuth mode: no auth header, let MCP handle OAuth\n if (!apiKey) {\n return {\n command: 'npx',\n args: ['-y', 'mcp-remote@latest', urlWithFeatures],\n };\n }\n\n // API key mode: include auth header\n return {\n command: 'npx',\n args: [\n '-y',\n 'mcp-remote@latest',\n urlWithFeatures,\n '--header',\n `Authorization:\\${POSTHOG_AUTH_HEADER}`,\n ],\n env: {\n POSTHOG_AUTH_HEADER: `Bearer ${apiKey}`,\n },\n };\n};\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-B_-DWIq7.js";
2
- import { C as Integration, b as DETECTION_TIMEOUT_MS } from "./debug-BOogNcWX.js";
3
- import { t as FRAMEWORK_REGISTRY } from "./registry-DpROZPnl.js";
2
+ import { O as Integration, T as DETECTION_TIMEOUT_MS } from "./debug-C4jRuzny.js";
3
+ import { t as FRAMEWORK_REGISTRY } from "./registry-DqbwO5EL.js";
4
4
  import * as semver from "semver";
5
5
  import { readFileSync } from "fs";
6
6
  import { join } from "path";
@@ -203,4 +203,4 @@ var detection_exports = /* @__PURE__ */ __exportAll({
203
203
  //#endregion
204
204
  export { detectFramework as a, discoverFeatures as i, checkFrameworkVersion as n, gatherFrameworkContext as r, detection_exports as t };
205
205
 
206
- //# sourceMappingURL=detection-OCF8fpfp.js.map
206
+ //# sourceMappingURL=detection-4eukp9HD.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"detection-OCF8fpfp.js","names":[],"sources":["../src/lib/detection/framework.ts","../src/lib/detection/features.ts","../src/lib/detection/context.ts","../src/lib/detection/index.ts"],"sourcesContent":["/**\n * Framework detection — identify which PostHog-supported framework\n * is present in the project directory.\n *\n * Pure function: takes an install dir, returns the detected integration\n * (or undefined). No store mutations, no UI calls.\n */\n\nimport { Integration, DETECTION_TIMEOUT_MS } from '@lib/constants';\nimport { FRAMEWORK_REGISTRY } from '@lib/registry';\n\n/**\n * Loop through all registered frameworks and return the first one\n * whose `detect()` predicate matches the given directory.\n * Returns undefined if no framework is detected or detection times out.\n */\nexport async function detectFramework(\n installDir: string,\n): Promise<Integration | undefined> {\n for (const integration of Object.values(Integration)) {\n const config = FRAMEWORK_REGISTRY[integration];\n try {\n const detected = await Promise.race([\n config.detection.detect({ installDir }),\n new Promise<false>((resolve) =>\n setTimeout(() => resolve(false), DETECTION_TIMEOUT_MS),\n ),\n ]);\n if (detected) {\n return integration;\n }\n } catch {\n // Skip frameworks whose detection throws\n }\n }\n}\n","/**\n * Feature discovery — scan project dependencies for known SDK patterns\n * that indicate additional PostHog programs are relevant.\n *\n * Pure function: takes an install dir, returns a set of discovered features.\n * No store mutations, no UI calls.\n */\n\nimport { readFileSync } from 'fs';\nimport { join } from 'path';\nimport { DiscoveredFeature } from '@lib/wizard-session';\n\nconst STRIPE_PACKAGES = ['stripe', '@stripe/stripe-js'];\n\nconst LLM_PACKAGES = [\n 'openai',\n '@anthropic-ai/sdk',\n 'ai',\n '@ai-sdk/openai',\n 'langchain',\n '@langchain/openai',\n '@langchain/langgraph',\n '@google/generative-ai',\n '@google/genai',\n '@instructor-ai/instructor',\n '@mastra/core',\n 'portkey-ai',\n];\n\n// PyPI normalizes `_` to `-` and is case-insensitive; compare via normalizePyName.\nconst PYTHON_LLM_PACKAGES = [\n 'openai',\n 'anthropic',\n 'langchain',\n 'langchain-openai',\n 'langchain-anthropic',\n 'langchain-google-genai',\n 'langgraph',\n 'litellm',\n 'llama-index',\n 'pydantic-ai',\n 'crewai',\n 'instructor',\n 'dspy-ai',\n 'mistralai',\n 'cohere',\n 'google-generativeai',\n 'google-genai',\n 'portkey-ai',\n];\n\nexport function discoverFeatures(installDir: string): DiscoveredFeature[] {\n const features: DiscoveredFeature[] = [];\n discoverNodeFeatures(installDir, features);\n discoverPythonFeatures(installDir, features);\n return features;\n}\n\nfunction discoverNodeFeatures(\n installDir: string,\n features: DiscoveredFeature[],\n): void {\n const packageJsonText = safeRead(installDir, 'package.json');\n if (!packageJsonText) return;\n\n let packageJson: {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n };\n try {\n packageJson = JSON.parse(packageJsonText);\n } catch {\n return;\n }\n\n const depNames = Object.keys({\n ...packageJson.dependencies,\n ...packageJson.devDependencies,\n });\n\n if (depNames.some((depName) => STRIPE_PACKAGES.includes(depName))) {\n features.push(DiscoveredFeature.Stripe);\n }\n if (depNames.some((depName) => LLM_PACKAGES.includes(depName))) {\n features.push(DiscoveredFeature.LLM);\n }\n}\n\nfunction discoverPythonFeatures(\n installDir: string,\n features: DiscoveredFeature[],\n): void {\n if (features.includes(DiscoveredFeature.LLM)) return;\n\n const depNames: string[] = [];\n\n const requirementsTxt = safeRead(installDir, 'requirements.txt');\n if (requirementsTxt) depNames.push(...parseRequirementsTxt(requirementsTxt));\n\n const pyprojectToml = safeRead(installDir, 'pyproject.toml');\n if (pyprojectToml) depNames.push(...parsePyprojectToml(pyprojectToml));\n\n const pipfile = safeRead(installDir, 'Pipfile');\n if (pipfile) depNames.push(...parsePipfile(pipfile));\n\n if (depNames.some((depName) => PYTHON_LLM_PACKAGES.includes(depName))) {\n features.push(DiscoveredFeature.LLM);\n }\n}\n\nfunction safeRead(installDir: string, file: string): string | null {\n try {\n return readFileSync(join(installDir, file), 'utf-8');\n } catch {\n return null;\n }\n}\n\nfunction normalizePyName(name: string): string {\n return name.toLowerCase().replace(/_/g, '-');\n}\n\nexport function parseRequirementsTxt(content: string): string[] {\n return content\n .split('\\n')\n .map((line) => line.trim())\n .filter((line) => line && !line.startsWith('#') && !line.startsWith('-'))\n .map((line) => line.replace(/\\[[^\\]]*\\]/, ''))\n .map((line) => line.split(/[<>=!~;\\s]/)[0])\n .filter(Boolean)\n .map(normalizePyName);\n}\n\n// Pragmatic, not a full TOML parser — only the dep shapes we care about.\nexport function parsePyprojectToml(content: string): string[] {\n const depNames: string[] = [];\n\n for (const arrayMatch of content.matchAll(\n /dependencies\\s*=\\s*\\[([^\\]]*)\\]/g,\n )) {\n const arrayBody = arrayMatch[1];\n for (const quotedMatch of arrayBody.matchAll(/[\"']([^\"']+)[\"']/g)) {\n const depSpec = quotedMatch[1];\n const name = depSpec.replace(/\\[[^\\]]*\\]/, '').split(/[<>=!~;\\s]/)[0];\n if (name) depNames.push(normalizePyName(name));\n }\n }\n\n const poetrySectionRe =\n /\\[tool\\.poetry\\.(?:dev-dependencies|dependencies|group\\.[^.\\]]+\\.dependencies)\\]([\\s\\S]*?)(?=\\n\\[|$)/g;\n for (const sectionMatch of content.matchAll(poetrySectionRe)) {\n const sectionBody = sectionMatch[1];\n depNames.push(...extractTomlSectionKeys(sectionBody, { skip: ['python'] }));\n }\n\n return depNames;\n}\n\nexport function parsePipfile(content: string): string[] {\n const depNames: string[] = [];\n const sectionRe = /\\[(packages|dev-packages)\\]([\\s\\S]*?)(?=\\n\\[|$)/g;\n for (const sectionMatch of content.matchAll(sectionRe)) {\n const sectionBody = sectionMatch[2];\n depNames.push(...extractTomlSectionKeys(sectionBody));\n }\n return depNames;\n}\n\nfunction extractTomlSectionKeys(\n sectionBody: string,\n opts: { skip?: string[] } = {},\n): string[] {\n const skipNames = new Set(opts.skip ?? []);\n const depNames: string[] = [];\n for (const line of sectionBody.split('\\n')) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) continue;\n const equalsIndex = trimmed.indexOf('=');\n if (equalsIndex <= 0) continue;\n const name = trimmed.slice(0, equalsIndex).trim();\n if (!/^[a-zA-Z0-9._-]+$/.test(name)) continue;\n if (skipNames.has(name.toLowerCase())) continue;\n depNames.push(normalizePyName(name));\n }\n return depNames;\n}\n","/**\n * Framework context gathering — run gatherContext and version checks\n * for a detected framework.\n *\n * Pure functions: take a framework config and options, return results.\n * No store mutations, no UI calls.\n */\n\nimport * as semver from 'semver';\nimport { DETECTION_TIMEOUT_MS } from '@lib/constants';\nimport type { FrameworkConfig } from '@lib/framework-config';\nimport type { WizardOptions } from '@utils/types';\n\n/**\n * Run a framework's `gatherContext()` to collect variant-specific\n * metadata (e.g., router type for Next.js, Expo vs bare for React Native).\n *\n * Returns the gathered context, or an empty object on failure/timeout.\n */\nexport async function gatherFrameworkContext(\n config: FrameworkConfig,\n options: WizardOptions,\n): Promise<Record<string, unknown>> {\n if (!config.metadata.gatherContext) return {};\n\n try {\n return await Promise.race([\n config.metadata.gatherContext(options),\n new Promise<Record<string, never>>((resolve) =>\n setTimeout(() => resolve({}), DETECTION_TIMEOUT_MS),\n ),\n ]);\n } catch {\n return {};\n }\n}\n\nexport interface VersionCheckResult {\n /** Whether the installed version is supported */\n supported:\n | true\n | {\n current: string;\n minimum: string;\n docsUrl: string;\n };\n}\n\n/**\n * Check whether the installed framework version meets the minimum requirement.\n *\n * Returns `{ supported: true }` if the version is fine (or no check is needed).\n * Returns the version details if unsupported.\n */\nexport async function checkFrameworkVersion(\n config: FrameworkConfig,\n options: WizardOptions,\n): Promise<VersionCheckResult> {\n if (\n !config.detection.minimumVersion ||\n !config.detection.getInstalledVersion\n ) {\n return { supported: true };\n }\n\n const version = await config.detection.getInstalledVersion(options);\n if (!version) return { supported: true };\n\n const coerced = semver.coerce(version);\n if (coerced && semver.lt(coerced, config.detection.minimumVersion)) {\n return {\n supported: {\n current: version,\n minimum: config.detection.minimumVersion,\n docsUrl:\n config.metadata.unsupportedVersionDocsUrl ?? config.metadata.docsUrl,\n },\n };\n }\n\n return { supported: true };\n}\n","export { detectFramework } from './framework.js';\nexport { discoverFeatures } from './features.js';\nexport {\n gatherFrameworkContext,\n checkFrameworkVersion,\n type VersionCheckResult,\n} from './context.js';\n"],"mappings":"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"}
1
+ {"version":3,"file":"detection-4eukp9HD.js","names":[],"sources":["../src/lib/detection/framework.ts","../src/lib/detection/features.ts","../src/lib/detection/context.ts","../src/lib/detection/index.ts"],"sourcesContent":["/**\n * Framework detection — identify which PostHog-supported framework\n * is present in the project directory.\n *\n * Pure function: takes an install dir, returns the detected integration\n * (or undefined). No store mutations, no UI calls.\n */\n\nimport { Integration, DETECTION_TIMEOUT_MS } from '@lib/constants';\nimport { FRAMEWORK_REGISTRY } from '@lib/registry';\n\n/**\n * Loop through all registered frameworks and return the first one\n * whose `detect()` predicate matches the given directory.\n * Returns undefined if no framework is detected or detection times out.\n */\nexport async function detectFramework(\n installDir: string,\n): Promise<Integration | undefined> {\n for (const integration of Object.values(Integration)) {\n const config = FRAMEWORK_REGISTRY[integration];\n try {\n const detected = await Promise.race([\n config.detection.detect({ installDir }),\n new Promise<false>((resolve) =>\n setTimeout(() => resolve(false), DETECTION_TIMEOUT_MS),\n ),\n ]);\n if (detected) {\n return integration;\n }\n } catch {\n // Skip frameworks whose detection throws\n }\n }\n}\n","/**\n * Feature discovery — scan project dependencies for known SDK patterns\n * that indicate additional PostHog programs are relevant.\n *\n * Pure function: takes an install dir, returns a set of discovered features.\n * No store mutations, no UI calls.\n */\n\nimport { readFileSync } from 'fs';\nimport { join } from 'path';\nimport { DiscoveredFeature } from '@lib/wizard-session';\n\nconst STRIPE_PACKAGES = ['stripe', '@stripe/stripe-js'];\n\nconst LLM_PACKAGES = [\n 'openai',\n '@anthropic-ai/sdk',\n 'ai',\n '@ai-sdk/openai',\n 'langchain',\n '@langchain/openai',\n '@langchain/langgraph',\n '@google/generative-ai',\n '@google/genai',\n '@instructor-ai/instructor',\n '@mastra/core',\n 'portkey-ai',\n];\n\n// PyPI normalizes `_` to `-` and is case-insensitive; compare via normalizePyName.\nconst PYTHON_LLM_PACKAGES = [\n 'openai',\n 'anthropic',\n 'langchain',\n 'langchain-openai',\n 'langchain-anthropic',\n 'langchain-google-genai',\n 'langgraph',\n 'litellm',\n 'llama-index',\n 'pydantic-ai',\n 'crewai',\n 'instructor',\n 'dspy-ai',\n 'mistralai',\n 'cohere',\n 'google-generativeai',\n 'google-genai',\n 'portkey-ai',\n];\n\nexport function discoverFeatures(installDir: string): DiscoveredFeature[] {\n const features: DiscoveredFeature[] = [];\n discoverNodeFeatures(installDir, features);\n discoverPythonFeatures(installDir, features);\n return features;\n}\n\nfunction discoverNodeFeatures(\n installDir: string,\n features: DiscoveredFeature[],\n): void {\n const packageJsonText = safeRead(installDir, 'package.json');\n if (!packageJsonText) return;\n\n let packageJson: {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n };\n try {\n packageJson = JSON.parse(packageJsonText);\n } catch {\n return;\n }\n\n const depNames = Object.keys({\n ...packageJson.dependencies,\n ...packageJson.devDependencies,\n });\n\n if (depNames.some((depName) => STRIPE_PACKAGES.includes(depName))) {\n features.push(DiscoveredFeature.Stripe);\n }\n if (depNames.some((depName) => LLM_PACKAGES.includes(depName))) {\n features.push(DiscoveredFeature.LLM);\n }\n}\n\nfunction discoverPythonFeatures(\n installDir: string,\n features: DiscoveredFeature[],\n): void {\n if (features.includes(DiscoveredFeature.LLM)) return;\n\n const depNames: string[] = [];\n\n const requirementsTxt = safeRead(installDir, 'requirements.txt');\n if (requirementsTxt) depNames.push(...parseRequirementsTxt(requirementsTxt));\n\n const pyprojectToml = safeRead(installDir, 'pyproject.toml');\n if (pyprojectToml) depNames.push(...parsePyprojectToml(pyprojectToml));\n\n const pipfile = safeRead(installDir, 'Pipfile');\n if (pipfile) depNames.push(...parsePipfile(pipfile));\n\n if (depNames.some((depName) => PYTHON_LLM_PACKAGES.includes(depName))) {\n features.push(DiscoveredFeature.LLM);\n }\n}\n\nfunction safeRead(installDir: string, file: string): string | null {\n try {\n return readFileSync(join(installDir, file), 'utf-8');\n } catch {\n return null;\n }\n}\n\nfunction normalizePyName(name: string): string {\n return name.toLowerCase().replace(/_/g, '-');\n}\n\nexport function parseRequirementsTxt(content: string): string[] {\n return content\n .split('\\n')\n .map((line) => line.trim())\n .filter((line) => line && !line.startsWith('#') && !line.startsWith('-'))\n .map((line) => line.replace(/\\[[^\\]]*\\]/, ''))\n .map((line) => line.split(/[<>=!~;\\s]/)[0])\n .filter(Boolean)\n .map(normalizePyName);\n}\n\n// Pragmatic, not a full TOML parser — only the dep shapes we care about.\nexport function parsePyprojectToml(content: string): string[] {\n const depNames: string[] = [];\n\n for (const arrayMatch of content.matchAll(\n /dependencies\\s*=\\s*\\[([^\\]]*)\\]/g,\n )) {\n const arrayBody = arrayMatch[1];\n for (const quotedMatch of arrayBody.matchAll(/[\"']([^\"']+)[\"']/g)) {\n const depSpec = quotedMatch[1];\n const name = depSpec.replace(/\\[[^\\]]*\\]/, '').split(/[<>=!~;\\s]/)[0];\n if (name) depNames.push(normalizePyName(name));\n }\n }\n\n const poetrySectionRe =\n /\\[tool\\.poetry\\.(?:dev-dependencies|dependencies|group\\.[^.\\]]+\\.dependencies)\\]([\\s\\S]*?)(?=\\n\\[|$)/g;\n for (const sectionMatch of content.matchAll(poetrySectionRe)) {\n const sectionBody = sectionMatch[1];\n depNames.push(...extractTomlSectionKeys(sectionBody, { skip: ['python'] }));\n }\n\n return depNames;\n}\n\nexport function parsePipfile(content: string): string[] {\n const depNames: string[] = [];\n const sectionRe = /\\[(packages|dev-packages)\\]([\\s\\S]*?)(?=\\n\\[|$)/g;\n for (const sectionMatch of content.matchAll(sectionRe)) {\n const sectionBody = sectionMatch[2];\n depNames.push(...extractTomlSectionKeys(sectionBody));\n }\n return depNames;\n}\n\nfunction extractTomlSectionKeys(\n sectionBody: string,\n opts: { skip?: string[] } = {},\n): string[] {\n const skipNames = new Set(opts.skip ?? []);\n const depNames: string[] = [];\n for (const line of sectionBody.split('\\n')) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) continue;\n const equalsIndex = trimmed.indexOf('=');\n if (equalsIndex <= 0) continue;\n const name = trimmed.slice(0, equalsIndex).trim();\n if (!/^[a-zA-Z0-9._-]+$/.test(name)) continue;\n if (skipNames.has(name.toLowerCase())) continue;\n depNames.push(normalizePyName(name));\n }\n return depNames;\n}\n","/**\n * Framework context gathering — run gatherContext and version checks\n * for a detected framework.\n *\n * Pure functions: take a framework config and options, return results.\n * No store mutations, no UI calls.\n */\n\nimport * as semver from 'semver';\nimport { DETECTION_TIMEOUT_MS } from '@lib/constants';\nimport type { FrameworkConfig } from '@lib/framework-config';\nimport type { WizardRunOptions } from '@utils/types';\n\n/**\n * Run a framework's `gatherContext()` to collect variant-specific\n * metadata (e.g., router type for Next.js, Expo vs bare for React Native).\n *\n * Returns the gathered context, or an empty object on failure/timeout.\n */\nexport async function gatherFrameworkContext(\n config: FrameworkConfig,\n options: WizardRunOptions,\n): Promise<Record<string, unknown>> {\n if (!config.metadata.gatherContext) return {};\n\n try {\n return await Promise.race([\n config.metadata.gatherContext(options),\n new Promise<Record<string, never>>((resolve) =>\n setTimeout(() => resolve({}), DETECTION_TIMEOUT_MS),\n ),\n ]);\n } catch {\n return {};\n }\n}\n\nexport interface VersionCheckResult {\n /** Whether the installed version is supported */\n supported:\n | true\n | {\n current: string;\n minimum: string;\n docsUrl: string;\n };\n}\n\n/**\n * Check whether the installed framework version meets the minimum requirement.\n *\n * Returns `{ supported: true }` if the version is fine (or no check is needed).\n * Returns the version details if unsupported.\n */\nexport async function checkFrameworkVersion(\n config: FrameworkConfig,\n options: WizardRunOptions,\n): Promise<VersionCheckResult> {\n if (\n !config.detection.minimumVersion ||\n !config.detection.getInstalledVersion\n ) {\n return { supported: true };\n }\n\n const version = await config.detection.getInstalledVersion(options);\n if (!version) return { supported: true };\n\n const coerced = semver.coerce(version);\n if (coerced && semver.lt(coerced, config.detection.minimumVersion)) {\n return {\n supported: {\n current: version,\n minimum: config.detection.minimumVersion,\n docsUrl:\n config.metadata.unsupportedVersionDocsUrl ?? config.metadata.docsUrl,\n },\n };\n }\n\n return { supported: true };\n}\n","export { detectFramework } from './framework.js';\nexport { discoverFeatures } from './features.js';\nexport {\n gatherFrameworkContext,\n checkFrameworkVersion,\n type VersionCheckResult,\n} from './context.js';\n"],"mappings":"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"}
@@ -17,4 +17,4 @@ function readApiKeyFromEnv() {
17
17
  //#endregion
18
18
  export { readApiKeyFromEnv };
19
19
 
20
- //# sourceMappingURL=env-api-key-D5G2PrXW.js.map
20
+ //# sourceMappingURL=env-api-key-DU8uIEvo.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"env-api-key-D5G2PrXW.js","names":["path","fs"],"sources":["../src/utils/env-api-key.ts"],"sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\n\n/**\n * Read POSTHOG_PERSONAL_API_KEY from .env.local or .env in the current\n * working directory. Returns undefined when no key is found.\n */\nexport function readApiKeyFromEnv(): string | undefined {\n const envFiles = ['.env.local', '.env'];\n for (const envFile of envFiles) {\n const envPath = path.join(process.cwd(), envFile);\n if (fs.existsSync(envPath)) {\n const content = fs.readFileSync(envPath, 'utf8');\n const match = content.match(/^POSTHOG_PERSONAL_API_KEY=(.+)$/m);\n if (match) {\n return match[1].trim();\n }\n }\n }\n return undefined;\n}\n"],"mappings":";;;;;;;AAOA,SAAgB,oBAAwC;AAEtD,MAAK,MAAM,WADM,CAAC,cAAc,OAAO,EACP;EAC9B,MAAM,UAAUA,OAAK,KAAK,QAAQ,KAAK,EAAE,QAAQ;AACjD,MAAIC,KAAG,WAAW,QAAQ,EAAE;GAE1B,MAAM,QADUA,KAAG,aAAa,SAAS,OAAO,CAC1B,MAAM,mCAAmC;AAC/D,OAAI,MACF,QAAO,MAAM,GAAG,MAAM"}
1
+ {"version":3,"file":"env-api-key-DU8uIEvo.js","names":["path","fs"],"sources":["../src/utils/env-api-key.ts"],"sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\n\n/**\n * Read POSTHOG_PERSONAL_API_KEY from .env.local or .env in the current\n * working directory. Returns undefined when no key is found.\n */\nexport function readApiKeyFromEnv(): string | undefined {\n const envFiles = ['.env.local', '.env'];\n for (const envFile of envFiles) {\n const envPath = path.join(process.cwd(), envFile);\n if (fs.existsSync(envPath)) {\n const content = fs.readFileSync(envPath, 'utf8');\n const match = content.match(/^POSTHOG_PERSONAL_API_KEY=(.+)$/m);\n if (match) {\n return match[1].trim();\n }\n }\n }\n return undefined;\n}\n"],"mappings":";;;;;;;AAOA,SAAgB,oBAAwC;AAEtD,MAAK,MAAM,WADM,CAAC,cAAc,OAAO,EACP;EAC9B,MAAM,UAAUA,OAAK,KAAK,QAAQ,KAAK,EAAE,QAAQ;AACjD,MAAIC,KAAG,WAAW,QAAQ,EAAE;GAE1B,MAAM,QADUA,KAAG,aAAa,SAAS,OAAO,CAC1B,MAAM,mCAAmC;AAC/D,OAAI,MACF,QAAO,MAAM,GAAG,MAAM"}
@@ -35,4 +35,4 @@ const IGNORED_DIRS = new Set([
35
35
  //#endregion
36
36
  export { IGNORED_DIRS as t };
37
37
 
38
- //# sourceMappingURL=file-utils-DPmgn9Vm.js.map
38
+ //# sourceMappingURL=file-utils-DnTSiTJw.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-utils-DnTSiTJw.js","names":[],"sources":["../src/utils/file-utils.ts"],"sourcesContent":["import path from 'path';\nimport fs from 'fs';\nimport type { WizardRunOptions } from './types';\n\nexport function getDotGitignore({\n installDir,\n}: Pick<WizardRunOptions, 'installDir'>) {\n const gitignorePath = path.join(installDir, '.gitignore');\n const gitignoreExists = fs.existsSync(gitignorePath);\n\n if (gitignoreExists) {\n return gitignorePath;\n }\n\n return undefined;\n}\n\n/**\n * Directory names to skip when recursively scanning a project tree.\n * Used by detection logic (e.g. finding all package.json files) to avoid\n * dependency directories, build output, virtual environments, etc.\n *\n * For fast-glob `ignore` patterns, map this to `**\\/<name>/**`.\n */\nexport const IGNORED_DIRS = new Set<string>([\n 'node_modules',\n '.git',\n '.next',\n '.nuxt',\n '.svelte-kit',\n '.turbo',\n '.cache',\n '.parcel-cache',\n 'dist',\n 'build',\n 'out',\n 'coverage',\n '.coverage',\n 'venv',\n '.venv',\n '__pycache__',\n '.pytest_cache',\n 'vendor',\n 'target',\n '.gradle',\n '.idea',\n '.vscode',\n]);\n"],"mappings":";;;;;;;;;;AAwBA,MAAa,eAAe,IAAI,IAAY;CAC1C;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC"}