@posthog/wizard 2.82.0 → 2.83.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 (121) hide show
  1. package/dist/{agent-interface-3YfIWZmY.js → agent-interface-fcDXqb-_.js} +84 -30
  2. package/dist/agent-interface-fcDXqb-_.js.map +1 -0
  3. package/dist/{agent-prompt-loader-hOHONY7u.js → agent-prompt-loader-F9gGPMt0.js} +6 -6
  4. package/dist/{agent-prompt-loader-hOHONY7u.js.map → agent-prompt-loader-F9gGPMt0.js.map} +1 -1
  5. package/dist/analytics-C9QnGvuc.js +2 -0
  6. package/dist/{analytics-B_xFshPY.js → analytics-GQv--mQm.js} +4 -3
  7. package/dist/analytics-GQv--mQm.js.map +1 -0
  8. package/dist/api-CsXfZKkq.js +2 -0
  9. package/dist/{api-C_9KsN-7.js → api-WUOSLXPJ.js} +2 -2
  10. package/dist/{api-C_9KsN-7.js.map → api-WUOSLXPJ.js.map} +1 -1
  11. package/dist/api-key-login-CDSxsYtP.js +2 -0
  12. package/dist/{api-key-login-oUJQDmOV.js → api-key-login-tysMeZnR.js} +5 -5
  13. package/dist/{api-key-login-oUJQDmOV.js.map → api-key-login-tysMeZnR.js.map} +1 -1
  14. package/dist/bin.js +1 -1
  15. package/dist/{bounded-fs-iRaQcKYL.js → bounded-fs-B31zq2ir.js} +3 -3
  16. package/dist/{bounded-fs-iRaQcKYL.js.map → bounded-fs-B31zq2ir.js.map} +1 -1
  17. package/dist/{ci-install-BGlijoTo.js → ci-install-CYSFbFXd.js} +4 -4
  18. package/dist/{ci-install-BGlijoTo.js.map → ci-install-CYSFbFXd.js.map} +1 -1
  19. package/dist/{debug-BvEbemym.js → debug-BTUMatFI.js} +3 -3
  20. package/dist/{debug-BvEbemym.js.map → debug-BTUMatFI.js.map} +1 -1
  21. package/dist/{gateway-CWoYlPz7.js → gateway-CJ8Jqbll.js} +20 -6
  22. package/dist/{gateway-CWoYlPz7.js.map → gateway-CJ8Jqbll.js.map} +1 -1
  23. package/dist/{headless-Gisv3faN.js → headless-DZ3mq07K.js} +1 -1
  24. package/dist/{headless-Bfi950Qh.js → headless-le-QqOuj.js} +2 -2
  25. package/dist/{headless-Bfi950Qh.js.map → headless-le-QqOuj.js.map} +1 -1
  26. package/dist/{host-resolution-BxnNn8Jm.js → host-resolution-Cht8bL39.js} +4 -4
  27. package/dist/{host-resolution-BxnNn8Jm.js.map → host-resolution-Cht8bL39.js.map} +1 -1
  28. package/dist/{install-CX65IxGa.js → install-55JbRsO-.js} +1 -1
  29. package/dist/{install-CDVeUT_5.js → install-BhnFP3p3.js} +5 -5
  30. package/dist/{install-CDVeUT_5.js.map → install-BhnFP3p3.js.map} +1 -1
  31. package/dist/{interactive-5-Numwwb.js → interactive-9qRL8259.js} +3 -3
  32. package/dist/{interactive-5-Numwwb.js.map → interactive-9qRL8259.js.map} +1 -1
  33. package/dist/{links-Dmj3Wj9X.js → links-5Blqk4Im.js} +3 -3
  34. package/dist/{links-Dmj3Wj9X.js.map → links-5Blqk4Im.js.map} +1 -1
  35. package/dist/{main-5KNn80Vt.js → main-CUIcozEG.js} +24 -21
  36. package/dist/main-CUIcozEG.js.map +1 -0
  37. package/dist/{mcp-Buf9sfFm.js → mcp-D73aCOHK.js} +3 -3
  38. package/dist/{mcp-Buf9sfFm.js.map → mcp-D73aCOHK.js.map} +1 -1
  39. package/dist/{mcp-prompt-streaming-DHPxJK-F.js → mcp-prompt-streaming-B5lIQ0l1.js} +5 -5
  40. package/dist/{mcp-prompt-streaming-DHPxJK-F.js.map → mcp-prompt-streaming-B5lIQ0l1.js.map} +1 -1
  41. package/dist/{models-C9rjXPZ6.js → models-CLTglHFZ.js} +6 -2
  42. package/dist/models-CLTglHFZ.js.map +1 -0
  43. package/dist/{oauth-session-Bi1MLRCC.js → oauth-session-CfkZ339p.js} +2 -2
  44. package/dist/{oauth-session-Bi1MLRCC.js.map → oauth-session-CfkZ339p.js.map} +1 -1
  45. package/dist/{orchestrator-tools-DyKws92o.js → orchestrator-tools-lvNVQhzs.js} +3 -3
  46. package/dist/{orchestrator-tools-DyKws92o.js.map → orchestrator-tools-lvNVQhzs.js.map} +1 -1
  47. package/dist/{package-manager-DpCdmMmB.js → package-manager-BqRNp5y_.js} +4 -4
  48. package/dist/{package-manager-DpCdmMmB.js.map → package-manager-BqRNp5y_.js.map} +1 -1
  49. package/dist/{pi-DTj1hsJe.js → pi-2pYz2OY3.js} +43 -23
  50. package/dist/pi-2pYz2OY3.js.map +1 -0
  51. package/dist/{playground-CiH6zZPb.js → playground-jxZNxRwC.js} +4 -4
  52. package/dist/{playground-CiH6zZPb.js.map → playground-jxZNxRwC.js.map} +1 -1
  53. package/dist/{posthog-integration-CpinLWNO.js → posthog-integration-DxRkw5DI.js} +21 -21
  54. package/dist/{posthog-integration-CpinLWNO.js.map → posthog-integration-DxRkw5DI.js.map} +1 -1
  55. package/dist/programs-D2793-PK.js +3 -0
  56. package/dist/{programs-Bq9Ju9xk.js → programs-eTv2T2rs.js} +129 -54
  57. package/dist/programs-eTv2T2rs.js.map +1 -0
  58. package/dist/provisioning-CtQ0GEHa.js +2 -0
  59. package/dist/{provisioning-D-AM_7DG.js → provisioning-c5JJ30KX.js} +4 -4
  60. package/dist/{provisioning-D-AM_7DG.js.map → provisioning-c5JJ30KX.js.map} +1 -1
  61. package/dist/{queue-tools-BoIITT7w.js → queue-tools-10w8lhEs.js} +14 -5
  62. package/dist/queue-tools-10w8lhEs.js.map +1 -0
  63. package/dist/{results-CDqlHogZ.js → results-C45prSKD.js} +2 -2
  64. package/dist/{results-CDqlHogZ.js.map → results-C45prSKD.js.map} +1 -1
  65. package/dist/{run-DcaVJSeI.js → run-CM24OgPF.js} +10 -10
  66. package/dist/{run-DcaVJSeI.js.map → run-CM24OgPF.js.map} +1 -1
  67. package/dist/{run-CfMArkpV.js → run-jugssomh.js} +7 -7
  68. package/dist/{run-CfMArkpV.js.map → run-jugssomh.js.map} +1 -1
  69. package/dist/run-tool-BZFgFb_2.js +2 -0
  70. package/dist/{run-tool-DJZWnnR9.js → run-tool-DZrZFoGq.js} +13 -13
  71. package/dist/{run-tool-DJZWnnR9.js.map → run-tool-DZrZFoGq.js.map} +1 -1
  72. package/dist/{runners-Cvnk9BcA.js → runners-CoIYt0iI.js} +8 -8
  73. package/dist/{runners-Cvnk9BcA.js.map → runners-CoIYt0iI.js.map} +1 -1
  74. package/dist/{security-Cz3a-d7r.js → security-ppK2MwCn.js} +6 -5
  75. package/dist/{security-Cz3a-d7r.js.map → security-ppK2MwCn.js.map} +1 -1
  76. package/dist/{setup-utils-C7kaDP5X.js → setup-utils-B5E1rXLa.js} +3 -3
  77. package/dist/{setup-utils-C7kaDP5X.js.map → setup-utils-B5E1rXLa.js.map} +1 -1
  78. package/dist/{start-playground-B62_pYfu.js → start-playground-DujiUNFT.js} +7 -7
  79. package/dist/{start-playground-B62_pYfu.js.map → start-playground-DujiUNFT.js.map} +1 -1
  80. package/dist/{subagent-BBfETG17.js → subagent-BdDWA8j5.js} +12 -4
  81. package/dist/subagent-BdDWA8j5.js.map +1 -0
  82. package/dist/{task-CmNe3xeg.js → task-Y8lWoDE7.js} +34 -23
  83. package/dist/task-Y8lWoDE7.js.map +1 -0
  84. package/dist/{telemetry-DKM7VGuJ.js → telemetry-Cwqf0iur.js} +2 -2
  85. package/dist/{telemetry-DKM7VGuJ.js.map → telemetry-Cwqf0iur.js.map} +1 -1
  86. package/dist/{terminal-Bkxwzkhn.js → terminal-BLL-X6YP.js} +397 -36
  87. package/dist/terminal-BLL-X6YP.js.map +1 -0
  88. package/dist/{tools-DZCEvDv9.js → tools-C8k90ISV.js} +13 -13
  89. package/dist/{tools-DZCEvDv9.js.map → tools-C8k90ISV.js.map} +1 -1
  90. package/dist/{tools-Bm0FDT6f.js → tools-g42e5kJz.js} +8 -8
  91. package/dist/{tools-Bm0FDT6f.js.map → tools-g42e5kJz.js.map} +1 -1
  92. package/dist/{tui-tKI95MSr.js → tui-BPWJ-J-k.js} +1 -1
  93. package/dist/{tui-B56jvkbi.js → tui-CBnRWnrm.js} +4 -4
  94. package/dist/tui-CBnRWnrm.js.map +1 -0
  95. package/dist/{upload-step-DqTgn6UB.js → upload-step-CFoxwd5t.js} +3 -3
  96. package/dist/{upload-step-DqTgn6UB.js.map → upload-step-CFoxwd5t.js.map} +1 -1
  97. package/dist/{urls-B82v7gfO.js → urls-BTZhm5eA.js} +2 -2
  98. package/dist/{urls-B82v7gfO.js.map → urls-BTZhm5eA.js.map} +1 -1
  99. package/dist/{wizard-abort-Cd-7sfCw.js → wizard-abort-HtpiSsQO.js} +4 -4
  100. package/dist/{wizard-abort-Cd-7sfCw.js.map → wizard-abort-HtpiSsQO.js.map} +1 -1
  101. package/dist/{yara-hooks-BS0n3ekf.js → yara-hooks-BPYhN9WM.js} +4 -4
  102. package/dist/{yara-hooks-BS0n3ekf.js.map → yara-hooks-BPYhN9WM.js.map} +1 -1
  103. package/dist/{yara-hooks-CxksH-GZ.js → yara-hooks-BwhEDXIt.js} +1 -1
  104. package/package.json +1 -1
  105. package/dist/agent-interface-3YfIWZmY.js.map +0 -1
  106. package/dist/analytics-B_xFshPY.js.map +0 -1
  107. package/dist/analytics-DGDr6-iD.js +0 -2
  108. package/dist/api-DhLSO3ai.js +0 -2
  109. package/dist/api-key-login-DiRuZ8Lm.js +0 -2
  110. package/dist/main-5KNn80Vt.js.map +0 -1
  111. package/dist/models-C9rjXPZ6.js.map +0 -1
  112. package/dist/pi-DTj1hsJe.js.map +0 -1
  113. package/dist/programs-Bq9Ju9xk.js.map +0 -1
  114. package/dist/programs-CnOSdQo1.js +0 -3
  115. package/dist/provisioning-D6Cqbc36.js +0 -2
  116. package/dist/queue-tools-BoIITT7w.js.map +0 -1
  117. package/dist/run-tool-zMLQroVh.js +0 -2
  118. package/dist/subagent-BBfETG17.js.map +0 -1
  119. package/dist/task-CmNe3xeg.js.map +0 -1
  120. package/dist/terminal-Bkxwzkhn.js.map +0 -1
  121. package/dist/tui-B56jvkbi.js.map +0 -1
@@ -1,15 +1,15 @@
1
1
  import { n as ErrorCodes, t as emitWizardError } from "./emit-BqLCdV8Y.js";
2
- import { t as configureLogFile } from "./debug-BvEbemym.js";
3
- import { M as POSTHOG_DOCS_URL, lt as initLocalDev, n as analytics, rt as getSkillsBaseUrl, ut as localMcpSkillsNotice } from "./analytics-B_xFshPY.js";
4
- import { $ as config$4, I as config$10, M as config$5, N as config$11, Q as config$6, T as Program, V as config$9, X as config$8, Z as config$7, _t as headlessOption, ct as config$2, dt as createSkillProgram, ft as CLI_STEERING_TARGETS, k as getProgramConfig, lt as config$1, st as config$3, ut as config, vt as isHeadless, yt as regionOption } from "./programs-Bq9Ju9xk.js";
2
+ import { t as configureLogFile } from "./debug-BTUMatFI.js";
3
+ import { N as POSTHOG_DOCS_URL, dt as localMcpSkillsNotice, it as getSkillsBaseUrl, n as analytics, ut as initLocalDev } from "./analytics-GQv--mQm.js";
4
+ import { $ as config$8, F as config$12, I as config$11, M as config$5, St as regionOption, T as Program, W as config$9, bt as headlessOption, dt as config$2, et as config$7, ft as config$1, ht as CLI_STEERING_TARGETS, k as getProgramConfig, mt as createSkillProgram, nt as config$4, pt as config, tt as config$6, ut as config$3, xt as isHeadless, z as config$10 } from "./programs-eTv2T2rs.js";
5
5
  import "./errors-DhFeR8Sp.js";
6
- import { n as setEntryCommand } from "./links-Dmj3Wj9X.js";
7
- import { a as runWizard, c as underSignals, i as readApiKeyFromEnv, l as withSignals, n as runWizardCI, o as tuiSessionArgs, s as exitWith, t as runWizardHeadless, u as isNonInteractiveEnvironment } from "./runners-Cvnk9BcA.js";
6
+ import { n as setEntryCommand } from "./links-5Blqk4Im.js";
7
+ import { a as runWizard, c as underSignals, i as readApiKeyFromEnv, l as withSignals, n as runWizardCI, o as tuiSessionArgs, s as exitWith, t as runWizardHeadless, u as isNonInteractiveEnvironment } from "./runners-CoIYt0iI.js";
8
8
  import { t as consoleLog } from "./console-log-DJiTqYT2.js";
9
- import { R as WIZARD_TOOL_NAMES, u as recoverOrphanedSettingsBackups } from "./agent-interface-3YfIWZmY.js";
10
- import "./posthog-integration-CpinLWNO.js";
11
- import { x as AUDIT_CHECKS_FILE, y as fetchSkillMenu } from "./yara-hooks-BS0n3ekf.js";
12
- import { a as runCliAdd, d as runDoctorReport, i as runProvision, o as addMCPServerToClientsStep, r as listSkills, s as removeMCPServerFromClientsStep, t as Tool, u as DOCTOR } from "./tools-DZCEvDv9.js";
9
+ import { R as WIZARD_TOOL_NAMES, u as recoverOrphanedSettingsBackups } from "./agent-interface-fcDXqb-_.js";
10
+ import "./posthog-integration-DxRkw5DI.js";
11
+ import { x as AUDIT_CHECKS_FILE, y as fetchSkillMenu } from "./yara-hooks-BPYhN9WM.js";
12
+ import { a as runCliAdd, d as runDoctorReport, i as runProvision, o as addMCPServerToClientsStep, r as listSkills, s as removeMCPServerFromClientsStep, t as Tool, u as DOCTOR } from "./tools-C8k90ISV.js";
13
13
  import { Agent, setGlobalDispatcher } from "undici";
14
14
  import yargs from "yargs";
15
15
  import { hideBin } from "yargs/helpers";
