@posthog/wizard 2.80.0 → 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-m4CCPX4f.js → PickerMenu-BGGeYqd-.js} +104 -4
  3. package/dist/PickerMenu-BGGeYqd-.js.map +1 -0
  4. package/dist/README.md +9 -6
  5. package/dist/{agent-interface-CzyCmp7q.js → agent-interface-CemBvTAA.js} +115 -346
  6. package/dist/agent-interface-CemBvTAA.js.map +1 -0
  7. package/dist/{agent-prompt-loader-4wMxlYSX.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-C3Dc4LFl.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-CC_NDtoP.js → bounded-fs-CAsuF6al.js} +3 -3
  21. package/dist/{bounded-fs-CC_NDtoP.js.map → bounded-fs-CAsuF6al.js.map} +1 -1
  22. package/dist/{ci-install-DfcAMhlu.js → ci-install-CEYE02t-.js} +21 -25
  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-DyARf5TF.js → debug-BfQPD2Hg.js} +18 -52
  27. package/dist/debug-BfQPD2Hg.js.map +1 -0
  28. package/dist/{defaults-DpfMnH2q.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-BmjYUSua.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-DVSb7kXb.js → host-resolution-D8GhEVoX.js} +4 -4
  42. package/dist/{host-resolution-DVSb7kXb.js.map → host-resolution-D8GhEVoX.js.map} +1 -1
  43. package/dist/install-Bw8tvDvS.js +2 -0
  44. package/dist/{install-Bk5TNk27.js → install-paPCzPHI.js} +26 -93
  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/{links-9LWZPSCq.js → links-Cyj6v8kg.js} +3 -3
  49. package/dist/{links-9LWZPSCq.js.map → links-Cyj6v8kg.js.map} +1 -1
  50. package/dist/{main-DKPjFHEV.js → main-0p-YxUNa.js} +204 -469
  51. package/dist/main-0p-YxUNa.js.map +1 -0
  52. package/dist/{mcp-Co8VRF62.js → mcp-D3Z5MXhA.js} +3 -4
  53. package/dist/{mcp-Co8VRF62.js.map → mcp-D3Z5MXhA.js.map} +1 -1
  54. package/dist/mcp-install-smoke-test.ts +2 -2
  55. package/dist/{mcp-prompt-streaming-ljCVoQ9I.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-Dba8ITeo.js → models-D1SnCzvl.js} +2 -2
  60. package/dist/{models-Dba8ITeo.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-D-RfcVmr.js → oauth-session-Dde79Ycm.js} +3 -3
  64. package/dist/{oauth-session-D-RfcVmr.js.map → oauth-session-Dde79Ycm.js.map} +1 -1
  65. package/dist/{orchestrator-tools-CVJ1F9Ub.js → orchestrator-tools-BSNhzzkT.js} +3 -3
  66. package/dist/{orchestrator-tools-CVJ1F9Ub.js.map → orchestrator-tools-BSNhzzkT.js.map} +1 -1
  67. package/dist/{package-json-Cowya9-3.js → package-json-2UrhE6kP.js} +1 -1
  68. package/dist/{package-json-Cowya9-3.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-B5YTBRDv.js → pi-cM_4Gd_9.js} +16 -18
  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-CLhuKqXH.js → provisioning-JbJtq7hq.js} +4 -5
  83. package/dist/{provisioning-CLhuKqXH.js.map → provisioning-JbJtq7hq.js.map} +1 -1
  84. package/dist/{queue-tools-knnPQP0e.js → queue-tools-BIZSJyt6.js} +6 -8
  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-BvdSFDuM.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-BLsCfHmQ.js → start-playground-DL4mVEUx.js} +43 -34
  103. package/dist/start-playground-DL4mVEUx.js.map +1 -0
  104. package/dist/{subagent-D_Sqak94.js → subagent-CnFvAq6E.js} +3 -3
  105. package/dist/{subagent-D_Sqak94.js.map → subagent-CnFvAq6E.js.map} +1 -1
  106. package/dist/{task-DiTI6Sak.js → task-BOScSm4W.js} +16 -17
  107. package/dist/task-BOScSm4W.js.map +1 -0
  108. package/dist/{tasks-ChZ_F1YP.js → tasks-BfJhVky2.js} +1 -1
  109. package/dist/tasks-BfJhVky2.js.map +1 -0
  110. package/dist/{telemetry-BNKsDxNS.js → telemetry-CP4rGicd.js} +2 -2
  111. package/dist/{telemetry-BNKsDxNS.js.map → telemetry-CP4rGicd.js.map} +1 -1
  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-C8LQ8QFz.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-Hc28zVc_.js → upload-step-CEacB2RV.js} +14 -16
  122. package/dist/upload-step-CEacB2RV.js.map +1 -0
  123. package/dist/{urls-BI4kJ4qQ.js → urls-BDELGZHq.js} +2 -2
  124. package/dist/{urls-BI4kJ4qQ.js.map → urls-BDELGZHq.js.map} +1 -1
  125. package/dist/warlock-smoke-test.ts +1 -2
  126. package/dist/{wizard-abort-DBKtfnBR.js → wizard-abort-D3-75KyV.js} +40 -33
  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-C3L6lBij.js → yara-hooks-D8YDyX7o.js} +283 -21
  130. package/dist/yara-hooks-D8YDyX7o.js.map +1 -0
  131. package/package.json +6 -6
  132. package/dist/PickerMenu-m4CCPX4f.js.map +0 -1
  133. package/dist/agent-BkBbVuNq.js +0 -3189
  134. package/dist/agent-BkBbVuNq.js.map +0 -1
  135. package/dist/agent-QGK2YzlX.js +0 -6
  136. package/dist/agent-interface-CzyCmp7q.js.map +0 -1
  137. package/dist/agent-prompt-loader-4wMxlYSX.js.map +0 -1
  138. package/dist/analytics-B6q5PN7a.js +0 -301
  139. package/dist/analytics-B6q5PN7a.js.map +0 -1
  140. package/dist/analytics-BXtfK9o7.js +0 -2
  141. package/dist/api-C3Dc4LFl.js.map +0 -1
  142. package/dist/api-yNjrfZs2.js +0 -2
  143. package/dist/check-screens.tsx +0 -190
  144. package/dist/ci-install-DfcAMhlu.js.map +0 -1
  145. package/dist/constants-DO4X70po.js +0 -260
  146. package/dist/constants-DO4X70po.js.map +0 -1
  147. package/dist/debug-BueK5mRR.js +0 -2
  148. package/dist/debug-DyARf5TF.js.map +0 -1
  149. package/dist/defaults-DpfMnH2q.js.map +0 -1
  150. package/dist/endpoints-D-4KxZiB.js +0 -108
  151. package/dist/endpoints-D-4KxZiB.js.map +0 -1
  152. package/dist/env-api-key-CHGLe0iz.js +0 -2
  153. package/dist/env-api-key-COf0U-Au.js +0 -17
  154. package/dist/env-api-key-COf0U-Au.js.map +0 -1
  155. package/dist/environment-DrLaSsA8.js +0 -39
  156. package/dist/environment-DrLaSsA8.js.map +0 -1
  157. package/dist/environment-hBj7ngmO.js +0 -2
  158. package/dist/file-CVA9ocIC.js +0 -60
  159. package/dist/file-CVA9ocIC.js.map +0 -1
  160. package/dist/file-CmoKK_Pp.js +0 -2
  161. package/dist/file-watcher-C3Su8vXm.js +0 -123
  162. package/dist/file-watcher-C3Su8vXm.js.map +0 -1
  163. package/dist/gateway-BmjYUSua.js.map +0 -1
  164. package/dist/headless-ui-CUbv12Yx.js +0 -44
  165. package/dist/headless-ui-CUbv12Yx.js.map +0 -1
  166. package/dist/install-Bk5TNk27.js.map +0 -1
  167. package/dist/install-F4wm3RSl.js +0 -2
  168. package/dist/interactive-C5LNvDj6.js +0 -11
  169. package/dist/interactive-C5LNvDj6.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-p6XKVmTx.js +0 -226
  173. package/dist/logging-ui-p6XKVmTx.js.map +0 -1
  174. package/dist/main-DKPjFHEV.js.map +0 -1
  175. package/dist/mcp-prompt-streaming-ljCVoQ9I.js.map +0 -1
  176. package/dist/mint-failure-C0HyvEwO.js +0 -6403
  177. package/dist/mint-failure-C0HyvEwO.js.map +0 -1
  178. package/dist/non-interactive-CLMJrj_7.js +0 -18
  179. package/dist/non-interactive-CLMJrj_7.js.map +0 -1
  180. package/dist/package-json--ppioh2F.js +0 -2
  181. package/dist/pi-B5YTBRDv.js.map +0 -1
  182. package/dist/playground-BLsCfHmQ.js.map +0 -1
  183. package/dist/posthog-B2E0hpZt.js +0 -2
  184. package/dist/posthog-B42rt_1S.js +0 -124
  185. package/dist/posthog-B42rt_1S.js.map +0 -1
  186. package/dist/project-data--L-WZyvj.js +0 -2
  187. package/dist/project-data-BO9IXn9y.js +0 -1131
  188. package/dist/project-data-BO9IXn9y.js.map +0 -1
  189. package/dist/provisioning-C01REIU2.js +0 -2
  190. package/dist/queue-tools-knnPQP0e.js.map +0 -1
  191. package/dist/registry-B3rC5U4b.js +0 -3464
  192. package/dist/registry-B3rC5U4b.js.map +0 -1
  193. package/dist/registry-BamsM7J9.js +0 -2
  194. package/dist/run-agent-legacy-CwUmPfQF.js +0 -2
  195. package/dist/run-agent-legacy-DWBajsMh.js +0 -3467
  196. package/dist/run-agent-legacy-DWBajsMh.js.map +0 -1
  197. package/dist/runners-D1PqqpjA.js +0 -834
  198. package/dist/runners-D1PqqpjA.js.map +0 -1
  199. package/dist/security-BvdSFDuM.js.map +0 -1
  200. package/dist/setup-utils-ChXXTi1m.js +0 -301
  201. package/dist/setup-utils-ChXXTi1m.js.map +0 -1
  202. package/dist/start-tui-DicLfgsj.js +0 -6964
  203. package/dist/start-tui-DicLfgsj.js.map +0 -1
  204. package/dist/steps-Hc28zVc_.js.map +0 -1
  205. package/dist/store-COCO6U0P.js +0 -5
  206. package/dist/store-D3509G87.js +0 -1030
  207. package/dist/store-D3509G87.js.map +0 -1
  208. package/dist/task-DiTI6Sak.js.map +0 -1
  209. package/dist/task-status-CmrrR7zo.js +0 -16
  210. package/dist/task-status-CmrrR7zo.js.map +0 -1
  211. package/dist/task-stream-BckhG_cB.js +0 -363
  212. package/dist/task-stream-BckhG_cB.js.map +0 -1
  213. package/dist/tasks-ChZ_F1YP.js.map +0 -1
  214. package/dist/terminal-PK9bCLRi.js +0 -7222
  215. package/dist/terminal-PK9bCLRi.js.map +0 -1
  216. package/dist/tools-C8LQ8QFz.js.map +0 -1
  217. package/dist/ui-tPNpM6vj.js +0 -15
  218. package/dist/ui-tPNpM6vj.js.map +0 -1
  219. package/dist/version-5_ydHkM6.js +0 -6
  220. package/dist/version-5_ydHkM6.js.map +0 -1
  221. package/dist/wizard-abort-BVjqLyeA.js +0 -3
  222. package/dist/wizard-abort-DBKtfnBR.js.map +0 -1
  223. package/dist/wizard-session-B7BHnay0.js +0 -2
  224. package/dist/wizard-session-BYw6LzpS.js +0 -133
  225. package/dist/wizard-session-BYw6LzpS.js.map +0 -1
  226. package/dist/yara-hooks-C3L6lBij.js.map +0 -1
  227. package/dist/yara-hooks-CF_IsoaA.js +0 -2
