@posthog/wizard 2.79.1 → 2.80.1

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 (227) hide show
  1. package/README.md +187 -57
  2. package/dist/{PickerMenu-dG5DQCZA.js → PickerMenu-BGGeYqd-.js} +112 -12
  3. package/dist/PickerMenu-BGGeYqd-.js.map +1 -0
  4. package/dist/README.md +9 -6
  5. package/dist/{agent-interface-FkbaBJwz.js → agent-interface-CemBvTAA.js} +130 -324
  6. package/dist/agent-interface-CemBvTAA.js.map +1 -0
  7. package/dist/{agent-prompt-loader-D0weQ-7k.js → agent-prompt-loader-DPnj6SwU.js} +6 -5
  8. package/dist/agent-prompt-loader-DPnj6SwU.js.map +1 -0
  9. package/dist/analytics-B3ROGuIr.js +2 -0
  10. package/dist/analytics-D21z3E5l.js +732 -0
  11. package/dist/analytics-D21z3E5l.js.map +1 -0
  12. package/dist/{api-CrbCIQOz.js → api-DtGIqQ2U.js} +2 -3
  13. package/dist/api-DtGIqQ2U.js.map +1 -0
  14. package/dist/api-IhROOQNv.js +2 -0
  15. package/dist/api-key-login-OEntFvu5.js +2 -0
  16. package/dist/api-key-login-h3E2G3zu.js +55 -0
  17. package/dist/api-key-login-h3E2G3zu.js.map +1 -0
  18. package/dist/bin.js +2 -2
  19. package/dist/bin.js.map +1 -1
  20. package/dist/{bounded-fs-vAq-T-K7.js → bounded-fs-CAsuF6al.js} +3 -3
  21. package/dist/{bounded-fs-vAq-T-K7.js.map → bounded-fs-CAsuF6al.js.map} +1 -1
  22. package/dist/{ci-install-COcV8SY2.js → ci-install-CEYE02t-.js} +22 -26
  23. package/dist/ci-install-CEYE02t-.js.map +1 -0
  24. package/dist/console-log-O828zyiq.js +32 -0
  25. package/dist/console-log-O828zyiq.js.map +1 -0
  26. package/dist/{debug-kAHwWGg7.js → debug-BfQPD2Hg.js} +18 -52
  27. package/dist/debug-BfQPD2Hg.js.map +1 -0
  28. package/dist/{defaults-a9TelDhJ.js → defaults-DDVl3tKN.js} +2 -51
  29. package/dist/defaults-DDVl3tKN.js.map +1 -0
  30. package/dist/{emit-BSetXzDV.js → emit-RfAewcWv.js} +1 -1
  31. package/dist/{emit-BSetXzDV.js.map → emit-RfAewcWv.js.map} +1 -1
  32. package/dist/{errors-C2domSkK.js → errors-CHrJzAZb.js} +4 -4
  33. package/dist/{errors-C2domSkK.js.map → errors-CHrJzAZb.js.map} +1 -1
  34. package/dist/family-picker-BKs-tTyu.js +46 -0
  35. package/dist/family-picker-BKs-tTyu.js.map +1 -0
  36. package/dist/{gateway-C9-GlLO9.js → gateway-D3gIlR6b.js} +122 -11
  37. package/dist/gateway-D3gIlR6b.js.map +1 -0
  38. package/dist/headless-BJjhP0SI.js +10 -0
  39. package/dist/headless-BJjhP0SI.js.map +1 -0
  40. package/dist/headless-DIX68UUA.js +3 -0
  41. package/dist/host-resolution-D8GhEVoX.js +114 -0
  42. package/dist/host-resolution-D8GhEVoX.js.map +1 -0
  43. package/dist/install-Bw8tvDvS.js +2 -0
  44. package/dist/{add-mcp-server-to-clients-DIaTRWMY.js → install-paPCzPHI.js} +34 -100
  45. package/dist/install-paPCzPHI.js.map +1 -0
  46. package/dist/interactive-tdxZKWax.js +11 -0
  47. package/dist/interactive-tdxZKWax.js.map +1 -0
  48. package/dist/{telemetry-B7zJdRmA.js → links-Cyj6v8kg.js} +4 -13
  49. package/dist/links-Cyj6v8kg.js.map +1 -0
  50. package/dist/{main-CgKxbwMP.js → main-0p-YxUNa.js} +233 -490
  51. package/dist/main-0p-YxUNa.js.map +1 -0
  52. package/dist/{mcp-DnAyW0-w.js → mcp-D3Z5MXhA.js} +3 -4
  53. package/dist/{mcp-DnAyW0-w.js.map → mcp-D3Z5MXhA.js.map} +1 -1
  54. package/dist/mcp-install-smoke-test.ts +2 -2
  55. package/dist/{mcp-prompt-streaming-DDWQ-FCA.js → mcp-prompt-streaming-COVbWnHt.js} +12 -12
  56. package/dist/mcp-prompt-streaming-COVbWnHt.js.map +1 -0
  57. package/dist/mode-label-DB3ol_sj.js +9 -0
  58. package/dist/mode-label-DB3ol_sj.js.map +1 -0
  59. package/dist/{models-WcwUnSKb.js → models-D1SnCzvl.js} +2 -2
  60. package/dist/{models-WcwUnSKb.js.map → models-D1SnCzvl.js.map} +1 -1
  61. package/dist/non-interactive-DxRBc73O.js +18 -0
  62. package/dist/non-interactive-DxRBc73O.js.map +1 -0
  63. package/dist/{oauth-session-DYM2Hrl2.js → oauth-session-Dde79Ycm.js} +3 -3
  64. package/dist/{oauth-session-DYM2Hrl2.js.map → oauth-session-Dde79Ycm.js.map} +1 -1
  65. package/dist/{orchestrator-tools-DbgNBFGA.js → orchestrator-tools-BSNhzzkT.js} +3 -3
  66. package/dist/{orchestrator-tools-DbgNBFGA.js.map → orchestrator-tools-BSNhzzkT.js.map} +1 -1
  67. package/dist/{package-json-Atg34fa4.js → package-json-2UrhE6kP.js} +1 -1
  68. package/dist/{package-json-Atg34fa4.js.map → package-json-2UrhE6kP.js.map} +1 -1
  69. package/dist/package-json-Dblip2_X.js +2 -0
  70. package/dist/package-manager-BRXlXo0p.js +105 -0
  71. package/dist/package-manager-BRXlXo0p.js.map +1 -0
  72. package/dist/{pi-8KsYsPmM.js → pi-cM_4Gd_9.js} +19 -20
  73. package/dist/pi-cM_4Gd_9.js.map +1 -0
  74. package/dist/playground-DTKy0XHT.js +12 -0
  75. package/dist/playground-DTKy0XHT.js.map +1 -0
  76. package/dist/posthog-integration-bwHwE87a.js +10291 -0
  77. package/dist/posthog-integration-bwHwE87a.js.map +1 -0
  78. package/dist/programs-BhtyA3lE.js +3 -0
  79. package/dist/programs-SeT1qNik.js +5348 -0
  80. package/dist/programs-SeT1qNik.js.map +1 -0
  81. package/dist/provisioning-BcXfeCMc.js +2 -0
  82. package/dist/{provisioning-Bo2NRxFz.js → provisioning-JbJtq7hq.js} +5 -67
  83. package/dist/provisioning-JbJtq7hq.js.map +1 -0
  84. package/dist/{queue-tools-C8mXOh7e.js → queue-tools-BIZSJyt6.js} +7 -9
  85. package/dist/queue-tools-BIZSJyt6.js.map +1 -0
  86. package/dist/results-DtKICAdz.js +55 -0
  87. package/dist/results-DtKICAdz.js.map +1 -0
  88. package/dist/run-CDurA5tO.js +248 -0
  89. package/dist/run-CDurA5tO.js.map +1 -0
  90. package/dist/run-DDCvLILJ.js +246 -0
  91. package/dist/run-DDCvLILJ.js.map +1 -0
  92. package/dist/run-tool-CTq9OOdT.js +2 -0
  93. package/dist/run-tool-DML8JJvt.js +2420 -0
  94. package/dist/run-tool-DML8JJvt.js.map +1 -0
  95. package/dist/runners-Dhu4pZTN.js +253 -0
  96. package/dist/runners-Dhu4pZTN.js.map +1 -0
  97. package/dist/{security-C71pkwqH.js → security-DEH8Rn0_.js} +5 -5
  98. package/dist/security-DEH8Rn0_.js.map +1 -0
  99. package/dist/setup-utils-C5-WM-hS.js +118 -0
  100. package/dist/setup-utils-C5-WM-hS.js.map +1 -0
  101. package/dist/smoke-test.sh +1 -1
  102. package/dist/{playground-BlYRBMj7.js → start-playground-DL4mVEUx.js} +63 -54
  103. package/dist/start-playground-DL4mVEUx.js.map +1 -0
  104. package/dist/{subagent-D1TrTchE.js → subagent-CnFvAq6E.js} +3 -3
  105. package/dist/{subagent-D1TrTchE.js.map → subagent-CnFvAq6E.js.map} +1 -1
  106. package/dist/{task-DqRlQBfs.js → task-BOScSm4W.js} +17 -18
  107. package/dist/task-BOScSm4W.js.map +1 -0
  108. package/dist/{tasks-ChWufsdO.js → tasks-BfJhVky2.js} +1 -1
  109. package/dist/tasks-BfJhVky2.js.map +1 -0
  110. package/dist/telemetry-CP4rGicd.js +13 -0
  111. package/dist/telemetry-CP4rGicd.js.map +1 -0
  112. package/dist/terminal-J3OD3dN0.js +16162 -0
  113. package/dist/terminal-J3OD3dN0.js.map +1 -0
  114. package/dist/tools-CCMV3DmB.js +544 -0
  115. package/dist/tools-CCMV3DmB.js.map +1 -0
  116. package/dist/{tools-CkJ2y9Wt.js → tools-Cz8tDptL.js} +9 -9
  117. package/dist/tools-Cz8tDptL.js.map +1 -0
  118. package/dist/tui-BUZ2PWqN.js +2 -0
  119. package/dist/tui-Csf7VJxt.js +25 -0
  120. package/dist/tui-Csf7VJxt.js.map +1 -0
  121. package/dist/{steps-BPcg3_3Q.js → upload-step-CEacB2RV.js} +17 -19
  122. package/dist/upload-step-CEacB2RV.js.map +1 -0
  123. package/dist/urls-BDELGZHq.js +67 -0
  124. package/dist/urls-BDELGZHq.js.map +1 -0
  125. package/dist/warlock-smoke-test.ts +1 -2
  126. package/dist/{wizard-abort-BPdv07np.js → wizard-abort-D3-75KyV.js} +41 -32
  127. package/dist/wizard-abort-D3-75KyV.js.map +1 -0
  128. package/dist/yara-hooks-CZ1tKxy_.js +2 -0
  129. package/dist/{yara-hooks-BnxejtXK.js → yara-hooks-D8YDyX7o.js} +283 -21
  130. package/dist/yara-hooks-D8YDyX7o.js.map +1 -0
  131. package/package.json +7 -8
  132. package/dist/PickerMenu-dG5DQCZA.js.map +0 -1
  133. package/dist/add-mcp-server-to-clients-DIaTRWMY.js.map +0 -1
  134. package/dist/add-mcp-server-to-clients-artmN7mz.js +0 -2
  135. package/dist/agent-BEjARD2a.js +0 -6
  136. package/dist/agent-BWFhuLgo.js +0 -3178
  137. package/dist/agent-BWFhuLgo.js.map +0 -1
  138. package/dist/agent-interface-FkbaBJwz.js.map +0 -1
  139. package/dist/agent-prompt-loader-D0weQ-7k.js.map +0 -1
  140. package/dist/analytics-DFtbRjYh.js +0 -2
  141. package/dist/analytics-DXK1gc12.js +0 -301
  142. package/dist/analytics-DXK1gc12.js.map +0 -1
  143. package/dist/api-Cm9UtKZh.js +0 -2
  144. package/dist/api-CrbCIQOz.js.map +0 -1
  145. package/dist/check-screens.tsx +0 -190
  146. package/dist/ci-install-COcV8SY2.js.map +0 -1
  147. package/dist/constants-DHCBSfnx.js +0 -260
  148. package/dist/constants-DHCBSfnx.js.map +0 -1
  149. package/dist/debug-BuYHGr6_.js +0 -2
  150. package/dist/debug-kAHwWGg7.js.map +0 -1
  151. package/dist/defaults-a9TelDhJ.js.map +0 -1
  152. package/dist/endpoints-BVMYm9F4.js +0 -108
  153. package/dist/endpoints-BVMYm9F4.js.map +0 -1
  154. package/dist/env-api-key-BP-NFFXt.js +0 -17
  155. package/dist/env-api-key-BP-NFFXt.js.map +0 -1
  156. package/dist/env-api-key-CaWEDj_9.js +0 -2
  157. package/dist/environment-BATlQxcQ.js +0 -39
  158. package/dist/environment-BATlQxcQ.js.map +0 -1
  159. package/dist/environment-CwD8OPYj.js +0 -2
  160. package/dist/file-C5JMsyR1.js +0 -2
  161. package/dist/file-DcRKycV8.js +0 -60
  162. package/dist/file-DcRKycV8.js.map +0 -1
  163. package/dist/file-watcher-Brq2nnHV.js +0 -123
  164. package/dist/file-watcher-Brq2nnHV.js.map +0 -1
  165. package/dist/gateway-C9-GlLO9.js.map +0 -1
  166. package/dist/headless-ui-CqI2gXlD.js +0 -44
  167. package/dist/headless-ui-CqI2gXlD.js.map +0 -1
  168. package/dist/interactive-B_Ti_CsS.js +0 -11
  169. package/dist/interactive-B_Ti_CsS.js.map +0 -1
  170. package/dist/local-dev-McsurOC-.js +0 -135
  171. package/dist/local-dev-McsurOC-.js.map +0 -1
  172. package/dist/logging-ui-Dza4D0MK.js +0 -226
  173. package/dist/logging-ui-Dza4D0MK.js.map +0 -1
  174. package/dist/main-CgKxbwMP.js.map +0 -1
  175. package/dist/mcp-prompt-streaming-DDWQ-FCA.js.map +0 -1
  176. package/dist/mint-failure-u8xQKNOn.js +0 -6392
  177. package/dist/mint-failure-u8xQKNOn.js.map +0 -1
  178. package/dist/non-interactive-DyVC1AGc.js +0 -18
  179. package/dist/non-interactive-DyVC1AGc.js.map +0 -1
  180. package/dist/package-json-D8Ga03tK.js +0 -2
  181. package/dist/pi-8KsYsPmM.js.map +0 -1
  182. package/dist/playground-BlYRBMj7.js.map +0 -1
  183. package/dist/posthog-Bt0Aplb8.js +0 -124
  184. package/dist/posthog-Bt0Aplb8.js.map +0 -1
  185. package/dist/posthog-CUgCEhH0.js +0 -2
  186. package/dist/provisioning-Bo2NRxFz.js.map +0 -1
  187. package/dist/provisioning-OGFGlzf7.js +0 -2
  188. package/dist/queue-tools-C8mXOh7e.js.map +0 -1
  189. package/dist/registry-C06e_x-p.js +0 -2
  190. package/dist/registry-CD5RQt38.js +0 -3464
  191. package/dist/registry-CD5RQt38.js.map +0 -1
  192. package/dist/run-agent-legacy-ChacZImU.js +0 -2
  193. package/dist/run-agent-legacy-DOlM6DQu.js +0 -3540
  194. package/dist/run-agent-legacy-DOlM6DQu.js.map +0 -1
  195. package/dist/runners-ov3EXF1n.js +0 -834
  196. package/dist/runners-ov3EXF1n.js.map +0 -1
  197. package/dist/security-C71pkwqH.js.map +0 -1
  198. package/dist/setup-utils-B26Lf2yF.js +0 -1512
  199. package/dist/setup-utils-B26Lf2yF.js.map +0 -1
  200. package/dist/setup-utils-CVS86NYR.js +0 -2
  201. package/dist/start-tui-Bo2L0bar.js +0 -6962
  202. package/dist/start-tui-Bo2L0bar.js.map +0 -1
  203. package/dist/steps-BPcg3_3Q.js.map +0 -1
  204. package/dist/store-BTzcvRGT.js +0 -992
  205. package/dist/store-BTzcvRGT.js.map +0 -1
  206. package/dist/store-BpqySPXm.js +0 -5
  207. package/dist/task-DqRlQBfs.js.map +0 -1
  208. package/dist/task-stream-Bw6JaLCX.js +0 -363
  209. package/dist/task-stream-Bw6JaLCX.js.map +0 -1
  210. package/dist/tasks-ChWufsdO.js.map +0 -1
  211. package/dist/telemetry-B7zJdRmA.js.map +0 -1
  212. package/dist/terminal-zgkEfoCL.js +0 -7196
  213. package/dist/terminal-zgkEfoCL.js.map +0 -1
  214. package/dist/tools-CkJ2y9Wt.js.map +0 -1
  215. package/dist/ui-Q6-RvERF.js +0 -15
  216. package/dist/ui-Q6-RvERF.js.map +0 -1
  217. package/dist/version-CHhJjz_H.js +0 -6
  218. package/dist/version-CHhJjz_H.js.map +0 -1
  219. package/dist/wizard-abort-BPdv07np.js.map +0 -1
  220. package/dist/wizard-abort-Br1qMDNa.js +0 -3
  221. package/dist/wizard-session-2w4Ru-Wz.js +0 -131
  222. package/dist/wizard-session-2w4Ru-Wz.js.map +0 -1
  223. package/dist/wizard-session-DGaUHOF3.js +0 -2
  224. package/dist/wizard-ui-DVqrYaOM.js +0 -16
  225. package/dist/wizard-ui-DVqrYaOM.js.map +0 -1
  226. package/dist/yara-hooks-BnxejtXK.js.map +0 -1
  227. package/dist/yara-hooks-DSuExwb4.js +0 -2