@@ -262,11 +262,11 @@ const basicIntegrationCommand = {
262
262
  setEntryCommand("integrate");
263
263
  (async () => {
264
264
  if (isHeadless(argv)) {
265
- const { runHeadlessInstall } = await import("./ci-install-BGlijoTo.js");
265
+ const { runHeadlessInstall } = await import("./ci-install-CYSFbFXd.js");
266
266
  return runHeadlessInstall(argv);
267
267
  }
268
268
  if (argv.ci) {
269
- const { runCIInstall } = await import("./ci-install-BGlijoTo.js");
269
+ const { runCIInstall } = await import("./ci-install-CYSFbFXd.js");
270
270
  return runCIInstall(argv);
271
271
  }
272
272
  if (isNonInteractiveEnvironment()) {
@@ -274,10 +274,10 @@ const basicIntegrationCommand = {
274
274
  return failNonInteractive();
275
275
  }
276
276
  if (argv.playground) {
277
- const { runPlayground } = await import("./playground-CiH6zZPb.js");
277
+ const { runPlayground } = await import("./playground-jxZNxRwC.js");
278
278
  return runPlayground();
279
279
  }
280
- const { runInteractive } = await import("./interactive-5-Numwwb.js");
280
+ const { runInteractive } = await import("./interactive-9qRL8259.js");
281
281
  runInteractive(argv);
282
282
  })();
283
283
  }
@@ -333,7 +333,7 @@ function runMcpAdd(argv) {
333
333
  }
334
334
  exitWith(async () => {
335
335
  try {
336
- const { runTuiTool } = await import("./tui-tKI95MSr.js");
336
+ const { runTuiTool } = await import("./tui-BPWJ-J-k.js");
337
337
  return await underSignals((signal) => runTuiTool(Tool.McpAdd, {
338
338
  session: {
339
339
  debug: argv.debug,
@@ -378,7 +378,7 @@ function runMcpRemove(argv) {
378
378
  }
379
379
  exitWith(async () => {
380
380
  try {
381
- const { runTuiTool } = await import("./tui-tKI95MSr.js");
381
+ const { runTuiTool } = await import("./tui-BPWJ-J-k.js");
382
382
  return await underSignals((signal) => runTuiTool(Tool.McpRemove, {
383
383
  session: {
384
384
  debug: argv.debug,
@@ -408,7 +408,7 @@ const mcpTutorialCommand = {
408
408
  function runMcpTutorial(argv) {
409
409
  exitWith(async () => {
410
410
  try {
411
- const { runTuiTool } = await import("./tui-tKI95MSr.js");
411
+ const { runTuiTool } = await import("./tui-BPWJ-J-k.js");
412
412
  return await underSignals((signal) => runTuiTool(Tool.McpTutorial, {
413
413
  session: {
414
414
  debug: argv.debug,
@@ -782,7 +782,7 @@ function orderFamilyChildren(children) {
782
782
  async function chooseFamilyChild(parentLabel, children) {
783
783
  const ordered = orderFamilyChildren(children);
784
784
  if (ordered.length === 0) return null;
785
- const { renderFamilyPicker } = await import("./tui-tKI95MSr.js");
785
+ const { renderFamilyPicker } = await import("./tui-BPWJ-J-k.js");
786
786
  return renderFamilyPicker(parentLabel, ordered.map((child) => ({
787
787
  label: describe(child),
788
788
  value: child,
@@ -890,7 +890,7 @@ const doctorCommand = {
890
890
  return;
891
891
  }
892
892
  withSignals(async (signal) => {
893
- const { runTuiTool } = await import("./tui-tKI95MSr.js");
893
+ const { runTuiTool } = await import("./tui-BPWJ-J-k.js");
894
894
  return runTuiTool(Tool.PosthogDoctor, {
895
895
  session: tuiSessionArgs(options),
896
896
  signal
@@ -973,7 +973,7 @@ const slackCommand = {
973
973
  function runSlackConnect(argv) {
974
974
  exitWith(async () => {
975
975
  try {
976
- const { runTuiTool } = await import("./tui-tKI95MSr.js");
976
+ const { runTuiTool } = await import("./tui-BPWJ-J-k.js");
977
977
  return await underSignals((signal) => runTuiTool(Tool.SlackConnect, {
978
978
  session: {
979
979
  debug: argv.debug,
@@ -1022,6 +1022,9 @@ const uploadSourcemapsCommand = {
1022
1022
  */
1023
1023
  const errorTrackingCommand = nativeCommandFactory(config$11);
1024
1024
  //#endregion
1025
+ //#region src/cli/commands/feature-flags.ts
1026
+ const featureFlagsCommand = nativeCommandFactory(config$12);
1027
+ //#endregion
1025
1028
  //#region src/cli/commands/basic-integration/skill.ts
1026
1029
  /** Run an arbitrary context-mill skill by id (`wizard skill <id>`, headless with `--ci`). */
1027
1030
  function runSkillMode(argv) {
@@ -1118,7 +1121,7 @@ const skillCommand = {
1118
1121
  /** The CLI's one entry: `main.ts` runs the `wizard` command line through it. */
1119
1122
  /** Register every command and run the one `process.argv` names. */
1120
1123
  function runCli() {
1121
- Wizard.use(basicIntegrationCommand).use(mcpCommand).use(mcpAnalyticsCommand).use(replayVisionCommand).use(aiObservabilityCommand).use(metricsCommand).use(cliCommand).use(auditCommand).use(doctorCommand).use(migrateCommand).use(revenueCommand).use(warehouseCommand).use(selfDrivingCommand).use(slackCommand).use(uploadSourcemapsCommand).use(errorTrackingCommand).use(skillCommand).init();
1124
+ Wizard.use(basicIntegrationCommand).use(mcpCommand).use(mcpAnalyticsCommand).use(replayVisionCommand).use(aiObservabilityCommand).use(metricsCommand).use(cliCommand).use(auditCommand).use(doctorCommand).use(migrateCommand).use(revenueCommand).use(warehouseCommand).use(selfDrivingCommand).use(slackCommand).use(uploadSourcemapsCommand).use(errorTrackingCommand).use(featureFlagsCommand).use(skillCommand).init();
1122
1125
  }
1123
1126
  //#endregion
1124
1127
  //#region main.ts
@@ -1136,4 +1139,4 @@ runCli();
1136
1139
  //#endregion
1137
1140
  export {};
1138
1141
 
1139
- //# sourceMappingURL=main-5KNn80Vt.js.map
1142
+ //# sourceMappingURL=main-CUIcozEG.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main-CUIcozEG.js","names":["mcpAnalyticsConfig","replayVisionConfig","aiObservabilityConfig","metricsConfig","webAnalyticsDoctorConfig","agentSkillConfig","migrationConfig","revenueAnalyticsConfig","warehouseSourceConfig","selfDrivingConfig","errorTrackingUploadSourceMapsConfig","errorTrackingConfig","featureFlagsConfig"],"sources":["../src/cli/commands/command.ts","../src/cli/wizard.ts","../src/cli/commands/provision.ts","../src/cli/commands/basic-integration/index.ts","../src/cli/commands/mcp/tui-availability.ts","../src/cli/commands/mcp/add.ts","../src/cli/commands/mcp/remove.ts","../src/cli/commands/mcp/tutorial.ts","../src/cli/commands/mcp/index.ts","../src/cli/commands/skill-program-options.ts","../src/cli/commands/factories/shared.ts","../src/cli/commands/factories/native-command-factory.ts","../src/cli/commands/mcp-analytics.ts","../src/cli/commands/replay-vision.ts","../src/cli/commands/ai-observability.ts","../src/cli/commands/metrics.ts","../src/cli/commands/cli/add.ts","../src/cli/commands/cli/index.ts","../src/cli/commands/dispatch-family.ts","../src/cli/commands/factories/family-picker.ts","../src/cli/commands/factories/family-command-factory.ts","../src/cli/commands/audit.ts","../src/cli/commands/doctor.ts","../src/cli/commands/migrate.ts","../src/cli/commands/revenue.ts","../src/cli/commands/warehouse.ts","../src/cli/commands/self-driving.ts","../src/cli/commands/slack.ts","../src/cli/commands/upload-sourcemaps.ts","../src/cli/commands/error-tracking.ts","../src/cli/commands/feature-flags.ts","../src/cli/commands/basic-integration/skill.ts","../src/cli/commands/skill.ts","../src/cli/index.ts","../main.ts"],"sourcesContent":["import type {\n Arguments,\n Argv,\n CommandModule,\n Options,\n PositionalOptions,\n} from 'yargs';\nimport { setEntryCommand } from '@utils/links';\n\nexport interface Command {\n /** Yargs command name. Use `['$0']` for the default command. */\n name: string | readonly string[];\n description: string;\n /** Flags exposed by this command. Same shape as yargs `.options()`. */\n options?: Record<string, Options>;\n /**\n * Positional arguments declared in `name` (e.g. the `id` in `skill [id]`).\n * Under `.strictOptions()`, yargs only treats a positional as a known\n * argument once it's registered via `.positional()` — a command-string\n * positional alone is rejected as `Unknown argument`. Declare each one here\n * so an optional positional like `skill [id]` actually accepts its value.\n */\n positionals?: Record<string, PositionalOptions>;\n /** Nested subcommands. */\n children?: readonly Command[];\n /** `--help` examples shown for this command. */\n examples?: ReadonlyArray<readonly [string, string]>;\n /**\n * Called synchronously by yargs when the command matches. Wrap async work in\n * `void (async () => { ... })()`. Optional only when `children` is set — in\n * that case yargs requires the user to pick a subcommand (or to set\n * `interactiveDefault` for an in-process picker).\n */\n handler?: (argv: Arguments) => void;\n /**\n * Cross-flag validation run by yargs after parsing. Throw to reject (yargs\n * prints the message and exits non-zero); return `true` to accept. Prefer\n * this over per-option `conflicts` for mutually exclusive flags: yargs\n * counts a `default`-valued flag as \"present\", so `conflicts` misfires on\n * boolean flags that default to `false` — a hand-written predicate only\n * sees what you test for (e.g. truthiness).\n */\n check?: (argv: Arguments) => boolean;\n /**\n * Optional handler invoked when this command has `children` but the user\n * supplied no subcommand. Use it to mount an interactive picker over the\n * children so `wizard audit` (no leaf) opens a TUI menu instead of yargs\n * help. When set, suppresses the implicit `demandCommand(1)`.\n *\n * May return a Promise — yargs awaits the result before exiting.\n */\n interactiveDefault?: (argv: Arguments) => void | Promise<void>;\n /**\n * When true, this child is the \"default\" leaf in its family: the\n * family picker pre-highlights it so a single Enter runs it. The picker\n * still always opens — this never auto-runs the child. At most one child\n * per parent should be marked. Propagated from the context-mill manifest\n * entry's `default` flag through `skillCommandFactory`.\n */\n default?: boolean;\n}\n\n/** Extract the bare command word(s) from a yargs name spec, dropping positionals and aliases' arg syntax. */\nexport function commandKeys(name: string | readonly string[]): string[] {\n const list: readonly string[] = typeof name === 'string' ? [name] : name;\n return list.map((n) => n.trim().split(/\\s+/)[0]);\n}\n\nexport function toCommandModule(\n cmd: Command,\n parentPath: readonly string[],\n): CommandModule {\n // `wizard slack` → 'slack', `wizard mcp add` → 'mcp-add'. The default\n // `$0` resolves to '' and is skipped — its handler reports itself.\n const entryCommand = [...parentPath, commandKeys(cmd.name)[0]]\n .filter((key) => key !== '$0')\n .join('-');\n return {\n command: cmd.name,\n describe: cmd.description,\n builder: (y: Argv) => {\n let next = cmd.options ? y.options(cmd.options) : y;\n for (const [key, opts] of Object.entries(cmd.positionals ?? {})) {\n next = next.positional(key, opts);\n }\n if (cmd.check) next = next.check(cmd.check);\n for (const [usage, description] of cmd.examples ?? []) {\n next = next.example(usage, description);\n }\n const ownPath = [...parentPath, commandKeys(cmd.name)[0]];\n for (const child of cmd.children ?? []) {\n next = next.command(toCommandModule(child, ownPath));\n }\n if (cmd.children?.length && !cmd.handler && !cmd.interactiveDefault) {\n next = next.demandCommand(1);\n }\n return next;\n },\n handler: (argv: Arguments) => {\n if (entryCommand) setEntryCommand(entryCommand);\n const run = cmd.handler ?? cmd.interactiveDefault ?? (() => undefined);\n run(argv);\n },\n };\n}\n","import yargs from 'yargs';\nimport { hideBin } from 'yargs/helpers';\nimport type { Argv } from 'yargs';\nimport { IS_PRODUCTION_BUILD } from '@env';\nimport { Harness, Sequence } from '@shared/constants';\nimport { regionOption } from '@shared/headless-mode';\nimport { initLocalDev, localMcpSkillsNotice } from '@shared/local-dev';\nimport { configureLogFile } from '@utils/debug';\nimport { toCommandModule, type Command } from './commands/command';\nimport { ErrorCodes } from '@shared/errors';\nimport { emitWizardError } from '@shared/errors';\n\n/**\n * Global yargs options applied to every command. These are read from the\n * `POSTHOG_WIZARD` env prefix as well as flags.\n *\n * Options with `hidden: true` are \"internal modes\" — they don't show up in\n * `--help` but are still accepted on every command. The `--local-*` flags live\n * in the constructor's `!IS_PRODUCTION_BUILD` block instead, so published\n * builds reject them; see `docs/local-dev.md`.\n */\nexport const GLOBAL_OPTIONS = {\n debug: {\n default: false,\n describe: 'Enable verbose logging\\nenv: POSTHOG_WIZARD_DEBUG',\n type: 'boolean' as const,\n },\n 'log-file': {\n describe:\n 'Write the debug log to this file (default: posthog-wizard.log in the temp dir)\\nenv: POSTHOG_WIZARD_LOG_FILE',\n type: 'string' as const,\n },\n signup: {\n default: false,\n describe:\n 'Create a new PostHog account during setup\\nenv: POSTHOG_WIZARD_SIGNUP',\n type: 'boolean' as const,\n },\n telemetry: {\n default: true,\n describe:\n 'Send wizard run state to PostHog (pass --no-telemetry to disable)\\nenv: POSTHOG_WIZARD_TELEMETRY',\n type: 'boolean' as const,\n },\n 'api-key': {\n describe:\n 'PostHog personal API key (phx_xxx) for authentication\\nenv: POSTHOG_WIZARD_API_KEY',\n type: 'string' as const,\n },\n 'project-id': {\n describe:\n 'PostHog project ID to use (optional; when not set, uses default from API key or OAuth)\\nenv: POSTHOG_WIZARD_PROJECT_ID',\n type: 'string' as const,\n },\n email: {\n describe:\n 'Email address for signup (used with --signup)\\nenv: POSTHOG_WIZARD_EMAIL',\n type: 'string' as const,\n },\n // ── Internal modes ─────────────────────────────────────────────────\n // Hidden from `--help`.\n // NB: the experimental headless flag is deliberately NOT global. Supported\n // commands declare it through `headlessOption` in @shared/headless-mode.\n 'base-url': {\n describe:\n 'Override the PostHog base URL (e.g. http://localhost:8010), bypassing region resolution. Pins the API host, cloud URL, and OAuth server.\\nenv: POSTHOG_WIZARD_BASE_URL',\n type: 'string' as const,\n hidden: true,\n },\n 'run-id': {\n describe: 'Assigned cloud WizardRun UUID',\n type: 'string' as const,\n hidden: true,\n },\n benchmark: {\n default: false,\n describe:\n 'Run in benchmark mode with per-phase token tracking\\nenv: POSTHOG_WIZARD_BENCHMARK',\n type: 'boolean' as const,\n hidden: true,\n },\n 'yara-report': {\n default: false,\n describe:\n 'Print YARA scanner summary after the agent run\\nenv: POSTHOG_WIZARD_YARA_REPORT',\n type: 'boolean' as const,\n hidden: true,\n },\n};\n\nexport class Wizard {\n private cli: Argv;\n\n private constructor() {\n let cli: Argv = yargs(hideBin(process.argv))\n .env('POSTHOG_WIZARD')\n .options(GLOBAL_OPTIONS);\n\n // CI mode (--ci) is only supported in dev/test. It is left undeclared in\n // published builds (NODE_ENV==='production'), so .strictOptions() rejects\n // it there as an unknown argument — exactly like any other unrecognized\n // flag. init() additionally detects it up front to print a clearer message.\n // The published-build, non-interactive path is the experimental headless\n // flag, declared per-command through `headlessOption` (see\n // @shared/headless-mode). CI needs `region` globally because the workbench\n // passes it to every command. --ci and headless stay separate so their\n // behavior can diverge.\n if (!IS_PRODUCTION_BUILD) {\n cli = cli\n .options(regionOption)\n .option('ci', {\n default: false,\n describe:\n 'Enable CI mode for non-interactive execution\\nenv: POSTHOG_WIZARD_CI',\n type: 'boolean',\n hidden: true,\n })\n // Runner overrides — dev/test only, same lifecycle as --ci.\n .option('harness', {\n describe:\n 'Override the agent harness (anthropic | pi). Wins over the PostHog runner flag.\\nenv: POSTHOG_WIZARD_HARNESS',\n choices: Object.values(Harness),\n type: 'string',\n hidden: true,\n })\n .option('sequence', {\n describe:\n 'Override the runner sequence (linear | orchestrator). Wins over the PostHog orchestrator flag.\\nenv: POSTHOG_WIZARD_SEQUENCE',\n choices: Object.values(Sequence),\n type: 'string',\n hidden: true,\n })\n .option('model', {\n describe:\n 'Override the agent model (gateway id, e.g. claude-sonnet-5 | openai/gpt-5.6-terra). Wins over the binding default.\\nenv: POSTHOG_WIZARD_MODEL',\n type: 'string',\n hidden: true,\n })\n .option('capture-aio', {\n default: false,\n describe:\n \"Capture wizard LLM calls as $ai_generation events in the authenticated project's AI Observability tab.\\nenv: POSTHOG_WIZARD_CAPTURE_AIO\",\n type: 'boolean',\n hidden: true,\n })\n // Rides beside the PostHog destination rather than replacing it, so a\n // logged run is the same run the backend sees.\n .option('task-stream-log', {\n describe:\n 'Append every task-stream payload to a local JSONL file. Pass a path, or pass the flag alone for /tmp/posthog-wizard-task-stream.jsonl\\nenv: POSTHOG_WIZARD_TASK_STREAM_LOG',\n type: 'string',\n })\n // ── Local dev targets (see docs/local-dev.md) ──────────────────\n // Not `hidden`: the build gate already keeps them from users, so\n // hiding them would only cost the dev-build help row. Deliberately not\n // named `--local`, which `wizard mcp add` already uses for something\n // unrelated.\n .option('local-dev', {\n default: false,\n describe:\n 'Point context-mill, MCP, and PostHog at local dev servers\\nenv: POSTHOG_WIZARD_LOCAL_DEV',\n type: 'boolean',\n })\n // No `default` on the three below — they must stay `undefined` when\n // absent for resolveLocalDev() to honour the umbrella and `--no-*`.\n .option('local-context-mill', {\n describe:\n 'Fetch skills from the local context-mill server (http://localhost:8765)\\nenv: POSTHOG_WIZARD_LOCAL_CONTEXT_MILL',\n type: 'boolean',\n })\n .option('local-mcp', {\n describe:\n 'Use the local MCP server (http://localhost:8787/mcp). Affects MCP only — use --local-context-mill for skills.\\nenv: POSTHOG_WIZARD_LOCAL_MCP',\n type: 'boolean',\n })\n .option('local-posthog', {\n describe:\n 'Point every PostHog origin (API, app, OAuth, gateway) at http://localhost:8010\\nenv: POSTHOG_WIZARD_LOCAL_POSTHOG',\n type: 'boolean',\n });\n }\n\n this.cli = cli\n // Middleware rather than an argv scan so the env path is covered too,\n // and it runs before any TUI takes the terminal.\n .middleware((argv) => {\n if (typeof argv.logFile === 'string' && argv.logFile) {\n configureLogFile({ path: argv.logFile, pin: true });\n }\n // The one place local targets are resolved; everything downstream reads\n // getLocalDev().\n initLocalDev(argv);\n\n // Temporary.\n const notice = localMcpSkillsNotice({\n localDev: argv.localDev as boolean | undefined,\n localMcp: argv.localMcp as boolean | undefined,\n localContextMill: argv.localContextMill as boolean | undefined,\n });\n if (notice) {\n process.stderr.write(`\\n\\x1b[33m! ${notice}\\x1b[0m\\n\\n`);\n }\n })\n .strictOptions()\n // Reject unrecognized commands (e.g. `wizard bogus`) instead of letting\n // them fall through to the default `$0` integration flow.\n .strictCommands()\n // Print a concise error and point to `--help`, instead of yargs' default\n // of dumping the entire usage screen under every failure.\n .fail((msg, err) => {\n const text = msg || (err && err.message) || 'Invalid arguments';\n process.stderr.write(\n `\\n\\x1b[1;91m✖ ${text}\\x1b[0m\\n` +\n ` Run \\`wizard --help\\` to see available commands and options.\\n\\n`,\n );\n emitWizardError({ code: ErrorCodes.CliBadArgs, message: text });\n process.exit(1);\n })\n .help()\n .alias('help', 'h')\n .version()\n .alias('version', 'v');\n }\n\n /** Start a chain; equivalent to `new Wizard().use(...cmds)`. */\n static use(...cmds: Command[]): Wizard {\n return new Wizard().use(...cmds);\n }\n\n /** Register one or more commands with yargs. */\n use(...cmds: Command[]): this {\n for (const cmd of cmds) {\n this.cli = this.cli.command(toCommandModule(cmd, []));\n }\n return this;\n }\n\n /** Parse argv and dispatch to the matching registered command. */\n init(): void {\n // In published builds, `--ci` is undeclared, so yargs would reject it as\n // an unknown argument — accurate but unhelpful, since --help doesn't list\n // --ci either and the user has no path forward. POSTHOG_WIZARD_CI silently\n // no-ops for the same reason (yargs only resolves env vars for declared\n // options). Detect both up front and exit with a message that explains why.\n if (IS_PRODUCTION_BUILD) {\n const args = process.argv.slice(2);\n const argvHasCI = args.some(\n (a) => a === '--ci' || a === '--no-ci' || a.startsWith('--ci='),\n );\n const envHasCI =\n process.env.POSTHOG_WIZARD_CI != null &&\n process.env.POSTHOG_WIZARD_CI !== '';\n if (argvHasCI || envHasCI) {\n process.stderr.write(\n `\\n\\x1b[1;91m✖ CI mode is not currently supported in published builds.\\x1b[0m\\n\\n`,\n );\n emitWizardError({\n code: ErrorCodes.CliFlagUnavailable,\n message: 'CI mode is not supported in published builds.',\n });\n process.exit(1);\n }\n\n // --harness / --sequence / --model / --capture-aio are dev/test-only.\n // In published builds the env vars would silently no-op, so reject them\n // explicitly instead.\n const argvHasOverride = args.some(\n (a) =>\n a === '--harness' ||\n a.startsWith('--harness=') ||\n a === '--sequence' ||\n a.startsWith('--sequence=') ||\n a === '--model' ||\n a.startsWith('--model=') ||\n a === '--capture-aio' ||\n a === '--no-capture-aio' ||\n a.startsWith('--capture-aio='),\n );\n const envHasOverride =\n (process.env.POSTHOG_WIZARD_HARNESS != null &&\n process.env.POSTHOG_WIZARD_HARNESS !== '') ||\n (process.env.POSTHOG_WIZARD_SEQUENCE != null &&\n process.env.POSTHOG_WIZARD_SEQUENCE !== '') ||\n (process.env.POSTHOG_WIZARD_MODEL != null &&\n process.env.POSTHOG_WIZARD_MODEL !== '') ||\n (process.env.POSTHOG_WIZARD_CAPTURE_AIO != null &&\n process.env.POSTHOG_WIZARD_CAPTURE_AIO !== '');\n if (argvHasOverride || envHasOverride) {\n process.stderr.write(\n `\\n\\x1b[1;91m✖ The --harness, --sequence, --model, and --capture-aio overrides are not available in published builds.\\x1b[0m\\n\\n`,\n );\n emitWizardError({\n code: ErrorCodes.CliFlagUnavailable,\n message:\n 'The --harness, --sequence, --model, and --capture-aio overrides are not available in published builds.',\n });\n process.exit(1);\n }\n\n // `--local-mcp` used to be declared unconditionally, so published builds\n // accepted it and quietly aimed the run at localhost. Reject explicitly.\n const argvHasLocalTarget = args.some((a) =>\n LOCAL_TARGET_FLAGS.some(\n (f) => a === `--${f}` || a === `--no-${f}` || a.startsWith(`--${f}=`),\n ),\n );\n const envHasLocalTarget = LOCAL_TARGET_ENV_VARS.some(\n (k) => process.env[k] != null && process.env[k] !== '',\n );\n if (argvHasLocalTarget || envHasLocalTarget) {\n process.stderr.write(\n `\\n\\x1b[1;91m✖ The --local-dev, --local-context-mill, --local-mcp, and --local-posthog targets are not available in published builds.\\x1b[0m\\n` +\n ` They point the wizard at development servers on localhost.\\n\\n`,\n );\n emitWizardError({\n code: ErrorCodes.CliFlagUnavailable,\n message:\n 'The --local-dev, --local-context-mill, --local-mcp, and --local-posthog targets are not available in published builds.',\n });\n process.exit(1);\n }\n }\n void this.cli.wrap(process.stdout.isTTY ? this.cli.terminalWidth() : 80)\n .argv;\n }\n}\n\n/** Excludes bare `local`: `wizard mcp add --local` stays available in prod. */\nconst LOCAL_TARGET_FLAGS = [\n 'local-dev',\n 'local-context-mill',\n 'local-mcp',\n 'local-posthog',\n] as const;\n\nconst LOCAL_TARGET_ENV_VARS = [\n 'POSTHOG_WIZARD_LOCAL_DEV',\n 'POSTHOG_WIZARD_LOCAL_CONTEXT_MILL',\n 'POSTHOG_WIZARD_LOCAL_MCP',\n 'POSTHOG_WIZARD_LOCAL_POSTHOG',\n] as const;\n","import type { Arguments } from 'yargs';\nimport { consoleLog } from '@shared/console-log';\nimport { runProvision } from '@tools';\nimport { exitWith } from '@cli/runners';\nimport type { Command } from './command';\n\nexport const provisionCommand: Command = {\n name: 'provision',\n description: 'Create a new PostHog account (headless, no TUI)',\n options: {\n email: {\n describe: 'Email address for the new account',\n type: 'string',\n demandOption: true,\n },\n region: {\n describe: 'Cloud region (us or eu)',\n choices: ['us', 'eu'] as const,\n default: 'us',\n },\n name: {\n describe: 'Name for the new account',\n type: 'string',\n default: '',\n },\n json: {\n describe:\n 'Emit JSON result to stdout (defaults to true when stdout is not a TTY)',\n type: 'boolean',\n },\n },\n examples: [\n ['wizard provision --email matt+test@posthog.com --region us', ''],\n ['wizard provision --email user@example.com --region eu --json', ''],\n ],\n handler: provision,\n};\n\nfunction provision(argv: Arguments): void {\n const jsonMode =\n argv.json === undefined ? !process.stdout.isTTY : Boolean(argv.json);\n exitWith(() =>\n runProvision(\n {\n email: argv.email as string,\n region: (argv.region as string).toUpperCase() as 'US' | 'EU',\n name: (argv.name as string) ?? '',\n baseUrl: argv.baseUrl as string | undefined,\n jsonMode,\n },\n { log: consoleLog },\n ),\n );\n}\n","import { isNonInteractiveEnvironment } from '@utils/environment';\nimport { setEntryCommand } from '@utils/links';\nimport {\n headlessOption,\n isHeadless,\n regionOption,\n} from '@shared/headless-mode';\nimport { provisionCommand } from '../provision';\nimport type { Command } from '../command';\n\nexport const basicIntegrationCommand: Command = {\n name: ['$0'],\n description: 'Run the PostHog setup wizard',\n // provision is a one-shot HTTP call tied to the base flow, not a wizard\n // program — it rides under the base command rather than as a peer.\n children: [provisionCommand],\n options: {\n 'install-dir': {\n describe:\n 'Directory to install PostHog in\\nenv: POSTHOG_WIZARD_INSTALL_DIR',\n type: 'string',\n },\n name: {\n describe:\n 'Name for account creation with --ci --signup\\nenv: POSTHOG_WIZARD_NAME',\n type: 'string',\n },\n // ── Internal modes ───────────────────────────────────────────────\n // Hidden from `--help`. See CONTRIBUTING.md for what each one does.\n playground: {\n default: false,\n describe: 'Launch the TUI primitives playground',\n type: 'boolean',\n hidden: true,\n },\n // The experimental headless flag — declared here (and on `audit`) rather\n // than globally. Routed by this command's handler via runHeadlessInstall.\n ...headlessOption,\n ...regionOption,\n },\n check: (argv) => {\n // --playground is the standalone TUI demo; it can't combine with a\n // non-interactive run (either --ci or the experimental headless flag).\n if (argv.playground && (argv.ci || isHeadless(argv))) {\n throw new Error('--playground cannot be combined with a headless run.');\n }\n return true;\n },\n handler: (argv) => {\n // The bare run is the integrate flow.\n setEntryCommand('integrate');\n // Each mode file is loaded only when its branch is taken, so a plain\n // `npx @posthog/wizard` never pulls in the CI or playground paths.\n void (async () => {\n // ── The CI / headless division ───────────────────────────────────\n // --ci (dev/test only) and the experimental headless flag (the\n // published-build, non-interactive path; see @shared/headless-mode) both\n // request a non-interactive install, but route to dedicated entry points\n // — runHeadlessInstall vs runCIInstall (and below them runWizardHeadless\n // vs runWizardCI). Both share one pipeline today but are separate\n // functions end-to-end, so headless can diverge later without touching\n // the CI path or its callers.\n if (isHeadless(argv)) {\n const { runHeadlessInstall } = await import('./ci-install');\n return runHeadlessInstall(argv);\n }\n if (argv.ci) {\n const { runCIInstall } = await import('./ci-install');\n return runCIInstall(argv);\n }\n if (isNonInteractiveEnvironment()) {\n const { failNonInteractive } = await import('./non-interactive');\n return failNonInteractive();\n }\n if (argv.playground) {\n const { runPlayground } = await import('./playground');\n return runPlayground();\n }\n const { runInteractive } = await import('./interactive');\n runInteractive(argv);\n })();\n },\n};\n","import { ErrorCodes } from '@shared/errors';\n\n/**\n * startTUI throws CliInteractiveRequired, and Ink throws \"Raw mode is not\n * supported\", when stdin has no TTY (piped input, CI, some IDE terminals).\n * That is the only TUI failure the mcp commands degrade to console output for\n * — any other error from the TUI path is a real bug and must surface rather\n * than be silently swallowed.\n */\nexport function isTUIUnavailable(error: unknown): boolean {\n if (!(error instanceof Error)) return false;\n return (\n (error as { code?: unknown }).code === ErrorCodes.CliInteractiveRequired ||\n /raw mode is not supported/i.test(error.message)\n );\n}\n","import type { Arguments } from 'yargs';\nimport { consoleLog } from '@shared/console-log';\nimport { headlessOption, isHeadless } from '@shared/headless-mode';\nimport { readApiKeyFromEnv } from '@utils/env-api-key';\nimport { addMCPServerToClientsStep, Tool } from '@tools';\nimport { exitWith, underSignals } from '@cli/runners';\nimport type { Command } from '../command';\nimport { isTUIUnavailable } from './tui-availability';\n\nexport const mcpAddCommand: Command = {\n name: 'add',\n description: 'Install PostHog MCP server to supported clients',\n options: {\n local: {\n default: false,\n describe: 'Add local development MCP server (http://localhost:8787)',\n type: 'boolean',\n },\n features: {\n describe: 'Comma-separated list of features to enable (default: all)',\n type: 'string',\n },\n 'api-key': {\n describe: 'PostHog personal API key (phx_xxx) for MCP authentication',\n type: 'string',\n },\n // Reuses the run pipeline's headless flag rather than minting a public one:\n // this stays reversible, and today the only caller is our own CI.\n ...headlessOption,\n },\n handler: runMcpAdd,\n};\n\nfunction runMcpAdd(argv: Arguments): void {\n const features = parseFeatures(argv.features);\n const apiKey = (argv.apiKey as string | undefined) || readApiKeyFromEnv();\n const localMcp = argv.local as boolean | undefined;\n // Never forwards `ci`: headless implies session.ci elsewhere, and the step\n // reads that as \"skip MCP entirely\" — the opposite of what we're here to do.\n const headless = () =>\n addMCPServerToClientsStep(\n { local: localMcp, features, apiKey },\n { log: consoleLog.log },\n );\n\n // Ink renders into a pipe happily and only throws on raw-mode input, so a\n // non-TTY run reaches the confirm prompt and stalls there rather than\n // hitting the isTUIUnavailable fallback below. The headless flag is the\n // only reliable way to install from a script.\n if (isHeadless(argv)) {\n exitWith(headless);\n return;\n }\n\n exitWith(async () => {\n try {\n const { runTuiTool } = await import('@tui');\n return await underSignals((signal) =>\n runTuiTool(Tool.McpAdd, {\n session: {\n debug: argv.debug as boolean | undefined,\n localMcp,\n mcpFeatures: features,\n apiKey,\n baseUrl: argv.baseUrl as string | undefined,\n },\n signal,\n }),\n );\n } catch (error) {\n if (!isTUIUnavailable(error)) throw error;\n return headless();\n }\n });\n}\n\nfunction parseFeatures(raw: unknown): string[] | undefined {\n if (typeof raw !== 'string') return undefined;\n return raw\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean);\n}\n","import type { Arguments } from 'yargs';\nimport { consoleLog } from '@shared/console-log';\nimport { headlessOption, isHeadless } from '@shared/headless-mode';\nimport { removeMCPServerFromClientsStep, Tool } from '@tools';\nimport { exitWith, underSignals } from '@cli/runners';\nimport type { Command } from '../command';\nimport { isTUIUnavailable } from './tui-availability';\n\nexport const mcpRemoveCommand: Command = {\n name: 'remove',\n description: 'Remove PostHog MCP server from supported clients',\n options: {\n local: {\n default: false,\n describe: 'Remove local development MCP server (http://localhost:8787)',\n type: 'boolean',\n },\n // Mirrors `mcp add` — see the note there on reusing the run pipeline's flag.\n ...headlessOption,\n },\n handler: runMcpRemove,\n};\n\nfunction runMcpRemove(argv: Arguments): void {\n const localMcp = argv.local as boolean | undefined;\n const headless = () =>\n removeMCPServerFromClientsStep(\n { local: localMcp },\n { log: consoleLog.log },\n );\n\n // See the note in add.ts: a non-TTY run stalls on the confirm prompt\n // instead of falling back, so scripts need an explicit flag.\n if (isHeadless(argv)) {\n exitWith(headless);\n return;\n }\n\n exitWith(async () => {\n try {\n const { runTuiTool } = await import('@tui');\n return await underSignals((signal) =>\n runTuiTool(Tool.McpRemove, {\n session: {\n debug: argv.debug as boolean | undefined,\n localMcp,\n baseUrl: argv.baseUrl as string | undefined,\n },\n signal,\n }),\n );\n } catch (error) {\n // Same guard as `mcp add`: only a missing TTY falls back to the console,\n // so a genuine TUI bug surfaces instead of looking like a plain shell.\n if (!isTUIUnavailable(error)) throw error;\n return headless();\n }\n });\n}\n","import type { Arguments } from 'yargs';\nimport { consoleLog } from '@shared/console-log';\nimport { ErrorCodes, emitWizardError } from '@shared/errors';\nimport { Tool } from '@tools';\nimport { exitWith, underSignals } from '@cli/runners';\nimport type { Command } from '../command';\n\nexport const mcpTutorialCommand: Command = {\n name: 'tutorial',\n description: 'Try the PostHog MCP with your agent (no install needed)',\n options: {\n local: {\n default: false,\n describe:\n 'Point the tutorial at the local MCP server (http://localhost:8787)',\n type: 'boolean',\n },\n },\n handler: runMcpTutorial,\n};\n\nfunction runMcpTutorial(argv: Arguments): void {\n exitWith(async () => {\n try {\n const { runTuiTool } = await import('@tui');\n return await underSignals((signal) =>\n runTuiTool(Tool.McpTutorial, {\n session: {\n debug: argv.debug as boolean | undefined,\n localMcp: argv.local as boolean | undefined,\n baseUrl: argv.baseUrl as string | undefined,\n },\n signal,\n }),\n );\n } catch (err) {\n // TUI unavailable — the tutorial has no headless fallback.\n consoleLog.log.error(\n `The MCP tutorial requires an interactive terminal. ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n emitWizardError({\n code: ErrorCodes.CliInteractiveRequired,\n message: 'The MCP tutorial requires an interactive terminal.',\n });\n return 1;\n }\n });\n}\n","import { mcpAddCommand } from './add';\nimport { mcpRemoveCommand } from './remove';\nimport { mcpTutorialCommand } from './tutorial';\nimport type { Command } from '../command';\n\nexport const mcpCommand: Command = {\n name: 'mcp',\n description: 'MCP server management commands',\n children: [mcpAddCommand, mcpRemoveCommand, mcpTutorialCommand],\n};\n","/**\n * Per-command options shared by every skill-based program command\n * (`audit events`, `migrate statsig`, `revenue`, `source-maps`, …).\n *\n * Only flags unique to skill commands live here. Global flags are declared\n * once in `wizard.ts` — both in `GLOBAL_OPTIONS` and, for the dev-only ones,\n * the `Wizard` constructor — and apply to every command automatically.\n */\nexport const skillProgramOptions = {\n 'install-dir': {\n describe: 'Directory to install in',\n type: 'string' as const,\n },\n};\n","import type { Arguments, Options } from 'yargs';\n\nimport { runWizard, runWizardCI, runWizardHeadless } from '@cli/runners';\nimport { isHeadless } from '@shared/headless-mode';\nimport type { ProgramConfig } from '@programs/types';\n\nimport { skillProgramOptions } from '../skill-program-options';\nimport { ErrorCodes } from '@shared/errors';\nimport { emitWizardError } from '@shared/errors';\n\n/**\n * Dispatch a parsed yargs invocation to the wizard runner. Applies the\n * program's `mapCliOptions` transform, then routes to `runWizardHeadless`,\n * `runWizardCI`, or `runWizard` based on the headless / `--ci` flags.\n *\n * Every command file used to inline this; the factories call it instead.\n */\n/**\n * Run a command's async body as fire-and-forget while still surfacing failures.\n * yargs handlers are synchronous, so async work kicks off a detached promise —\n * without this, a rejection becomes an unhandled promise rejection (no message,\n * wrong exit code). This awaits the work and turns any error into a clean\n * message + non-zero exit.\n */\nexport function runCommandHandler(work: () => void | Promise<void>): void {\n void (async () => {\n try {\n await work();\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n process.stderr.write(`\\n\\x1b[1;91m✖ ${msg}\\x1b[0m\\n\\n`);\n emitWizardError({ code: ErrorCodes.InternalUnhandled, message: msg });\n process.exit(1);\n }\n })();\n}\n\nexport function dispatchProgram(config: ProgramConfig, argv: Arguments): void {\n const argvRecord: Record<string, unknown> = { ...argv };\n const extras = config.mapCliOptions?.(argvRecord) ?? {};\n const options = { ...argvRecord, ...extras };\n if (isHeadless(options)) {\n // Same non-interactive pipeline `--ci` uses; validation (api-key,\n // install-dir, region) is owned by runNonInteractive.\n runWizardHeadless(config, options);\n } else if (options.ci) {\n runWizardCI(config, options);\n } else {\n runWizard(config, options);\n }\n}\n\n/**\n * Merge the standard skill-program flags (`--debug`, `--install-dir`, etc.)\n * with any program-specific options declared on `cliOptions`.\n *\n * Program-specific options shadow the standard ones — that's intentional, so\n * a program can override a default flag if it ever needs to.\n */\nexport function mergeCommandOptions(\n config: ProgramConfig,\n): Record<string, Options> {\n return {\n ...skillProgramOptions,\n ...((config.cliOptions ?? {}) as Record<string, Options>),\n };\n}\n","import type { ProgramConfig } from '@programs/types';\n\nimport type { Command } from '../command';\n\nimport { dispatchProgram, mergeCommandOptions } from './shared';\n\nexport interface NativeCommandFactoryOpts {\n /** Subcommands nested under this command. */\n children?: readonly Command[];\n}\n\n/**\n * Build a yargs `Command` from a wizard-native `ProgramConfig`.\n *\n * Collapses the previously duplicated boilerplate (read `config.command`,\n * merge skill-program flags with program-specific options, dispatch via\n * `runWizard` / `runWizardCI`) into a single call.\n */\nexport function nativeCommandFactory(\n config: ProgramConfig,\n opts: NativeCommandFactoryOpts = {},\n): Command {\n if (!config.command) {\n throw new Error(\n `nativeCommandFactory: program \"${config.id}\" has no \\`command\\` — wizard-native programs must declare a CLI name`,\n );\n }\n return {\n name: config.command,\n description: config.description,\n options: mergeCommandOptions(config),\n children: opts.children,\n handler: (argv) => dispatchProgram(config, argv),\n };\n}\n","import { config as mcpAnalyticsConfig } from '@programs/mcp-analytics';\n\nimport type { Command } from './command';\nimport { nativeCommandFactory } from './factories/native-command-factory';\n\n/**\n * `wizard mcp-analytics` — flat skill command, instrument-an-MCP-server today.\n *\n * Distinct from `wizard mcp add`: this instruments the user's own MCP server\n * with the PostHog MCP SDK for its language, rather than installing the PostHog MCP server\n * into a coding agent. Stays flat while instrumenting is the only action.\n */\nexport const mcpAnalyticsCommand: Command =\n nativeCommandFactory(mcpAnalyticsConfig);\n","import { config as replayVisionConfig } from '@programs/replay-vision';\n\nimport type { Command } from './command';\nimport { nativeCommandFactory } from './factories/native-command-factory';\n\n/**\n * `wizard replay-vision` — flat skill command, set up Replay vision today.\n *\n * Enables session replay recording and creates vision scanners tailored to\n * the product's key flows. Runs the `replay-vision` orchestrator flow, which\n * reuses the integration-v2 install/init mini-agents when the repo has no\n * PostHog integration yet.\n */\nexport const replayVisionCommand: Command =\n nativeCommandFactory(replayVisionConfig);\n","import { config as aiObservabilityConfig } from '@programs/ai-observability';\n\nimport type { Command } from './command';\nimport { nativeCommandFactory } from './factories/native-command-factory';\n\n/**\n * `wizard ai-observability` — flat skill command, wire AI Observability into a\n * project today.\n *\n * Installs the OpenTelemetry SDK, the PostHog span processor, and the\n * provider-specific instrumentation so LLM calls emit `$ai_generation` events.\n * The `ai-observability` context-mill skill has one variant per (LLM provider ×\n * language); the agent picks the right one at run time by scanning the\n * project's manifest and (when ambiguous) asking the user via `wizard_ask`.\n * Stays flat while a single \"add AIO to a project\" flow is the only action.\n */\nexport const aiObservabilityCommand: Command = nativeCommandFactory(\n aiObservabilityConfig,\n);\n","import { config as metricsConfig } from '@programs/metrics';\n\nimport type { Command } from './command';\nimport { nativeCommandFactory } from './factories/native-command-factory';\n\n/**\n * `wizard metrics` — flat skill command, wire PostHog application metrics\n * (counters, gauges, histograms via \\`posthog.metrics\\`) into a project.\n *\n * The `metrics` context-mill skill has one variant per platform (python,\n * nodejs, javascript, kubernetes, other/OTLP); the agent picks the right one\n * at run time by scanning the project's manifest and (when ambiguous) asking\n * the user via `wizard_ask`. Stays flat while a single \"add metrics to a\n * project\" flow is the only action.\n */\nexport const metricsCommand: Command = nativeCommandFactory(metricsConfig);\n","import { consoleLog } from '@shared/console-log';\nimport { CLI_STEERING_TARGETS } from '@shared/install-cli-steering';\nimport { runCliAdd } from '@tools';\nimport { exitWith } from '@cli/runners';\nimport type { Command } from '../command';\n\nexport const cliAddCommand: Command = {\n name: 'add',\n description:\n \"Install or update PostHog CLI and add steering instructions to your coding agent's global instructions file\",\n options: {\n agent: {\n describe: 'Agent to install the instructions for',\n choices: CLI_STEERING_TARGETS.map((target) => target.id),\n type: 'string',\n },\n path: {\n describe:\n 'Write to an explicit instructions file instead of a detected agent',\n type: 'string',\n },\n all: {\n default: false,\n describe: 'Install for every detected agent without prompting',\n type: 'boolean',\n },\n },\n examples: [\n ['wizard cli add', 'Detect your coding agents and pick one'],\n [\n 'wizard cli add --agent claude-code',\n 'Install for Claude Code (~/.claude/CLAUDE.md)',\n ],\n ['wizard cli add --all', 'Install for every detected agent'],\n [\n 'wizard cli add --path ./AGENTS.md',\n 'Install into a specific instructions file',\n ],\n ],\n check: (argv) => {\n if (argv.all && (argv.agent || argv.path)) {\n throw new Error('--all cannot be combined with --agent or --path');\n }\n return true;\n },\n handler: (argv) => {\n exitWith(() =>\n runCliAdd(\n {\n agent: typeof argv.agent === 'string' ? argv.agent : undefined,\n path: typeof argv.path === 'string' ? argv.path : undefined,\n all: argv.all === true,\n },\n { log: consoleLog },\n ),\n );\n },\n};\n","import { cliAddCommand } from './add';\nimport type { Command } from '../command';\n\nexport const cliCommand: Command = {\n name: 'cli',\n description: 'PostHog CLI agent integration commands',\n children: [cliAddCommand],\n};\n","import type { Arguments } from 'yargs';\n\nimport { AUDIT_CHECKS_FILE } from '@programs/audit';\nimport { WIZARD_TOOL_NAMES } from '@agent';\nimport { getProgramConfig, Program } from '@programs';\nimport { config as agentSkillConfig } from '@programs/agent-skill';\nimport { config as webAnalyticsDoctorConfig } from '@programs/web-analytics-doctor';\nimport type { ProgramConfig } from '@programs/types';\nimport { getSkillsBaseUrl } from '@shared/constants';\nimport { fetchSkillMenu, type CliEntry } from '@shared/skill-menu';\nimport { analytics } from '@utils/analytics';\n\nimport { dispatchProgram } from './factories/shared';\nimport type { Command } from './command';\nimport { ErrorCodes } from '@shared/errors';\nimport { emitWizardError } from '@shared/errors';\n\n/**\n * Capture a CLI dispatch error, flush analytics, and exit. The wizard never\n * starts a run from these paths — use flush() (not shutdown()) so we don't\n * fire a \"setup wizard finished\" event for a parse error that didn't run.\n */\nasync function exitDispatchError(\n reason: string,\n properties: Record<string, unknown>,\n message: string,\n code = 1,\n): Promise<never> {\n analytics.wizardCapture('cli dispatch error', { reason, ...properties });\n try {\n await analytics.flush();\n } catch {\n /* flush is best-effort; never block the exit */\n }\n process.stderr.write(message);\n emitWizardError({ code: ErrorCodes.CliBadArgs, message: reason });\n return process.exit(code);\n}\n\n/**\n * Family commands (`wizard audit`, `wizard migrate`, ...) resolve their\n * subcommands at runtime against the published `cliEntries` inside\n * `skill-menu.json`. Adding a subcommand is a context-mill release — no\n * wizard release needed.\n *\n * Wizard-native subcommands (programs that aren't backed by a single skill,\n * e.g. `wizard audit web-analytics`) live here in code, dispatched directly\n * without touching the registry. Adding a native is a wizard PR.\n */\n\n/** Wizard-native subcommands keyed by family. */\nconst NATIVE_HANDLERS: Record<string, Record<string, ProgramConfig>> = {\n audit: { 'web-analytics': webAnalyticsDoctorConfig },\n};\n\n/**\n * Resolve a fetched CliEntry to the ProgramConfig that actually runs it.\n * Most entries run via the generic agent-skill program with the entry's\n * `skillId` injected. The comprehensive `audit all` is the one exception —\n * skillId 'audit' triggers the specialized `audit` program (custom hooks,\n * content blocks, screens).\n *\n * This is the one place that knows a subcommand belongs to `audit`, so the\n * generic skill program picks up the ledger here rather than for every skill.\n */\nfunction configForCliEntry(entry: CliEntry, family: string): ProgramConfig {\n if (entry.skillId === 'audit') return getProgramConfig(Program.Audit);\n return {\n ...agentSkillConfig,\n skillId: entry.skillId,\n ...(family === 'audit'\n ? {\n auditLedgerFile: AUDIT_CHECKS_FILE,\n streamWorkflowId: family,\n allowedTools: [\n ...(agentSkillConfig.allowedTools ?? []),\n WIZARD_TOOL_NAMES.auditSeedChecks,\n WIZARD_TOOL_NAMES.auditAddChecks,\n WIZARD_TOOL_NAMES.auditResolveChecks,\n ],\n }\n : {}),\n };\n}\n\nfunction familyEntries(family: string, entries: CliEntry[]): CliEntry[] {\n return entries.filter(\n (e) =>\n e.role === 'command' && e.parentCommand === family && Boolean(e.command),\n );\n}\n\n/**\n * Dispatch `wizard <family> <sub>` to the right program.\n *\n * Order:\n * 1. Native handler for (family, sub) — runs immediately, no network.\n * 2. Fetched CliEntry — runs the resolved skill.\n * 3. Unknown — prints the available list and exits non-zero.\n */\nexport async function dispatchFamily(\n family: string,\n argv: Arguments,\n): Promise<void> {\n const sub = (argv.skill as string | undefined)?.trim();\n if (!sub) {\n // Reached only in non-TTY/CI — an interactive terminal routes the no-sub\n // case to the picker before this runs, so don't suggest opening it here.\n return exitDispatchError(\n 'missing subcommand',\n { family },\n `\\n\\x1b[1;91m✖ \\`wizard ${family}\\` requires a subcommand.\\x1b[0m\\n` +\n ` Pass one (e.g. \\`wizard ${family} <subcommand>\\`), or run it in an interactive terminal to pick from a menu.\\n\\n`,\n );\n }\n\n const native = NATIVE_HANDLERS[family]?.[sub];\n if (native) {\n dispatchProgram(native, argv);\n return;\n }\n\n const skillsBaseUrl = getSkillsBaseUrl();\n const menu = await fetchSkillMenu(skillsBaseUrl);\n if (!menu) {\n return exitDispatchError(\n 'registry unreachable',\n { family, sub, skillsBaseUrl },\n `\\n\\x1b[1;91m✖ Couldn't reach the skill registry at ${skillsBaseUrl}.\\x1b[0m\\n` +\n ` Check your network connection and try again.\\n\\n`,\n );\n }\n\n const entries = menu.cliEntries ?? [];\n const entry = familyEntries(family, entries).find((e) => e.command === sub);\n if (entry) {\n dispatchProgram(configForCliEntry(entry, family), argv);\n return;\n }\n\n const available = [\n ...Object.keys(NATIVE_HANDLERS[family] ?? {}),\n ...familyEntries(family, entries).map((e) => e.command!),\n ].sort();\n return exitDispatchError(\n 'unknown subcommand',\n { family, sub, available },\n `\\n\\x1b[1;91m✖ Unknown subcommand \"${sub}\" under \\`${family}\\`.\\x1b[0m\\n` +\n (available.length\n ? ` Available: ${available.join(', ')}\\n\\n`\n : ` No subcommands published for \"${family}\" yet.\\n\\n`),\n );\n}\n\n/**\n * Build the children list shown in the family's interactive picker.\n * Combines native handlers with skill-backed entries from the live registry.\n * Used by `familyCommandFactory`'s `interactiveDefault`.\n */\nexport function buildFamilyPickerChildren(\n family: string,\n entries: CliEntry[],\n): Command[] {\n const natives: Command[] = Object.entries(NATIVE_HANDLERS[family] ?? {}).map(\n ([cmd, program]) => ({\n name: cmd,\n description: program.description,\n handler: (argv: Arguments) => dispatchProgram(program, argv),\n }),\n );\n const live: Command[] = familyEntries(family, entries).map((entry) => ({\n name: entry.command!,\n description: entry.description,\n handler: (argv: Arguments) => {\n void dispatchFamily(family, {\n ...argv,\n skill: entry.command,\n } as Arguments);\n },\n default: entry.default,\n }));\n return [...natives, ...live];\n}\n\n/**\n * The children the family picker shows **today**: only the leaf marked\n * `default` (e.g. `audit events`). Every other subcommand stays runnable\n * directly (`wizard audit <name>`) — they just aren't listed in the picker yet.\n * Falls back to all children when nothing is marked `default`.\n *\n * Temporary: when we're ready to surface the full menu, return `children`\n * unchanged (and delete this note).\n */\nexport function pickerChildrenToShow(children: readonly Command[]): Command[] {\n const defaults = children.filter((c) => c.default);\n return defaults.length > 0 ? [...defaults] : [...children];\n}\n","/**\n * Mount an Ink picker over a command's `children` and dispatch the\n * selected child's handler.\n *\n * Used as the `interactiveDefault` for family parents like\n * `wizard audit` — when the user invokes the parent without a leaf, this\n * shows a TUI menu instead of yargs's `demandCommand(1)` help dump.\n *\n * The picker opens when a family surfaces more than one option; the `default`\n * flag controls which one is pre-highlighted. When a family surfaces a single\n * option (today `audit` → `events`), `familyCommandFactory` runs it directly\n * instead, so the user lands on its intro screen rather than a one-item menu.\n *\n * Single-option commands aren't families — they should be flat\n * commands wired with `skillCommandFactory` / `nativeCommandFactory`\n * directly, not run through this module.\n */\n\nimport type { Arguments } from 'yargs';\n\nimport { commandKeys, type Command } from '../command';\n\nfunction describe(child: Command): string {\n // Strip positional syntax (`search <query>` → `search`) for the picker label.\n return commandKeys(child.name)[0] ?? '';\n}\n\n/**\n * Reorder children so the `default`-marked entry is first, while\n * preserving the relative order of the rest. The picker's initial\n * focus is index 0, so this is what makes \"press Enter on\n * `wizard audit`\" run the default leaf (today `audit events`).\n *\n * Exported for testability — the ordering logic stays pure and\n * inspectable without mounting Ink.\n */\nexport function orderFamilyChildren(children: readonly Command[]): Command[] {\n const selectable = children.filter((c) => c.handler || c.children?.length);\n const defaults = selectable.filter((c) => c.default);\n const rest = selectable.filter((c) => !c.default);\n return [...defaults, ...rest];\n}\n\n/**\n * Render the picker over a family's children. Resolves once the user has\n * selected a child; dispatching the child's handler is the caller's\n * responsibility.\n */\nexport async function chooseFamilyChild(\n parentLabel: string,\n children: readonly Command[],\n): Promise<Command | null> {\n const ordered = orderFamilyChildren(children);\n if (ordered.length === 0) return null;\n\n // Loaded here: a headless run never loads the TUI.\n const { renderFamilyPicker } = await import('@tui');\n return renderFamilyPicker(\n parentLabel,\n ordered.map((child) => ({\n label: describe(child),\n value: child,\n hint: child.description,\n })),\n );\n}\n\n/**\n * Returns an `interactiveDefault` handler for a family parent's no-leaf\n * invocation. Always opens the picker; the `default`-marked child is\n * shown first (pre-highlighted), so a single Enter keystroke runs it.\n *\n * Discovery + consent in one extra keystroke vs. auto-running silently.\n *\n * Wire onto a family parent:\n * export const auditCommand: Command = {\n * name: 'audit',\n * description: '...',\n * children: [...],\n * interactiveDefault: createFamilyPickerDefault('audit', auditChildren),\n * };\n */\nexport function createFamilyPickerDefault(\n parentLabel: string,\n children: readonly Command[],\n chooser: (\n label: string,\n children: readonly Command[],\n ) => Promise<Command | null> = chooseFamilyChild,\n): (argv: Arguments) => Promise<void> {\n return async (argv) => {\n const chosen = await chooser(parentLabel, children);\n if (!chosen) return;\n // We forward the PARENT's parsed argv straight to the chosen child. The\n // child's own option defaults and `check` validator do NOT run on this\n // path — they only run when the leaf is invoked directly\n // (`wizard audit events`). Harmless while leaves declare neither, but if a\n // leaf ever grows a `check` or a defaulted option, this path will skip it.\n await Promise.resolve(chosen.handler?.(argv));\n };\n}\n","import type { Arguments } from 'yargs';\n\nimport type { ProgramConfig } from '@programs/types';\nimport {\n buildFamilyPickerChildren,\n dispatchFamily,\n pickerChildrenToShow,\n} from '../dispatch-family';\nimport { getSkillsBaseUrl } from '@shared/constants';\nimport { fetchSkillMenu } from '@shared/skill-menu';\n\nimport type { Command } from '../command';\nimport { createFamilyPickerDefault } from './family-picker';\nimport { mergeCommandOptions, runCommandHandler } from './shared';\n\nexport interface FamilyCommandFactoryOpts {\n /** The family's CLI name (e.g. 'audit'). */\n family: string;\n /** Help text for `wizard <family> --help`. */\n description: string;\n /**\n * Source for shared CLI options (e.g. --install-dir) merged onto the\n * family parent. Usually the family's flagship native config, or the\n * generic agent-skill config.\n */\n optionsFrom: ProgramConfig;\n}\n\n/**\n * Build a yargs `Command` for a family parent (`wizard audit`, etc.).\n *\n * - `wizard <family> <sub>` — `dispatchFamily` resolves `<sub>` against\n * native handlers first, then the live `cliEntries` from\n * `skill-menu.json`. Unknown subs error with the available list.\n * - `wizard <family>` (no positional) — in an interactive terminal, runs the\n * family's single shown entry directly (today `audit events`, so the user\n * lands on its intro screen); opens the picker once a family shows more than\n * one. In non-TTY/CI, falls through to `dispatchFamily`, which prints\n * \"requires a subcommand\" rather than running something unprompted.\n *\n * No static yargs children. New skill-backed subcommands appear after a\n * context-mill release without a wizard release. New *native* subcommands\n * (rare) are added by updating `NATIVE_HANDLERS` in `dispatch-family.ts`.\n */\nexport function familyCommandFactory({\n family,\n description,\n optionsFrom,\n}: FamilyCommandFactoryOpts): Command {\n // Bare `wizard <family>` in an interactive terminal. With a single option\n // today (e.g. `audit events`), skip the picker and run it directly so the\n // user lands on its own intro screen rather than a one-item menu. When a\n // family grows past one shown option, this opens the picker instead — no\n // wiring change needed.\n const openFamilyEntry = async (argv: Arguments): Promise<void> => {\n const skillsBaseUrl = getSkillsBaseUrl();\n const menu = await fetchSkillMenu(skillsBaseUrl);\n const children = buildFamilyPickerChildren(family, menu?.cliEntries ?? []);\n const toShow = pickerChildrenToShow(children);\n if (toShow.length === 1 && toShow[0]?.handler) {\n await Promise.resolve(toShow[0].handler(argv));\n return;\n }\n const picker = createFamilyPickerDefault(`wizard ${family}`, toShow);\n await picker(argv);\n };\n\n return {\n name: `${family} [skill]`,\n description,\n options: mergeCommandOptions(optionsFrom),\n positionals: {\n skill: {\n type: 'string',\n describe: 'Subcommand to run (omit to run the default)',\n },\n },\n handler: (argv: Arguments) => {\n const sub = (argv.skill as string | undefined)?.trim();\n // With a subcommand, resolve and run it. Without one, run the family's\n // default entry (or open the picker if there's more than one) — but only\n // in an interactive terminal. In non-TTY/CI, fall through to\n // dispatchFamily, which prints \"requires a subcommand\" rather than\n // running something unprompted or hanging on a picker that can't render.\n // runCommandHandler awaits the async work so a rejection surfaces as a\n // clean error instead of an unhandled promise rejection.\n runCommandHandler(() =>\n sub || !process.stdout.isTTY\n ? dispatchFamily(family, argv)\n : openFamilyEntry(argv),\n );\n },\n interactiveDefault: openFamilyEntry,\n };\n}\n","import { getProgramConfig, Program } from '@programs';\n\nimport type { Command } from './command';\nimport { familyCommandFactory } from './factories/family-command-factory';\n\n/**\n * The `wizard audit` family.\n *\n * Subcommands are resolved at runtime: the wizard fetches `cliEntries` from\n * `skill-menu.json` and dispatches based on `parentCommand: 'audit'`. The\n * wizard-native handler for `web-analytics` lives in `NATIVE_HANDLERS` over\n * in `dispatch-family.ts`. `wizard audit` with no positional opens the\n * family picker, which combines native + live entries.\n *\n * Adding a new skill-backed audit subcommand is a context-mill release —\n * no wizard release needed.\n */\nconst audit = getProgramConfig(Program.Audit);\n\nexport const auditCommand: Command = familyCommandFactory({\n family: 'audit',\n description: audit.description,\n optionsFrom: audit,\n});\n","import { consoleLog } from '@shared/console-log';\nimport { readApiKeyFromEnv } from '@utils/env-api-key';\nimport { DOCTOR, runDoctorReport, Tool } from '@tools';\nimport { exitWith, tuiSessionArgs, withSignals } from '@cli/runners';\nimport { skillProgramOptions } from './skill-program-options';\nimport type { Command } from './command';\n\nexport const doctorCommand: Command = {\n name: 'doctor',\n description: DOCTOR.description,\n options: { ...skillProgramOptions },\n handler: (argv) => {\n const options = { ...argv } as Record<string, unknown>;\n // In CI there is no screen: fetch the project's health issues and print them.\n if (options.ci) {\n exitWith(() =>\n runDoctorReport(\n {\n apiKey:\n (options.apiKey as string | undefined) ??\n readApiKeyFromEnv() ??\n undefined,\n projectId: options.projectId\n ? Number(options.projectId as string)\n : undefined,\n baseUrl: options.baseUrl as string | undefined,\n },\n { log: consoleLog },\n ),\n );\n return;\n }\n withSignals(async (signal) => {\n // Loaded here, not at startup: a console run never loads the TUI.\n const { runTuiTool } = await import('@tui');\n return runTuiTool(Tool.PosthogDoctor, {\n session: tuiSessionArgs(options),\n signal,\n });\n });\n },\n};\n","import { config as migrationConfig } from '@programs/migration';\n\nimport type { Command } from './command';\nimport { nativeCommandFactory } from './factories/native-command-factory';\n\n/**\n * `wizard migrate` — flat skill command, Statsig today.\n *\n * Stays flat while there's only one vendor. When a second vendor lands,\n * restructure into a family with `familyCommandFactory` and publish each\n * vendor as a `cliEntries` entry with `parentCommand: 'migrate'` from\n * context-mill. That move is a deliberate breaking change for users\n * (`wizard migrate` stops running Statsig directly), so do it explicitly\n * when the second vendor arrives, not pre-emptively.\n */\nexport const migrateCommand: Command = nativeCommandFactory(migrationConfig);\n","import { config as revenueAnalyticsConfig } from '@programs/revenue-analytics';\n\nimport type { Command } from './command';\nimport { nativeCommandFactory } from './factories/native-command-factory';\n\n/**\n * `wizard revenue-analytics` — flat skill command, Stripe today.\n *\n * Stays flat while there's only one provider. Restructure into a family\n * if/when a second provider lands.\n */\nexport const revenueCommand: Command = nativeCommandFactory(\n revenueAnalyticsConfig,\n);\n","import { config as warehouseSourceConfig } from '@programs/warehouse-source';\n\nimport type { Command } from './command';\nimport { nativeCommandFactory } from './factories/native-command-factory';\n\n/**\n * `wizard warehouse` — detect and connect a data warehouse source.\n *\n * Mirrors `revenue-analytics`: flat skill command driven by the\n * warehouse-source program.\n */\nexport const warehouseCommand: Command = nativeCommandFactory(\n warehouseSourceConfig,\n);\n","import { runWizard, runWizardCI } from '@cli/runners';\nimport { config as selfDrivingConfig } from '@programs/self-driving';\nimport { skillProgramOptions } from './skill-program-options';\nimport type { Command } from './command';\n\nexport const selfDrivingCommand: Command = {\n name: 'self-driving',\n description: selfDrivingConfig.description,\n options: {\n ...skillProgramOptions,\n integrate: {\n describe:\n 'Integrate the PostHog SDK first, then set up Self-driving — skips the integration prompt and logs you in via OAuth (no \"create an account?\" question). Use when the project isn\\'t set up yet but you already have a PostHog account.',\n type: 'boolean',\n default: false,\n },\n ...(selfDrivingConfig.cliOptions ?? {}),\n },\n check: (argv) => {\n // self-driving builds on an existing integration and is fully interactive,\n // so the modes that break it are rejected before the TUI/agent loop spins\n // up rather than failing late (a 403 on the first MCP probe under --signup,\n // or a stalled `wizard_ask` with no bridge under --ci).\n if (argv.signup) {\n throw new Error(\n '`self-driving` cannot run with --signup. Just run `wizard ' +\n 'self-driving`: when your project has no PostHog, it asks whether ' +\n 'you already have an account and offers to create one for you ' +\n '(no flag needed).',\n );\n }\n if (argv.ci) {\n throw new Error(\n '`self-driving` cannot run in CI mode — it requires interactive steps ' +\n '(GitHub connect, issue-tracker selection, custom-scout approval).',\n );\n }\n return true;\n },\n handler: (argv) => {\n const extras =\n selfDrivingConfig.mapCliOptions?.(argv as Record<string, unknown>) ?? {};\n const options = { ...argv, ...extras };\n if (options.ci) {\n runWizardCI(selfDrivingConfig, options);\n } else {\n runWizard(selfDrivingConfig, options);\n }\n },\n};\n","import type { Arguments } from 'yargs';\nimport { consoleLog } from '@shared/console-log';\nimport { ErrorCodes, emitWizardError } from '@shared/errors';\nimport { Tool } from '@tools';\nimport { exitWith, underSignals } from '@cli/runners';\nimport type { Command } from './command';\n\nexport const slackCommand: Command = {\n name: 'slack',\n description: 'Connect PostHog to your Slack',\n handler: runSlackConnect,\n // Mirrors the mcp command family shape: `wizard slack` and\n // `wizard slack add` run the same connect flow.\n children: [\n {\n name: 'add',\n description: 'Connect PostHog to your Slack',\n handler: runSlackConnect,\n },\n ],\n};\n\nfunction runSlackConnect(argv: Arguments): void {\n exitWith(async () => {\n try {\n const { runTuiTool } = await import('@tui');\n return await underSignals((signal) =>\n runTuiTool(Tool.SlackConnect, {\n session: {\n debug: argv.debug as boolean | undefined,\n baseUrl: argv.baseUrl as string | undefined,\n },\n signal,\n }),\n );\n } catch (err) {\n // TUI unavailable — connecting Slack has no headless fallback.\n consoleLog.log.error(\n `Connecting Slack requires an interactive terminal. ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n emitWizardError({\n code: ErrorCodes.CliInteractiveRequired,\n message: 'Connecting Slack requires an interactive terminal.',\n });\n return 1;\n }\n });\n}\n","import { runWizard, runWizardCI } from '@cli/runners';\nimport { config as errorTrackingUploadSourceMapsConfig } from '@programs/error-tracking-upload-source-maps';\nimport { skillProgramOptions } from './skill-program-options';\nimport type { Command } from './command';\n\nexport const uploadSourcemapsCommand: Command = {\n // Must match ProgramConfig.command; legacy alias kept for #489 regression.\n name: [errorTrackingUploadSourceMapsConfig.command!, 'upload-sourcemaps'],\n description: errorTrackingUploadSourceMapsConfig.description,\n options: {\n ...skillProgramOptions,\n ...(errorTrackingUploadSourceMapsConfig.cliOptions ?? {}),\n },\n handler: (argv) => {\n const extras =\n errorTrackingUploadSourceMapsConfig.mapCliOptions?.(\n argv as Record<string, unknown>,\n ) ?? {};\n const options = { ...argv, ...extras };\n if (options.ci) {\n runWizardCI(errorTrackingUploadSourceMapsConfig, options);\n } else {\n runWizard(errorTrackingUploadSourceMapsConfig, options);\n }\n },\n};\n","import { config as errorTrackingConfig } from '@programs/error-tracking';\n\nimport type { Command } from './command';\nimport { nativeCommandFactory } from './factories/native-command-factory';\n\n/**\n * `wizard error-tracking` — flat skill command, set up error tracking today.\n *\n * Wires up exception capture and — where the platform needs it — source-map /\n * debug-symbol upload. Runs the `error-tracking` orchestrator flow, which\n * reuses the integration-v2 install/init mini-agents when the repo has no\n * PostHog integration yet, so it works on uninstrumented projects too.\n */\nexport const errorTrackingCommand: Command =\n nativeCommandFactory(errorTrackingConfig);\n","import { config as featureFlagsConfig } from '@programs/feature-flags';\n\nimport type { Command } from './command';\nimport { nativeCommandFactory } from './factories/native-command-factory';\n\nexport const featureFlagsCommand: Command =\n nativeCommandFactory(featureFlagsConfig);\n","import type { Arguments } from 'yargs';\nimport { POSTHOG_DOCS_URL } from '@shared/constants';\nimport { runWizard, runWizardCI } from '@cli/runners';\nimport { createSkillProgram } from '@programs';\n\n/** Run an arbitrary context-mill skill by id (`wizard skill <id>`, headless with `--ci`). */\nexport function runSkillMode(argv: Arguments): void {\n const skillId = argv.skill as string;\n const config = createSkillProgram({\n skillId,\n command: 'skill',\n id: 'agent-skill',\n description: `Run skill: ${skillId}`,\n integrationLabel: skillId,\n successMessage: `${skillId} completed!`,\n reportFile: `posthog-${skillId}-report.md`,\n docsUrl: POSTHOG_DOCS_URL,\n spinnerMessage: `Running ${skillId}...`,\n estimatedDurationMinutes: 5,\n });\n const options = { ...argv, skillId };\n if (argv.ci) {\n runWizardCI(config, options);\n } else {\n runWizard(config, options);\n }\n}\n","import type { Arguments } from 'yargs';\n\nimport { getSkillsBaseUrl } from '@shared/constants';\nimport { fetchSkillMenu } from '@shared/skill-menu';\nimport { analytics } from '@utils/analytics';\nimport { listSkills } from '@tools';\nimport { exitWith } from '@cli/runners';\n\nimport { runSkillMode } from './basic-integration/skill';\nimport { skillProgramOptions } from './skill-program-options';\nimport { runCommandHandler } from './factories/shared';\nimport type { Command } from './command';\n\n/** Read the `<skill-name>` positional (yargs camelCases the hyphenated key). */\nfunction readSkillName(argv: Arguments): string {\n return String(argv.skillName ?? argv['skill-name'] ?? '').trim();\n}\n\n/**\n * Reject an unknown skill id before the wizard authenticates.\n *\n * Without this, `readSkillName` accepts any non-empty string and the name is\n * only validated far downstream, when the agent tries to download it — after\n * the user has already logged in. A typo then costs a full auth round-trip\n * (the concern raised in review). We resolve against the same set\n * `downloadSkill` uses (`categories` flattened by `id`), so this never\n * false-rejects a skill the download would have accepted.\n *\n * If the registry is unreachable we stay silent and defer to the download\n * step's own `menu-fetch-failed` handling, rather than adding a second network\n * dependency that could block an otherwise-valid run.\n */\nasync function assertSkillExists(skillName: string): Promise<void> {\n const skillsBaseUrl = getSkillsBaseUrl();\n const menu = await fetchSkillMenu(skillsBaseUrl);\n if (!menu) return; // registry down — let the download step surface it\n const known = Object.values(menu.categories)\n .flat()\n .some((s) => s.id === skillName);\n if (known) return;\n analytics.wizardCapture('cli dispatch error', {\n reason: 'unknown skill',\n family: 'skill',\n sub: skillName,\n skillsBaseUrl,\n });\n try {\n await analytics.flush();\n } catch {\n /* best-effort */\n }\n throw new Error(\n `Unknown skill \"${skillName}\". Run \\`wizard skill list\\` to see available skills.`,\n );\n}\n\n/**\n * `wizard skill <skill-name>` — run a single context-mill skill by id.\n * `wizard skill list` — list every browsable skill in the catalog.\n *\n * Replaces the old `--skill=<id>` flag on the default command. The skill id\n * is fetched from context-mill's release at runtime (same mechanism the flag\n * used), so any published skill id works. Pass `--ci` to run headlessly.\n */\nexport const skillCommand: Command = {\n name: 'skill <skill-name>',\n description: 'Run a specific context-mill skill by name (or `list` them)',\n options: {\n ...skillProgramOptions,\n },\n // Under `.strictOptions()` yargs rejects a positional declared only in the\n // command string as an \"Unknown argument\" — it has to be registered via\n // `.positional()` too (see the `positionals` note on the Command interface).\n // Declare `skill-name` here so `wizard skill <id>` actually accepts its value.\n positionals: {\n 'skill-name': {\n type: 'string',\n describe: 'Skill id to run (e.g. audit-events), or `list`',\n },\n },\n // yargs already enforces the presence of the `<skill-name>` positional, but\n // an explicitly-empty value (`wizard skill \"\"`) would otherwise slip\n // through to a broken run. Reject it with the same friendly message\n // the old --skill flag gave.\n check: (argv) => {\n if (!readSkillName(argv)) {\n throw new Error(\n 'skill needs a skill name, e.g. `wizard skill audit-events`',\n );\n }\n return true;\n },\n handler: (argv) => {\n // `list` is the positional's one reserved value, not a skill id.\n if (readSkillName(argv) === 'list') return exitWith(listSkills);\n runCommandHandler(async () => {\n const skillName = readSkillName(argv);\n await assertSkillExists(skillName);\n // runSkillMode reads `argv.skill`; bridge the positional onto it.\n runSkillMode({ ...argv, skill: skillName });\n });\n },\n};\n","/** The CLI's one entry: `main.ts` runs the `wizard` command line through it. */\nimport { Wizard } from './wizard';\nimport { basicIntegrationCommand } from './commands/basic-integration';\nimport { mcpCommand } from './commands/mcp';\nimport { mcpAnalyticsCommand } from './commands/mcp-analytics';\nimport { replayVisionCommand } from './commands/replay-vision';\nimport { aiObservabilityCommand } from './commands/ai-observability';\nimport { metricsCommand } from './commands/metrics';\nimport { cliCommand } from './commands/cli';\nimport { auditCommand } from './commands/audit';\nimport { doctorCommand } from './commands/doctor';\nimport { migrateCommand } from './commands/migrate';\nimport { revenueCommand } from './commands/revenue';\nimport { warehouseCommand } from './commands/warehouse';\nimport { selfDrivingCommand } from './commands/self-driving';\nimport { slackCommand } from './commands/slack';\nimport { uploadSourcemapsCommand } from './commands/upload-sourcemaps';\nimport { errorTrackingCommand } from './commands/error-tracking';\nimport { featureFlagsCommand } from './commands/feature-flags';\nimport { skillCommand } from './commands/skill';\n\n/** Register every command and run the one `process.argv` names. */\nexport function runCli(): void {\n Wizard.use(basicIntegrationCommand)\n .use(mcpCommand)\n .use(mcpAnalyticsCommand)\n .use(replayVisionCommand)\n .use(aiObservabilityCommand)\n .use(metricsCommand)\n .use(cliCommand)\n .use(auditCommand)\n .use(doctorCommand)\n .use(migrateCommand)\n .use(revenueCommand)\n .use(warehouseCommand)\n .use(selfDrivingCommand)\n .use(slackCommand)\n .use(uploadSourcemapsCommand)\n .use(errorTrackingCommand)\n .use(featureFlagsCommand)\n .use(skillCommand)\n .init();\n}\n","import { Agent, setGlobalDispatcher } from 'undici';\n\n/*\n * TODO(#1198): remove when fetch over HTTP/2 is safe on Node 26. Remove when all\n * of these are true:\n * - nodejs/node no longer creates an orphan ClientHttp2Stream when a client\n * session gets HEADERS for a stream id it already reset. Repro: abort a fetch\n * before its response headers, then idle 4s on Node 26. Fixed when the\n * process survives.\n * - modelcontextprotocol/typescript-sdk#2526 is closed.\n * - pi-coding-agent's CLI drops `allowH2: false` from its http-dispatcher.\n * Same workaround as pi's CLI and typescript-sdk#2526: HTTP/1.1 only.\n */\nsetGlobalDispatcher(new Agent({ allowH2: false }));\n\nimport { runCli } from '@cli';\nimport { recoverOrphanedSettingsBackups } from '@shared/claude-settings';\n\n// Heal any .claude/settings backup a previous interrupted run left orphaned,\n// before anything else reads Claude settings — conflict detection, OAuth, and\n// the agent all need to see the user's real settings file. The install dir is\n// read directly from argv/env because yargs hasn't parsed yet.\nrecoverOrphanedSettingsBackups(resolveInstallDir());\n\nfunction resolveInstallDir(): string {\n const args = process.argv.slice(2);\n const flagIndex = args.indexOf('--install-dir');\n if (flagIndex !== -1 && args[flagIndex + 1]) return args[flagIndex + 1];\n const inline = args.find((a) => a.startsWith('--install-dir='));\n if (inline) return inline.slice('--install-dir='.length);\n return process.env.POSTHOG_WIZARD_INSTALL_DIR ?? process.cwd();\n}\n\nrunCli();\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import { f as VERSION, o as logToFile } from "./debug-BvEbemym.js";
2
- import { o as onAccessTokenRotated } from "./oauth-session-Bi1MLRCC.js";
1
+ import { f as VERSION, o as logToFile } from "./debug-BTUMatFI.js";
2
+ import { o as onAccessTokenRotated } from "./oauth-session-CfkZ339p.js";
3
3
  import { Client } from "@modelcontextprotocol/sdk/client/index.js";
4
4
  import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
5
5
  import { createJiti } from "jiti";
@@ -93,4 +93,4 @@ async function setupPostHogMcp(opts) {
93
93
  //#endregion
94
94
  export { fetchInstructions, setupPostHogMcp };
95
95
 
96
- //# sourceMappingURL=mcp-Buf9sfFm.js.map
96
+ //# sourceMappingURL=mcp-D73aCOHK.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-Buf9sfFm.js","names":[],"sources":["../src/agent/runner/harness/pi/mcp.ts"],"sourcesContent":["/**\n * pi has no built-in MCP; `pi-mcp-adapter` — pi's own MCP extension, built here\n * with its supported `createMcpAdapter` embedding API — bridges the same hosted\n * MCP the anthropic path uses into the agent.\n */\n\nimport { Client } from '@modelcontextprotocol/sdk/client/index.js';\nimport { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';\nimport { createJiti } from 'jiti';\nimport { VERSION } from '@shared/version';\nimport { logToFile } from '@utils/debug';\nimport { onAccessTokenRotated } from '@shared/oauth-session';\n\nconst MCP_TOKEN_ENV = 'POSTHOG_MCP_TOKEN';\nlet mcpTokenOwners = 0;\nlet activeMcpToken: string | undefined;\nlet previousMcpToken: string | undefined;\n\nlet stopFollowingRotations: (() => void) | undefined;\n\nfunction setMcpToken(token: string): void {\n activeMcpToken = token;\n process.env[MCP_TOKEN_ENV] = token;\n}\n\nfunction acquireMcpToken(token: string): () => void {\n if (mcpTokenOwners === 0) {\n previousMcpToken = process.env[MCP_TOKEN_ENV];\n // The adapter reads the env on each connect, so reconnects take the rotated token.\n stopFollowingRotations = onAccessTokenRotated(setMcpToken);\n }\n // A later session after a rotation carries the newer token of the same login.\n if (activeMcpToken !== token) setMcpToken(token);\n mcpTokenOwners += 1;\n let released = false;\n return () => {\n if (released) return;\n released = true;\n mcpTokenOwners -= 1;\n if (mcpTokenOwners > 0) return;\n stopFollowingRotations?.();\n stopFollowingRotations = undefined;\n if (previousMcpToken === undefined) delete process.env[MCP_TOKEN_ENV];\n else process.env[MCP_TOKEN_ENV] = previousMcpToken;\n activeMcpToken = undefined;\n previousMcpToken = undefined;\n };\n}\n\nexport interface PostHogMcpSetup {\n /** pi ExtensionFactory to add to the resource loader's `extensionFactories`. */\n extensionFactory: (pi: unknown) => void;\n /** Release this setup's token ownership. Call after the run. */\n cleanup: () => void;\n}\n\n/** Server `instructions` for the system prompt — the adapter exposes no accessor, so one standard-SDK handshake; best-effort. */\nexport async function fetchInstructions(\n mcpUrl: string,\n accessToken: string,\n userAgent: string,\n): Promise<string | undefined> {\n const client = new Client({ name: 'posthog-wizard', version: VERSION });\n try {\n const transport = new StreamableHTTPClientTransport(new URL(mcpUrl), {\n requestInit: {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n 'User-Agent': userAgent,\n },\n },\n });\n await client.connect(transport);\n const instructions = client.getInstructions() || undefined;\n logToFile(`[pi-mcp] instructions ${instructions?.length ?? 0} chars`);\n return instructions;\n } catch (err) {\n logToFile(`[pi-mcp] instructions fetch skipped: ${String(err)}`);\n return undefined;\n } finally {\n await client.close().catch(() => undefined);\n }\n}\n\nexport async function setupPostHogMcp(opts: {\n mcpUrl: string;\n accessToken: string;\n userAgent: string;\n}): Promise<PostHogMcpSetup> {\n const { mcpUrl, accessToken, userAgent } = opts;\n\n // By env NAME: the token stays in this process, off disk, and never reaches pi's env-scrubbed tool subprocesses.\n const cleanup = acquireMcpToken(accessToken);\n\n try {\n // The adapter ships raw TypeScript; loading through jiti is its documented requirement.\n const jiti = createJiti(import.meta.url);\n const mod = await jiti.import<{\n createMcpAdapter: (\n options: unknown,\n ) => PostHogMcpSetup['extensionFactory'];\n }>('pi-mcp-adapter');\n const extensionFactory = mod.createMcpAdapter({\n config: {\n mcpServers: {\n posthog: {\n url: mcpUrl,\n auth: 'bearer',\n bearerTokenEnv: MCP_TOKEN_ENV,\n headers: { 'User-Agent': userAgent },\n // Connect at extension load — direct tools register without a session_start.\n lifecycle: 'eager',\n // Register only `exec`: `directTools: true` also mints a `posthog_get_<name>` tool per MCP resource, whose sentence-length names overflow Anthropic's 128-char tool-name limit and 400 the whole request.\n directTools: ['exec'],\n exposeResources: false,\n },\n },\n // Disable the proxy `mcp` tool (its search indirection pollutes context); the adapter re-enables it only if no direct tools resolve.\n settings: { disableProxyTool: true, toolPrefix: 'posthog' },\n },\n });\n logToFile(`[pi-mcp] adapter loaded; posthog MCP at ${mcpUrl}`);\n return { extensionFactory, cleanup };\n } catch (error) {\n cleanup();\n throw error;\n }\n}\n"],"mappings":";;;;;;;;;;;AAaA,MAAM,gBAAgB;AACtB,IAAI,iBAAiB;AACrB,IAAI;AACJ,IAAI;AAEJ,IAAI;AAEJ,SAAS,YAAY,OAAqB;AACxC,kBAAiB;AACjB,SAAQ,IAAI,iBAAiB;;AAG/B,SAAS,gBAAgB,OAA2B;AAClD,KAAI,mBAAmB,GAAG;AACxB,qBAAmB,QAAQ,IAAI;AAE/B,2BAAyB,qBAAqB,YAAY;;AAG5D,KAAI,mBAAmB,MAAO,aAAY,MAAM;AAChD,mBAAkB;CAClB,IAAI,WAAW;AACf,cAAa;AACX,MAAI,SAAU;AACd,aAAW;AACX,oBAAkB;AAClB,MAAI,iBAAiB,EAAG;AACxB,4BAA0B;AAC1B,2BAAyB,KAAA;AACzB,MAAI,qBAAqB,KAAA,EAAW,QAAO,QAAQ,IAAI;MAClD,SAAQ,IAAI,iBAAiB;AAClC,mBAAiB,KAAA;AACjB,qBAAmB,KAAA;;;;AAYvB,eAAsB,kBACpB,QACA,aACA,WAC6B;CAC7B,MAAM,SAAS,IAAI,OAAO;EAAE,MAAM;EAAkB,SAAS;EAAS,CAAC;AACvE,KAAI;EACF,MAAM,YAAY,IAAI,8BAA8B,IAAI,IAAI,OAAO,EAAE,EACnE,aAAa,EACX,SAAS;GACP,eAAe,UAAU;GACzB,cAAc;GACf,EACF,EACF,CAAC;AACF,QAAM,OAAO,QAAQ,UAAU;EAC/B,MAAM,eAAe,OAAO,iBAAiB,IAAI,KAAA;AACjD,YAAU,yBAAyB,cAAc,UAAU,EAAE,QAAQ;AACrE,SAAO;UACA,KAAK;AACZ,YAAU,wCAAwC,OAAO,IAAI,GAAG;AAChE;WACQ;AACR,QAAM,OAAO,OAAO,CAAC,YAAY,KAAA,EAAU;;;AAI/C,eAAsB,gBAAgB,MAIT;CAC3B,MAAM,EAAE,QAAQ,aAAa,cAAc;CAG3C,MAAM,UAAU,gBAAgB,YAAY;AAE5C,KAAI;EAQF,MAAM,oBALM,MADC,WAAW,OAAO,KAAK,IAAI,CACjB,OAIpB,iBAAiB,EACS,iBAAiB,EAC5C,QAAQ;GACN,YAAY,EACV,SAAS;IACP,KAAK;IACL,MAAM;IACN,gBAAgB;IAChB,SAAS,EAAE,cAAc,WAAW;IAEpC,WAAW;IAEX,aAAa,CAAC,OAAO;IACrB,iBAAiB;IAClB,EACF;GAED,UAAU;IAAE,kBAAkB;IAAM,YAAY;IAAW;GAC5D,EACF,CAAC;AACF,YAAU,2CAA2C,SAAS;AAC9D,SAAO;GAAE;GAAkB;GAAS;UAC7B,OAAO;AACd,WAAS;AACT,QAAM"}
1
+ {"version":3,"file":"mcp-D73aCOHK.js","names":[],"sources":["../src/agent/runner/harness/pi/mcp.ts"],"sourcesContent":["/**\n * pi has no built-in MCP; `pi-mcp-adapter` — pi's own MCP extension, built here\n * with its supported `createMcpAdapter` embedding API — bridges the same hosted\n * MCP the anthropic path uses into the agent.\n */\n\nimport { Client } from '@modelcontextprotocol/sdk/client/index.js';\nimport { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';\nimport { createJiti } from 'jiti';\nimport { VERSION } from '@shared/version';\nimport { logToFile } from '@utils/debug';\nimport { onAccessTokenRotated } from '@shared/oauth-session';\n\nconst MCP_TOKEN_ENV = 'POSTHOG_MCP_TOKEN';\nlet mcpTokenOwners = 0;\nlet activeMcpToken: string | undefined;\nlet previousMcpToken: string | undefined;\n\nlet stopFollowingRotations: (() => void) | undefined;\n\nfunction setMcpToken(token: string): void {\n activeMcpToken = token;\n process.env[MCP_TOKEN_ENV] = token;\n}\n\nfunction acquireMcpToken(token: string): () => void {\n if (mcpTokenOwners === 0) {\n previousMcpToken = process.env[MCP_TOKEN_ENV];\n // The adapter reads the env on each connect, so reconnects take the rotated token.\n stopFollowingRotations = onAccessTokenRotated(setMcpToken);\n }\n // A later session after a rotation carries the newer token of the same login.\n if (activeMcpToken !== token) setMcpToken(token);\n mcpTokenOwners += 1;\n let released = false;\n return () => {\n if (released) return;\n released = true;\n mcpTokenOwners -= 1;\n if (mcpTokenOwners > 0) return;\n stopFollowingRotations?.();\n stopFollowingRotations = undefined;\n if (previousMcpToken === undefined) delete process.env[MCP_TOKEN_ENV];\n else process.env[MCP_TOKEN_ENV] = previousMcpToken;\n activeMcpToken = undefined;\n previousMcpToken = undefined;\n };\n}\n\nexport interface PostHogMcpSetup {\n /** pi ExtensionFactory to add to the resource loader's `extensionFactories`. */\n extensionFactory: (pi: unknown) => void;\n /** Release this setup's token ownership. Call after the run. */\n cleanup: () => void;\n}\n\n/** Server `instructions` for the system prompt — the adapter exposes no accessor, so one standard-SDK handshake; best-effort. */\nexport async function fetchInstructions(\n mcpUrl: string,\n accessToken: string,\n userAgent: string,\n): Promise<string | undefined> {\n const client = new Client({ name: 'posthog-wizard', version: VERSION });\n try {\n const transport = new StreamableHTTPClientTransport(new URL(mcpUrl), {\n requestInit: {\n headers: {\n Authorization: `Bearer ${accessToken}`,\n 'User-Agent': userAgent,\n },\n },\n });\n await client.connect(transport);\n const instructions = client.getInstructions() || undefined;\n logToFile(`[pi-mcp] instructions ${instructions?.length ?? 0} chars`);\n return instructions;\n } catch (err) {\n logToFile(`[pi-mcp] instructions fetch skipped: ${String(err)}`);\n return undefined;\n } finally {\n await client.close().catch(() => undefined);\n }\n}\n\nexport async function setupPostHogMcp(opts: {\n mcpUrl: string;\n accessToken: string;\n userAgent: string;\n}): Promise<PostHogMcpSetup> {\n const { mcpUrl, accessToken, userAgent } = opts;\n\n // By env NAME: the token stays in this process, off disk, and never reaches pi's env-scrubbed tool subprocesses.\n const cleanup = acquireMcpToken(accessToken);\n\n try {\n // The adapter ships raw TypeScript; loading through jiti is its documented requirement.\n const jiti = createJiti(import.meta.url);\n const mod = await jiti.import<{\n createMcpAdapter: (\n options: unknown,\n ) => PostHogMcpSetup['extensionFactory'];\n }>('pi-mcp-adapter');\n const extensionFactory = mod.createMcpAdapter({\n config: {\n mcpServers: {\n posthog: {\n url: mcpUrl,\n auth: 'bearer',\n bearerTokenEnv: MCP_TOKEN_ENV,\n headers: { 'User-Agent': userAgent },\n // Connect at extension load — direct tools register without a session_start.\n lifecycle: 'eager',\n // Register only `exec`: `directTools: true` also mints a `posthog_get_<name>` tool per MCP resource, whose sentence-length names overflow Anthropic's 128-char tool-name limit and 400 the whole request.\n directTools: ['exec'],\n exposeResources: false,\n },\n },\n // Disable the proxy `mcp` tool (its search indirection pollutes context); the adapter re-enables it only if no direct tools resolve.\n settings: { disableProxyTool: true, toolPrefix: 'posthog' },\n },\n });\n logToFile(`[pi-mcp] adapter loaded; posthog MCP at ${mcpUrl}`);\n return { extensionFactory, cleanup };\n } catch (error) {\n cleanup();\n throw error;\n }\n}\n"],"mappings":";;;;;;;;;;;AAaA,MAAM,gBAAgB;AACtB,IAAI,iBAAiB;AACrB,IAAI;AACJ,IAAI;AAEJ,IAAI;AAEJ,SAAS,YAAY,OAAqB;AACxC,kBAAiB;AACjB,SAAQ,IAAI,iBAAiB;;AAG/B,SAAS,gBAAgB,OAA2B;AAClD,KAAI,mBAAmB,GAAG;AACxB,qBAAmB,QAAQ,IAAI;AAE/B,2BAAyB,qBAAqB,YAAY;;AAG5D,KAAI,mBAAmB,MAAO,aAAY,MAAM;AAChD,mBAAkB;CAClB,IAAI,WAAW;AACf,cAAa;AACX,MAAI,SAAU;AACd,aAAW;AACX,oBAAkB;AAClB,MAAI,iBAAiB,EAAG;AACxB,4BAA0B;AAC1B,2BAAyB,KAAA;AACzB,MAAI,qBAAqB,KAAA,EAAW,QAAO,QAAQ,IAAI;MAClD,SAAQ,IAAI,iBAAiB;AAClC,mBAAiB,KAAA;AACjB,qBAAmB,KAAA;;;;AAYvB,eAAsB,kBACpB,QACA,aACA,WAC6B;CAC7B,MAAM,SAAS,IAAI,OAAO;EAAE,MAAM;EAAkB,SAAS;EAAS,CAAC;AACvE,KAAI;EACF,MAAM,YAAY,IAAI,8BAA8B,IAAI,IAAI,OAAO,EAAE,EACnE,aAAa,EACX,SAAS;GACP,eAAe,UAAU;GACzB,cAAc;GACf,EACF,EACF,CAAC;AACF,QAAM,OAAO,QAAQ,UAAU;EAC/B,MAAM,eAAe,OAAO,iBAAiB,IAAI,KAAA;AACjD,YAAU,yBAAyB,cAAc,UAAU,EAAE,QAAQ;AACrE,SAAO;UACA,KAAK;AACZ,YAAU,wCAAwC,OAAO,IAAI,GAAG;AAChE;WACQ;AACR,QAAM,OAAO,OAAO,CAAC,YAAY,KAAA,EAAU;;;AAI/C,eAAsB,gBAAgB,MAIT;CAC3B,MAAM,EAAE,QAAQ,aAAa,cAAc;CAG3C,MAAM,UAAU,gBAAgB,YAAY;AAE5C,KAAI;EAQF,MAAM,oBALM,MADC,WAAW,OAAO,KAAK,IAAI,CACjB,OAIpB,iBAAiB,EACS,iBAAiB,EAC5C,QAAQ;GACN,YAAY,EACV,SAAS;IACP,KAAK;IACL,MAAM;IACN,gBAAgB;IAChB,SAAS,EAAE,cAAc,WAAW;IAEpC,WAAW;IAEX,aAAa,CAAC,OAAO;IACrB,iBAAiB;IAClB,EACF;GAED,UAAU;IAAE,kBAAkB;IAAM,YAAY;IAAW;GAC5D,EACF,CAAC;AACF,YAAU,2CAA2C,SAAS;AAC9D,SAAO;GAAE;GAAkB;GAAS;UAC7B,OAAO;AACd,WAAS;AACT,QAAM"}
@@ -1,7 +1,7 @@
1
- import { o as logToFile } from "./debug-BvEbemym.js";
2
- import { f as DEFAULT_AGENT_MODEL, n as analytics, nt as WIZARD_USER_AGENT } from "./analytics-B_xFshPY.js";
3
- import { d as gatewayAuth } from "./gateway-CWoYlPz7.js";
4
- import { f as sanitizeAgentSubprocessEnv, n as buildRunTags, o as createIsolatedAgentConfigDir, t as buildAgentEnv } from "./agent-interface-3YfIWZmY.js";
1
+ import { o as logToFile } from "./debug-BTUMatFI.js";
2
+ import { f as DEFAULT_AGENT_MODEL, n as analytics, rt as WIZARD_USER_AGENT } from "./analytics-GQv--mQm.js";
3
+ import { f as gatewayAuth } from "./gateway-CJ8Jqbll.js";
4
+ import { f as sanitizeAgentSubprocessEnv, n as buildRunTags, o as createIsolatedAgentConfigDir, t as buildAgentEnv } from "./agent-interface-fcDXqb-_.js";
5
5
  //#region src/agent/mcp-prompt-streaming.ts
6
6
  let _sdkModule = null;
7
7
  async function loadSdk() {
@@ -250,4 +250,4 @@ async function* streamMcpPrompt(args) {
250
250
  //#endregion
251
251
  export { streamMcpPrompt };
252
252
 
253
- //# sourceMappingURL=mcp-prompt-streaming-DHPxJK-F.js.map
253
+ //# sourceMappingURL=mcp-prompt-streaming-B5lIQ0l1.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-prompt-streaming-DHPxJK-F.js","names":[],"sources":["../src/agent/mcp-prompt-streaming.ts"],"sourcesContent":["/**\n * Streaming prompt runner for the McpSuggestedPromptsScreen.\n *\n * Calls the Claude Agent SDK's `query()` directly with just the PostHog\n * MCP server configured — no skills, no sandbox, no settings sources,\n * no wizard-tools. This is the lightweight cousin of `runAgent` in\n * `agent-interface.ts`: same SDK, much narrower surface, suitable for\n * \"user asked a question, show the answer\" interactions.\n *\n * The function is an async generator that yields `McpPromptChunk`s extracted\n * from the SDK's message stream. Callers (the screen) consume them via\n * `for await (...)` and render as they arrive.\n */\n\nimport type { Credentials } from '@shared/api';\nimport { DEFAULT_AGENT_MODEL, WIZARD_USER_AGENT } from '@shared/constants';\nimport { logToFile } from '@utils/debug';\nimport { gatewayAuth } from './gateway-session';\nimport { buildAgentEnv, buildRunTags } from './agent-interface';\nimport { sanitizeAgentSubprocessEnv } from '@shared/agent-env-isolation';\nimport { createIsolatedAgentConfigDir } from './stored-login';\nimport { analytics } from '@utils/analytics';\n\n/**\n * Discriminated union covering every kind of streamed event the screen\n * needs to render. Production yields these from Claude SDK messages;\n * the playground yields them from canned scripts.\n */\nexport type McpPromptChunk =\n | { kind: 'text'; text: string }\n /** `command` carries CLI mode's exec command string (`call <tool> …`) so the\n * screen can recover the inner tool for context-aware follow-ups. */\n | { kind: 'tool-call'; toolName: string; detail: string; command?: string }\n | { kind: 'tool-result'; toolName: string; detail: string }\n | { kind: 'error'; text: string }\n /** Stream completed. `sessionId` is the SDK session ID of the just-\n * completed turn; pass it back as `resumeSessionId` on a follow-up\n * call to continue the conversation with full history. */\n | { kind: 'done'; sessionId?: string };\n\n// Cached SDK module — first call pays the dynamic-import cost; later\n// calls reuse the same module.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nlet _sdkModule: any | null = null;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nasync function loadSdk(): Promise<any> {\n if (!_sdkModule) {\n _sdkModule = await import('@anthropic-ai/claude-agent-sdk');\n }\n return _sdkModule;\n}\n\nconst MODEL = DEFAULT_AGENT_MODEL;\n\n// Bounded turn count so a single prompt can't loop forever on the\n// user's nickel. 20 gives the agent room for non-trivial multi-step\n// chains (multi-tool reads → reason → write → verify → summarize) while\n// still capping runaway loops. Worth tuning down once we see real\n// telemetry on average turn counts per prompt.\nconst MAX_TURNS = 30;\n\n/**\n * Extract a short, single-line summary from an arbitrary value. Used\n * for tool-call args and tool-result bodies so the screen has something\n * compact to render.\n */\nfunction summarize(value: unknown, maxLen = 120): string {\n if (value == null) return '';\n let text: string;\n if (typeof value === 'string') text = value;\n else {\n try {\n text = JSON.stringify(value);\n } catch {\n text = String(value);\n }\n }\n text = text.replace(/\\s+/g, ' ').trim();\n if (text.length > maxLen) text = text.slice(0, maxLen - 1) + '…';\n return text;\n}\n\n/**\n * Convert one SDK message into zero or more AgentChunks. Mirrors the\n * subset of message shapes the wizard's main runAgent middleware\n * handles, but narrowed to just the kinds the screen needs to render.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction messageToChunks(message: any): McpPromptChunk[] {\n const chunks: McpPromptChunk[] = [];\n\n if (message?.type === 'assistant') {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n const content = message.message?.content;\n if (Array.isArray(content)) {\n for (const block of content) {\n if (!block || typeof block !== 'object') continue;\n const type = (block as { type?: string }).type;\n if (type === 'text') {\n const text = (block as { text?: string }).text ?? '';\n if (text) chunks.push({ kind: 'text', text });\n } else if (type === 'tool_use') {\n const name = (block as { name?: string }).name ?? 'tool';\n const input = (block as { input?: unknown }).input;\n // CLI mode's exec tool takes a `command` string; keep it verbatim so\n // the screen can recover the inner tool name for follow-ups.\n const command = (input as { command?: unknown })?.command;\n chunks.push({\n kind: 'tool-call',\n toolName: name,\n detail: summarize(input),\n command: typeof command === 'string' ? command : undefined,\n });\n }\n }\n }\n }\n\n if (message?.type === 'user') {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n const content = message.message?.content;\n if (Array.isArray(content)) {\n for (const block of content) {\n if (!block || typeof block !== 'object') continue;\n const type = (block as { type?: string }).type;\n if (type === 'tool_result') {\n const detail = summarize((block as { content?: unknown }).content);\n chunks.push({ kind: 'tool-result', toolName: 'tool', detail });\n }\n }\n }\n }\n\n if (message?.type === 'result') {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const sessionId = (message as { session_id?: string }).session_id;\n chunks.push({ kind: 'done', sessionId });\n }\n\n return chunks;\n}\n\n/**\n * Build a system-prompt append that nudges the agent to fit its response\n * inside the current terminal window. We can't actually constrain Claude\n * — this is a soft cap that the model usually honors. The screen also\n * applies a hard truncation cap as a fallback for non-compliant runs.\n *\n * Core principle nudged at the model: TALL CONTENT IS BAD, WIDE CONTENT\n * IS GOOD. Default terminal is 120 columns × 24 rows — that's a lot of\n * horizontal space, not much vertical. Spread data across columns, never\n * stack it down rows when a horizontal layout would work.\n */\nfunction buildTerminalFitPrompt(): string {\n const cols = process.stdout.columns ?? 120;\n const rows = process.stdout.rows ?? 24;\n // Reserve rows for wizard chrome (title, status, hint, margins).\n const messageBudget = Math.max(8, rows - 10);\n\n return [\n `You are responding inside a CLI window that is exactly ${cols} columns wide and ${rows} rows tall. The user CAN'T SCROLL — your entire reply must fit on screen.`,\n ``,\n `LAYOUT PRINCIPLE: tall content is the enemy, wide content is your friend. You have ${cols} columns of horizontal space; use them. Spread data across columns instead of stacking it down rows.`,\n ``,\n `Tables:`,\n `- Max 5 body rows. The prompts the user picks already constrain results to 5 or fewer — honor that and do not pad with extra rows.`,\n `- If a tool result returns more than 5 items, show the top 5 and mention the rest count inline (e.g. \"...and 12 more\").`,\n `- Prefer transposing wide-but-short data (items across columns, metrics down rows) when labels are short.`,\n `- A two-column table with many rows is the tall layout to AVOID.`,\n ``,\n `Other limits:`,\n `- Aim for 3-5 lines of prose. Maximum ${messageBudget} lines total.`,\n `- DO NOT announce what you are about to do. Skip preamble like \"I'll query…\", \"Let me check…\", \"Now I'll…\", \"I'm going to…\". Go straight to running tools and then the answer.`,\n `- Lists: if there are 6+ short items, format them inline (comma-separated), not as a vertical bullet list.`,\n `- For tool results, summarize the 1-3 numbers that matter. Do NOT echo raw JSON or the full payload.`,\n `- Code blocks: no language tag, no leading blank lines.`,\n `- No closing pleasantries (\"let me know if…\", \"feel free to…\"). Stop when the answer is delivered.`,\n `- No section headers unless the response actually has multiple sections.`,\n ``,\n `Naming saved artifacts:`,\n `- Every dashboard, insight, notebook, or annotation you create MUST include \"(wizard MCP tutorial)\" at the end of its title or name field. Examples: \"Weekly signups (wizard MCP tutorial)\", \"Top errors this week (wizard MCP tutorial)\", \"Onboarding analysis (wizard MCP tutorial)\".`,\n `- This applies on both create AND rename calls. If the user asks you to rename a saved artifact, preserve the \"(wizard MCP tutorial)\" suffix unless they explicitly ask you to drop it.`,\n `- Reason: lets the user find / clean up everything this tutorial created from one search in PostHog. Don't skip it — it's the only signal they'll have that an artifact came from the wizard.`,\n ``,\n `Tone & framing:`,\n `- This is a tutorial demoing PostHog (the product the user just installed). You are showing it off, not auditing it. Stay constructive and neutral about PostHog throughout.`,\n `- Don't editorialize about PostHog's reliability, performance, or cost. Describe what the data shows; treat anomalies as the user's data, not a platform issue.`,\n `- If a tool call fails or returns nothing, say \"the query didn't return data — try a different angle\" or similar. Do NOT speculate about outages, gateway issues, MCP problems, or service health.`,\n `- Avoid value-laden phrases like \"worth investigating\", \"concerning\", \"red flag\", \"problematic\", \"suspicious\", \"alarming\" when describing the user's metrics. Stick to what the numbers show; the user draws conclusions.`,\n ].join('\\n');\n}\n\n/**\n * Gateway trace tags for a tutorial prompt run — without them the gateway has\n * nothing to attribute its `$ai_generation` events to. Returns `{}` when no\n * program is supplied. Exported so the contract is testable without the SDK.\n */\nexport function buildTutorialRunTags(args: {\n programId?: string;\n integration?: string;\n}): Record<string, string> {\n if (!args.programId) return {};\n return buildRunTags({\n programId: args.programId,\n // The tutorial usually has no detected framework; fall back to the\n // program so the axis is never an empty string.\n integration: args.integration ?? args.programId,\n runId: analytics.runId,\n build: analytics.build,\n });\n}\n\nexport async function* streamMcpPrompt(args: {\n prompt: string;\n credentials: Credentials;\n signal: AbortSignal;\n /** When set, the SDK loads the named session's prior turns as\n * context so the follow-up prompt can reference what the agent\n * already showed. */\n resumeSessionId?: string;\n /** Program this run's gateway spend attributes to. Omitting it fails the run\n * rather than going unattributed, so every caller must supply one. */\n programId?: string;\n /** Integration label for the trace tags; the tutorial usually has none. */\n integration?: string;\n}): AsyncIterable<McpPromptChunk> {\n const { prompt, credentials, signal, resumeSessionId } = args;\n\n // Assembled here rather than passed in so the TUI service layer doesn't\n // have to import this module's dependencies.\n const wizardMetadata = buildTutorialRunTags(args);\n\n // Route the SDK's LLM calls through the PostHog AI gateway, authed\n // with the run's minted token. Set BEFORE loading the SDK in\n // case any in-process code reads env at module init (cached base\n // URLs, OAuth setup, etc.) — same reason `initializeAgent` does this\n // before its query() call. Without these the SDK tries to\n // authenticate directly against Anthropic and 401s with \"Invalid\n // authentication credentials\".\n process.env.CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS = 'true';\n\n // The url and the bearer are one unit: a run must take both from the same\n // mint.\n const auth = await gatewayAuth(\n credentials.host,\n credentials.accessToken,\n args.programId,\n );\n const gatewayUrl = auth.gatewayUrl;\n process.env.ANTHROPIC_BASE_URL = gatewayUrl;\n process.env.ANTHROPIC_AUTH_TOKEN = auth.token;\n process.env.CLAUDE_CODE_OAUTH_TOKEN = auth.token;\n\n logToFile(\n `[streamMcpPrompt] gatewayUrl=${gatewayUrl} tokenPrefix=${\n auth.token ? auth.token.slice(0, 4) + '***' : '(missing)'\n }`,\n );\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const { query } = await loadSdk();\n\n // Bridge external AbortSignal → SDK AbortController.\n const abortController = new AbortController();\n if (signal.aborted) abortController.abort();\n else\n signal.addEventListener('abort', () => abortController.abort(), {\n once: true,\n });\n\n const mcpUrl = credentials.host.mcpUrl;\n logToFile(\n `[streamMcpPrompt] mcpUrl=${mcpUrl} model=${MODEL} resume=${\n resumeSessionId ?? '(none)'\n }`,\n );\n\n // The SDK expects an async generator for the prompt that stays open\n // until the result is received. For a single-turn prompt we yield one\n // user message and then await an abort (which fires when streaming\n // completes or the caller cancels).\n const createPromptStream = async function* () {\n yield {\n type: 'user' as const,\n session_id: '',\n message: { role: 'user' as const, content: prompt },\n parent_tool_use_id: null,\n };\n // Hold the stream open until abort. The SDK closes its end when it\n // sees a `result` message; we close ours via the abortController in\n // the finally block below.\n await new Promise<void>((resolve) => {\n if (abortController.signal.aborted) {\n resolve();\n return;\n }\n abortController.signal.addEventListener('abort', () => resolve(), {\n once: true,\n });\n });\n };\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call\n const response = query({\n prompt: createPromptStream(),\n options: {\n abortController,\n model: MODEL,\n cwd: process.cwd(),\n permissionMode: 'acceptEdits',\n maxTurns: MAX_TURNS,\n // Match agent-interface.ts — the 1M context beta is what keeps\n // resumed follow-up sessions from truncating after a few turns.\n betas: ['context-1m-2025-08-07'],\n // Only load project-level skills/settings. Without this the SDK\n // defaults to ['user', 'project'] and a user's\n // `~/.claude/settings.json` (apiKeyHelper / env block) can\n // override the OAuth routing we set above.\n settingSources: ['project'],\n // Repo hooks would run as the developer outside the MCP-only gate.\n settings: { disableAllHooks: true },\n // When set, the SDK replays the named session's turns into the\n // new query so the follow-up prompt has full conversation\n // context. Omit on the first prompt for a fresh session.\n ...(resumeSessionId ? { resume: resumeSessionId } : {}),\n // Without `canUseTool` the SDK falls back to \"ask the user\" on\n // every MCP tool call — `permissionMode: 'acceptEdits'` only\n // relaxes Edit/Write, not MCP. Our Ink TUI has no surface to\n // answer that prompt, so the agent would stall mid-stream\n // saying things like \"needs your approval to create dashboard\".\n // The tutorial's whole point is demoing the MCP tools against\n // the user's project, so we auto-allow everything that matches\n // the prefix and deny anything else (defense in depth — the\n // `allowedTools` filter above already enforces this).\n canUseTool: (toolName: string, input: unknown) => {\n if (toolName.startsWith('mcp__posthog-wizard__')) {\n return Promise.resolve({\n behavior: 'allow' as const,\n updatedInput: (input ?? {}) as Record<string, unknown>,\n });\n }\n logToFile(`[streamMcpPrompt] denying non-MCP tool: ${toolName}`);\n return Promise.resolve({\n behavior: 'deny' as const,\n message: `${toolName} is not available in the MCP tutorial — only PostHog MCP tools are permitted.`,\n });\n },\n systemPrompt: {\n type: 'preset',\n preset: 'claude_code',\n append: buildTerminalFitPrompt(),\n },\n mcpServers: {\n 'posthog-wizard': {\n type: 'http',\n url: mcpUrl,\n headers: {\n // Env reference, not the token: the SDK puts this config on the\n // spawned CLI's argv, where `ps` shows it to any local process.\n Authorization: 'Bearer ${POSTHOG_MCP_TOKEN}',\n 'User-Agent': WIZARD_USER_AGENT,\n },\n // CLI mode's single `exec` tool carries the full command reference\n // on its schema — keep it in context, never deferred behind tool\n // search.\n alwaysLoad: true,\n },\n },\n // Only let the agent use MCP tools — no shell, no file I/O,\n // no Read/Edit/Write. This is a chat-with-MCP run, not a\n // wizard skill execution.\n allowedTools: ['mcp__posthog-wizard__*'],\n env: {\n // Drop the ENTIRE ANTHROPIC_*/CLAUDE_CODE_* namespace from the\n // inherited env so no shell/settings value can silently bypass the\n // PostHog gateway and defeat quota tracking / the OAuth flow; the\n // wizard's own gateway routing is injected fresh below. See\n // agent-env-isolation.ts.\n ...sanitizeAgentSubprocessEnv(process.env),\n // Gateway routing from this run's own auth, not process.env: a\n // concurrent run writes those globals too, and there is an await\n // between the write above and this read.\n ANTHROPIC_BASE_URL: auth.gatewayUrl,\n ANTHROPIC_AUTH_TOKEN: auth.token,\n CLAUDE_CODE_OAUTH_TOKEN: auth.token,\n // Point the binary at an empty config dir so it cannot resolve a\n // stored Claude login and send that to the gateway, which 401s it.\n // See stored-login.ts.\n CLAUDE_CONFIG_DIR: createIsolatedAgentConfigDir(),\n CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS: 'true',\n // The MCP config resolves this in the child; sending the value would\n // put it on the CLI's argv.\n POSTHOG_MCP_TOKEN: credentials.accessToken,\n // SDK 0.3.142+ connects MCP servers in the background by\n // default; without this the agent may try to call tools\n // before posthog-wizard is connected on turn 1.\n MCP_CONNECTION_NONBLOCKING: '0',\n // This run's trace tags, which the gateway reads to attribute its\n // `$ai_generation` events. Flags stay empty: the tutorial doesn't\n // fork on any.\n ANTHROPIC_CUSTOM_HEADERS: buildAgentEnv(\n wizardMetadata ?? {},\n {},\n auth.teamId,\n ),\n },\n },\n });\n\n for await (const message of response as AsyncIterable<unknown>) {\n if (signal.aborted) return;\n for (const chunk of messageToChunks(message)) {\n yield chunk;\n if (chunk.kind === 'done') return;\n }\n }\n } catch (err) {\n const text = err instanceof Error ? err.message : String(err);\n logToFile(`[streamMcpPrompt] error: ${text}`);\n yield { kind: 'error', text };\n } finally {\n // Closes the prompt stream so `query()` shuts down cleanly even if\n // we never saw a 'result' message.\n abortController.abort();\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"mcp-prompt-streaming-B5lIQ0l1.js","names":[],"sources":["../src/agent/mcp-prompt-streaming.ts"],"sourcesContent":["/**\n * Streaming prompt runner for the McpSuggestedPromptsScreen.\n *\n * Calls the Claude Agent SDK's `query()` directly with just the PostHog\n * MCP server configured — no skills, no sandbox, no settings sources,\n * no wizard-tools. This is the lightweight cousin of `runAgent` in\n * `agent-interface.ts`: same SDK, much narrower surface, suitable for\n * \"user asked a question, show the answer\" interactions.\n *\n * The function is an async generator that yields `McpPromptChunk`s extracted\n * from the SDK's message stream. Callers (the screen) consume them via\n * `for await (...)` and render as they arrive.\n */\n\nimport type { Credentials } from '@shared/api';\nimport { DEFAULT_AGENT_MODEL, WIZARD_USER_AGENT } from '@shared/constants';\nimport { logToFile } from '@utils/debug';\nimport { gatewayAuth } from './gateway-session';\nimport { buildAgentEnv, buildRunTags } from './agent-interface';\nimport { sanitizeAgentSubprocessEnv } from '@shared/agent-env-isolation';\nimport { createIsolatedAgentConfigDir } from './stored-login';\nimport { analytics } from '@utils/analytics';\n\n/**\n * Discriminated union covering every kind of streamed event the screen\n * needs to render. Production yields these from Claude SDK messages;\n * the playground yields them from canned scripts.\n */\nexport type McpPromptChunk =\n | { kind: 'text'; text: string }\n /** `command` carries CLI mode's exec command string (`call <tool> …`) so the\n * screen can recover the inner tool for context-aware follow-ups. */\n | { kind: 'tool-call'; toolName: string; detail: string; command?: string }\n | { kind: 'tool-result'; toolName: string; detail: string }\n | { kind: 'error'; text: string }\n /** Stream completed. `sessionId` is the SDK session ID of the just-\n * completed turn; pass it back as `resumeSessionId` on a follow-up\n * call to continue the conversation with full history. */\n | { kind: 'done'; sessionId?: string };\n\n// Cached SDK module — first call pays the dynamic-import cost; later\n// calls reuse the same module.\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nlet _sdkModule: any | null = null;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nasync function loadSdk(): Promise<any> {\n if (!_sdkModule) {\n _sdkModule = await import('@anthropic-ai/claude-agent-sdk');\n }\n return _sdkModule;\n}\n\nconst MODEL = DEFAULT_AGENT_MODEL;\n\n// Bounded turn count so a single prompt can't loop forever on the\n// user's nickel. 20 gives the agent room for non-trivial multi-step\n// chains (multi-tool reads → reason → write → verify → summarize) while\n// still capping runaway loops. Worth tuning down once we see real\n// telemetry on average turn counts per prompt.\nconst MAX_TURNS = 30;\n\n/**\n * Extract a short, single-line summary from an arbitrary value. Used\n * for tool-call args and tool-result bodies so the screen has something\n * compact to render.\n */\nfunction summarize(value: unknown, maxLen = 120): string {\n if (value == null) return '';\n let text: string;\n if (typeof value === 'string') text = value;\n else {\n try {\n text = JSON.stringify(value);\n } catch {\n text = String(value);\n }\n }\n text = text.replace(/\\s+/g, ' ').trim();\n if (text.length > maxLen) text = text.slice(0, maxLen - 1) + '…';\n return text;\n}\n\n/**\n * Convert one SDK message into zero or more AgentChunks. Mirrors the\n * subset of message shapes the wizard's main runAgent middleware\n * handles, but narrowed to just the kinds the screen needs to render.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction messageToChunks(message: any): McpPromptChunk[] {\n const chunks: McpPromptChunk[] = [];\n\n if (message?.type === 'assistant') {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n const content = message.message?.content;\n if (Array.isArray(content)) {\n for (const block of content) {\n if (!block || typeof block !== 'object') continue;\n const type = (block as { type?: string }).type;\n if (type === 'text') {\n const text = (block as { text?: string }).text ?? '';\n if (text) chunks.push({ kind: 'text', text });\n } else if (type === 'tool_use') {\n const name = (block as { name?: string }).name ?? 'tool';\n const input = (block as { input?: unknown }).input;\n // CLI mode's exec tool takes a `command` string; keep it verbatim so\n // the screen can recover the inner tool name for follow-ups.\n const command = (input as { command?: unknown })?.command;\n chunks.push({\n kind: 'tool-call',\n toolName: name,\n detail: summarize(input),\n command: typeof command === 'string' ? command : undefined,\n });\n }\n }\n }\n }\n\n if (message?.type === 'user') {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n const content = message.message?.content;\n if (Array.isArray(content)) {\n for (const block of content) {\n if (!block || typeof block !== 'object') continue;\n const type = (block as { type?: string }).type;\n if (type === 'tool_result') {\n const detail = summarize((block as { content?: unknown }).content);\n chunks.push({ kind: 'tool-result', toolName: 'tool', detail });\n }\n }\n }\n }\n\n if (message?.type === 'result') {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const sessionId = (message as { session_id?: string }).session_id;\n chunks.push({ kind: 'done', sessionId });\n }\n\n return chunks;\n}\n\n/**\n * Build a system-prompt append that nudges the agent to fit its response\n * inside the current terminal window. We can't actually constrain Claude\n * — this is a soft cap that the model usually honors. The screen also\n * applies a hard truncation cap as a fallback for non-compliant runs.\n *\n * Core principle nudged at the model: TALL CONTENT IS BAD, WIDE CONTENT\n * IS GOOD. Default terminal is 120 columns × 24 rows — that's a lot of\n * horizontal space, not much vertical. Spread data across columns, never\n * stack it down rows when a horizontal layout would work.\n */\nfunction buildTerminalFitPrompt(): string {\n const cols = process.stdout.columns ?? 120;\n const rows = process.stdout.rows ?? 24;\n // Reserve rows for wizard chrome (title, status, hint, margins).\n const messageBudget = Math.max(8, rows - 10);\n\n return [\n `You are responding inside a CLI window that is exactly ${cols} columns wide and ${rows} rows tall. The user CAN'T SCROLL — your entire reply must fit on screen.`,\n ``,\n `LAYOUT PRINCIPLE: tall content is the enemy, wide content is your friend. You have ${cols} columns of horizontal space; use them. Spread data across columns instead of stacking it down rows.`,\n ``,\n `Tables:`,\n `- Max 5 body rows. The prompts the user picks already constrain results to 5 or fewer — honor that and do not pad with extra rows.`,\n `- If a tool result returns more than 5 items, show the top 5 and mention the rest count inline (e.g. \"...and 12 more\").`,\n `- Prefer transposing wide-but-short data (items across columns, metrics down rows) when labels are short.`,\n `- A two-column table with many rows is the tall layout to AVOID.`,\n ``,\n `Other limits:`,\n `- Aim for 3-5 lines of prose. Maximum ${messageBudget} lines total.`,\n `- DO NOT announce what you are about to do. Skip preamble like \"I'll query…\", \"Let me check…\", \"Now I'll…\", \"I'm going to…\". Go straight to running tools and then the answer.`,\n `- Lists: if there are 6+ short items, format them inline (comma-separated), not as a vertical bullet list.`,\n `- For tool results, summarize the 1-3 numbers that matter. Do NOT echo raw JSON or the full payload.`,\n `- Code blocks: no language tag, no leading blank lines.`,\n `- No closing pleasantries (\"let me know if…\", \"feel free to…\"). Stop when the answer is delivered.`,\n `- No section headers unless the response actually has multiple sections.`,\n ``,\n `Naming saved artifacts:`,\n `- Every dashboard, insight, notebook, or annotation you create MUST include \"(wizard MCP tutorial)\" at the end of its title or name field. Examples: \"Weekly signups (wizard MCP tutorial)\", \"Top errors this week (wizard MCP tutorial)\", \"Onboarding analysis (wizard MCP tutorial)\".`,\n `- This applies on both create AND rename calls. If the user asks you to rename a saved artifact, preserve the \"(wizard MCP tutorial)\" suffix unless they explicitly ask you to drop it.`,\n `- Reason: lets the user find / clean up everything this tutorial created from one search in PostHog. Don't skip it — it's the only signal they'll have that an artifact came from the wizard.`,\n ``,\n `Tone & framing:`,\n `- This is a tutorial demoing PostHog (the product the user just installed). You are showing it off, not auditing it. Stay constructive and neutral about PostHog throughout.`,\n `- Don't editorialize about PostHog's reliability, performance, or cost. Describe what the data shows; treat anomalies as the user's data, not a platform issue.`,\n `- If a tool call fails or returns nothing, say \"the query didn't return data — try a different angle\" or similar. Do NOT speculate about outages, gateway issues, MCP problems, or service health.`,\n `- Avoid value-laden phrases like \"worth investigating\", \"concerning\", \"red flag\", \"problematic\", \"suspicious\", \"alarming\" when describing the user's metrics. Stick to what the numbers show; the user draws conclusions.`,\n ].join('\\n');\n}\n\n/**\n * Gateway trace tags for a tutorial prompt run — without them the gateway has\n * nothing to attribute its `$ai_generation` events to. Returns `{}` when no\n * program is supplied. Exported so the contract is testable without the SDK.\n */\nexport function buildTutorialRunTags(args: {\n programId?: string;\n integration?: string;\n}): Record<string, string> {\n if (!args.programId) return {};\n return buildRunTags({\n programId: args.programId,\n // The tutorial usually has no detected framework; fall back to the\n // program so the axis is never an empty string.\n integration: args.integration ?? args.programId,\n runId: analytics.runId,\n build: analytics.build,\n });\n}\n\nexport async function* streamMcpPrompt(args: {\n prompt: string;\n credentials: Credentials;\n signal: AbortSignal;\n /** When set, the SDK loads the named session's prior turns as\n * context so the follow-up prompt can reference what the agent\n * already showed. */\n resumeSessionId?: string;\n /** Program this run's gateway spend attributes to. Omitting it fails the run\n * rather than going unattributed, so every caller must supply one. */\n programId?: string;\n /** Integration label for the trace tags; the tutorial usually has none. */\n integration?: string;\n}): AsyncIterable<McpPromptChunk> {\n const { prompt, credentials, signal, resumeSessionId } = args;\n\n // Assembled here rather than passed in so the TUI service layer doesn't\n // have to import this module's dependencies.\n const wizardMetadata = buildTutorialRunTags(args);\n\n // Route the SDK's LLM calls through the PostHog AI gateway, authed\n // with the run's minted token. Set BEFORE loading the SDK in\n // case any in-process code reads env at module init (cached base\n // URLs, OAuth setup, etc.) — same reason `initializeAgent` does this\n // before its query() call. Without these the SDK tries to\n // authenticate directly against Anthropic and 401s with \"Invalid\n // authentication credentials\".\n process.env.CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS = 'true';\n\n // The url and the bearer are one unit: a run must take both from the same\n // mint.\n const auth = await gatewayAuth(\n credentials.host,\n credentials.accessToken,\n args.programId,\n );\n const gatewayUrl = auth.gatewayUrl;\n process.env.ANTHROPIC_BASE_URL = gatewayUrl;\n process.env.ANTHROPIC_AUTH_TOKEN = auth.token;\n process.env.CLAUDE_CODE_OAUTH_TOKEN = auth.token;\n\n logToFile(\n `[streamMcpPrompt] gatewayUrl=${gatewayUrl} tokenPrefix=${\n auth.token ? auth.token.slice(0, 4) + '***' : '(missing)'\n }`,\n );\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const { query } = await loadSdk();\n\n // Bridge external AbortSignal → SDK AbortController.\n const abortController = new AbortController();\n if (signal.aborted) abortController.abort();\n else\n signal.addEventListener('abort', () => abortController.abort(), {\n once: true,\n });\n\n const mcpUrl = credentials.host.mcpUrl;\n logToFile(\n `[streamMcpPrompt] mcpUrl=${mcpUrl} model=${MODEL} resume=${\n resumeSessionId ?? '(none)'\n }`,\n );\n\n // The SDK expects an async generator for the prompt that stays open\n // until the result is received. For a single-turn prompt we yield one\n // user message and then await an abort (which fires when streaming\n // completes or the caller cancels).\n const createPromptStream = async function* () {\n yield {\n type: 'user' as const,\n session_id: '',\n message: { role: 'user' as const, content: prompt },\n parent_tool_use_id: null,\n };\n // Hold the stream open until abort. The SDK closes its end when it\n // sees a `result` message; we close ours via the abortController in\n // the finally block below.\n await new Promise<void>((resolve) => {\n if (abortController.signal.aborted) {\n resolve();\n return;\n }\n abortController.signal.addEventListener('abort', () => resolve(), {\n once: true,\n });\n });\n };\n\n try {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call\n const response = query({\n prompt: createPromptStream(),\n options: {\n abortController,\n model: MODEL,\n cwd: process.cwd(),\n permissionMode: 'acceptEdits',\n maxTurns: MAX_TURNS,\n // Match agent-interface.ts — the 1M context beta is what keeps\n // resumed follow-up sessions from truncating after a few turns.\n betas: ['context-1m-2025-08-07'],\n // Only load project-level skills/settings. Without this the SDK\n // defaults to ['user', 'project'] and a user's\n // `~/.claude/settings.json` (apiKeyHelper / env block) can\n // override the OAuth routing we set above.\n settingSources: ['project'],\n // Repo hooks would run as the developer outside the MCP-only gate.\n settings: { disableAllHooks: true },\n // When set, the SDK replays the named session's turns into the\n // new query so the follow-up prompt has full conversation\n // context. Omit on the first prompt for a fresh session.\n ...(resumeSessionId ? { resume: resumeSessionId } : {}),\n // Without `canUseTool` the SDK falls back to \"ask the user\" on\n // every MCP tool call — `permissionMode: 'acceptEdits'` only\n // relaxes Edit/Write, not MCP. Our Ink TUI has no surface to\n // answer that prompt, so the agent would stall mid-stream\n // saying things like \"needs your approval to create dashboard\".\n // The tutorial's whole point is demoing the MCP tools against\n // the user's project, so we auto-allow everything that matches\n // the prefix and deny anything else (defense in depth — the\n // `allowedTools` filter above already enforces this).\n canUseTool: (toolName: string, input: unknown) => {\n if (toolName.startsWith('mcp__posthog-wizard__')) {\n return Promise.resolve({\n behavior: 'allow' as const,\n updatedInput: (input ?? {}) as Record<string, unknown>,\n });\n }\n logToFile(`[streamMcpPrompt] denying non-MCP tool: ${toolName}`);\n return Promise.resolve({\n behavior: 'deny' as const,\n message: `${toolName} is not available in the MCP tutorial — only PostHog MCP tools are permitted.`,\n });\n },\n systemPrompt: {\n type: 'preset',\n preset: 'claude_code',\n append: buildTerminalFitPrompt(),\n },\n mcpServers: {\n 'posthog-wizard': {\n type: 'http',\n url: mcpUrl,\n headers: {\n // Env reference, not the token: the SDK puts this config on the\n // spawned CLI's argv, where `ps` shows it to any local process.\n Authorization: 'Bearer ${POSTHOG_MCP_TOKEN}',\n 'User-Agent': WIZARD_USER_AGENT,\n },\n // CLI mode's single `exec` tool carries the full command reference\n // on its schema — keep it in context, never deferred behind tool\n // search.\n alwaysLoad: true,\n },\n },\n // Only let the agent use MCP tools — no shell, no file I/O,\n // no Read/Edit/Write. This is a chat-with-MCP run, not a\n // wizard skill execution.\n allowedTools: ['mcp__posthog-wizard__*'],\n env: {\n // Drop the ENTIRE ANTHROPIC_*/CLAUDE_CODE_* namespace from the\n // inherited env so no shell/settings value can silently bypass the\n // PostHog gateway and defeat quota tracking / the OAuth flow; the\n // wizard's own gateway routing is injected fresh below. See\n // agent-env-isolation.ts.\n ...sanitizeAgentSubprocessEnv(process.env),\n // Gateway routing from this run's own auth, not process.env: a\n // concurrent run writes those globals too, and there is an await\n // between the write above and this read.\n ANTHROPIC_BASE_URL: auth.gatewayUrl,\n ANTHROPIC_AUTH_TOKEN: auth.token,\n CLAUDE_CODE_OAUTH_TOKEN: auth.token,\n // Point the binary at an empty config dir so it cannot resolve a\n // stored Claude login and send that to the gateway, which 401s it.\n // See stored-login.ts.\n CLAUDE_CONFIG_DIR: createIsolatedAgentConfigDir(),\n CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS: 'true',\n // The MCP config resolves this in the child; sending the value would\n // put it on the CLI's argv.\n POSTHOG_MCP_TOKEN: credentials.accessToken,\n // SDK 0.3.142+ connects MCP servers in the background by\n // default; without this the agent may try to call tools\n // before posthog-wizard is connected on turn 1.\n MCP_CONNECTION_NONBLOCKING: '0',\n // This run's trace tags, which the gateway reads to attribute its\n // `$ai_generation` events. Flags stay empty: the tutorial doesn't\n // fork on any.\n ANTHROPIC_CUSTOM_HEADERS: buildAgentEnv(\n wizardMetadata ?? {},\n {},\n auth.teamId,\n ),\n },\n },\n });\n\n for await (const message of response as AsyncIterable<unknown>) {\n if (signal.aborted) return;\n for (const chunk of messageToChunks(message)) {\n yield chunk;\n if (chunk.kind === 'done') return;\n }\n }\n } catch (err) {\n const text = err instanceof Error ? err.message : String(err);\n logToFile(`[streamMcpPrompt] error: ${text}`);\n yield { kind: 'error', text };\n } finally {\n // Closes the prompt stream so `query()` shuts down cleanly even if\n // we never saw a 'result' message.\n abortController.abort();\n }\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { C as HAIKU_MODEL, H as SONNET_5_MODEL, S as GPT5_6_TERRA_MODEL, b as GPT5_6_LUNA_MODEL, w as HAIKU_TRIAGE_MODEL, x as GPT5_6_SOL_MODEL } from "./analytics-B_xFshPY.js";
1
+ import { C as GPT6_SOL_MODEL, S as GPT5_6_TERRA_MODEL, T as HAIKU_TRIAGE_MODEL, U as SONNET_5_MODEL, b as GPT5_6_LUNA_MODEL, w as HAIKU_MODEL, x as GPT5_6_SOL_MODEL } from "./analytics-GQv--mQm.js";
2
2
  //#region src/agent/runner/switchboard/models.ts
3
3
  /** Reasoning effort, mapped by each harness to its provider transport. */
4
4
  const THINKING_LEVELS = [
@@ -41,6 +41,10 @@ const MODEL_CAPABILITIES = {
41
41
  [GPT5_6_SOL_MODEL]: {
42
42
  reasoning: true,
43
43
  thinkingLevel: "medium"
44
+ },
45
+ [GPT6_SOL_MODEL]: {
46
+ reasoning: true,
47
+ thinkingLevel: "medium"
44
48
  }
45
49
  };
46
50
  const VALID_MODELS = new Set(Object.keys(MODEL_CAPABILITIES));
@@ -80,4 +84,4 @@ function modelCapabilities(modelId, effortOverride) {
80
84
  //#endregion
81
85
  export { requireKnownModel as a, modelCapabilities as i, isThinkingLevel as n, triageModelFor as o, isValidModel as r, VALID_MODELS as t };
82
86
 
83
- //# sourceMappingURL=models-C9rjXPZ6.js.map
87
+ //# sourceMappingURL=models-CLTglHFZ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models-CLTglHFZ.js","names":[],"sources":["../src/agent/runner/switchboard/models.ts"],"sourcesContent":["// Local capabilities inform transport parameters; gateway policy independently admits models and efforts.\nimport {\n SONNET_5_MODEL,\n HAIKU_MODEL,\n GPT5_6_LUNA_MODEL,\n GPT5_6_SOL_MODEL,\n GPT5_6_TERRA_MODEL,\n GPT6_SOL_MODEL,\n HAIKU_TRIAGE_MODEL,\n Harness,\n} from '@shared/constants';\n\n/** Reasoning effort, mapped by each harness to its provider transport. */\nconst THINKING_LEVELS = [\n 'off',\n 'minimal',\n 'low',\n 'medium',\n 'high',\n 'xhigh',\n] as const;\nexport type ThinkingLevel = (typeof THINKING_LEVELS)[number];\n\n/** Whether a value (e.g. remote prompt frontmatter) names a valid effort. */\nexport function isThinkingLevel(value: unknown): value is ThinkingLevel {\n return (THINKING_LEVELS as readonly unknown[]).includes(value);\n}\n\n/**\n * An effort *override* is always a positive level — `'off'` is a model trait\n * (`reasoning: false`), not something a flag may force onto a reasoning model.\n */\nexport type EffortLevel = Exclude<ThinkingLevel, 'off'>;\n\nexport interface ModelCapabilities {\n /** Model supports reasoning; safe to request reasoning effort. */\n reasoning: boolean;\n /** Effort to request when reasoning. Omit for the harness/provider default. */\n thinkingLevel?: ThinkingLevel;\n}\n\n/**\n * Explicit per-model traits. Anything absent falls back to `defaultCaps`.\n *\n * A reasoning model without a `thinkingLevel` leaves the effort to the harness,\n * and the mint pins effort per model (posthog `WIZARD_MODEL_ALLOWLIST`), so an\n * unpinned reasoning model is refused with no tool calls. Every level below is\n * one the mint allows for that model.\n */\nexport const MODEL_CAPABILITIES: Record<string, ModelCapabilities> = {\n // The mint takes sonnet 5 at `none` or `high`; high is the only level it\n // serves once reasoning is on.\n [SONNET_5_MODEL]: { reasoning: true, thinkingLevel: 'high' },\n // The mint takes haiku with no effort parameter at all, which is `off`.\n [HAIKU_MODEL]: { reasoning: true, thinkingLevel: 'off' },\n // The openai 5.6 line; all reasoning models, so they must opt in past the\n // openai-completions default (reasoning off). Luna stays low for cheap,\n // short-context mechanical work; terra runs medium as the sonnet-tier parallel\n // — enough reasoning depth for the judgment tasks without high's latency blowup.\n [GPT5_6_LUNA_MODEL]: { reasoning: true, thinkingLevel: 'low' },\n [GPT5_6_TERRA_MODEL]: { reasoning: true, thinkingLevel: 'medium' },\n [GPT5_6_SOL_MODEL]: { reasoning: true, thinkingLevel: 'medium' },\n [GPT6_SOL_MODEL]: { reasoning: true, thinkingLevel: 'medium' },\n};\n\n/**\n * The mint's per-model effort pin, mirrored from posthog\n * `WIZARD_MODEL_ALLOWLIST`. `'off'` is the CLI's spelling of the mint's\n * `\"none\"` — a call carrying no effort parameter.\n */\nexport const MINT_ALLOWED_EFFORTS: Record<string, readonly ThinkingLevel[]> = {\n [SONNET_5_MODEL]: ['off', 'high'],\n [HAIKU_MODEL]: ['off'],\n [GPT5_6_LUNA_MODEL]: ['low'],\n [GPT5_6_SOL_MODEL]: ['medium'],\n [GPT5_6_TERRA_MODEL]: ['low', 'medium', 'high'],\n [GPT6_SOL_MODEL]: ['low', 'medium', 'high'],\n};\n\n// Local model choices; gateway admission also requires allowed models, efforts, and prompt compatibility.\nexport const VALID_MODELS: ReadonlySet<string> = new Set(\n Object.keys(MODEL_CAPABILITIES),\n);\n\n/** Whether the value is an allow-listed model. */\nexport function isValidModel(model: unknown): model is string {\n return typeof model === 'string' && VALID_MODELS.has(model);\n}\n\n/** First allow-listed candidate, else throw so a bad id fails loud. */\nexport function requireKnownModel(\n ...candidates: (string | undefined)[]\n): string {\n for (const c of candidates) if (isValidModel(c)) return c;\n throw new Error(\n `No valid model to dispatch on (tried ${JSON.stringify(candidates)}). ` +\n `Allowed: ${[...VALID_MODELS].join(', ')}.`,\n );\n}\n\n// Unknown Anthropic models default to reasoning; OpenAI models must opt in through the local table.\nfunction defaultCaps(modelId: string): ModelCapabilities {\n return { reasoning: !modelId.startsWith('openai/') };\n}\n\n// Triage requests must satisfy gateway safety policy and preserve Warlock’s classifier format.\nexport const TRIAGE_MODELS: Record<Harness, string> = {\n [Harness.anthropic]: HAIKU_TRIAGE_MODEL,\n [Harness.pi]: GPT5_6_LUNA_MODEL,\n};\n\nexport function triageModelFor(harness: Harness): string {\n return TRIAGE_MODELS[harness];\n}\n\n/**\n * Capabilities for a gateway model id, table override then transport default.\n * `effortOverride` is a switchboard-resolved effort (e.g. from a pi effort\n * flag); it applies only when the model reasons at all — a non-reasoning model\n * rejects reasoning effort, so the override is dropped.\n */\nexport function modelCapabilities(\n modelId: string,\n effortOverride?: EffortLevel,\n): ModelCapabilities {\n const caps = MODEL_CAPABILITIES[modelId] ?? defaultCaps(modelId);\n if (caps.reasoning && effortOverride) {\n return { ...caps, thinkingLevel: effortOverride };\n }\n return caps;\n}\n"],"mappings":";;;AAaA,MAAM,kBAAkB;CACtB;CACA;CACA;CACA;CACA;CACA;CACD;;AAID,SAAgB,gBAAgB,OAAwC;AACtE,QAAQ,gBAAuC,SAAS,MAAM;;;;;;;;;;AAwBhE,MAAa,qBAAwD;EAGlE,iBAAiB;EAAE,WAAW;EAAM,eAAe;EAAQ;EAE3D,cAAc;EAAE,WAAW;EAAM,eAAe;EAAO;EAKvD,oBAAoB;EAAE,WAAW;EAAM,eAAe;EAAO;EAC7D,qBAAqB;EAAE,WAAW;EAAM,eAAe;EAAU;EACjE,mBAAmB;EAAE,WAAW;EAAM,eAAe;EAAU;EAC/D,iBAAiB;EAAE,WAAW;EAAM,eAAe;EAAU;CAC/D;AAiBD,MAAa,eAAoC,IAAI,IACnD,OAAO,KAAK,mBAAmB,CAChC;;AAGD,SAAgB,aAAa,OAAiC;AAC5D,QAAO,OAAO,UAAU,YAAY,aAAa,IAAI,MAAM;;;AAI7D,SAAgB,kBACd,GAAG,YACK;AACR,MAAK,MAAM,KAAK,WAAY,KAAI,aAAa,EAAE,CAAE,QAAO;AACxD,OAAM,IAAI,MACR,wCAAwC,KAAK,UAAU,WAAW,CAAC,cACrD,CAAC,GAAG,aAAa,CAAC,KAAK,KAAK,CAAC,GAC5C;;AAIH,SAAS,YAAY,SAAoC;AACvD,QAAO,EAAE,WAAW,CAAC,QAAQ,WAAW,UAAU,EAAE;;AAItD,MAAa,gBAAyC;gBAC/B;SACP;CACf;AAED,SAAgB,eAAe,SAA0B;AACvD,QAAO,cAAc;;;;;;;;AASvB,SAAgB,kBACd,SACA,gBACmB;CACnB,MAAM,OAAO,mBAAmB,YAAY,YAAY,QAAQ;AAChE,KAAI,KAAK,aAAa,eACpB,QAAO;EAAE,GAAG;EAAM,eAAe;EAAgB;AAEnD,QAAO"}