@@ -1,108 +0,0 @@
1
- import { s as logToFile } from "./debug-DyARf5TF.js";
2
- import { g as GITHUB_SKILLS_BASE_URL, o as AWS_SKILLS_BASE_URL } from "./constants-DO4X70po.js";
3
- //#region src/shared/health-checks/endpoints.ts
4
- function noConnectionResult(error, attempts) {
5
- return {
6
- status: "no-connection",
7
- error,
8
- rawIndicator: attempts > 1 ? `attempts=${attempts}` : void 0
9
- };
10
- }
11
- function downResult(error) {
12
- return {
13
- status: "down",
14
- error
15
- };
16
- }
17
- const RETRY_BACKOFFS_MS = [500, 2e3];
18
- async function attemptFetch(url, timeoutMs, redirect) {
19
- const controller = new AbortController();
20
- const tid = setTimeout(() => controller.abort(), timeoutMs);
21
- try {
22
- const res = await fetch(url, {
23
- signal: controller.signal,
24
- redirect
25
- });
26
- clearTimeout(tid);
27
- return {
28
- kind: "response",
29
- res
30
- };
31
- } catch (e) {
32
- clearTimeout(tid);
33
- const err = e instanceof Error ? e : /* @__PURE__ */ new Error("Unknown error");
34
- return {
35
- kind: "error",
36
- error: err,
37
- timedOut: err.name === "AbortError"
38
- };
39
- }
40
- }
41
- async function fetchEndpointHealth(url, timeoutMs = 5e3, isExpectedStatus = (s) => s === 200, redirect = "follow") {
42
- let lastHttpStatus = null;
43
- let lastError = "Unknown error";
44
- let attempts = 0;
45
- for (let i = 0; i <= RETRY_BACKOFFS_MS.length; i++) {
46
- if (i > 0) {
47
- const wait = RETRY_BACKOFFS_MS[i - 1];
48
- logToFile(`[health-checks] retry ${i}/${RETRY_BACKOFFS_MS.length} for ${url} in ${wait}ms (last: ${lastError})`);
49
- await new Promise((r) => setTimeout(r, wait));
50
- }
51
- attempts++;
52
- const outcome = await attemptFetch(url, timeoutMs, redirect);
53
- if (outcome.kind === "response") {
54
- const res = outcome.res;
55
- if (isExpectedStatus(res.status)) {
56
- const result = {
57
- status: "healthy",
58
- rawIndicator: attempts > 1 ? `HTTP ${res.status} (attempts=${attempts})` : `HTTP ${res.status}`
59
- };
60
- logToFile(`[health-checks] GET ${url} -> ${result.status} (${result.rawIndicator})`);
61
- return result;
62
- }
63
- lastHttpStatus = res.status;
64
- lastError = `HTTP ${res.status}`;
65
- continue;
66
- }
67
- lastError = outcome.timedOut ? `Request timed out after ${timeoutMs}ms` : outcome.error.message;
68
- }
69
- const result = lastHttpStatus !== null ? downResult(`HTTP ${lastHttpStatus} (attempts=${attempts})`) : noConnectionResult(lastError, attempts);
70
- logToFile(`[health-checks] GET ${url} -> ${result.status} (attempts=${attempts}, ${result.error})`);
71
- return result;
72
- }
73
- const checkLlmGatewayHealth = (gatewayUrl) => fetchEndpointHealth(new URL("/readyz", gatewayUrl).href);
74
- /**
75
- * Skills are published to two origins under the same filenames and
76
- * `fetchWithRetry` fails over between them, so the run is only blocked when
77
- * neither answers. Probed in parallel — sequential probes would double the
78
- * worst case past `READINESS_TIMEOUT_MS`.
79
- */
80
- const checkSkillsOriginHealth = async () => {
81
- const [github, aws] = await Promise.all([fetchEndpointHealth(`${GITHUB_SKILLS_BASE_URL}/skill-menu.json`), fetchEndpointHealth(`${AWS_SKILLS_BASE_URL}/skill-menu.json`)]);
82
- return combineOriginHealth(github, aws);
83
- };
84
- /**
85
- * Mirrors `fetchWithRetry`: a download tries GitHub, then AWS, so the run is
86
- * only blocked when neither origin answers. Whichever failure the probes saw,
87
- * one origin serving means skills are reachable.
88
- */
89
- function combineOriginHealth(github, aws) {
90
- if (github.status === "healthy") return aws.status === "healthy" ? github : withIndicatorSuffix(github, "aws unavailable");
91
- if (aws.status === "healthy") return withIndicatorSuffix(aws, "via aws, github unavailable");
92
- const error = `github: ${github.error ?? "unknown"} | aws: ${aws.error ?? "unknown"}`;
93
- return {
94
- status: github.status === "down" || aws.status === "down" ? "down" : "no-connection",
95
- error,
96
- rawIndicator: github.rawIndicator ?? aws.rawIndicator
97
- };
98
- }
99
- function withIndicatorSuffix(result, suffix) {
100
- return {
101
- ...result,
102
- rawIndicator: result.rawIndicator ? `${result.rawIndicator} (${suffix})` : suffix
103
- };
104
- }
105
- //#endregion
106
- export { checkSkillsOriginHealth as n, checkLlmGatewayHealth as t };
107
-
108
- //# sourceMappingURL=endpoints-D-4KxZiB.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"endpoints-D-4KxZiB.js","names":[],"sources":["../src/shared/health-checks/endpoints.ts"],"sourcesContent":["import { AWS_SKILLS_BASE_URL, GITHUB_SKILLS_BASE_URL } from '@shared/constants';\nimport { logToFile } from '@utils/debug';\nimport { ServiceHealthStatus, type BaseHealthResult } from './types';\n\n// Direct gateway and skill-origin checks distinguish HTTP failures from connection failures.\n\nfunction noConnectionResult(error: string, attempts: number): BaseHealthResult {\n return {\n status: ServiceHealthStatus.NoConnection,\n error,\n rawIndicator: attempts > 1 ? `attempts=${attempts}` : undefined,\n };\n}\n\nfunction downResult(error: string): BaseHealthResult {\n return { status: ServiceHealthStatus.Down, error };\n}\n\n// Backoffs sized to cover typical wifi flakiness — a single dropped\n// packet recovers via the 500ms retry; a wifi access point reconnect\n// or wifi↔LTE handoff (2-5s) is caught by the 2000ms retry. Tighter\n// schedules miss multi-second blips because all retries land in the\n// same dead window.\nconst RETRY_BACKOFFS_MS = [500, 2000];\n\nasync function attemptFetch(\n url: string,\n timeoutMs: number,\n redirect: 'follow' | 'manual' | 'error',\n): Promise<\n | { kind: 'response'; res: Response }\n | { kind: 'error'; error: Error; timedOut: boolean }\n> {\n const controller = new AbortController();\n const tid = setTimeout(() => controller.abort(), timeoutMs);\n try {\n const res = await fetch(url, { signal: controller.signal, redirect });\n clearTimeout(tid);\n return { kind: 'response', res };\n } catch (e) {\n clearTimeout(tid);\n const err = e instanceof Error ? e : new Error('Unknown error');\n return { kind: 'error', error: err, timedOut: err.name === 'AbortError' };\n }\n}\n\n// Exported so tests can pin the retry/taxonomy machinery directly.\nexport async function fetchEndpointHealth(\n url: string,\n timeoutMs = 5000,\n isExpectedStatus: (status: number) => boolean = (s) => s === 200,\n redirect: 'follow' | 'manual' | 'error' = 'follow',\n): Promise<BaseHealthResult> {\n // Total attempts = 1 initial + RETRY_BACKOFFS_MS.length retries. Both\n // unexpected HTTP statuses (4xx/5xx) and network errors trigger a retry:\n // transient 5xx and Cloudflare edge blips often recover on a retry, and\n // even nominally deterministic 4xx can be transient (CDN propagation\n // lag after a release, token rotation, rate-limit window resets). GETs\n // are idempotent so retrying is safe.\n //\n // Final status if every attempt fails:\n // - At least one HTTP response observed → `Down` (server-side evidence)\n // - Only network errors observed → `NoConnection`\n let lastHttpStatus: number | null = null;\n let lastError = 'Unknown error';\n let attempts = 0;\n\n for (let i = 0; i <= RETRY_BACKOFFS_MS.length; i++) {\n if (i > 0) {\n const wait = RETRY_BACKOFFS_MS[i - 1];\n logToFile(\n `[health-checks] retry ${i}/${RETRY_BACKOFFS_MS.length} for ${url} in ${wait}ms (last: ${lastError})`,\n );\n await new Promise((r) => setTimeout(r, wait));\n }\n attempts++;\n\n const outcome = await attemptFetch(url, timeoutMs, redirect);\n\n if (outcome.kind === 'response') {\n const res = outcome.res;\n if (isExpectedStatus(res.status)) {\n const result: BaseHealthResult = {\n status: ServiceHealthStatus.Healthy,\n rawIndicator:\n attempts > 1\n ? `HTTP ${res.status} (attempts=${attempts})`\n : `HTTP ${res.status}`,\n };\n logToFile(\n `[health-checks] GET ${url} -> ${result.status}` +\n ` (${result.rawIndicator})`,\n );\n return result;\n }\n lastHttpStatus = res.status;\n lastError = `HTTP ${res.status}`;\n continue;\n }\n\n lastError = outcome.timedOut\n ? `Request timed out after ${timeoutMs}ms`\n : outcome.error.message;\n }\n\n const result =\n lastHttpStatus !== null\n ? downResult(`HTTP ${lastHttpStatus} (attempts=${attempts})`)\n : noConnectionResult(lastError, attempts);\n logToFile(\n `[health-checks] GET ${url} -> ${result.status}` +\n ` (attempts=${attempts}, ${result.error})`,\n );\n return result;\n}\n\nexport const checkLlmGatewayHealth = (\n gatewayUrl: string,\n): Promise<BaseHealthResult> =>\n fetchEndpointHealth(new URL('/readyz', gatewayUrl).href);\n\n/**\n * Skills are published to two origins under the same filenames and\n * `fetchWithRetry` fails over between them, so the run is only blocked when\n * neither answers. Probed in parallel — sequential probes would double the\n * worst case past `READINESS_TIMEOUT_MS`.\n */\nexport const checkSkillsOriginHealth = async (): Promise<BaseHealthResult> => {\n const [github, aws] = await Promise.all([\n fetchEndpointHealth(`${GITHUB_SKILLS_BASE_URL}/skill-menu.json`),\n fetchEndpointHealth(`${AWS_SKILLS_BASE_URL}/skill-menu.json`),\n ]);\n return combineOriginHealth(github, aws);\n};\n\n/**\n * Mirrors `fetchWithRetry`: a download tries GitHub, then AWS, so the run is\n * only blocked when neither origin answers. Whichever failure the probes saw,\n * one origin serving means skills are reachable.\n */\nfunction combineOriginHealth(\n github: BaseHealthResult,\n aws: BaseHealthResult,\n): BaseHealthResult {\n if (github.status === ServiceHealthStatus.Healthy) {\n // Naming the dead origin makes a one-sided outage legible in the log and\n // in the readiness reasons, where the status alone reads as \"fine\".\n return aws.status === ServiceHealthStatus.Healthy\n ? github\n : withIndicatorSuffix(github, 'aws unavailable');\n }\n\n if (aws.status === ServiceHealthStatus.Healthy) {\n return withIndicatorSuffix(aws, 'via aws, github unavailable');\n }\n\n const error = `github: ${github.error ?? 'unknown'} | aws: ${\n aws.error ?? 'unknown'\n }`;\n const confirmedDown =\n github.status === ServiceHealthStatus.Down ||\n aws.status === ServiceHealthStatus.Down;\n return {\n status: confirmedDown\n ? ServiceHealthStatus.Down\n : ServiceHealthStatus.NoConnection,\n error,\n // Keeps the `attempts=N` the blocked-readiness analytics parses.\n rawIndicator: github.rawIndicator ?? aws.rawIndicator,\n };\n}\n\nfunction withIndicatorSuffix(\n result: BaseHealthResult,\n suffix: string,\n): BaseHealthResult {\n return {\n ...result,\n rawIndicator: result.rawIndicator\n ? `${result.rawIndicator} (${suffix})`\n : suffix,\n };\n}\n"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- import { t as readApiKeyFromEnv } from "./env-api-key-COf0U-Au.js";
2
- export { readApiKeyFromEnv };
@@ -1,17 +0,0 @@
1
- import { i as readProjectFile } from "./bounded-fs-CC_NDtoP.js";
2
- import * as path$1 from "path";
3
- //#region src/shared/utils/env-api-key.ts
4
- /**
5
- * Read POSTHOG_PERSONAL_API_KEY from .env.local or .env in the current
6
- * working directory. Returns undefined when no key is found.
7
- */
8
- function readApiKeyFromEnv() {
9
- for (const envFile of [".env.local", ".env"]) {
10
- const match = readProjectFile(path$1.join(process.cwd(), envFile))?.match(/^POSTHOG_PERSONAL_API_KEY=(.+)$/m);
11
- if (match) return match[1].trim();
12
- }
13
- }
14
- //#endregion
15
- export { readApiKeyFromEnv as t };
16
-
17
- //# sourceMappingURL=env-api-key-COf0U-Au.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"env-api-key-COf0U-Au.js","names":["path"],"sources":["../src/shared/utils/env-api-key.ts"],"sourcesContent":["import * as path from 'path';\nimport { readProjectFile } from './bounded-fs';\n\n/**\n * Read POSTHOG_PERSONAL_API_KEY from .env.local or .env in the current\n * working directory. Returns undefined when no key is found.\n */\nexport function readApiKeyFromEnv(): string | undefined {\n for (const envFile of ['.env.local', '.env']) {\n // null when missing or unreadable, e.g. a `.env` directory (a Python virtualenv).\n const content = readProjectFile(path.join(process.cwd(), envFile));\n const match = content?.match(/^POSTHOG_PERSONAL_API_KEY=(.+)$/m);\n if (match) return match[1].trim();\n }\n return undefined;\n}\n"],"mappings":";;;;;;;AAOA,SAAgB,oBAAwC;AACtD,MAAK,MAAM,WAAW,CAAC,cAAc,OAAO,EAAE;EAG5C,MAAM,QADU,gBAAgBA,OAAK,KAAK,QAAQ,KAAK,EAAE,QAAQ,CAAC,EAC3C,MAAM,mCAAmC;AAChE,MAAI,MAAO,QAAO,MAAM,GAAG,MAAM"}
@@ -1,39 +0,0 @@
1
- import "./constants-DO4X70po.js";
2
- import "./bounded-fs-CC_NDtoP.js";
3
- import "./setup-utils-ChXXTi1m.js";
4
- import readEnvModule from "read-env";
5
- //#region src/shared/utils/environment.ts
6
- const readEnv = typeof readEnvModule === "function" ? readEnvModule : readEnvModule.default;
7
- function isNonInteractiveEnvironment() {
8
- if (!process.stdout.isTTY || !process.stderr.isTTY) return true;
9
- return false;
10
- }
11
- /**
12
- * Session fields the environment must never set, matched case-insensitively
13
- * against the camel-cased key `read-env` produces.
14
- *
15
- * `e2eAsk` re-wires the `wizard_ask` bridge in an otherwise non-interactive
16
- * run. Only the e2e TUI host may set it: a real `--ci` run has nobody to answer,
17
- * so every question would stall for the bridge timeout instead of failing fast
18
- * with an actionable error. See `shouldDisableAsk`.
19
- */
20
- const NEVER_FROM_ENV = ["e2eAsk", "runId"];
21
- /**
22
- * Session args from the `POSTHOG_WIZARD_*` environment variables.
23
- *
24
- * `read-env` camel-cases every prefixed variable into a key, and the CI runner
25
- * spreads the whole bag into `buildSession` — so adding a field to the session
26
- * silently adds an environment variable that sets it. Most of them are meant to
27
- * work that way (`POSTHOG_WIZARD_DEBUG` → `debug`); the ones in
28
- * {@link NEVER_FROM_ENV} are not, and are dropped here rather than at the call
29
- * site, so a second caller cannot reopen the door.
30
- */
31
- function readEnvironment() {
32
- const result = readEnv("POSTHOG_WIZARD");
33
- for (const key of Object.keys(result)) if (NEVER_FROM_ENV.some((k) => k.toLowerCase() === key.toLowerCase())) delete result[key];
34
- return result;
35
- }
36
- //#endregion
37
- export { readEnvironment as n, isNonInteractiveEnvironment as t };
38
-
39
- //# sourceMappingURL=environment-DrLaSsA8.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"environment-DrLaSsA8.js","names":[],"sources":["../src/shared/utils/environment.ts"],"sourcesContent":["import readEnvModule from 'read-env';\n\nconst readEnv =\n typeof readEnvModule === 'function'\n ? readEnvModule\n : (readEnvModule as any).default;\nimport { tryGetPackageJson } from './setup-utils';\nimport type { WizardRunOptions } from './types';\nimport { boundedGlob } from './bounded-fs';\nimport { IS_DEV } from '@shared/constants';\n\nexport function isNonInteractiveEnvironment(): boolean {\n if (IS_DEV) {\n return false;\n }\n\n if (!process.stdout.isTTY || !process.stderr.isTTY) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Session fields the environment must never set, matched case-insensitively\n * against the camel-cased key `read-env` produces.\n *\n * `e2eAsk` re-wires the `wizard_ask` bridge in an otherwise non-interactive\n * run. Only the e2e TUI host may set it: a real `--ci` run has nobody to answer,\n * so every question would stall for the bridge timeout instead of failing fast\n * with an actionable error. See `shouldDisableAsk`.\n */\nconst NEVER_FROM_ENV = ['e2eAsk', 'runId'];\n\n/**\n * Session args from the `POSTHOG_WIZARD_*` environment variables.\n *\n * `read-env` camel-cases every prefixed variable into a key, and the CI runner\n * spreads the whole bag into `buildSession` — so adding a field to the session\n * silently adds an environment variable that sets it. Most of them are meant to\n * work that way (`POSTHOG_WIZARD_DEBUG` → `debug`); the ones in\n * {@link NEVER_FROM_ENV} are not, and are dropped here rather than at the call\n * site, so a second caller cannot reopen the door.\n */\nexport function readEnvironment(): Record<string, unknown> {\n const result = readEnv('POSTHOG_WIZARD') as Record<string, unknown>;\n\n for (const key of Object.keys(result)) {\n if (NEVER_FROM_ENV.some((k) => k.toLowerCase() === key.toLowerCase())) {\n delete result[key];\n }\n }\n\n return result;\n}\n\nexport async function detectEnvVarPrefix(\n options: WizardRunOptions,\n): Promise<string> {\n const packageJson = await tryGetPackageJson(options);\n if (!packageJson) return 'VITE_PUBLIC_';\n\n const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };\n const has = (name: string) => name in deps;\n // O(1) matches per probe: one config file existing anywhere answers it.\n const hasAnyFile = async (patterns: string[]) => {\n const matches = await boundedGlob(patterns, {\n cwd: options.installDir,\n limit: 1,\n });\n return matches.length > 0;\n };\n\n // --- Next.js\n if (has('next') || (await hasAnyFile(['**/next.config.{js,ts,mjs,cjs}']))) {\n return 'NEXT_PUBLIC_';\n }\n\n // --- Create React App\n if (\n has('react-scripts') ||\n has('create-react-app') ||\n (await hasAnyFile(['**/config-overrides.js']))\n ) {\n return 'REACT_APP_';\n }\n\n // --- Vite (vanilla, TanStack, Solid, etc.)\n // Note: Vite does not need PUBLIC_ but we use it to follow the docs, to improve the chances of an LLM getting it right.\n if (has('vite') || (await hasAnyFile(['**/vite.config.{js,ts,mjs,cjs}']))) {\n return 'VITE_PUBLIC_';\n }\n\n // --- SvelteKit\n if (\n has('@sveltejs/kit') ||\n (await hasAnyFile(['**/svelte.config.{js,ts}']))\n ) {\n return 'PUBLIC_';\n }\n\n // --- TanStack Start (uses Vite)\n if (\n has('@tanstack/start') ||\n (await hasAnyFile(['**/tanstack.config.{js,ts}']))\n ) {\n return 'VITE_PUBLIC_';\n }\n\n // --- SolidStart (uses Vite)\n if (has('solid-start') || (await hasAnyFile(['**/solid.config.{js,ts}']))) {\n return 'VITE_PUBLIC_';\n }\n\n // --- Astro\n if (has('astro') || (await hasAnyFile(['**/astro.config.{js,ts,mjs}']))) {\n return 'PUBLIC_';\n }\n\n // We default to Vite if we can't detect a specific framework, since it's the most commonly used.\n return 'VITE_PUBLIC_';\n}\n"],"mappings":";;;;;AAEA,MAAM,UACJ,OAAO,kBAAkB,aACrB,gBACC,cAAsB;AAM7B,SAAgB,8BAAuC;AAKrD,KAAI,CAAC,QAAQ,OAAO,SAAS,CAAC,QAAQ,OAAO,MAC3C,QAAO;AAGT,QAAO;;;;;;;;;;;AAYT,MAAM,iBAAiB,CAAC,UAAU,QAAQ;;;;;;;;;;;AAY1C,SAAgB,kBAA2C;CACzD,MAAM,SAAS,QAAQ,iBAAiB;AAExC,MAAK,MAAM,OAAO,OAAO,KAAK,OAAO,CACnC,KAAI,eAAe,MAAM,MAAM,EAAE,aAAa,KAAK,IAAI,aAAa,CAAC,CACnE,QAAO,OAAO;AAIlB,QAAO"}
@@ -1,2 +0,0 @@
1
- import { n as readEnvironment } from "./environment-DrLaSsA8.js";
2
- export { readEnvironment };
@@ -1,60 +0,0 @@
1
- import { d as WIZARD_TASK_STREAM_FILE, s as logToFile } from "./debug-DyARf5TF.js";
2
- import { dirname, isAbsolute, resolve } from "node:path";
3
- import { appendFileSync, mkdirSync, writeFileSync } from "node:fs";
4
- //#region src/programs/session/task-stream/destinations/file.ts
5
- /**
6
- * Dumps every *attempted* sync to a local JSONL file, one line per push. A line
7
- * means the run published that payload, not that a backend accepted it — `--ci`
8
- * swaps the PostHog destination for this one, so a synthetic run never creates a
9
- * session row in a real project.
10
- *
11
- * Dev builds only: the payload holds the run's handoff report.
12
- */
13
- var FileDestination = class {
14
- name = "file";
15
- path;
16
- now;
17
- disabled = false;
18
- constructor(opts) {
19
- this.path = opts.path;
20
- this.now = opts.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
21
- this.write(() => writeFileSync(this.path, "", { mode: 384 }));
22
- }
23
- send(event, payload) {
24
- if (!this.disabled) {
25
- const line = `${JSON.stringify({
26
- at: this.now(),
27
- event,
28
- payload
29
- })}\n`;
30
- this.write(() => appendFileSync(this.path, line, { mode: 384 }));
31
- }
32
- return Promise.resolve();
33
- }
34
- /** Never throws, never writes to stdio; the first failure ends the dump. */
35
- write(op) {
36
- try {
37
- mkdirSync(dirname(this.path), { recursive: true });
38
- op();
39
- } catch (err) {
40
- this.disabled = true;
41
- logToFile(`[task-stream] file destination disabled (${err instanceof Error ? err.message : String(err)}): ${this.path}`);
42
- }
43
- }
44
- };
45
- /**
46
- * Resolve a `--task-stream-log` value, or null when the run did not ask for a
47
- * dump. `''` and `true` mean the default path — how `--ci` asks for one.
48
- */
49
- function createFileDestination(value, opts = {}) {
50
- if (opts.productionBuild ?? true) return null;
51
- if (value === void 0 || value === null || value === false) return null;
52
- const raw = typeof value === "string" ? value.trim() : "";
53
- const path = raw === "" ? WIZARD_TASK_STREAM_FILE : isAbsolute(raw) ? raw : resolve(opts.cwd ?? process.cwd(), raw);
54
- logToFile(`[task-stream] file destination enabled: ${path}`);
55
- return new FileDestination({ path });
56
- }
57
- //#endregion
58
- export { createFileDestination as n, FileDestination as t };
59
-
60
- //# sourceMappingURL=file-CVA9ocIC.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"file-CVA9ocIC.js","names":[],"sources":["../src/programs/session/task-stream/destinations/file.ts"],"sourcesContent":["/**\n * Dumps every *attempted* sync to a local JSONL file, one line per push. A line\n * means the run published that payload, not that a backend accepted it — `--ci`\n * swaps the PostHog destination for this one, so a synthetic run never creates a\n * session row in a real project.\n *\n * Dev builds only: the payload holds the run's handoff report.\n */\n\nimport { appendFileSync, mkdirSync, writeFileSync } from 'node:fs';\nimport { dirname, isAbsolute, resolve } from 'node:path';\nimport { IS_PRODUCTION_BUILD } from '@env';\nimport { WIZARD_TASK_STREAM_FILE } from '@utils/paths';\nimport { logToFile } from '@utils/debug';\nimport type {\n StreamEvent,\n TaskStreamDestination,\n TaskStreamUpdate,\n} from '@programs/session/task-stream/types';\n\nexport interface FileDestinationOptions {\n path: string;\n /** Override for tests. */\n now?: () => string;\n}\n\nexport class FileDestination implements TaskStreamDestination {\n readonly name = 'file';\n readonly path: string;\n\n private readonly now: () => string;\n private disabled = false;\n\n constructor(opts: FileDestinationOptions) {\n this.path = opts.path;\n this.now = opts.now ?? (() => new Date().toISOString());\n // Truncate up front: one run, one file.\n this.write(() => writeFileSync(this.path, '', { mode: 0o600 }));\n }\n\n send(event: StreamEvent, payload: TaskStreamUpdate): Promise<void> {\n if (!this.disabled) {\n const line = `${JSON.stringify({ at: this.now(), event, payload })}\\n`;\n this.write(() => appendFileSync(this.path, line, { mode: 0o600 }));\n }\n return Promise.resolve();\n }\n\n /** Never throws, never writes to stdio; the first failure ends the dump. */\n private write(op: () => void): void {\n try {\n mkdirSync(dirname(this.path), { recursive: true });\n op();\n } catch (err) {\n this.disabled = true;\n logToFile(\n `[task-stream] file destination disabled (${\n err instanceof Error ? err.message : String(err)\n }): ${this.path}`,\n );\n }\n }\n}\n\n/**\n * Resolve a `--task-stream-log` value, or null when the run did not ask for a\n * dump. `''` and `true` mean the default path — how `--ci` asks for one.\n */\nexport function createFileDestination(\n value: unknown,\n opts: { productionBuild?: boolean; cwd?: string } = {},\n): FileDestination | null {\n if (opts.productionBuild ?? IS_PRODUCTION_BUILD) return null;\n if (value === undefined || value === null || value === false) return null;\n\n const raw = typeof value === 'string' ? value.trim() : '';\n const path =\n raw === ''\n ? WIZARD_TASK_STREAM_FILE\n : isAbsolute(raw)\n ? raw\n : resolve(opts.cwd ?? process.cwd(), raw);\n\n logToFile(`[task-stream] file destination enabled: ${path}`);\n return new FileDestination({ path });\n}\n"],"mappings":";;;;;;;;;;;;AA0BA,IAAa,kBAAb,MAA8D;CAC5D,OAAgB;CAChB;CAEA;CACA,WAAmB;CAEnB,YAAY,MAA8B;AACxC,OAAK,OAAO,KAAK;AACjB,OAAK,MAAM,KAAK,+BAAc,IAAI,MAAM,EAAC,aAAa;AAEtD,OAAK,YAAY,cAAc,KAAK,MAAM,IAAI,EAAE,MAAM,KAAO,CAAC,CAAC;;CAGjE,KAAK,OAAoB,SAA0C;AACjE,MAAI,CAAC,KAAK,UAAU;GAClB,MAAM,OAAO,GAAG,KAAK,UAAU;IAAE,IAAI,KAAK,KAAK;IAAE;IAAO;IAAS,CAAC,CAAC;AACnE,QAAK,YAAY,eAAe,KAAK,MAAM,MAAM,EAAE,MAAM,KAAO,CAAC,CAAC;;AAEpE,SAAO,QAAQ,SAAS;;;CAI1B,MAAc,IAAsB;AAClC,MAAI;AACF,aAAU,QAAQ,KAAK,KAAK,EAAE,EAAE,WAAW,MAAM,CAAC;AAClD,OAAI;WACG,KAAK;AACZ,QAAK,WAAW;AAChB,aACE,4CACE,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI,CACjD,KAAK,KAAK,OACZ;;;;;;;;AASP,SAAgB,sBACd,OACA,OAAoD,EAAE,EAC9B;AACxB,KAAI,KAAK,mBAAA,KAAwC,QAAO;AACxD,KAAI,UAAU,KAAA,KAAa,UAAU,QAAQ,UAAU,MAAO,QAAO;CAErE,MAAM,MAAM,OAAO,UAAU,WAAW,MAAM,MAAM,GAAG;CACvD,MAAM,OACJ,QAAQ,KACJ,0BACA,WAAW,IAAI,GACf,MACA,QAAQ,KAAK,OAAO,QAAQ,KAAK,EAAE,IAAI;AAE7C,WAAU,2CAA2C,OAAO;AAC5D,QAAO,IAAI,gBAAgB,EAAE,MAAM,CAAC"}
@@ -1,2 +0,0 @@
1
- import { n as createFileDestination } from "./file-CVA9ocIC.js";
2
- export { createFileDestination };
@@ -1,123 +0,0 @@
1
- import { s as logToFile } from "./debug-DyARf5TF.js";
2
- import * as fs$1 from "fs";
3
- import { basename, dirname } from "node:path";
4
- //#region src/shared/utils/file-watcher.ts
5
- /**
6
- * JSON file watcher shared by runner and UI machinery.
7
- *
8
- * `fs.watch` alone is unreliable for atomic-rename writes, so the watcher
9
- * pairs it with a continuous mtime-polled re-read. The poll catches missed
10
- * events; the watch keeps latency low when it does fire.
11
- */
12
- const DEFAULT_POLL_INTERVAL_MS = 5e3;
13
- const DEFAULT_ATTACH_RETRY_INTERVAL_MS = 1e3;
14
- const DEFAULT_WATCH_DEBOUNCE_MS = 25;
15
- /** Watch `path` for JSON updates and call `onUpdate(parsed)` whenever the
16
- * file's mtime changes and the contents are valid JSON. Caller must invoke
17
- * `handle.stop()` to release the watcher. */
18
- function startFileWatcher(path, onUpdate, options = {}) {
19
- const pollIntervalMs = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
20
- const attachRetryIntervalMs = options.attachRetryIntervalMs ?? DEFAULT_ATTACH_RETRY_INTERVAL_MS;
21
- const watchDebounceMs = options.watchDebounceMs ?? DEFAULT_WATCH_DEBOUNCE_MS;
22
- const watchers = [];
23
- const intervals = [];
24
- const targetDir = dirname(path);
25
- const targetName = basename(path);
26
- let lastMtimeMs = 0;
27
- let ignoredInitialSignature = null;
28
- let watchDebounceTimer = null;
29
- let lastReadErrorSignature = null;
30
- let stopped = false;
31
- const signature = (stat) => `${stat.dev}:${stat.ino}:${stat.size}:${stat.mtimeMs}:${stat.ctimeMs}`;
32
- if (options.ignoreInitialFile) try {
33
- const stat = fs$1.lstatSync(path);
34
- if (stat.isFile() && !stat.isSymbolicLink()) ignoredInitialSignature = signature(stat);
35
- } catch {}
36
- const logReadError = (errorSignature, message) => {
37
- if (lastReadErrorSignature === errorSignature) return;
38
- lastReadErrorSignature = errorSignature;
39
- logToFile(`[file-watcher] ${message}: ${path}`);
40
- };
41
- const read = (force = false) => {
42
- let stat;
43
- try {
44
- stat = fs$1.lstatSync(path);
45
- } catch {
46
- return;
47
- }
48
- if (!stat.isFile() || stat.isSymbolicLink()) return;
49
- const fileSignature = signature(stat);
50
- try {
51
- if (ignoredInitialSignature) {
52
- if (fileSignature === ignoredInitialSignature) return;
53
- ignoredInitialSignature = null;
54
- }
55
- if (options.maxFileSizeBytes !== void 0 && stat.size > options.maxFileSizeBytes) {
56
- logReadError(`oversized:${fileSignature}`, `refusing oversized JSON file (${stat.size} bytes, limit ${options.maxFileSizeBytes} bytes)`);
57
- return;
58
- }
59
- if (!force && stat.mtimeMs === lastMtimeMs) return;
60
- lastMtimeMs = stat.mtimeMs;
61
- const parsed = JSON.parse(fs$1.readFileSync(path, "utf-8"));
62
- lastReadErrorSignature = null;
63
- onUpdate(parsed);
64
- } catch (error) {
65
- logReadError(`invalid:${fileSignature}:${String(error)}`, `could not read valid JSON (${String(error)})`);
66
- }
67
- };
68
- const scheduleRead = () => {
69
- if (stopped) return;
70
- if (watchDebounceTimer) clearTimeout(watchDebounceTimer);
71
- watchDebounceTimer = setTimeout(() => {
72
- watchDebounceTimer = null;
73
- read(true);
74
- }, watchDebounceMs);
75
- };
76
- const attachWatch = () => {
77
- watchers.push(fs$1.watch(targetDir, (_eventType, filename) => {
78
- if (filename == null || filename.toString() === targetName) scheduleRead();
79
- }));
80
- };
81
- intervals.push(setInterval(() => read(), pollIntervalMs));
82
- try {
83
- attachWatch();
84
- queueMicrotask(() => {
85
- if (!stopped) read(true);
86
- });
87
- } catch {
88
- const attachInterval = setInterval(() => {
89
- try {
90
- fs$1.accessSync(targetDir);
91
- clearInterval(attachInterval);
92
- const idx = intervals.indexOf(attachInterval);
93
- if (idx >= 0) intervals.splice(idx, 1);
94
- attachWatch();
95
- read(true);
96
- } catch {}
97
- }, attachRetryIntervalMs);
98
- intervals.push(attachInterval);
99
- }
100
- return {
101
- refresh() {
102
- if (stopped) return;
103
- if (watchDebounceTimer) {
104
- clearTimeout(watchDebounceTimer);
105
- watchDebounceTimer = null;
106
- }
107
- read(true);
108
- },
109
- stop() {
110
- stopped = true;
111
- if (watchDebounceTimer) {
112
- clearTimeout(watchDebounceTimer);
113
- watchDebounceTimer = null;
114
- }
115
- for (const watcher of watchers) watcher.close();
116
- for (const interval of intervals) clearInterval(interval);
117
- }
118
- };
119
- }
120
- //#endregion
121
- export { startFileWatcher as t };
122
-
123
- //# sourceMappingURL=file-watcher-C3Su8vXm.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"file-watcher-C3Su8vXm.js","names":["fs"],"sources":["../src/shared/utils/file-watcher.ts"],"sourcesContent":["/**\n * JSON file watcher shared by runner and UI machinery.\n *\n * `fs.watch` alone is unreliable for atomic-rename writes, so the watcher\n * pairs it with a continuous mtime-polled re-read. The poll catches missed\n * events; the watch keeps latency low when it does fire.\n */\n\nimport * as fs from 'fs';\nimport { basename, dirname } from 'node:path';\nimport { logToFile } from '@utils/debug';\n\nconst DEFAULT_POLL_INTERVAL_MS = 5000;\nconst DEFAULT_ATTACH_RETRY_INTERVAL_MS = 1000;\nconst DEFAULT_WATCH_DEBOUNCE_MS = 25;\n\nexport interface FileWatcherHandle {\n refresh(): void;\n stop(): void;\n}\n\nexport interface FileWatcherOptions {\n /** ms between mtime checks once the file exists. */\n pollIntervalMs?: number;\n /** ms between attach attempts while waiting for the file to appear. */\n attachRetryIntervalMs?: number;\n /** ms to coalesce duplicate filesystem events. */\n watchDebounceMs?: number;\n /** Ignore the file that exists when the watcher starts until it changes. */\n ignoreInitialFile?: boolean;\n /** Refuse to read files larger than this many bytes. */\n maxFileSizeBytes?: number;\n}\n\n/** Watch `path` for JSON updates and call `onUpdate(parsed)` whenever the\n * file's mtime changes and the contents are valid JSON. Caller must invoke\n * `handle.stop()` to release the watcher. */\nexport function startFileWatcher(\n path: string,\n onUpdate: (parsed: unknown) => void,\n options: FileWatcherOptions = {},\n): FileWatcherHandle {\n const pollIntervalMs = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;\n const attachRetryIntervalMs =\n options.attachRetryIntervalMs ?? DEFAULT_ATTACH_RETRY_INTERVAL_MS;\n const watchDebounceMs = options.watchDebounceMs ?? DEFAULT_WATCH_DEBOUNCE_MS;\n\n const watchers: fs.FSWatcher[] = [];\n const intervals: Array<ReturnType<typeof setInterval>> = [];\n const targetDir = dirname(path);\n const targetName = basename(path);\n let lastMtimeMs = 0;\n let ignoredInitialSignature: string | null = null;\n let watchDebounceTimer: ReturnType<typeof setTimeout> | null = null;\n let lastReadErrorSignature: string | null = null;\n let stopped = false;\n\n const signature = (stat: fs.Stats): string =>\n `${stat.dev}:${stat.ino}:${stat.size}:${stat.mtimeMs}:${stat.ctimeMs}`;\n\n if (options.ignoreInitialFile) {\n try {\n const stat = fs.lstatSync(path);\n if (stat.isFile() && !stat.isSymbolicLink()) {\n ignoredInitialSignature = signature(stat);\n }\n } catch {\n // No initial file to ignore.\n }\n }\n\n const logReadError = (errorSignature: string, message: string) => {\n if (lastReadErrorSignature === errorSignature) return;\n lastReadErrorSignature = errorSignature;\n logToFile(`[file-watcher] ${message}: ${path}`);\n };\n\n const read = (force = false) => {\n let stat: fs.Stats;\n try {\n stat = fs.lstatSync(path);\n } catch {\n return;\n }\n\n if (!stat.isFile() || stat.isSymbolicLink()) return;\n const fileSignature = signature(stat);\n\n try {\n if (ignoredInitialSignature) {\n if (fileSignature === ignoredInitialSignature) return;\n ignoredInitialSignature = null;\n }\n if (\n options.maxFileSizeBytes !== undefined &&\n stat.size > options.maxFileSizeBytes\n ) {\n logReadError(\n `oversized:${fileSignature}`,\n `refusing oversized JSON file (${stat.size} bytes, limit ${options.maxFileSizeBytes} bytes)`,\n );\n return;\n }\n if (!force && stat.mtimeMs === lastMtimeMs) return;\n lastMtimeMs = stat.mtimeMs;\n const parsed: unknown = JSON.parse(fs.readFileSync(path, 'utf-8'));\n lastReadErrorSignature = null;\n onUpdate(parsed);\n } catch (error) {\n logReadError(\n `invalid:${fileSignature}:${String(error)}`,\n `could not read valid JSON (${String(error)})`,\n );\n }\n };\n\n const scheduleRead = () => {\n if (stopped) return;\n if (watchDebounceTimer) clearTimeout(watchDebounceTimer);\n watchDebounceTimer = setTimeout(() => {\n watchDebounceTimer = null;\n read(true);\n }, watchDebounceMs);\n };\n\n const attachWatch = () => {\n watchers.push(\n fs.watch(targetDir, (_eventType, filename) => {\n if (filename == null || filename.toString() === targetName) {\n scheduleRead();\n }\n }),\n );\n };\n\n intervals.push(setInterval(() => read(), pollIntervalMs));\n\n try {\n attachWatch();\n // Defer the initial callback until the caller has received the handle, so\n // callbacks that stop their watcher cannot race handle assignment.\n queueMicrotask(() => {\n if (!stopped) read(true);\n });\n } catch {\n // Parent directory does not exist yet. Polling still covers a later file;\n // retry attaching the low-latency directory watcher until it appears.\n const attachInterval = setInterval(() => {\n try {\n fs.accessSync(targetDir);\n clearInterval(attachInterval);\n const idx = intervals.indexOf(attachInterval);\n if (idx >= 0) intervals.splice(idx, 1);\n attachWatch();\n read(true);\n } catch {\n // Still waiting.\n }\n }, attachRetryIntervalMs);\n intervals.push(attachInterval);\n }\n\n return {\n refresh() {\n if (stopped) return;\n if (watchDebounceTimer) {\n clearTimeout(watchDebounceTimer);\n watchDebounceTimer = null;\n }\n read(true);\n },\n stop() {\n stopped = true;\n if (watchDebounceTimer) {\n clearTimeout(watchDebounceTimer);\n watchDebounceTimer = null;\n }\n for (const watcher of watchers) watcher.close();\n for (const interval of intervals) clearInterval(interval);\n },\n };\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"gateway-BmjYUSua.js","names":[],"sources":["../src/agent/gateway-session.ts","../src/agent/signals.ts","../src/agent/runner/harness/pi/gateway.ts"],"sourcesContent":["/**\n * Gateway auth for a wizard run: a `phe_` scoped token the backend mints, with\n * pinned attribution, a spend cap and an expiry.\n *\n * Every mint failure throws: a silent downgrade would spend uncapped,\n * unattributed money to hide an outage.\n */\n\nimport { readFileSync } from 'node:fs';\nimport { logToFile } from '@utils/debug';\nimport { analytics } from '@utils/analytics';\nimport { ErrorCodes, WizardError } from '@shared/errors';\nimport type { HostResolution } from '@shared/host-resolution';\nimport { oauthLoginKey } from '@shared/oauth-session';\nimport { checkLlmGatewayHealth } from '@shared/health-checks/endpoints';\nimport { ServiceHealthStatus } from '@shared/health-checks/types';\nimport { IS_PRODUCTION_BUILD, runtimeEnv } from '@env';\nimport type { CloudRegion } from '@utils/types';\n\nexport interface GatewayAuth {\n /** Base URL for model calls (no `/v1`; transports append their route). */\n gatewayUrl: string;\n /** Gateway bearer, minted normally or supplied directly by CI. */\n token: string;\n /** Team verified by the mint, or explicitly supplied for CI attribution. */\n teamId?: number;\n /**\n * Instant past which a 401 on this bearer is age rather than a bad\n * credential: the cache re-mints past it, and a session still holding the\n * old bearer may re-mint once. Before it the mint has to be trusted.\n */\n refreshAtMs: number;\n}\n\ninterface CachedAuth {\n key: string;\n auth: GatewayAuth;\n /** Re-resolve once past this instant. */\n staleAtMs: number;\n}\n\nlet cached: CachedAuth | null = null;\n/**\n * Shared so concurrent callers mint once. The orchestrator starts every runnable\n * task at once, and each would otherwise take its own token and its own cap.\n */\nlet inFlight: { key: string; promise: Promise<GatewayAuth> } | null = null;\nlet ciAuth: GatewayAuth | null = null;\n\n// Snapshot CI supplies a gateway bearer without minting or re-minting.\nexport function configureGatewayCredentialsForCI(\n token: string,\n projectId: number,\n gatewayUrl: string,\n): void {\n if (IS_PRODUCTION_BUILD)\n throw new Error('CI gateway auth requires a non-production build');\n if (!token.trim() || !Number.isSafeInteger(projectId) || projectId <= 0) {\n throw new Error('CI gateway auth requires a token and valid project ID');\n }\n if (\n !/^https?:\\/\\//.test(gatewayUrl) ||\n !isTrustedGatewayUrl(gatewayUrl, '')\n ) {\n throw new Error('CI gateway auth requires a trusted gateway origin');\n }\n resetGatewaySession();\n ciAuth = {\n token: token.trim(),\n teamId: projectId,\n gatewayUrl: gatewayUrl.replace(/\\/+$/, ''),\n refreshAtMs: Infinity,\n };\n}\n\n// TODO: CI credential loading belongs outside the agent. It leaves with the rest\n// of this module once RunInput carries resolved inference auth, later in the\n// refactor.\nexport function configureGatewayFromCIEnvironment(\n projectId: number,\n region: CloudRegion,\n): void {\n if (IS_PRODUCTION_BUILD)\n throw new Error('CI gateway auth requires a non-production build');\n const path = runtimeEnv('WIZARD_CI_GATEWAY_TOKEN_FILE');\n if (!path) throw new Error('WIZARD_CI_GATEWAY_TOKEN_FILE is required for CI');\n const token = readFileSync(path, 'utf8');\n delete process.env.WIZARD_CI_GATEWAY_TOKEN_FILE;\n configureGatewayCredentialsForCI(\n token,\n projectId,\n runtimeEnv('WIZARD_CI_GATEWAY_URL') ||\n `https://ai-gateway.${region}.posthog.com`,\n );\n}\n\n/**\n * Adoption floor. The anthropic subprocess holds its credential until a 401\n * forces a re-mint, so a token below this would churn mints.\n */\nconst MIN_USABLE_TTL_MS = 2 * 60 * 1000;\n/** Re-resolve at this fraction of the token's life, leaving a usable remainder. */\nconst REFRESH_AT_FRACTION = 0.8;\n// Exceeds the backend's own 10s gateway timeout: a slow mint that lands after the\n// CLI hangs up spends a daily mint and orphans a live token.\nconst MINT_TIMEOUT_MS = 20_000;\n/** Longer than any refusal the mint writes; a body past this is not a message. */\nconst MAX_REFUSAL_DETAIL_LENGTH = 500;\n/** Outcomes are short snake_case labels; anything longer is not one. */\nconst MAX_REFUSAL_OUTCOME_LENGTH = 64;\n\n/** Resolve this run's gateway auth, minting and re-minting near expiry. */\nexport async function gatewayAuth(\n host: HostResolution,\n accessToken: string,\n program: string | undefined,\n): Promise<GatewayAuth> {\n if (ciAuth) return ciAuth;\n // Keyed by program: a token pins `wizard:<program>`, so reusing one across\n // programs bills the wrong budget. Keyed by login rather than OAuth token:\n // the token rotates mid-run, and each new one would spend a weekly mint.\n const key = `${host.apiHost}\\n${oauthLoginKey(accessToken)}\\n${\n program ?? ''\n }`;\n if (cached && cached.key === key && Date.now() < cached.staleAtMs) {\n return cached.auth;\n }\n if (inFlight && inFlight.key === key) return inFlight.promise;\n const promise = resolveGatewayAuth(host, accessToken, key, program);\n inFlight = { key, promise };\n try {\n return await promise;\n } finally {\n if (inFlight?.promise === promise) inFlight = null;\n }\n}\n\nasync function resolveGatewayAuth(\n host: HostResolution,\n accessToken: string,\n key: string,\n program: string | undefined,\n): Promise<GatewayAuth> {\n if (!program) {\n // Every run has one; absent means a caller was not wired, and the spend would\n // be unattributable.\n logToFile('[gateway] run has no program id; failing the run');\n throw new GatewayMintFailed(\n 'this run has no program to attribute its spend to',\n );\n }\n const minted = await mintGatewayToken(host, accessToken, program);\n const health = await checkLlmGatewayHealth(minted.gatewayUrl);\n if (health.status !== ServiceHealthStatus.Healthy) {\n throw new WizardError(\n 'The PostHog AI gateway is unavailable. Please try again later.',\n undefined,\n ErrorCodes.EnvServiceOutage,\n );\n }\n const expiresAtMs = Date.parse(minted.expiresAt);\n const ttlMs = expiresAtMs - Date.now();\n if (!Number.isFinite(expiresAtMs) || ttlMs < MIN_USABLE_TTL_MS) {\n // Expired, unreadable, or too short to serve a session. Adopting it would\n // 401 mid-run, and downgrading would spend the rest of the run uncapped.\n logToFile(\n `[gateway] mint returned a token with ${ttlMs}ms of life; failing the run`,\n );\n throw new GatewayMintFailed(\n `the PostHog gateway issued a token with ${ttlMs}ms of life`,\n );\n }\n const staleAtMs = Date.now() + ttlMs * REFRESH_AT_FRACTION;\n // Only failures are logged otherwise, so a successful run leaves no\n // local trace. Never log the token itself.\n logToFile(\n `[gateway] minted a scoped token: program=${program} team=${\n minted.teamId ?? 'unknown'\n } ttl=${Math.round(ttlMs / 1000)}s url=${minted.gatewayUrl}`,\n );\n const auth: GatewayAuth = {\n gatewayUrl: minted.gatewayUrl,\n token: minted.token,\n teamId: minted.teamId,\n refreshAtMs: staleAtMs,\n };\n cached = { key, auth, staleAtMs };\n return auth;\n}\n\n/** Test hook: drop the cached auth so the next call re-resolves. */\nexport function resetGatewaySession(): void {\n cached = null;\n inFlight = null;\n ciAuth = null;\n}\n\n/** Whether a 401 on this bearer may be age (past its refresh instant) rather than a bad credential. */\nexport function isPastRefresh(auth: GatewayAuth, now = Date.now()): boolean {\n return now >= auth.refreshAtMs;\n}\n\n/**\n * Whether a server-supplied origin may receive a bearer and prompt content:\n * https (loopback excepted), and either a current cloud gateway or the host the run\n * authenticated against.\n */\nexport function isTrustedGatewayUrl(value: string, apiHost: string): boolean {\n let url: URL;\n try {\n url = new URL(value);\n } catch {\n return false;\n }\n // Consumers append routes to this value, so anything beyond an origin\n // (path, query, fragment, userinfo) would build a malformed endpoint.\n if (\n url.pathname !== '/' ||\n url.search ||\n url.hash ||\n url.username ||\n url.password\n ) {\n return false;\n }\n const localhost =\n url.hostname === 'localhost' ||\n url.hostname === '127.0.0.1' ||\n url.hostname === 'host.docker.internal';\n // Loopback is the dev gateway, and is the one case allowed over http.\n if (localhost) return true;\n if (url.protocol !== 'https:') return false;\n if (url.hostname.endsWith('.posthog.com')) {\n return (\n url.origin === 'https://ai-gateway.us.posthog.com' ||\n url.origin === 'https://ai-gateway.eu.posthog.com'\n );\n }\n try {\n return url.hostname === new URL(apiHost).hostname;\n } catch {\n return false;\n }\n}\n\ninterface MintedToken {\n token: string;\n expiresAt: string;\n gatewayUrl: string;\n teamId?: number;\n}\n\n/**\n * A deliberate refusal from the mint endpoint, as opposed to the mint being\n * unavailable. Thrown so the run stops instead of proceeding without the\n * controls the refusal was enforcing. A WizardError, so the runners print its\n * message as-is and `wizardAbort` resolves its code.\n */\nexport class GatewayMintRefused extends WizardError {\n readonly status: number;\n /** The backend's refusal outcome (`blocked`, `throttled`, ...), when it sent one. */\n readonly outcome?: string;\n\n constructor(status: number, message: string, outcome?: string) {\n super(message, { status, outcome }, ErrorCodes.GatewayMintRefused);\n this.name = 'GatewayMintRefused';\n this.status = status;\n this.outcome = outcome;\n }\n}\n\n/**\n * The mint could not produce a usable credential: unreachable, a 5xx, or a\n * response the client cannot use.\n */\nexport class GatewayMintFailed extends WizardError {\n constructor(message: string) {\n super(message, undefined, ErrorCodes.GatewayMintFailed);\n this.name = 'GatewayMintFailed';\n }\n}\n\n/**\n * Whether a mint status means \"refused this run\" rather than \"not available\".\n * 429 the daily run limit, 403 revoked project access, 400 a login covering\n * more than one project, 401 a credential the mint does not accept, 404 an\n * instance without the mint endpoint.\n */\nfunction isMintRefusal(status: number): boolean {\n return (\n status === 400 ||\n status === 401 ||\n status === 403 ||\n status === 404 ||\n status === 429\n );\n}\n\ninterface MintRefusal {\n detail?: string;\n outcome?: string;\n}\n\n/**\n * The server's own reason for a refusal, when it sent one. DRF answers every\n * refusal as `{\"detail\": \"...\", \"code\": \"<outcome>\"}`; the blocklist's detail\n * names the contact address, which the fixed messages below cannot. `code` is\n * the backend's own label for the refusal (`outcome` on older backends) and\n * rides the client event.\n */\nfunction cleanRefusalText(value: unknown): string {\n if (typeof value !== 'string') return '';\n // Not because the server sends escapes, but because this string is printed\n // straight to a terminal: sanitizing at the boundary means no later message\n // can move the cursor or repaint the screen.\n // eslint-disable-next-line no-control-regex\n return value.replace(/[\\u0000-\\u001f\\u007f-\\u009f]/g, ' ').trim();\n}\n\nasync function readRefusal(resp: Response): Promise<MintRefusal> {\n try {\n const body = (await resp.json()) as {\n detail?: unknown;\n code?: unknown;\n outcome?: unknown;\n };\n const detail = cleanRefusalText(body?.detail);\n // The DRF handler flattens a dict detail, so the outcome rides as `code`.\n // A `code` that cleans to nothing does not shadow a usable `outcome`.\n const outcome =\n cleanRefusalText(body?.code) || cleanRefusalText(body?.outcome);\n return {\n detail:\n detail.length > 0 && detail.length <= MAX_REFUSAL_DETAIL_LENGTH\n ? detail\n : undefined,\n outcome:\n outcome.length > 0 && outcome.length <= MAX_REFUSAL_OUTCOME_LENGTH\n ? outcome\n : undefined,\n };\n } catch {\n return {};\n }\n}\n\nfunction mintRefusalMessage(status: number, detail?: string): string {\n if (detail) return detail;\n switch (status) {\n case 429:\n return 'This wizard program has used its daily run limit. Try again tomorrow.';\n case 403:\n return 'Your access to this project has changed. Re-authenticate and try again.';\n case 400:\n // The only 400 the mint answers is the exactly-one-project check.\n return 'Your PostHog login must cover exactly one project. Re-authenticate and try again.';\n case 401:\n return 'PostHog did not accept this login. Re-authenticate with `npx @posthog/wizard@latest`.';\n case 404:\n return 'This PostHog instance does not issue gateway tokens. Upgrade with `npx @posthog/wizard@latest` and try again.';\n default:\n return 'The PostHog gateway refused this run.';\n }\n}\n\nasync function mintGatewayToken(\n host: HostResolution,\n accessToken: string,\n program: string,\n): Promise<MintedToken> {\n try {\n const resp = await fetch(`${host.apiHost}/api/wizard/gateway_token/`, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${accessToken}`,\n 'Content-Type': 'application/json',\n },\n // The flag tells the server this build reads a refusal, so it may answer\n // with the reason. A build that omits it gets a 404, which is its signal\n // to fall back to the legacy gateway.\n body: JSON.stringify({ program, reads_refusal_reason: true }),\n signal: AbortSignal.timeout(MINT_TIMEOUT_MS),\n });\n if (!resp.ok) {\n if (isMintRefusal(resp.status)) {\n const refusal = await readRefusal(resp);\n logToFile(\n `[gateway] mint refused with HTTP ${resp.status} (${\n refusal.outcome ?? 'no outcome'\n }); failing the run`,\n );\n // The terminal denial event for this run. The backend's own event has\n // no run id, so this is what joins a refusal to the session.\n analytics.wizardCapture('gateway mint refused', {\n status: resp.status,\n outcome: refusal.outcome,\n program,\n });\n throw new GatewayMintRefused(\n resp.status,\n mintRefusalMessage(resp.status, refusal.detail),\n refusal.outcome,\n );\n }\n logToFile(\n `[gateway] mint failed with HTTP ${resp.status}; failing the run`,\n );\n throw new GatewayMintFailed(\n `the PostHog gateway could not issue a token (HTTP ${resp.status})`,\n );\n }\n const body = (await resp.json()) as {\n token?: string;\n expires_at?: string;\n gateway_url?: string;\n team_id?: number;\n };\n // Checked one at a time, not in a loop, so each clause narrows the optional\n // field for the return below and each names itself in the failure.\n if (!body.token) {\n logToFile('[gateway] mint response omitted token; failing the run');\n throw new GatewayMintFailed('mint response omitted token');\n }\n if (!body.expires_at) {\n logToFile('[gateway] mint response omitted expires_at; failing the run');\n throw new GatewayMintFailed('mint response omitted expires_at');\n }\n if (!body.gateway_url) {\n logToFile('[gateway] mint response omitted gateway_url; failing the run');\n throw new GatewayMintFailed('mint response omitted gateway_url');\n }\n if (!isTrustedGatewayUrl(body.gateway_url, host.apiHost)) {\n logToFile(\n '[gateway] mint returned an untrusted gateway url; failing the run',\n );\n throw new GatewayMintFailed('mint returned an untrusted gateway url');\n }\n const gatewayUrl = new URL(body.gateway_url);\n if (\n ['localhost', '127.0.0.1'].includes(new URL(host.apiHost).hostname) &&\n gatewayUrl.hostname === 'host.docker.internal'\n ) {\n gatewayUrl.hostname = 'localhost';\n }\n return {\n token: body.token,\n expiresAt: body.expires_at,\n gatewayUrl: gatewayUrl.origin,\n teamId: body.team_id,\n };\n } catch (e) {\n // Decisions and failures both pass through: this catch exists for transport\n // errors, and folding the others into it would lose the reason.\n if (e instanceof GatewayMintRefused || e instanceof GatewayMintFailed)\n throw e;\n logToFile(\n `[gateway] mint transport failure (${String(e)}); failing the run`,\n );\n throw new GatewayMintFailed(\n `could not reach the PostHog gateway (${String(e)})`,\n );\n }\n}\n\n/**\n * The v2 run-metadata carrier: one JSON blob for the `X-PostHog-Properties`\n * header. Plain keys only, since the gateway strips `$`-prefixed keys as reserved,\n * so feature-flag variants land as `wizard_flag_<key>` instead of the legacy\n * `$feature/<key>` (dashboards keying on `$feature/wizard-*` read the new key\n * post-cutover).\n */\nexport function buildWizardPropertiesBlob(\n wizardMetadata: Record<string, string>,\n wizardFlags: Record<string, string>,\n teamId?: number,\n): string {\n // The gateway pins `$ai_product` to `wizard:<program>`, and rejects a legacy\n // product override on a scoped token, so the unprefixed key every cost and\n // error consumer reads is only present if this blob declares it.\n const props: Record<string, string | number> = { ai_product: 'wizard' };\n if (teamId !== undefined) props.team_id = teamId;\n for (const [key, value] of Object.entries(wizardMetadata)) {\n props[stripPropertyPrefix(key)] = value;\n }\n for (const [flagKey, variant] of Object.entries(wizardFlags)) {\n if (!flagKey.toLowerCase().startsWith('wizard')) continue;\n props[`wizard_flag_${flagKey.toLowerCase()}`] = variant;\n }\n return JSON.stringify(props);\n}\n\nconst LEGACY_PROPERTY_PREFIX = 'X-POSTHOG-PROPERTY-';\n\nfunction stripPropertyPrefix(key: string): string {\n return key.toUpperCase().startsWith(LEGACY_PROPERTY_PREFIX)\n ? key.slice(LEGACY_PROPERTY_PREFIX.length).toLowerCase()\n : key;\n}\n","/**\n * Agent signal vocabulary — the marker strings the agent emits and the error\n * taxonomy the runner returns. Kept as a dependency-free leaf module so both\n * `agent-interface.ts` and `output-signals.ts` can import it without a cycle.\n */\n\nexport const AgentSignals = {\n /** Signal emitted when the agent reports progress to the user */\n STATUS: '[STATUS]',\n /** Signal emitted when the agent cannot access the PostHog MCP server */\n ERROR_MCP_MISSING: '[ERROR-MCP-MISSING]',\n /** Signal emitted when the agent cannot access the setup resource */\n ERROR_RESOURCE_MISSING: '[ERROR-RESOURCE-MISSING]',\n /**\n * Signal emitted when `install_skill` failed and the agent is continuing\n * the integration WITHOUT the skill (best-effort from its own knowledge).\n * Format: \"[SKILL-INSTALL-FAILED] <skill id — reason>\". Non-fatal by\n * design: a freestyled integration beats an outright failure, but the run\n * must be measurable — the runner captures it as an analytics event.\n */\n SKILL_INSTALL_FAILED: '[SKILL-INSTALL-FAILED]',\n /**\n * Signal emitted when the agent cannot complete the program and is\n * aborting intentionally (distinct from errors). Format: \"[ABORT] <reason>\".\n * Programs can declare an onAbort handler to render a custom screen.\n */\n ABORT: '[ABORT]',\n /** Signal emitted when the agent provides a remark about its run */\n WIZARD_REMARK: '[WIZARD-REMARK]',\n /** Signal prefix for benchmark logging */\n BENCHMARK: '[BENCHMARK]',\n /**\n * Signal emitted when the agent has created a PostHog dashboard for the\n * user. Format: `[DASHBOARD_URL] <full https url>`. The URL is captured\n * onto `session.dashboardUrl` and surfaced by programs in their outro.\n */\n DASHBOARD_URL: '[DASHBOARD_URL]',\n /**\n * Signal emitted when the agent has uploaded a report to a PostHog\n * notebook. Format: `[NOTEBOOK_URL] <full https url>`. The URL is captured\n * onto `session.notebookUrl` and surfaced by programs in their outro.\n */\n NOTEBOOK_URL: '[NOTEBOOK_URL]',\n} as const;\n\nexport type AgentSignal = (typeof AgentSignals)[keyof typeof AgentSignals];\n\n/**\n * End-of-run reflection ask, shared by both harnesses so remarks are\n * comparable. The format clause comes FIRST and nothing trails the marker —\n * literal models (gpt-5-mini) echo whatever text follows it. The parser also\n * drops remarks that quote this instruction (see AgentOutputSignals.remark).\n */\nexport const REMARK_INSTRUCTION = `Reply with a single line that starts with ${AgentSignals.WIZARD_REMARK} and no other lines. In that line, state briefly what information or guidance would have been useful to have in the integration prompt or documentation for this run — specifically anything that would have prevented tool failures, erroneous edits, or other wasted turns.`;\n\n/**\n * First prompt of a session resumed after a mid-run re-mint. The transcript\n * carries the work so far; the model only needs to pick it up.\n */\nexport const RESUME_INSTRUCTION =\n 'Your previous request failed with a transient gateway authentication error that has since been fixed. Continue the task from where you left off.';\n\n/**\n * Error types that can be returned from agent execution.\n * These correspond to the error signals that the agent emits.\n */\nexport enum AgentErrorType {\n /** The configured run deadline elapsed and the SDK query was aborted */\n AGENTIC_DETECTION_TIMEOUT = 'WIZARD_AGENTIC_DETECTION_TIMEOUT',\n /** Agent could not access the PostHog MCP server */\n MCP_MISSING = 'WIZARD_MCP_MISSING',\n /** Agent could not access the setup resource */\n RESOURCE_MISSING = 'WIZARD_RESOURCE_MISSING',\n /** API rate limit exceeded */\n RATE_LIMIT = 'WIZARD_RATE_LIMIT',\n /** Generic API error */\n API_ERROR = 'WIZARD_API_ERROR',\n /** YARA scanner detected a security violation */\n YARA_VIOLATION = 'WIZARD_YARA_VIOLATION',\n /** Agent intentionally aborted the program (emitted [ABORT] <reason>) */\n ABORT = 'WIZARD_ABORT',\n /** Agent ended without making a single tool call — a no-op run that did no work */\n NO_PROGRESS = 'WIZARD_NO_PROGRESS',\n /** A schema-bound run ended without output matching its schema */\n INVALID_STRUCTURED_OUTPUT = 'WIZARD_INVALID_STRUCTURED_OUTPUT',\n /** Agent acted but stopped short — planned tasks left open and/or no skill installed */\n INCOMPLETE_TASKS = 'WIZARD_INCOMPLETE_TASKS',\n}\n","/**\n * PostHog AI gateway provider spec for pi sessions, shared by the linear run\n * and the orchestrator's per-task runs so both speak to the gateway\n * identically: bearer auth, the wizard properties header, transport shape\n * inferred from the model id. The caller registers the spec on its own\n * (lazily imported, properly typed) pi ModelRegistry.\n */\n\nimport {\n buildWizardPropertiesBlob,\n isPastRefresh,\n type GatewayAuth,\n} from '@agent/gateway-session';\nimport {\n modelCapabilities,\n type ThinkingLevel,\n} from '../../switchboard/models';\nimport { AgentErrorType } from '@agent/signals';\n\n/** Provider registered on the in-memory registry for this run. */\nexport const GATEWAY_PROVIDER = 'posthog-gateway';\n\n/** The pi transports the gateway serves. */\nexport type GatewayApi =\n | 'anthropic-messages'\n | 'openai-completions'\n | 'openai-responses';\n\n/**\n * The gateway speaks two shapes on two endpoints: Anthropic models over\n * `anthropic-messages` (the SDK appends `/v1/messages`, so the base URL has no\n * `/v1`), and OpenAI-class models (`openai/gpt-5`, …) over an OpenAI shape at\n * `/v1/responses` or `/v1/chat/completions` (base URL keeps `/v1`). Infer the\n * shape from the model id so a pair's model selects the right transport.\n *\n * OpenAI models take the Responses API because OpenAI rejects function tools\n * combined with `reasoning_effort` on chat completions and every task sends both.\n */\nexport function gatewayApiFor(modelId: string): GatewayApi {\n return modelId.startsWith('openai/')\n ? 'openai-responses'\n : 'anthropic-messages';\n}\n\n/**\n * Gateway HTTP headers, mirroring `buildAgentEnv` on the anthropic path: one\n * `X-PostHog-Properties` JSON blob (Bedrock fallback is native, so no opt-in)\n * plus the 1M context beta, since pi otherwise runs at 200k and overflows on\n * larger projects (the post-run compaction failures).\n */\nexport function buildGatewayHeaders(\n wizardMetadata: Record<string, string>,\n wizardFlags: Record<string, string>,\n teamId?: number,\n): Record<string, string> {\n return {\n 'anthropic-beta': 'context-1m-2025-08-07',\n 'X-PostHog-Properties': buildWizardPropertiesBlob(\n wizardMetadata,\n wizardFlags,\n teamId,\n ),\n };\n}\n\nexport interface GatewayProviderInputs {\n gatewayUrl: string;\n accessToken: string;\n /** Customer team for the properties blob (from the mint response). */\n teamId?: number;\n wizardMetadata: Record<string, string>;\n wizardFlags: Record<string, string>;\n modelId: string;\n // Resolved effort override — the switchboard's flag/payload pick on linear\n // runs, the prompt-frontmatter effort on per-task agents. Overrides the\n // table default for a reasoning model when set.\n effort?: ThinkingLevel;\n}\n\n/**\n * One gateway model spec — the single description of how to reach a model on\n * the gateway. The provider spec below wraps it for pi's registry; one-shot\n * callers (scan triage) hand it straight to `completeSimple`.\n */\nexport function buildGatewayModel(inputs: GatewayProviderInputs) {\n const { gatewayUrl, wizardMetadata, wizardFlags, modelId, teamId } = inputs;\n const api = gatewayApiFor(modelId);\n return {\n id: modelId,\n name: `${modelId} (PostHog Gateway)`,\n api,\n provider: GATEWAY_PROVIDER,\n // Anthropic drops /v1 (the SDK appends /v1/messages); the OpenAI shape keeps it.\n baseUrl: api === 'anthropic-messages' ? gatewayUrl : `${gatewayUrl}/v1`,\n // A model trait resolved by the switchboard, not a harness guess:\n // non-reasoning openai models reject `reasoning_effort` (gpt-4o → gateway\n // UnsupportedParamsError → the run no-ops).\n reasoning: modelCapabilities(modelId).reasoning,\n input: ['text' as const],\n cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },\n contextWindow: 1_000_000,\n maxTokens: 64_000,\n headers: buildGatewayHeaders(wizardMetadata, wizardFlags, teamId),\n };\n}\n\n/**\n * The provider object for `registry.registerProvider(GATEWAY_PROVIDER, …)`,\n * plus the derived traits the session setup needs (`caps.thinkingLevel`).\n */\nexport function buildGatewayProvider(inputs: GatewayProviderInputs): {\n provider: Record<string, unknown>;\n api: GatewayApi;\n caps: ReturnType<typeof modelCapabilities>;\n gatewayUrl: string;\n baseUrl: string;\n} {\n const { gatewayUrl, accessToken, modelId, effort } = inputs;\n const api = gatewayApiFor(modelId);\n // One resolution point for the model's traits and the run's effort override.\n // pi clamps whatever comes out of here against the levels this spec declares,\n // so a level the spec doesn't carry is silently reduced by the session.\n const tableCaps = modelCapabilities(modelId);\n const caps =\n effort && effort !== 'off' && tableCaps.reasoning\n ? modelCapabilities(modelId, effort)\n : effort === 'off' && tableCaps.reasoning\n ? { ...tableCaps, thinkingLevel: 'off' as const }\n : tableCaps;\n\n const model = buildGatewayModel(inputs);\n const provider = {\n name: 'PostHog Gateway',\n baseUrl: model.baseUrl,\n apiKey: accessToken,\n authHeader: true,\n api,\n headers: model.headers,\n models: [model],\n };\n return { provider, api, caps, gatewayUrl, baseUrl: model.baseUrl };\n}\n\n/** The part of a pi assistant turn that says why it failed. */\nexport interface GatewayTurnError {\n errorMessage?: string;\n diagnostics?: { error?: { name?: string; code?: string | number } }[];\n}\n\nexport type GatewayTerminalFailure = {\n classification:\n | AgentErrorType.API_ERROR\n | AgentErrorType.RATE_LIMIT\n | AgentErrorType.ABORT;\n message: string;\n status?: number;\n};\n\nexport function gatewayTerminalFailure(\n turn: ({ stopReason?: string } & GatewayTurnError) | undefined,\n): GatewayTerminalFailure | undefined {\n if (!turn || (turn.stopReason !== 'error' && turn.stopReason !== 'aborted'))\n return undefined;\n const message =\n turn.errorMessage ||\n (turn.stopReason === 'aborted'\n ? 'Agent turn aborted'\n : 'Gateway request failed');\n if (turn.stopReason === 'aborted') {\n return { classification: AgentErrorType.ABORT, message };\n }\n const codes =\n turn.diagnostics\n ?.map((d) => d.error?.code)\n .filter((code) => code !== undefined) ?? [];\n const structuredStatus = codes\n .map(Number)\n .find((code) => Number.isInteger(code) && code >= 400 && code < 600);\n const rateLimited =\n structuredStatus !== undefined\n ? structuredStatus === 429\n : /\\b429\\b|rate limit/i.test(message);\n return {\n classification: rateLimited\n ? AgentErrorType.RATE_LIMIT\n : AgentErrorType.API_ERROR,\n message,\n status:\n structuredStatus ?? (isGatewayAuthRejection(turn) ? 401 : undefined),\n };\n}\n\n/**\n * Whether a turn's error is the gateway rejecting the bearer. pi attaches the\n * SDK's own error to `diagnostics`, so its code decides when one is present.\n * The message match is the fallback for a turn that failed before pi built a\n * diagnostic, where the status survives only as prose.\n */\nexport function isGatewayAuthRejection(\n turn: GatewayTurnError | string | undefined,\n): boolean {\n const { errorMessage, diagnostics } =\n typeof turn === 'string'\n ? { errorMessage: turn, diagnostics: undefined }\n : turn ?? {};\n const structuredStatus = (diagnostics ?? [])\n .map((diagnostic) => Number(diagnostic.error?.code))\n .find((code) => Number.isInteger(code) && code >= 400 && code < 600);\n if (structuredStatus !== undefined) return structuredStatus === 401;\n for (const diagnostic of diagnostics ?? []) {\n const code = diagnostic.error?.code;\n if (code === 401 || code === '401') return true;\n if (/^authentication_?error$/i.test(diagnostic.error?.name ?? ''))\n return true;\n }\n return /\\b401\\b|authentication_error|unauthorized/i.test(errorMessage ?? '');\n}\n\nexport interface GatewayRemintOptions {\n signal?: AbortSignal;\n session: { prompt(text: string): Promise<void> };\n registry: { registerProvider(providerName: string, config: never): void };\n auth: GatewayAuth;\n /** The cache: the same token while fresh, a new mint past the refresh point. */\n refreshAuth: () => Promise<GatewayAuth>;\n providerInputs: (auth: GatewayAuth) => GatewayProviderInputs;\n /** The prompt that resumes the work after a re-mint. */\n continueText: string | (() => string);\n onRemint?: () => void;\n}\n\n/**\n * Wraps a pi session's prompt(): when a turn ends on a 401 from a bearer past\n * its refresh instant, mint once, re-register the provider with the new\n * bearer (pi resolves the apiKey per request), and continue. A 401 on a fresh\n * bearer, or a second one, is left to the harness's normal failure path.\n */\nexport function withGatewayRemint(opts: GatewayRemintOptions): {\n prompt(text: string): Promise<void>;\n /** Feed every assistant `message_end`; the last turn decides. */\n noteAssistantTurn(message: unknown): void;\n terminalFailure(): GatewayTerminalFailure | undefined;\n} {\n let auth = opts.auth;\n let rejected = false;\n let reminted = false;\n let lastTurn: ({ stopReason?: string } & GatewayTurnError) | undefined;\n return {\n noteAssistantTurn(message) {\n lastTurn = message as\n | ({ stopReason?: string } & GatewayTurnError)\n | undefined;\n rejected =\n lastTurn?.stopReason === 'error' && isGatewayAuthRejection(lastTurn);\n },\n terminalFailure: () => gatewayTerminalFailure(lastTurn),\n async prompt(text) {\n if (opts.signal?.aborted) return;\n rejected = false;\n lastTurn = undefined;\n await opts.session.prompt(text);\n if (opts.signal?.aborted || !rejected || reminted || !isPastRefresh(auth))\n return;\n reminted = true;\n auth = await opts.refreshAuth();\n if (opts.signal?.aborted) return;\n opts.registry.registerProvider(\n GATEWAY_PROVIDER,\n buildGatewayProvider(opts.providerInputs(auth)).provider as never,\n );\n opts.onRemint?.();\n rejected = false;\n lastTurn = undefined;\n const next = opts.continueText;\n if (opts.signal?.aborted) return;\n await opts.session.prompt(typeof next === 'function' ? next() : next);\n },\n };\n}\n"],"mappings":"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"}
@@ -1,44 +0,0 @@
1
- import "./wizard-session-BYw6LzpS.js";
2
- import { t as LoggingUI } from "./logging-ui-p6XKVmTx.js";
3
- //#region src/ui/headless-ui.ts
4
- /**
5
- * `LoggingUI` plus it feeds run state into a `WizardStore` so the background
6
- * wizard-session sync (`TaskStreamPush`) can observe a headless run. We extend
7
- * `LoggingUI` (not `InkUI`) because its blocking/gate methods would wait on a
8
- * TUI that never renders; the runner drives phase transitions on the store
9
- * directly, so only UI-originated per-run updates tee through here. The audit
10
- * ledger arrives through `setFrameworkContext`, the seam every UI implements.
11
- */
12
- var HeadlessUI = class extends LoggingUI {
13
- constructor(store) {
14
- super();
15
- this.store = store;
16
- }
17
- startRun() {
18
- super.startRun();
19
- this.store.setRunPhase("running");
20
- }
21
- setCredentials(credentials) {
22
- this.store.setAccessToken(credentials);
23
- }
24
- setAccessToken(credentials) {
25
- this.store.setAccessToken(credentials);
26
- }
27
- syncTodos(todos) {
28
- super.syncTodos(todos);
29
- this.store.syncTodos(todos);
30
- }
31
- setHandoffText(text) {
32
- this.store.setHandoffText(text);
33
- }
34
- setFrameworkContext(key, value) {
35
- this.store.setFrameworkContext(key, value);
36
- }
37
- getFrameworkContext(key) {
38
- return this.store.session.frameworkContext[key];
39
- }
40
- };
41
- //#endregion
42
- export { HeadlessUI };
43
-
44
- //# sourceMappingURL=headless-ui-CUbv12Yx.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"headless-ui-CUbv12Yx.js","names":[],"sources":["../src/ui/headless-ui.ts"],"sourcesContent":["import { RunPhase, type Credentials } from '@programs/session/wizard-session';\nimport { LoggingUI } from '../headless/renderers/logging-ui';\nimport type { WizardStore } from '../tui/store';\n\n/**\n * `LoggingUI` plus it feeds run state into a `WizardStore` so the background\n * wizard-session sync (`TaskStreamPush`) can observe a headless run. We extend\n * `LoggingUI` (not `InkUI`) because its blocking/gate methods would wait on a\n * TUI that never renders; the runner drives phase transitions on the store\n * directly, so only UI-originated per-run updates tee through here. The audit\n * ledger arrives through `setFrameworkContext`, the seam every UI implements.\n */\nexport class HeadlessUI extends LoggingUI {\n constructor(private readonly store: WizardStore) {\n super();\n }\n\n startRun(): void {\n super.startRun();\n this.store.setRunPhase(RunPhase.Running);\n }\n\n setCredentials(credentials: Credentials): void {\n this.store.setAccessToken(credentials);\n }\n\n setAccessToken(credentials: Credentials): void {\n this.store.setAccessToken(credentials);\n }\n\n syncTodos(\n todos: Array<{\n id?: string;\n source?: string;\n content: string;\n status: string;\n activeForm?: string;\n }>,\n ): void {\n super.syncTodos(todos);\n this.store.syncTodos(todos);\n }\n\n setHandoffText(text: string): void {\n this.store.setHandoffText(text);\n }\n\n setFrameworkContext(key: string, value: unknown): void {\n this.store.setFrameworkContext(key, value);\n }\n\n getFrameworkContext(key: string): unknown {\n return this.store.session.frameworkContext[key];\n }\n}\n"],"mappings":";;;;;;;;;;;AAYA,IAAa,aAAb,cAAgC,UAAU;CACxC,YAAY,OAAqC;AAC/C,SAAO;AADoB,OAAA,QAAA;;CAI7B,WAAiB;AACf,QAAM,UAAU;AAChB,OAAK,MAAM,YAAA,UAA6B;;CAG1C,eAAe,aAAgC;AAC7C,OAAK,MAAM,eAAe,YAAY;;CAGxC,eAAe,aAAgC;AAC7C,OAAK,MAAM,eAAe,YAAY;;CAGxC,UACE,OAOM;AACN,QAAM,UAAU,MAAM;AACtB,OAAK,MAAM,UAAU,MAAM;;CAG7B,eAAe,MAAoB;AACjC,OAAK,MAAM,eAAe,KAAK;;CAGjC,oBAAoB,KAAa,OAAsB;AACrD,OAAK,MAAM,oBAAoB,KAAK,MAAM;;CAG5C,oBAAoB,KAAsB;AACxC,SAAO,KAAK,MAAM,QAAQ,iBAAiB"}