@@ -1,10 +1,10 @@
1
- import { $ as vaultSensitiveAnswers, A as CHECK_ENV_KEYS_FILE_PATH_DESCRIPTION, B as describeAskCancellation, C as AUDIT_ADD_CHECKS_PARAM_DESCRIPTION, D as AUDIT_SEED_CHECKS_PARAM_DESCRIPTION, E as AUDIT_SEED_CHECKS_DESCRIPTION, F as WIZARD_ASK_TOOL_DESCRIPTION, G as mergeEnvValues, H as ensureGitignoreCoverage, I as WIZARD_TOOL_NAMES, J as resolveAuditChecks, K as normaliseAskSubject, L as addAuditChecks, M as WIZARD_ASK_KIND_DESCRIPTION, N as WIZARD_ASK_SENSITIVE_DESCRIPTION, O as AUDIT_STATUSES, P as WIZARD_ASK_SUBJECT_DESCRIPTION, Q as templateEnvWriteRefusal, R as checkEnvKeys, S as AUDIT_ADD_CHECKS_DESCRIPTION, T as AUDIT_RESOLVE_CHECKS_PARAM_DESCRIPTION, U as installSkillById, W as legacyKeyNameRefusal, X as resolveEnvSecretRefs, Y as resolveEnvPath, Z as seedAuditChecks, _ as createSecretVault, b as PUBLISH_HANDOFF_TOOL_NAME, et as fetchSkillMenu, it as isFullyCancelled, j as ENV_FILE_PATH_DESCRIPTION, k as CHECK_ENV_KEYS_DESCRIPTION, q as resolveAskQuestionKinds, v as PUBLISH_HANDOFF_CONTENT_DESCRIPTION, w as AUDIT_RESOLVE_CHECKS_DESCRIPTION, x as publishHandoff, y as PUBLISH_HANDOFF_DESCRIPTION, z as createAskAccounting } from "./agent-interface-FkbaBJwz.js";
2
- import { s as logToFile } from "./debug-kAHwWGg7.js";
3
- import { n as analytics } from "./analytics-DXK1gc12.js";
4
- import { g as detectNodePackageManagers } from "./setup-utils-B26Lf2yF.js";
5
- import { o as withMode } from "./pi-8KsYsPmM.js";
6
- import { h as AUDIT_CHECKS_FILE } from "./yara-hooks-BnxejtXK.js";
7
- import { v as makeMutex } from "./queue-tools-C8mXOh7e.js";
1
+ import { o as logToFile } from "./debug-BfQPD2Hg.js";
2
+ import { n as analytics } from "./analytics-D21z3E5l.js";
3
+ import { n as detectNodePackageManagers } from "./package-manager-BRXlXo0p.js";
4
+ import { $ as vaultSensitiveAnswers, A as AUDIT_STATUSES, B as checkEnvKeys, C as publishHandoff, D as AUDIT_RESOLVE_CHECKS_PARAM_DESCRIPTION, E as AUDIT_RESOLVE_CHECKS_DESCRIPTION, F as WIZARD_ASK_SENSITIVE_DESCRIPTION, G as mergeEnvValues, H as describeAskCancellation, I as WIZARD_ASK_SUBJECT_DESCRIPTION, J as resolveAuditChecks, K as normaliseAskSubject, L as WIZARD_ASK_TOOL_DESCRIPTION, M as CHECK_ENV_KEYS_FILE_PATH_DESCRIPTION, N as ENV_FILE_PATH_DESCRIPTION, O as AUDIT_SEED_CHECKS_DESCRIPTION, P as WIZARD_ASK_KIND_DESCRIPTION, Q as templateEnvWriteRefusal, R as WIZARD_TOOL_NAMES, S as PUBLISH_HANDOFF_TOOL_NAME, T as AUDIT_ADD_CHECKS_PARAM_DESCRIPTION, U as ensureGitignoreCoverage, V as createAskAccounting, W as legacyKeyNameRefusal, X as resolveEnvSecretRefs, Y as resolveEnvPath, Z as seedAuditChecks, b as PUBLISH_HANDOFF_CONTENT_DESCRIPTION, j as CHECK_ENV_KEYS_DESCRIPTION, k as AUDIT_SEED_CHECKS_PARAM_DESCRIPTION, q as resolveAskQuestionKinds, tt as isFullyCancelled, w as AUDIT_ADD_CHECKS_DESCRIPTION, x as PUBLISH_HANDOFF_DESCRIPTION, y as createSecretVault, z as addAuditChecks } from "./agent-interface-CemBvTAA.js";
5
+ import { o as withMode } from "./pi-cM_4Gd_9.js";
6
+ import { _ as makeMutex } from "./queue-tools-BIZSJyt6.js";
7
+ import { p as scanInstalledSkill, v as installSkillById, x as AUDIT_CHECKS_FILE, y as fetchSkillMenu } from "./yara-hooks-D8YDyX7o.js";
8
8
  import fs from "fs";
9
9
  import path from "path";
10
10
  import { Type } from "typebox";
@@ -61,7 +61,7 @@ function createWizardPiTools(ctx) {
61
61
  promptSnippet: "install_skill(skillId) — install a skill, then read its SKILL.md",
62
62
  parameters: Type.Object({ skillId: Type.String({ description: "Skill ID from load_skill_menu" }) }),
63
63
  async execute(_id, args) {
64
- const result = await installSkillById(args.skillId, workingDirectory, skillsBaseUrl, { triage: triageProvider });
64
+ const result = await installSkillById(args.skillId, workingDirectory, skillsBaseUrl, { scan: (dir) => scanInstalledSkill(dir, triageProvider) });
65
65
  if (result.kind !== "ok") {
66
66
  logToFile(`[pi] install_skill ${args.skillId}: ${result.kind}`);
67
67
  return text(`Error installing skill "${args.skillId}": ${result.kind}. Use load_skill_menu to see valid IDs.`);
@@ -288,4 +288,4 @@ function createWizardPiTools(ctx) {
288
288
  //#endregion
289
289
  export { createWizardPiTools };
290
290
 
291
- //# sourceMappingURL=tools-CkJ2y9Wt.js.map
291
+ //# sourceMappingURL=tools-Cz8tDptL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools-Cz8tDptL.js","names":["checkEnvKeys","checkEnvKeysCore"],"sources":["../src/agent/runner/harness/pi/tools.ts"],"sourcesContent":["/**\n * Wizard capabilities as pi custom tools (#5). pi does not mount MCP servers,\n * so the tools the wizard prompt depends on — skill discovery/install and\n * fenced `.env` edits — are exposed to pi as native `defineTool` tools backed\n * by the same helpers the claude-agent-sdk path uses (`fetchSkillMenu`,\n * `installSkillById`, `checkEnvKeys`, `mergeEnvValues`). Same tool names as the\n * MCP server so the shared prompt is unchanged. `wizard_ask` is wired here too\n * (same schema, caps, and askBridge as the MCP tool) so interactive programs\n * can interview the user on pi; without a bridge (CI) it errors on call.\n * Sensitive answers are vaulted to `{secretRef}` and resolved host-side by\n * set_env_values — the raw value never enters the model conversation.\n */\n\nimport fs from 'fs';\nimport path from 'path';\nimport { Type } from 'typebox';\nimport { defineTool } from '@earendil-works/pi-coding-agent';\nimport type { ToolDefinition } from '@earendil-works/pi-coding-agent';\nimport { analytics } from '@utils/analytics';\nimport { logToFile } from '@utils/debug';\nimport {\n ASK_MAX_QUESTIONS_PER_CALL,\n AUDIT_ADD_CHECKS_DESCRIPTION,\n AUDIT_ADD_CHECKS_PARAM_DESCRIPTION,\n AUDIT_RESOLVE_CHECKS_DESCRIPTION,\n AUDIT_RESOLVE_CHECKS_PARAM_DESCRIPTION,\n AUDIT_SEED_CHECKS_DESCRIPTION,\n AUDIT_SEED_CHECKS_PARAM_DESCRIPTION,\n AUDIT_STATUSES,\n CHECK_ENV_KEYS_DESCRIPTION,\n CHECK_ENV_KEYS_FILE_PATH_DESCRIPTION,\n DEFAULT_ASK_MAX_QUESTIONS,\n ENV_FILE_PATH_DESCRIPTION,\n WIZARD_TOOL_NAMES,\n addAuditChecks,\n checkEnvKeys as checkEnvKeysCore,\n resolveAuditChecks,\n seedAuditChecks,\n createAskAccounting,\n describeAskCancellation,\n ensureGitignoreCoverage,\n mergeEnvValues,\n normaliseAskSubject,\n resolveAskQuestionKinds,\n resolveEnvPath,\n resolveEnvSecretRefs,\n templateEnvWriteRefusal,\n legacyKeyNameRefusal,\n vaultSensitiveAnswers,\n WIZARD_ASK_KIND_DESCRIPTION,\n WIZARD_ASK_SENSITIVE_DESCRIPTION,\n WIZARD_ASK_SUBJECT_DESCRIPTION,\n WIZARD_ASK_TOOL_DESCRIPTION,\n} from '../../../tools/tools';\nimport { fetchSkillMenu } from '@shared/skill-menu';\nimport { installSkillById } from '@shared/skill-install';\nimport type { LLMProvider } from '@posthog/warlock';\nimport { scanInstalledSkill } from '../../../yara-hooks';\nimport type { ProgressEmitter } from '../../../progress';\nimport {\n isFullyCancelled,\n type WizardAskBridge,\n} from '../../../wizard-ask-bridge';\nimport {\n PUBLISH_HANDOFF_CONTENT_DESCRIPTION,\n PUBLISH_HANDOFF_DESCRIPTION,\n PUBLISH_HANDOFF_TOOL_NAME,\n publishHandoff,\n} from '../../../tools/handoff';\nimport { createSecretVault } from '@shared/secret-vault';\nimport {\n AUDIT_CHECKS_FILE,\n type AuditCheck,\n type AuditStatus,\n} from '@shared/audit-ledger';\nimport { makeMutex } from '@utils/atomic-ledger';\nimport { withMode } from './index';\nimport {\n detectNodePackageManagers,\n type PackageManagerDetector,\n} from '@utils/package-manager';\n\nfunction text(s: string): {\n content: [{ type: 'text'; text: string }];\n details: unknown;\n} {\n return { content: [{ type: 'text', text: s }], details: {} };\n}\n\nexport interface PiToolsContext {\n workingDirectory: string;\n skillsBaseUrl: string;\n /** Framework's package-manager detector. Defaults to Node detection. */\n detectPackageManager?: PackageManagerDetector;\n /** Drives the `wizard_ask` overlay. Omitted in CI → the tool errors on call. */\n askBridge?: WizardAskBridge;\n /** Per-run cap on wizard_ask calls. Defaults to {@link DEFAULT_ASK_MAX_QUESTIONS}. */\n maxQuestions?: number;\n /** Overlay open/closed signal — the security gate blocks Write/Edit while open. */\n onAskPendingChange?: (pending: boolean) => void;\n /** Program disallow list; gates wizard_ask here since pi tools carry bare names the MCP-prefixed security gate misses. */\n disallowedTools?: readonly string[];\n /** Scan-triage classifier, resolved once in bootstrap. Absent → scans fail closed. */\n triageProvider?: LLMProvider;\n /** Where `publish_handoff` reports. Absent → the handoff is written but reported nowhere. */\n emit?: ProgressEmitter;\n /** Set for one task of an orchestrated run: `publish_handoff` then reminds it to report with complete_task. */\n taskAgent?: boolean;\n}\n\nexport function createWizardPiTools(ctx: PiToolsContext): ToolDefinition[] {\n const {\n workingDirectory,\n skillsBaseUrl,\n askBridge,\n onAskPendingChange,\n triageProvider,\n } = ctx;\n const detectPackageManager =\n ctx.detectPackageManager ?? detectNodePackageManagers;\n const askMaxQuestions = ctx.maxQuestions ?? DEFAULT_ASK_MAX_QUESTIONS;\n // Per-run wizard_ask accounting (total cap + one-time per-subject adjacency\n // nudge). Same shared implementation the MCP server drives, so the two\n // facades cannot diverge on the cap, the nudge or the refund.\n const askAccounting = createAskAccounting(askMaxQuestions);\n // Session-scoped secret vault, same contract as the MCP server: wizard_ask\n // mints `{secretRef}` for sensitive answers, set_env_values resolves them.\n const secretVault = createSecretVault();\n\n // Fetch the skill menu at most once per run — the agent calls load_skill_menu\n // 2-3× otherwise, each a fresh HTTP round-trip (profiled slowness).\n let menuPromise: ReturnType<typeof fetchSkillMenu> | undefined;\n const getSkillMenu = () => (menuPromise ??= fetchSkillMenu(skillsBaseUrl));\n\n const loadSkillMenu = defineTool({\n name: 'load_skill_menu',\n label: 'Load skill menu',\n description:\n 'Load available PostHog skills for a category. Returns skill IDs and names. Call this first, then install_skill with the chosen ID.',\n promptSnippet:\n 'load_skill_menu(category) — list installable PostHog skills',\n parameters: Type.Object({\n category: Type.String({\n description: 'Skill category, e.g. \"integration\"',\n }),\n }),\n async execute(_id, args) {\n const menu = await getSkillMenu();\n if (!menu) return text('Error: could not load the skill menu.');\n const skills = menu.categories[args.category] ?? [];\n if (skills.length === 0) {\n return text(`No skills found for category \"${args.category}\".`);\n }\n logToFile(`[pi] load_skill_menu: ${skills.length} skills`);\n return text(skills.map((s) => `- ${s.id}: ${s.name}`).join('\\n'));\n },\n });\n\n const installSkill = defineTool({\n name: 'install_skill',\n label: 'Install skill',\n description:\n 'Download and install a PostHog skill by ID into .claude/skills/<skillId>/. Call load_skill_menu first. Then read the installed SKILL.md and follow it.',\n promptSnippet:\n 'install_skill(skillId) — install a skill, then read its SKILL.md',\n parameters: Type.Object({\n skillId: Type.String({ description: 'Skill ID from load_skill_menu' }),\n }),\n async execute(_id, args) {\n const result = await installSkillById(\n args.skillId,\n workingDirectory,\n skillsBaseUrl,\n { scan: (dir) => scanInstalledSkill(dir, triageProvider) },\n );\n if (result.kind !== 'ok') {\n logToFile(`[pi] install_skill ${args.skillId}: ${result.kind}`);\n return text(\n `Error installing skill \"${args.skillId}\": ${result.kind}. Use load_skill_menu to see valid IDs.`,\n );\n }\n logToFile(`[pi] install_skill ${args.skillId} -> ${result.path}`);\n return text(\n `Installed \"${args.skillId}\" at ${result.path}. Read ${result.path}/SKILL.md and follow it.`,\n );\n },\n });\n\n const checkEnvKeys = defineTool({\n name: 'check_env_keys',\n label: 'Check env keys',\n description: CHECK_ENV_KEYS_DESCRIPTION,\n promptSnippet:\n 'check_env_keys(keys) — see which .env keys exist, and in which file',\n parameters: Type.Object({\n filePath: Type.Optional(\n Type.String({\n description: CHECK_ENV_KEYS_FILE_PATH_DESCRIPTION,\n }),\n ),\n keys: Type.Array(Type.String(), {\n description: 'Environment variable key names to check',\n }),\n }),\n // `async` with nothing to await, on purpose: it is what turns a thrown\n // error into a rejection. `checkEnvKeys` throws on a filePath that escapes\n // the working directory, and pi wraps `execute` in a plain (non-async)\n // arrow, so without this the throw leaves the tool synchronously instead\n // of arriving as a failed tool call. The scan replaced an awaited read,\n // which is the only reason there is nothing left to await.\n // eslint-disable-next-line @typescript-eslint/require-await\n async execute(_id, args) {\n const results = checkEnvKeysCore(\n workingDirectory,\n args.keys,\n args.filePath,\n );\n return text(JSON.stringify(results, null, 2));\n },\n });\n\n const setEnvValues = defineTool({\n name: 'set_env_values',\n label: 'Set env values',\n description:\n 'Create or update environment variable keys in a .env file (creates the file if missing). Each value is either a literal string or a secret reference `{ \"secretRef\": \"secret:...\" }` returned by wizard_ask — refs are resolved locally, so the actual value is written to the file but never returned to the agent.',\n promptSnippet:\n 'set_env_values(filePath, values) — write .env keys (never hardcode secrets in source)',\n parameters: Type.Object({\n filePath: Type.String({\n description: ENV_FILE_PATH_DESCRIPTION,\n }),\n values: Type.Record(\n Type.String(),\n Type.Union([Type.String(), Type.Object({ secretRef: Type.String() })]),\n {\n description:\n 'Key → (literal string OR { secretRef } pointing to a vaulted secret)',\n },\n ),\n }),\n async execute(_id, args) {\n const keyRefusal = legacyKeyNameRefusal(\n workingDirectory,\n Object.keys(args.values),\n );\n if (keyRefusal) return text(keyRefusal);\n // Resolve secret refs host-side; the value never reaches the agent.\n const resolution = resolveEnvSecretRefs(args.values, secretVault);\n if (!resolution.ok) {\n return text(\n `Error: secret reference \"${resolution.secretRef}\" for key \"${resolution.key}\" is not known to the vault. The ref may have expired, been minted in a different run, or been mistyped.`,\n );\n }\n const resolved = resolveEnvPath(workingDirectory, args.filePath);\n const templateRefusal = templateEnvWriteRefusal(resolved);\n if (templateRefusal) {\n logToFile(`[pi] set_env_values: refused template target ${resolved}`);\n analytics.wizardCapture('set_env_values template target refused', {\n file_name: path.basename(resolved),\n });\n return text(templateRefusal);\n }\n const existing = fs.existsSync(resolved)\n ? await fs.promises.readFile(resolved, 'utf8')\n : '';\n const merged = mergeEnvValues(existing, resolution.values);\n const dir = path.dirname(resolved);\n if (!fs.existsSync(dir))\n await fs.promises.mkdir(dir, { recursive: true });\n await fs.promises.writeFile(resolved, merged, 'utf8');\n // Same post-write pass as the MCP facade: a credential file the\n // project does not ignore yet gets committed by the next `git add`.\n ensureGitignoreCoverage(workingDirectory, path.basename(resolved));\n logToFile(\n `[pi] set_env_values: ${resolved} keys=${Object.keys(args.values).join(\n ',',\n )}`,\n );\n return text(\n `Wrote ${Object.keys(args.values).length} key(s) to ${args.filePath}.`,\n );\n },\n });\n\n // ── Audit ledger ────────────────────────────────────────────────────\n // Native mirror of the three MCP audit tools; pi mounts no MCP server, so\n // without these an audit cannot move a check off pending. Descriptions and\n // write semantics come from the shared helpers, so the facades cannot drift.\n const auditLedgerPath = path.join(workingDirectory, AUDIT_CHECKS_FILE);\n const auditMutex = makeMutex();\n const auditStatus = Type.Union(\n AUDIT_STATUSES.map((s) => Type.Literal(s)),\n { description: 'Check outcome' },\n );\n const auditCheck = Type.Object({\n id: Type.String({ description: 'Stable kebab-case check id' }),\n area: Type.String({ description: 'Short group name, e.g. Installation' }),\n label: Type.String({ description: 'Short human name for the check' }),\n status: auditStatus,\n file: Type.Optional(Type.String({ description: 'Optional path:line' })),\n details: Type.Optional(\n Type.String({ description: 'Optional one-line explanation' }),\n ),\n });\n\n const auditSeedChecks = defineTool({\n name: 'audit_seed_checks',\n label: 'Seed audit checks',\n description: AUDIT_SEED_CHECKS_DESCRIPTION,\n promptSnippet:\n 'audit_seed_checks(checks) — write the full pending checklist to the audit ledger',\n parameters: Type.Object({\n checks: Type.Array(auditCheck, {\n description: AUDIT_SEED_CHECKS_PARAM_DESCRIPTION,\n }),\n }),\n execute: (_id, args) =>\n auditMutex(() => {\n const result = seedAuditChecks(\n auditLedgerPath,\n args.checks as AuditCheck[],\n );\n logToFile(`[pi] audit_seed_checks: ${result.message}`);\n return text(result.message);\n }),\n });\n\n const auditAddChecks = defineTool({\n name: 'audit_add_checks',\n label: 'Add audit checks',\n description: AUDIT_ADD_CHECKS_DESCRIPTION,\n promptSnippet:\n 'audit_add_checks(checks) — append runtime-discovered checks to the ledger',\n parameters: Type.Object({\n checks: Type.Array(auditCheck, {\n minItems: 1,\n description: AUDIT_ADD_CHECKS_PARAM_DESCRIPTION,\n }),\n }),\n execute: (_id, args) =>\n auditMutex(() => {\n const result = addAuditChecks(\n auditLedgerPath,\n args.checks as AuditCheck[],\n );\n logToFile(`[pi] audit_add_checks: ${result.message}`);\n return text(result.message);\n }),\n });\n\n const auditResolveChecks = defineTool({\n name: 'audit_resolve_checks',\n label: 'Resolve audit checks',\n description: AUDIT_RESOLVE_CHECKS_DESCRIPTION,\n promptSnippet:\n 'audit_resolve_checks(updates) — patch each check by id as you finish it',\n parameters: Type.Object({\n updates: Type.Array(\n Type.Object({\n id: Type.String({ description: 'Existing check id' }),\n status: auditStatus,\n file: Type.Optional(\n Type.String({ description: 'Optional path:line' }),\n ),\n details: Type.Optional(\n Type.String({ description: 'Optional one-line explanation' }),\n ),\n }),\n { minItems: 1, description: AUDIT_RESOLVE_CHECKS_PARAM_DESCRIPTION },\n ),\n }),\n execute: (_id, args) =>\n auditMutex(() => {\n const result = resolveAuditChecks(\n auditLedgerPath,\n args.updates as Array<{\n id: string;\n status: AuditStatus;\n file?: string;\n details?: string;\n }>,\n );\n logToFile(`[pi] audit_resolve_checks: ${result.message}`);\n return text(result.message);\n }),\n });\n\n const detectPm = defineTool({\n name: 'detect_package_manager',\n label: 'Detect package manager',\n description:\n \"Detect the project's package manager(s). Returns the name and the install command for each. Call this before installing a dependency, then RUN the returned install command (with the posthog package) via bash — the SDK package must end up in the project manifest, or the app will not build.\",\n promptSnippet:\n 'detect_package_manager() — find the PM + install command, then run it via bash to add the SDK',\n parameters: Type.Object({}),\n async execute() {\n const result = await detectPackageManager(workingDirectory);\n logToFile(\n `[pi] detect_package_manager: ${result.detected.length} detected`,\n );\n return text(JSON.stringify(result, null, 2));\n },\n });\n\n // Native mirror of the MCP `wizard_ask` tool: same name, schema, and\n // askBridge, so the shared prompt is unchanged.\n const wizardAsk = defineTool({\n name: 'wizard_ask',\n label: 'Ask the user',\n description: WIZARD_ASK_TOOL_DESCRIPTION,\n promptSnippet:\n 'wizard_ask(questions, subject) — ask the user structured questions and wait for answers; tag each call with the subject it collects for',\n parameters: Type.Object({\n questions: Type.Array(\n Type.Object({\n id: Type.String({\n description: 'Stable key for the answer in the response map',\n }),\n prompt: Type.String({\n description: 'Question text shown to the user',\n }),\n kind: Type.Optional(\n Type.Union(\n [\n Type.Literal('single'),\n Type.Literal('multi'),\n Type.Literal('text'),\n ],\n { description: WIZARD_ASK_KIND_DESCRIPTION },\n ),\n ),\n options: Type.Optional(\n Type.Array(\n Type.Object({\n label: Type.String(),\n value: Type.String(),\n description: Type.Optional(Type.String()),\n }),\n {\n description:\n 'Required for kind=single|multi; ignored for kind=text',\n },\n ),\n ),\n required: Type.Optional(\n Type.Boolean({ description: 'Defaults to true' }),\n ),\n sensitive: Type.Optional(\n Type.Boolean({\n description: WIZARD_ASK_SENSITIVE_DESCRIPTION,\n }),\n ),\n }),\n { minItems: 1, maxItems: ASK_MAX_QUESTIONS_PER_CALL },\n ),\n subject: Type.Optional(\n Type.String({ description: WIZARD_ASK_SUBJECT_DESCRIPTION }),\n ),\n }),\n async execute(_id, args) {\n if (!askBridge) {\n return text(\n 'Error: wizard_ask is not available in this environment (CI / non-interactive). Proceed with sensible defaults or emit [ABORT] requirements-incomplete.',\n );\n }\n\n const cap = askAccounting.evaluate(args.subject);\n if (cap.kind === 'capped') {\n const { callCount } = askAccounting.snapshot();\n logToFile(\n `[pi] wizard_ask capped: reason=${cap.reason} count=${callCount} subject=${cap.subject} run=${cap.subjectRunLength}`,\n );\n analytics.wizardCapture('wizard_ask capped', {\n reason: cap.reason,\n call_count: callCount,\n max_questions: askMaxQuestions,\n subject: cap.subject,\n subject_run_length: cap.subjectRunLength,\n });\n return text(cap.message);\n }\n\n // A question with no kind takes the one its options imply, so the\n // overlay always has an input to render. See resolveAskQuestionKinds.\n const questions = resolveAskQuestionKinds(args.questions);\n\n // The schema can't enforce per-kind requirements or unique ids.\n const ids = new Set<string>();\n for (const q of questions) {\n if ((q.kind === 'single' || q.kind === 'multi') && !q.options?.length) {\n return text(\n `Error: question \"${q.id}\" has kind=\"${q.kind}\" but no options. Provide at least one { label, value }, or use kind=\"text\".`,\n );\n }\n if (q.sensitive && q.kind !== 'text') {\n return text(\n `Error: question \"${q.id}\" sets sensitive=true but kind=\"${q.kind}\". Only kind=\"text\" answers can be sensitive.`,\n );\n }\n if (ids.has(q.id)) {\n return text(\n `Error: duplicate question id \"${q.id}\". Each question needs a unique id.`,\n );\n }\n ids.add(q.id);\n }\n\n // Optimistically take the slot; refund it on a cancellation or a bridge\n // error so a declined/failed ask doesn't burn the budget for later ones.\n askAccounting.record(args.subject);\n // Block Write/Edit for as long as the overlay is open, so the agent can't\n // mutate files while it's waiting on the user's answer.\n onAskPendingChange?.(true);\n try {\n const { answers, timedOut } = await askBridge.request({\n questions,\n subject: normaliseAskSubject(args.subject),\n });\n if (isFullyCancelled(answers)) askAccounting.refund(args.subject);\n // Sensitive answers go to the vault; the agent sees an opaque ref\n // (same contract as the MCP wizard_ask).\n const sanitised = vaultSensitiveAnswers(\n questions,\n answers,\n secretVault,\n );\n // State an uncollected field as an outcome rather than leaving the\n // agent to recognise a sentinel answer value (same as the MCP facade).\n const cancelled = describeAskCancellation(sanitised, timedOut);\n logToFile(\n `[pi] wizard_ask: resolved ${\n Object.keys(answers).length\n } answer(s) for ${args.questions.length} question(s)${\n cancelled ? `, cancelled: ${cancelled.reason}` : ''\n }`,\n );\n return text(\n JSON.stringify(\n { answers: sanitised, ...(cancelled ? { cancelled } : {}) },\n null,\n 2,\n ),\n );\n } catch (err) {\n askAccounting.refund(args.subject);\n const message = err instanceof Error ? err.message : String(err);\n logToFile(`[pi] wizard_ask: error: ${message}`);\n return text(`Error: wizard_ask failed: ${message}`);\n } finally {\n onAskPendingChange?.(false);\n }\n },\n });\n\n // Native mirror of the MCP `publish_handoff` tool (shared description, so no drift).\n const publishHandoffTool = defineTool({\n name: PUBLISH_HANDOFF_TOOL_NAME,\n label: 'Publish handoff',\n description: PUBLISH_HANDOFF_DESCRIPTION,\n promptSnippet:\n 'publish_handoff(content) — publish the full report markdown to the wizard session',\n parameters: Type.Object({\n content: Type.String({\n description: PUBLISH_HANDOFF_CONTENT_DESCRIPTION,\n }),\n }),\n execute(_id, args) {\n const result = publishHandoff(args.content, ctx.emit, {\n taskAgent: ctx.taskAgent,\n });\n logToFile(`[pi] publish_handoff: ${result.message}`);\n return Promise.resolve(text(result.message));\n },\n });\n\n const tools = [\n loadSkillMenu,\n installSkill,\n checkEnvKeys,\n setEnvValues,\n detectPm,\n // Parallel: the mutex serializes the writes, so a subagent fan-out is safe.\n withMode(auditSeedChecks, 'parallel'),\n withMode(auditAddChecks, 'parallel'),\n withMode(auditResolveChecks, 'parallel'),\n // Sequential: it publishes the run's handoff.\n withMode(publishHandoffTool, 'sequential'),\n ];\n // Register wizard_ask only when the program allows it. posthog-integration\n // disallows it (runs without structured user input); self-driving keeps it.\n // Sequential: the ask bridge holds a single in-flight question slot, so a\n // batched turn must never dispatch two asks (or an ask + a write) at once.\n const askDisallowed =\n ctx.disallowedTools?.includes(WIZARD_TOOL_NAMES.wizardAsk) ?? false;\n if (!askDisallowed) tools.push(withMode(wizardAsk, 'sequential'));\n return tools;\n}\n"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { i as runTuiTool, r as runTui, t as renderFamilyPicker } from "./tui-Csf7VJxt.js";
2
+ export { renderFamilyPicker, runTui, runTuiTool };
@@ -0,0 +1,25 @@
1
+ //#region src/tui/index.ts
2
+ /** Run `config` in the TUI; resolves with the exit code. */
3
+ async function runTui(config, launch) {
4
+ const { runTui: run } = await import("./run-CDurA5tO.js");
5
+ return run(config, launch);
6
+ }
7
+ /** Run a tool's screens; resolves with the exit code, rejects when the TUI cannot start. */
8
+ async function runTuiTool(toolId, launch) {
9
+ const { runTuiTool: run } = await import("./run-tool-CTq9OOdT.js");
10
+ return run(toolId, launch);
11
+ }
12
+ /** Pick one of a family's subcommands; resolves with the picked value. */
13
+ async function renderFamilyPicker(parentLabel, options) {
14
+ const { renderFamilyPicker: render } = await import("./family-picker-BKs-tTyu.js");
15
+ return render(parentLabel, options);
16
+ }
17
+ /** Launch the TUI primitives playground; resolves 0 once it closes. */
18
+ async function runPlayground(version) {
19
+ const { startPlayground } = await import("./start-playground-DL4mVEUx.js");
20
+ return startPlayground(version);
21
+ }
22
+ //#endregion
23
+ export { runTuiTool as i, runPlayground as n, runTui as r, renderFamilyPicker as t };
24
+
25
+ //# sourceMappingURL=tui-Csf7VJxt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tui-Csf7VJxt.js","names":[],"sources":["../src/tui/index.ts"],"sourcesContent":["/** The TUI's one entry for other layers; each function loads its module on first call. */\nimport type { ProgramId } from '@programs';\nimport type { ProgramConfig } from '@programs/types';\nimport type { ToolId } from '@tools';\nimport type { FamilyPickerOption } from './family-picker.js';\nimport type { FlowStep } from './flow.js';\nimport type { TuiLaunch, TuiToolLaunch } from './launch.js';\nimport type { MountedScreens, MountServices } from './harness.js';\nimport type { WizardStore } from './store.js';\nimport type { TuiState } from './tui-state.js';\n\nexport { Overlay, ScreenId } from './screen-ids.js';\n// The programs' and tools' screen ids, from their leaf modules so the entry stays light.\nexport { AiObservabilityScreenId } from './programs/ai-observability/screen-ids.js';\nexport { AuditScreenId } from './programs/audit/screen-ids.js';\nexport { ErrorTrackingScreenId } from './programs/error-tracking/screen-ids.js';\nexport { SourceMapsScreenId } from './programs/error-tracking-upload-source-maps/screen-ids.js';\nexport { MetricsScreenId } from './programs/metrics/screen-ids.js';\nexport { MigrationScreenId } from './programs/migration/screen-ids.js';\nexport { PostHogIntegrationScreenId } from './programs/posthog-integration/screen-ids.js';\nexport { RevenueAnalyticsScreenId } from './programs/revenue-analytics/screen-ids.js';\nexport { SelfDrivingScreenId } from './programs/self-driving/screen-ids.js';\nexport { SkillScreenId } from './programs/shared/screen-ids.js';\nexport { WarehouseSourceScreenId } from './programs/warehouse-source/screen-ids.js';\nexport { PosthogDoctorScreenId } from './tools/doctor/screen-ids.js';\nexport { McpScreenId } from './tools/mcp/screen-ids.js';\nexport type { FamilyPickerOption } from './family-picker.js';\nexport type { FlowStep } from './flow.js';\nexport type { TuiLaunch, TuiToolLaunch } from './launch.js';\nexport type { McpInstaller } from './services/mcp-installer.js';\nexport type { WizardStore } from './store.js';\nexport type { TuiLaunchChoices } from './tui-state.js';\nexport type { MountedScreens, MountServices } from './harness.js';\n\n/** Run `config` in the TUI; resolves with the exit code. */\nexport async function runTui(\n config: ProgramConfig,\n launch: TuiLaunch,\n): Promise<number> {\n const { runTui: run } = await import('./run.js');\n return run(config, launch);\n}\n\n/** Run a tool's screens; resolves with the exit code, rejects when the TUI cannot start. */\nexport async function runTuiTool(\n toolId: ToolId,\n launch: TuiToolLaunch,\n): Promise<number> {\n const { runTuiTool: run } = await import('./run-tool.js');\n return run(toolId, launch);\n}\n\n/** Pick one of a family's subcommands; resolves with the picked value. */\nexport async function renderFamilyPicker<T>(\n parentLabel: string,\n options: FamilyPickerOption<T>[],\n): Promise<T> {\n const { renderFamilyPicker: render } = await import('./family-picker.js');\n return render(parentLabel, options);\n}\n\n/** Launch the TUI primitives playground; resolves 0 once it closes. */\nexport async function runPlayground(version: string): Promise<number> {\n const { startPlayground } = await import('./playground/start-playground.js');\n return startPlayground(version);\n}\n\n/** A program's TUI screen flow, from the TUI program registry: for walking a flow in tests. */\nexport async function tuiProgramFlow(\n programId: ProgramId,\n): Promise<readonly FlowStep[]> {\n const { getTuiProgram } = await import('./programs/index.js');\n return getTuiProgram(programId).flow;\n}\n\n/** Every screen id the TUI mounts: the core's, the overlays and each program's and tool's own: for checking a table covers them all. */\nexport async function tuiScreenIds(): Promise<string[]> {\n const { tuiScreenIds: ids } = await import('./harness.js');\n return ids();\n}\n\n/** A TUI store for `programId` with no terminal: for walking a flow in tests. */\nexport async function createTuiStore(\n programId: ProgramId,\n): Promise<WizardStore> {\n const { createTuiStore: create } = await import('./harness.js');\n return create(programId);\n}\n\n/** The state only the screens use, as `store` holds it now: for asserting what a commit changed. */\nexport async function readTuiState(store: WizardStore): Promise<TuiState> {\n const { readTuiState: read } = await import('./harness.js');\n return read(store);\n}\n\n/** The real screens `store` shows, on a test terminal that takes the keys a test types: for driving screens by keyboard. */\nexport async function mountScreens(\n store: WizardStore,\n services?: MountServices,\n): Promise<MountedScreens> {\n const { mountScreens: mount } = await import('./harness.js');\n return mount(store, services);\n}\n"],"mappings":";;AAmCA,eAAsB,OACpB,QACA,QACiB;CACjB,MAAM,EAAE,QAAQ,QAAQ,MAAM,OAAO;AACrC,QAAO,IAAI,QAAQ,OAAO;;;AAI5B,eAAsB,WACpB,QACA,QACiB;CACjB,MAAM,EAAE,YAAY,QAAQ,MAAM,OAAO;AACzC,QAAO,IAAI,QAAQ,OAAO;;;AAI5B,eAAsB,mBACpB,aACA,SACY;CACZ,MAAM,EAAE,oBAAoB,WAAW,MAAM,OAAO;AACpD,QAAO,OAAO,aAAa,QAAQ;;;AAIrC,eAAsB,cAAc,SAAkC;CACpE,MAAM,EAAE,oBAAoB,MAAM,OAAO;AACzC,QAAO,gBAAgB,QAAQ"}
@@ -1,14 +1,9 @@
1
- import { n as analytics } from "./analytics-DXK1gc12.js";
2
- import { t as withProgress } from "./telemetry-B7zJdRmA.js";
3
- import "./bounded-fs-vAq-T-K7.js";
4
- import "./setup-utils-B26Lf2yF.js";
5
- import { t as getUI } from "./ui-Q6-RvERF.js";
6
- import "./add-mcp-server-to-clients-DIaTRWMY.js";
1
+ import { n as analytics } from "./analytics-D21z3E5l.js";
2
+ import { t as withProgress } from "./telemetry-CP4rGicd.js";
7
3
  import * as fs$1 from "fs";
8
4
  import * as path$1 from "path";
9
- import "path";
10
- import { execSync as execSync$1, spawn as spawn$1, spawnSync as spawnSync$1 } from "child_process";
11
- //#region src/steps/upload-environment-variables/EnvironmentProvider.ts
5
+ import { execSync, spawn, spawnSync } from "child_process";
6
+ //#region src/programs/posthog-integration/upload-environment-variables/EnvironmentProvider.ts
12
7
  var EnvironmentProvider = class {
13
8
  options;
14
9
  name;
@@ -17,7 +12,7 @@ var EnvironmentProvider = class {
17
12
  }
18
13
  };
19
14
  //#endregion
20
- //#region src/steps/upload-environment-variables/providers/vercel.ts
15
+ //#region src/programs/posthog-integration/upload-environment-variables/providers/vercel.ts
21
16
  var VercelEnvironmentProvider = class extends EnvironmentProvider {
22
17
  name = "Vercel";
23
18
  environments = [
@@ -39,7 +34,7 @@ var VercelEnvironmentProvider = class extends EnvironmentProvider {
39
34
  }
40
35
  hasVercelCli() {
41
36
  try {
42
- execSync$1("vercel --version", { stdio: "ignore" });
37
+ execSync("vercel --version", { stdio: "ignore" });
43
38
  analytics.setTag("vercel-cli-installed", true);
44
39
  return true;
45
40
  } catch {
@@ -53,7 +48,7 @@ var VercelEnvironmentProvider = class extends EnvironmentProvider {
53
48
  return isProjectLinked;
54
49
  }
55
50
  isAuthenticated() {
56
- const result = spawnSync$1("vercel", ["whoami"], {
51
+ const result = spawnSync("vercel", ["whoami"], {
57
52
  encoding: "utf-8",
58
53
  stdio: [
59
54
  "pipe",
@@ -76,7 +71,7 @@ var VercelEnvironmentProvider = class extends EnvironmentProvider {
76
71
  }
77
72
  async uploadEnvironmentVariable(key, value, environment) {
78
73
  await new Promise((resolve, reject) => {
79
- const proc = spawn$1("vercel", [
74
+ const proc = spawn("vercel", [
80
75
  "env",
81
76
  "add",
82
77
  key,
@@ -102,7 +97,7 @@ var VercelEnvironmentProvider = class extends EnvironmentProvider {
102
97
  async uploadEnvVars(vars) {
103
98
  const results = {};
104
99
  for (const [key, value] of Object.entries(vars)) {
105
- const spinner = getUI().spinner();
100
+ const spinner = this.options.runner.spinner();
106
101
  spinner.start(`Uploading ${key} to ${this.name}...`);
107
102
  await Promise.all(this.environments.map((environment) => this.uploadEnvironmentVariable(key, value, environment))).then(() => {
108
103
  spinner.stop(`✅ Uploaded ${key} to ${this.name}`);
@@ -116,9 +111,12 @@ var VercelEnvironmentProvider = class extends EnvironmentProvider {
116
111
  }
117
112
  };
118
113
  //#endregion
119
- //#region src/steps/upload-environment-variables/index.ts
120
- const uploadEnvironmentVariablesStep = async (envVars, { integration, session }) => {
121
- const providers = [new VercelEnvironmentProvider({ installDir: session.installDir })];
114
+ //#region src/programs/posthog-integration/upload-environment-variables/upload-step.ts
115
+ const uploadEnvironmentVariablesStep = async (envVars, { integration, installDir, runner }) => {
116
+ const providers = [new VercelEnvironmentProvider({
117
+ installDir,
118
+ runner
119
+ })];
122
120
  let provider = null;
123
121
  for (const p of providers) if (await p.detect()) {
124
122
  provider = p;
@@ -131,7 +129,7 @@ const uploadEnvironmentVariablesStep = async (envVars, { integration, session })
131
129
  });
132
130
  return [];
133
131
  }
134
- getUI().log.info(`Uploading environment variables to ${provider.name}...`);
132
+ runner.log.info(`Uploading environment variables to ${provider.name}...`);
135
133
  const results = await withProgress("uploading environment variables", async () => {
136
134
  return await provider.uploadEnvVars(envVars);
137
135
  });
@@ -144,4 +142,4 @@ const uploadEnvironmentVariablesStep = async (envVars, { integration, session })
144
142
  //#endregion
145
143
  export { uploadEnvironmentVariablesStep };
146
144
 
147
- //# sourceMappingURL=steps-BPcg3_3Q.js.map
145
+ //# sourceMappingURL=upload-step-CEacB2RV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upload-step-CEacB2RV.js","names":["path","fs"],"sources":["../src/programs/posthog-integration/upload-environment-variables/EnvironmentProvider.ts","../src/programs/posthog-integration/upload-environment-variables/providers/vercel.ts","../src/programs/posthog-integration/upload-environment-variables/upload-step.ts"],"sourcesContent":["import type { RunnerContext } from '../../runner-context';\n\nexport type EnvironmentProviderOptions = {\n installDir: string;\n /** Where the upload reports progress: the running program's runner. */\n runner: Pick<RunnerContext, 'log' | 'spinner'>;\n};\n\nexport abstract class EnvironmentProvider {\n protected options: EnvironmentProviderOptions;\n\n name: string;\n\n constructor(options: EnvironmentProviderOptions) {\n this.options = options;\n }\n\n abstract detect(): Promise<boolean>;\n\n abstract uploadEnvVars(\n vars: Record<string, string>,\n ): Promise<Record<string, boolean>>;\n}\n","import { execSync, spawn, spawnSync } from 'child_process';\nimport {\n EnvironmentProvider,\n type EnvironmentProviderOptions,\n} from '../EnvironmentProvider';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { analytics } from '@utils/analytics';\n\nexport class VercelEnvironmentProvider extends EnvironmentProvider {\n name = 'Vercel';\n environments = ['production', 'preview', 'development'];\n\n constructor(options: EnvironmentProviderOptions) {\n super(options);\n }\n\n // eslint-disable-next-line @typescript-eslint/require-await\n async detect(): Promise<boolean> {\n const vercelDetected =\n this.hasVercelCli() && this.isProjectLinked() && this.isAuthenticated();\n\n analytics.setTag('vercel-detected', vercelDetected);\n\n return vercelDetected;\n }\n\n hasDotVercelDir(): boolean {\n const dotVercelDir = path.join(this.options.installDir, '.vercel');\n return fs.existsSync(dotVercelDir);\n }\n\n hasVercelCli(): boolean {\n try {\n execSync('vercel --version', { stdio: 'ignore' });\n analytics.setTag('vercel-cli-installed', true);\n return true;\n } catch {\n analytics.setTag('vercel-cli-installed', false);\n return false;\n }\n }\n\n isProjectLinked(): boolean {\n const isProjectLinked = fs.existsSync(\n path.join(this.options.installDir, '.vercel', 'project.json'),\n );\n\n analytics.setTag('vercel-project-linked', isProjectLinked);\n\n return isProjectLinked;\n }\n\n isAuthenticated(): boolean {\n const result = spawnSync('vercel', ['whoami'], {\n encoding: 'utf-8',\n stdio: ['pipe', 'pipe', 'pipe'], // suppress prompts\n env: {\n ...process.env,\n FORCE_COLOR: '0', // avoid ANSI formatting\n CI: '1', // hint to CLI that it's a non-interactive env\n },\n });\n\n const output = (\n String(result.stdout) + String(result.stderr)\n ).toLowerCase();\n\n if (\n output.includes('log in to vercel') ||\n output.includes('vercel login') ||\n result.status !== 0\n ) {\n analytics.setTag('vercel-authenticated', false);\n return false;\n }\n\n analytics.setTag('vercel-authenticated', true);\n\n return true;\n }\n\n async uploadEnvironmentVariable(\n key: string,\n value: string,\n environment: string,\n ): Promise<void> {\n await new Promise<void>((resolve, reject) => {\n const proc = spawn('vercel', ['env', 'add', key, environment], {\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n let stderr = '';\n proc.stderr.on('data', (data) => {\n stderr += data.toString();\n });\n\n proc.stdin.write(value);\n proc.stdin.end();\n\n proc.on('close', (code) => {\n if (\n stderr.includes('already exists') ||\n stderr.includes('already been added') ||\n stderr.includes('vercel env rm')\n ) {\n reject(\n new Error(\n `❌ Environment variable ${key} already exists in ${this.name}. Please upload it manually.`,\n ),\n );\n } else if (code === 0) {\n resolve();\n } else {\n reject(\n new Error(\n `❌ Failed to upload environment variable ${key} to ${this.name}. Please upload it manually.`,\n ),\n );\n }\n });\n });\n }\n\n async uploadEnvVars(\n vars: Record<string, string>,\n ): Promise<Record<string, boolean>> {\n const results: Record<string, boolean> = {};\n\n for (const [key, value] of Object.entries(vars)) {\n const spinner = this.options.runner.spinner();\n\n spinner.start(`Uploading ${key} to ${this.name}...`);\n await Promise.all(\n this.environments.map((environment) =>\n this.uploadEnvironmentVariable(key, value, environment),\n ),\n )\n .then(() => {\n spinner.stop(`✅ Uploaded ${key} to ${this.name}`);\n results[key] = true;\n })\n .catch((err) => {\n spinner.stop(\n err instanceof Error\n ? err.message\n : `❌ Failed to upload environment variables to ${this.name}. Please upload it manually.`,\n );\n results[key] = false;\n });\n }\n\n return results;\n }\n}\n","import type { Integration } from '@shared/constants';\nimport { withProgress } from '@utils/telemetry';\nimport { analytics } from '@utils/analytics';\nimport type { RunnerContext } from '../../runner-context';\nimport { EnvironmentProvider } from './EnvironmentProvider';\nimport { VercelEnvironmentProvider } from './providers/vercel';\n\nexport const uploadEnvironmentVariablesStep = async (\n envVars: Record<string, string>,\n {\n integration,\n installDir,\n runner,\n }: {\n integration: Integration;\n installDir: string;\n runner: Pick<RunnerContext, 'log' | 'spinner'>;\n },\n): Promise<string[]> => {\n const providers: EnvironmentProvider[] = [\n new VercelEnvironmentProvider({ installDir, runner }),\n ];\n\n let provider: EnvironmentProvider | null = null;\n\n for (const p of providers) {\n if (await p.detect()) {\n provider = p;\n break;\n }\n }\n\n if (!provider) {\n analytics.wizardCapture('env upload skipped', {\n reason: 'no environment provider found',\n integration,\n });\n return [];\n }\n\n // Auto-accept — the agent already wrote env vars via MCP tools\n runner.log.info(`Uploading environment variables to ${provider.name}...`);\n\n const results = await withProgress(\n 'uploading environment variables',\n async () => {\n return await provider.uploadEnvVars(envVars);\n },\n );\n\n analytics.wizardCapture('env uploaded', {\n provider: provider.name,\n integration,\n });\n\n return Object.keys(results).filter((key) => results[key]);\n};\n"],"mappings":";;;;;;AAQA,IAAsB,sBAAtB,MAA0C;CACxC;CAEA;CAEA,YAAY,SAAqC;AAC/C,OAAK,UAAU;;;;;ACLnB,IAAa,4BAAb,cAA+C,oBAAoB;CACjE,OAAO;CACP,eAAe;EAAC;EAAc;EAAW;EAAc;CAEvD,YAAY,SAAqC;AAC/C,QAAM,QAAQ;;CAIhB,MAAM,SAA2B;EAC/B,MAAM,iBACJ,KAAK,cAAc,IAAI,KAAK,iBAAiB,IAAI,KAAK,iBAAiB;AAEzE,YAAU,OAAO,mBAAmB,eAAe;AAEnD,SAAO;;CAGT,kBAA2B;EACzB,MAAM,eAAeA,OAAK,KAAK,KAAK,QAAQ,YAAY,UAAU;AAClE,SAAOC,KAAG,WAAW,aAAa;;CAGpC,eAAwB;AACtB,MAAI;AACF,YAAS,oBAAoB,EAAE,OAAO,UAAU,CAAC;AACjD,aAAU,OAAO,wBAAwB,KAAK;AAC9C,UAAO;UACD;AACN,aAAU,OAAO,wBAAwB,MAAM;AAC/C,UAAO;;;CAIX,kBAA2B;EACzB,MAAM,kBAAkBA,KAAG,WACzBD,OAAK,KAAK,KAAK,QAAQ,YAAY,WAAW,eAAe,CAC9D;AAED,YAAU,OAAO,yBAAyB,gBAAgB;AAE1D,SAAO;;CAGT,kBAA2B;EACzB,MAAM,SAAS,UAAU,UAAU,CAAC,SAAS,EAAE;GAC7C,UAAU;GACV,OAAO;IAAC;IAAQ;IAAQ;IAAO;GAC/B,KAAK;IACH,GAAG,QAAQ;IACX,aAAa;IACb,IAAI;IACL;GACF,CAAC;EAEF,MAAM,UACJ,OAAO,OAAO,OAAO,GAAG,OAAO,OAAO,OAAO,EAC7C,aAAa;AAEf,MACE,OAAO,SAAS,mBAAmB,IACnC,OAAO,SAAS,eAAe,IAC/B,OAAO,WAAW,GAClB;AACA,aAAU,OAAO,wBAAwB,MAAM;AAC/C,UAAO;;AAGT,YAAU,OAAO,wBAAwB,KAAK;AAE9C,SAAO;;CAGT,MAAM,0BACJ,KACA,OACA,aACe;AACf,QAAM,IAAI,SAAe,SAAS,WAAW;GAC3C,MAAM,OAAO,MAAM,UAAU;IAAC;IAAO;IAAO;IAAK;IAAY,EAAE,EAC7D,OAAO;IAAC;IAAQ;IAAQ;IAAO,EAChC,CAAC;GAEF,IAAI,SAAS;AACb,QAAK,OAAO,GAAG,SAAS,SAAS;AAC/B,cAAU,KAAK,UAAU;KACzB;AAEF,QAAK,MAAM,MAAM,MAAM;AACvB,QAAK,MAAM,KAAK;AAEhB,QAAK,GAAG,UAAU,SAAS;AACzB,QACE,OAAO,SAAS,iBAAiB,IACjC,OAAO,SAAS,qBAAqB,IACrC,OAAO,SAAS,gBAAgB,CAEhC,wBACE,IAAI,MACF,0BAA0B,IAAI,qBAAqB,KAAK,KAAK,8BAC9D,CACF;aACQ,SAAS,EAClB,UAAS;QAET,wBACE,IAAI,MACF,2CAA2C,IAAI,MAAM,KAAK,KAAK,8BAChE,CACF;KAEH;IACF;;CAGJ,MAAM,cACJ,MACkC;EAClC,MAAM,UAAmC,EAAE;AAE3C,OAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,KAAK,EAAE;GAC/C,MAAM,UAAU,KAAK,QAAQ,OAAO,SAAS;AAE7C,WAAQ,MAAM,aAAa,IAAI,MAAM,KAAK,KAAK,KAAK;AACpD,SAAM,QAAQ,IACZ,KAAK,aAAa,KAAK,gBACrB,KAAK,0BAA0B,KAAK,OAAO,YAAY,CACxD,CACF,CACE,WAAW;AACV,YAAQ,KAAK,cAAc,IAAI,MAAM,KAAK,OAAO;AACjD,YAAQ,OAAO;KACf,CACD,OAAO,QAAQ;AACd,YAAQ,KACN,eAAe,QACX,IAAI,UACJ,+CAA+C,KAAK,KAAK,8BAC9D;AACD,YAAQ,OAAO;KACf;;AAGN,SAAO;;;;;ACjJX,MAAa,iCAAiC,OAC5C,SACA,EACE,aACA,YACA,aAMoB;CACtB,MAAM,YAAmC,CACvC,IAAI,0BAA0B;EAAE;EAAY;EAAQ,CAAC,CACtD;CAED,IAAI,WAAuC;AAE3C,MAAK,MAAM,KAAK,UACd,KAAI,MAAM,EAAE,QAAQ,EAAE;AACpB,aAAW;AACX;;AAIJ,KAAI,CAAC,UAAU;AACb,YAAU,cAAc,sBAAsB;GAC5C,QAAQ;GACR;GACD,CAAC;AACF,SAAO,EAAE;;AAIX,QAAO,IAAI,KAAK,sCAAsC,SAAS,KAAK,KAAK;CAEzE,MAAM,UAAU,MAAM,aACpB,mCACA,YAAY;AACV,SAAO,MAAM,SAAS,cAAc,QAAQ;GAE/C;AAED,WAAU,cAAc,gBAAgB;EACtC,UAAU,SAAS;EACnB;EACD,CAAC;AAEF,QAAO,OAAO,KAAK,QAAQ,CAAC,QAAQ,QAAQ,QAAQ,KAAK"}
@@ -0,0 +1,67 @@
1
+ import { nt as WIZARD_USER_AGENT } from "./analytics-D21z3E5l.js";
2
+ import axios from "axios";
3
+ //#region src/shared/utils/urls.ts
4
+ /**
5
+ * Resolve a pinned PostHog base URL from an optional override. When present, it
6
+ * becomes the single source of truth for every PostHog origin — the
7
+ * API/ingestion host, the cloud/app URL, and the OAuth server — bypassing
8
+ * region resolution entirely.
9
+ *
10
+ * The override lives on the session (`session.baseUrl`, set by `--base-url`) and
11
+ * is threaded in by callers, so there is no hidden module-level state. A `--base-url`
12
+ * value wins; otherwise a dev/test build implies `localhost:8010`; otherwise the
13
+ * result is `undefined`, meaning region-based resolution applies.
14
+ *
15
+ * This is the runtime equivalent of the `IS_DEV` localhost routing: `IS_DEV` is a
16
+ * build-time constant that tsdown compiles out of production builds, so it can't
17
+ * point a shipped wizard at a local stack — `--base-url` can. Both feed this one
18
+ * resolver so every URL helper only asks the question once.
19
+ */
20
+ const resolveBaseUrl = (override) => {
21
+ return override?.trim() || void 0;
22
+ };
23
+ const getUiHostFromHost = (host) => {
24
+ if (host.includes("us.i.posthog.com")) return "https://us.posthog.com";
25
+ if (host.includes("eu.i.posthog.com")) return "https://eu.posthog.com";
26
+ return host;
27
+ };
28
+ const getHost = (region, baseUrl) => {
29
+ const override = resolveBaseUrl(baseUrl);
30
+ if (override) return override;
31
+ if (region === "eu") return "https://eu.i.posthog.com";
32
+ return "https://us.i.posthog.com";
33
+ };
34
+ const getCloudUrl = (region, baseUrl) => {
35
+ const override = resolveBaseUrl(baseUrl);
36
+ if (override) return override;
37
+ if (region === "eu") return "https://eu.posthog.com";
38
+ return "https://us.posthog.com";
39
+ };
40
+ async function detectRegion(accessToken, baseUrl) {
41
+ if (resolveBaseUrl(baseUrl)) return "us";
42
+ const headers = {
43
+ Authorization: `Bearer ${accessToken}`,
44
+ "User-Agent": WIZARD_USER_AGENT
45
+ };
46
+ const [usResult, euResult] = await Promise.allSettled([axios.get("https://us.posthog.com/api/users/@me/", { headers }), axios.get("https://eu.posthog.com/api/users/@me/", { headers })]);
47
+ if (usResult.status === "fulfilled") return "us";
48
+ if (euResult.status === "fulfilled") return "eu";
49
+ throw new Error("Could not determine cloud region from access token. Please check your PostHog account.");
50
+ }
51
+ /** Region-agnostic prod OAuth server. Resolves to the right region server-side. */
52
+ const PROD_OAUTH_URL = "https://oauth.posthog.com";
53
+ /**
54
+ * OAuth server URL. Follows the base-URL override (and thus IS_DEV → localhost),
55
+ * otherwise the region-agnostic prod OAuth host.
56
+ */
57
+ const getOAuthUrl = (baseUrl) => resolveBaseUrl(baseUrl) ?? PROD_OAUTH_URL;
58
+ /**
59
+ * One-click integration install/authorize deep-link. Opening it in the user's
60
+ * logged-in browser runs the install directly — no settings-page hunting. The
61
+ * one link covers fresh install, link-existing, and re-auth.
62
+ */
63
+ const getIntegrationAuthorizeUrl = (appHost, projectId, kind) => `${appHost.replace(/\/$/, "")}/api/environments/${projectId}/integrations/authorize?kind=${kind}`;
64
+ //#endregion
65
+ export { getOAuthUrl as a, getIntegrationAuthorizeUrl as i, getCloudUrl as n, getUiHostFromHost as o, getHost as r, resolveBaseUrl as s, detectRegion as t };
66
+
67
+ //# sourceMappingURL=urls-BDELGZHq.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"urls-BDELGZHq.js","names":[],"sources":["../src/shared/utils/urls.ts"],"sourcesContent":["import axios from 'axios';\nimport { IS_DEV, WIZARD_USER_AGENT } from '@shared/constants';\nimport type { CloudRegion } from './types';\n\n/**\n * Resolve a pinned PostHog base URL from an optional override. When present, it\n * becomes the single source of truth for every PostHog origin — the\n * API/ingestion host, the cloud/app URL, and the OAuth server — bypassing\n * region resolution entirely.\n *\n * The override lives on the session (`session.baseUrl`, set by `--base-url`) and\n * is threaded in by callers, so there is no hidden module-level state. A `--base-url`\n * value wins; otherwise a dev/test build implies `localhost:8010`; otherwise the\n * result is `undefined`, meaning region-based resolution applies.\n *\n * This is the runtime equivalent of the `IS_DEV` localhost routing: `IS_DEV` is a\n * build-time constant that tsdown compiles out of production builds, so it can't\n * point a shipped wizard at a local stack — `--base-url` can. Both feed this one\n * resolver so every URL helper only asks the question once.\n */\nexport const resolveBaseUrl = (override?: string): string | undefined => {\n return override?.trim() || (IS_DEV ? 'http://localhost:8010' : undefined);\n};\n\nexport const getUiHostFromHost = (host: string) => {\n if (host.includes('us.i.posthog.com')) {\n return 'https://us.posthog.com';\n }\n\n if (host.includes('eu.i.posthog.com')) {\n return 'https://eu.posthog.com';\n }\n\n return host;\n};\n\nexport const getHost = (region: CloudRegion, baseUrl?: string) => {\n const override = resolveBaseUrl(baseUrl);\n if (override) {\n return override;\n }\n\n if (region === 'eu') {\n return 'https://eu.i.posthog.com';\n }\n\n return 'https://us.i.posthog.com';\n};\n\nexport const getCloudUrl = (region: CloudRegion, baseUrl?: string) => {\n const override = resolveBaseUrl(baseUrl);\n if (override) {\n return override;\n }\n\n if (region === 'eu') {\n return 'https://eu.posthog.com';\n }\n\n return 'https://us.posthog.com';\n};\n\nexport async function detectRegion(\n accessToken: string,\n baseUrl?: string,\n): Promise<CloudRegion> {\n // With a pinned base URL there is only one instance to talk to — skip the\n // us/eu probe and default the region label to 'us'. (Covers IS_DEV too, via\n // resolveBaseUrl.) The URLs themselves come from the override, not this label.\n if (resolveBaseUrl(baseUrl)) {\n return 'us';\n }\n\n const headers = {\n Authorization: `Bearer ${accessToken}`,\n 'User-Agent': WIZARD_USER_AGENT,\n };\n\n const [usResult, euResult] = await Promise.allSettled([\n axios.get('https://us.posthog.com/api/users/@me/', { headers }),\n axios.get('https://eu.posthog.com/api/users/@me/', { headers }),\n ]);\n\n if (usResult.status === 'fulfilled') return 'us';\n if (euResult.status === 'fulfilled') return 'eu';\n\n throw new Error(\n 'Could not determine cloud region from access token. Please check your PostHog account.',\n );\n}\n\n/** Region-agnostic prod OAuth server. Resolves to the right region server-side. */\nconst PROD_OAUTH_URL = 'https://oauth.posthog.com';\n\n/**\n * OAuth server URL. Follows the base-URL override (and thus IS_DEV → localhost),\n * otherwise the region-agnostic prod OAuth host.\n */\nexport const getOAuthUrl = (baseUrl?: string): string =>\n resolveBaseUrl(baseUrl) ?? PROD_OAUTH_URL;\n\n/**\n * One-click integration install/authorize deep-link. Opening it in the user's\n * logged-in browser runs the install directly — no settings-page hunting. The\n * one link covers fresh install, link-existing, and re-auth.\n */\nexport const getIntegrationAuthorizeUrl = (\n appHost: string,\n projectId: number,\n kind: string,\n): string =>\n `${appHost.replace(\n /\\/$/,\n '',\n )}/api/environments/${projectId}/integrations/authorize?kind=${kind}`;\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAoBA,MAAa,kBAAkB,aAA0C;AACvE,QAAO,UAAU,MAAM,IAAwC,KAAA;;AAGjE,MAAa,qBAAqB,SAAiB;AACjD,KAAI,KAAK,SAAS,mBAAmB,CACnC,QAAO;AAGT,KAAI,KAAK,SAAS,mBAAmB,CACnC,QAAO;AAGT,QAAO;;AAGT,MAAa,WAAW,QAAqB,YAAqB;CAChE,MAAM,WAAW,eAAe,QAAQ;AACxC,KAAI,SACF,QAAO;AAGT,KAAI,WAAW,KACb,QAAO;AAGT,QAAO;;AAGT,MAAa,eAAe,QAAqB,YAAqB;CACpE,MAAM,WAAW,eAAe,QAAQ;AACxC,KAAI,SACF,QAAO;AAGT,KAAI,WAAW,KACb,QAAO;AAGT,QAAO;;AAGT,eAAsB,aACpB,aACA,SACsB;AAItB,KAAI,eAAe,QAAQ,CACzB,QAAO;CAGT,MAAM,UAAU;EACd,eAAe,UAAU;EACzB,cAAc;EACf;CAED,MAAM,CAAC,UAAU,YAAY,MAAM,QAAQ,WAAW,CACpD,MAAM,IAAI,yCAAyC,EAAE,SAAS,CAAC,EAC/D,MAAM,IAAI,yCAAyC,EAAE,SAAS,CAAC,CAChE,CAAC;AAEF,KAAI,SAAS,WAAW,YAAa,QAAO;AAC5C,KAAI,SAAS,WAAW,YAAa,QAAO;AAE5C,OAAM,IAAI,MACR,yFACD;;;AAIH,MAAM,iBAAiB;;;;;AAMvB,MAAa,eAAe,YAC1B,eAAe,QAAQ,IAAI;;;;;;AAO7B,MAAa,8BACX,SACA,WACA,SAEA,GAAG,QAAQ,QACT,OACA,GACD,CAAC,oBAAoB,UAAU,+BAA+B"}
@@ -11,8 +11,7 @@ import { scan, CATEGORIES, type Category } from '@posthog/warlock';
11
11
  import fs from 'fs';
12
12
  import os from 'os';
13
13
  import path from 'path';
14
- import { scanVerdict } from '@agent/yara-policy';
15
- import { scanInstalledSkill } from '@agent/yara-hooks';
14
+ import { scanVerdict, scanInstalledSkill } from '@agent';
16
15
 
17
16
  // Assembled at runtime so no scannable secret literal is committed.
18
17
  const fakeStripeKey = 'sk_' + 'live_' + '5'.repeat(24);
@@ -1,20 +1,41 @@
1
- import { t as emitWizardError } from "./emit-BSetXzDV.js";
2
- import { s as logToFile } from "./debug-kAHwWGg7.js";
3
- import "./wizard-session-2w4Ru-Wz.js";
4
- import { n as analytics } from "./analytics-DXK1gc12.js";
5
- import { a as WizardError, n as sanitizeErrorDetail } from "./errors-C2domSkK.js";
6
- import { t as LoggingUI } from "./logging-ui-Dza4D0MK.js";
7
- import { t as getUI } from "./ui-Q6-RvERF.js";
8
- //#region src/shared/utils/wizard-abort.ts
1
+ import { o as logToFile } from "./debug-BfQPD2Hg.js";
2
+ import { n as analytics } from "./analytics-D21z3E5l.js";
3
+ import { a as WizardError } from "./errors-CHrJzAZb.js";
4
+ import { m as runCleanups } from "./agent-interface-CemBvTAA.js";
5
+ //#region src/host/wizard-abort.ts
9
6
  /**
10
7
  * Single exit point for the wizard. Use instead of process.exit() directly.
11
8
  *
12
- * Sequence: cleanup -> error capture (optional) -> analytics shutdown -> outro -> process.exit
9
+ * Sequence: cleanup -> error capture (optional) -> analytics shutdown -> outro -> the host's exit
13
10
  *
14
- * WizardError (from `@lib/errors`) is a data carrier passed to wizardAbort() for analytics context, never thrown.
15
- * The legacy abort() in setup-utils.ts delegates here.
11
+ * WizardError (from `@shared/errors`) is a data carrier passed to wizardAbort() for analytics context, never thrown.
16
12
  */
17
- const cleanupFns = [];
13
+ /** Start a host's exit; the abort that ends it is handed this exit. */
14
+ function startHostExit() {
15
+ let resolve;
16
+ let reject;
17
+ const exited = new Promise((res, rej) => {
18
+ resolve = res;
19
+ reject = rej;
20
+ });
21
+ let ended = false;
22
+ return {
23
+ exited,
24
+ end(code) {
25
+ if (ended) return;
26
+ ended = true;
27
+ resolve(code);
28
+ },
29
+ fail(error) {
30
+ if (ended) return;
31
+ ended = true;
32
+ reject(error);
33
+ },
34
+ get ended() {
35
+ return ended;
36
+ }
37
+ };
38
+ }
18
39
  const shutdownFns = /* @__PURE__ */ new Set();
19
40
  function registerShutdown(fn) {
20
41
  shutdownFns.add(fn);
@@ -22,21 +43,11 @@ function registerShutdown(fn) {
22
43
  shutdownFns.delete(fn);
23
44
  };
24
45
  }
25
- function registerCleanup(fn) {
26
- cleanupFns.push(fn);
27
- }
28
- /** Runs all registered cleanup functions and drains the array. */
29
- function runCleanups() {
30
- const fns = cleanupFns.splice(0);
31
- for (const fn of fns) try {
32
- fn();
33
- } catch {}
34
- }
35
46
  function resolveErrorCode(options, error) {
36
47
  if (options.code) return options.code;
37
48
  if (error instanceof WizardError) return error.code;
38
49
  }
39
- async function wizardAbort(options) {
50
+ async function wizardAbort(host, options) {
40
51
  const { message = "Wizard setup cancelled.", outroData, error, exitCode = 1 } = options ?? {};
41
52
  const code = resolveErrorCode(options ?? {}, error);
42
53
  const detail = options?.detail;
@@ -51,7 +62,6 @@ async function wizardAbort(options) {
51
62
  ...code ? { error_code: code } : {}
52
63
  });
53
64
  await analytics.shutdown(status);
54
- const ui = getUI();
55
65
  const resolvedOutroData = outroData ?? {
56
66
  kind: "error",
57
67
  message
@@ -60,16 +70,15 @@ async function wizardAbort(options) {
60
70
  resolvedOutroData.errorCode ??= code;
61
71
  if (detail) resolvedOutroData.errorDetail ??= detail;
62
72
  }
63
- ui.outroError(resolvedOutroData);
64
- await ui.waitForOutroDismissed();
65
- if (code && ui instanceof LoggingUI) emitWizardError({
73
+ await host.present(resolvedOutroData, {
66
74
  code,
67
- message: resolvedOutroData.message ?? message,
68
- detail: sanitizeErrorDetail(resolvedOutroData.errorDetail ?? detail)
75
+ message,
76
+ detail
69
77
  });
70
- return process.exit(exitCode);
78
+ host.exit.end(exitCode);
79
+ return new Promise(() => void 0);
71
80
  }
72
81
  //#endregion
73
- export { wizardAbort as i, registerShutdown as n, runCleanups as r, registerCleanup as t };
82
+ export { startHostExit as n, wizardAbort as r, registerShutdown as t };
74
83
 
75
- //# sourceMappingURL=wizard-abort-BPdv07np.js.map
84
+ //# sourceMappingURL=wizard-abort-D3-75KyV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wizard-abort-D3-75KyV.js","names":[],"sources":["../src/host/wizard-abort.ts"],"sourcesContent":["/**\n * Single exit point for the wizard. Use instead of process.exit() directly.\n *\n * Sequence: cleanup -> error capture (optional) -> analytics shutdown -> outro -> the host's exit\n *\n * WizardError (from `@shared/errors`) is a data carrier passed to wizardAbort() for analytics context, never thrown.\n */\nimport { analytics } from '@utils/analytics';\nimport { logToFile } from '@utils/debug';\nimport { OutroKind, type OutroData } from '@shared/outro';\nimport type { ErrorCode } from '@shared/errors';\nimport { WizardError } from '@shared/errors';\nimport { clearCleanups, runCleanups } from '@utils/cleanup';\n\nexport interface WizardAbortOptions {\n message?: string;\n /** Structured error data for the outro; built from `message` when absent. */\n outroData?: OutroData;\n error?: Error | WizardError;\n exitCode?: number;\n code?: ErrorCode;\n detail?: Record<string, unknown>;\n /** Terminal analytics status. Defaults from whether `error` is set. */\n status?: 'error' | 'cancelled';\n}\n\n/**\n * Shows an abort's outro, waits for the user to dismiss it, and emits the\n * machine-readable error line where the host calls for one. Each caller passes\n * its host's presenter and exit to `wizardAbort`, so nothing looks either up.\n */\nexport type AbortPresenter = (\n outro: OutroData,\n report: {\n code?: ErrorCode;\n message: string;\n detail?: Record<string, unknown>;\n },\n) => Promise<void>;\n\n/** A host's end: the first `end` or `fail` wins, and `exited` settles with it. */\nexport interface HostExit {\n readonly exited: Promise<number>;\n end(code: number): void;\n fail(error: unknown): void;\n readonly ended: boolean;\n}\n\n/** What `wizardAbort` ends: how the host shows the outro, and the exit that takes the code. */\nexport interface AbortHost {\n present: AbortPresenter;\n exit: Pick<HostExit, 'end'>;\n}\n\n/** Start a host's exit; the abort that ends it is handed this exit. */\nexport function startHostExit(): HostExit {\n let resolve!: (code: number) => void;\n let reject!: (error: unknown) => void;\n const exited = new Promise<number>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n let ended = false;\n const exit: HostExit = {\n exited,\n end(code) {\n if (ended) return;\n ended = true;\n resolve(code);\n },\n fail(error) {\n if (ended) return;\n ended = true;\n reject(error);\n },\n get ended() {\n return ended;\n },\n };\n return exit;\n}\n\nconst shutdownFns = new Set<\n (outcome: 'failed' | 'cancelled') => Promise<void>\n>();\n\nexport function registerShutdown(\n fn: (outcome: 'failed' | 'cancelled') => Promise<void>,\n): () => void {\n shutdownFns.add(fn);\n return () => {\n shutdownFns.delete(fn);\n };\n}\n\nexport function clearCleanup(): void {\n clearCleanups();\n shutdownFns.clear();\n}\n\nfunction resolveErrorCode(\n options: WizardAbortOptions,\n error: Error | WizardError | undefined,\n): ErrorCode | undefined {\n if (options.code) return options.code;\n if (error instanceof WizardError) return error.code;\n return undefined;\n}\n\nexport async function wizardAbort(\n host: AbortHost,\n options?: WizardAbortOptions,\n): Promise<never> {\n const {\n message = 'Wizard setup cancelled.',\n outroData,\n error,\n exitCode = 1,\n } = options ?? {};\n\n const code = resolveErrorCode(options ?? {}, error);\n const detail = options?.detail;\n\n logToFile(\n `[wizard-abort] exitCode=${exitCode}, code=${\n code ?? 'none'\n }, message: ${message}`,\n );\n if (error) {\n logToFile('[wizard-abort] error:', error);\n }\n\n // 1. Run registered cleanup functions\n runCleanups();\n const status = options?.status ?? (error ? 'error' : 'cancelled');\n await Promise.allSettled(\n [...shutdownFns].map((fn) =>\n fn(status === 'cancelled' ? 'cancelled' : 'failed'),\n ),\n );\n\n // 2. Capture error in analytics. An 'error' ending with no Error object\n // is captured as its code and message.\n const captured =\n error ??\n (status === 'error'\n ? new WizardError(message, undefined, code)\n : undefined);\n if (captured) {\n analytics.captureException(captured, {\n ...((captured instanceof WizardError && captured.context) || {}),\n ...(code ? { error_code: code } : {}),\n });\n }\n\n // 3. Shutdown analytics\n await analytics.shutdown(status);\n\n // 4. Show the error outro through the host's presenter. Synthesize OutroData\n // from `message` when the caller didn't provide structured data.\n const resolvedOutroData: OutroData = outroData ?? {\n kind: OutroKind.Error,\n message,\n };\n if (code && resolvedOutroData.kind === OutroKind.Error) {\n resolvedOutroData.errorCode ??= code;\n if (detail) resolvedOutroData.errorDetail ??= detail;\n }\n await host.present(resolvedOutroData, { code, message, detail });\n\n // 5. Hand the code to the host and never settle, so nothing after an abort runs.\n host.exit.end(exitCode);\n return new Promise<never>(() => undefined);\n}\n"],"mappings":";;;;;;;;;;;;;AAuDA,SAAgB,gBAA0B;CACxC,IAAI;CACJ,IAAI;CACJ,MAAM,SAAS,IAAI,SAAiB,KAAK,QAAQ;AAC/C,YAAU;AACV,WAAS;GACT;CACF,IAAI,QAAQ;AAiBZ,QAhBuB;EACrB;EACA,IAAI,MAAM;AACR,OAAI,MAAO;AACX,WAAQ;AACR,WAAQ,KAAK;;EAEf,KAAK,OAAO;AACV,OAAI,MAAO;AACX,WAAQ;AACR,UAAO,MAAM;;EAEf,IAAI,QAAQ;AACV,UAAO;;EAEV;;AAIH,MAAM,8BAAc,IAAI,KAErB;AAEH,SAAgB,iBACd,IACY;AACZ,aAAY,IAAI,GAAG;AACnB,cAAa;AACX,cAAY,OAAO,GAAG;;;AAS1B,SAAS,iBACP,SACA,OACuB;AACvB,KAAI,QAAQ,KAAM,QAAO,QAAQ;AACjC,KAAI,iBAAiB,YAAa,QAAO,MAAM;;AAIjD,eAAsB,YACpB,MACA,SACgB;CAChB,MAAM,EACJ,UAAU,2BACV,WACA,OACA,WAAW,MACT,WAAW,EAAE;CAEjB,MAAM,OAAO,iBAAiB,WAAW,EAAE,EAAE,MAAM;CACnD,MAAM,SAAS,SAAS;AAExB,WACE,2BAA2B,SAAS,SAClC,QAAQ,OACT,aAAa,UACf;AACD,KAAI,MACF,WAAU,yBAAyB,MAAM;AAI3C,cAAa;CACb,MAAM,SAAS,SAAS,WAAW,QAAQ,UAAU;AACrD,OAAM,QAAQ,WACZ,CAAC,GAAG,YAAY,CAAC,KAAK,OACpB,GAAG,WAAW,cAAc,cAAc,SAAS,CACpD,CACF;CAID,MAAM,WACJ,UACC,WAAW,UACR,IAAI,YAAY,SAAS,KAAA,GAAW,KAAK,GACzC,KAAA;AACN,KAAI,SACF,WAAU,iBAAiB,UAAU;EACnC,GAAK,oBAAoB,eAAe,SAAS,WAAY,EAAE;EAC/D,GAAI,OAAO,EAAE,YAAY,MAAM,GAAG,EAAE;EACrC,CAAC;AAIJ,OAAM,UAAU,SAAS,OAAO;CAIhC,MAAM,oBAA+B,aAAa;EAChD,MAAA;EACA;EACD;AACD,KAAI,QAAQ,kBAAkB,SAAA,SAA0B;AACtD,oBAAkB,cAAc;AAChC,MAAI,OAAQ,mBAAkB,gBAAgB;;AAEhD,OAAM,KAAK,QAAQ,mBAAmB;EAAE;EAAM;EAAS;EAAQ,CAAC;AAGhE,MAAK,KAAK,IAAI,SAAS;AACvB,QAAO,IAAI,cAAqB,KAAA,EAAU"}
@@ -0,0 +1,2 @@
1
+ import { l as prewarmYaraScanner, p as scanInstalledSkill } from "./yara-hooks-D8YDyX7o.js";
2
+ export { prewarmYaraScanner, scanInstalledSkill };