@rulemetric/cli 0.7.3 → 0.7.5

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 (550) hide show
  1. package/README.md +10 -8
  2. package/dist/base-command.js +1 -14
  3. package/dist/chunk-2JRDG4LJ.js +31 -0
  4. package/dist/chunk-2TC6WCUT.js +34 -0
  5. package/dist/chunk-2WLVDSAP.js +2 -0
  6. package/dist/chunk-32EEBARV.js +1 -0
  7. package/dist/chunk-3AV3GTMP.js +1 -0
  8. package/dist/chunk-43YBXX7R.js +1 -0
  9. package/dist/chunk-4Z5ECCJE.js +1 -0
  10. package/dist/chunk-5RBLIVBF.js +1 -0
  11. package/dist/chunk-67QCYUJU.js +1 -0
  12. package/dist/chunk-6QKI756T.js +2 -0
  13. package/dist/chunk-6V4WM73L.js +1 -0
  14. package/dist/chunk-6XEC6474.js +1 -0
  15. package/dist/chunk-7DFNBRLY.js +61 -0
  16. package/dist/chunk-ARNZQBMX.js +1 -0
  17. package/dist/chunk-AYUJY37O.js +5 -0
  18. package/dist/chunk-CADKBP3D.js +58 -0
  19. package/dist/chunk-CDI5CCHU.js +1 -0
  20. package/dist/chunk-CNQ5DTNC.js +1 -0
  21. package/dist/chunk-DCLWFGEA.js +1 -0
  22. package/dist/chunk-DNF4HDI6.js +14 -0
  23. package/dist/chunk-DPFNJZUO.js +1 -0
  24. package/dist/chunk-DSO2U4Y6.js +56 -0
  25. package/dist/chunk-DVN7GFJG.js +1 -0
  26. package/dist/chunk-G63KMH6U.js +1 -0
  27. package/dist/chunk-G6XGDHGC.js +2 -0
  28. package/dist/chunk-GBMF3TP6.js +1 -0
  29. package/dist/chunk-GY5IJ4RS.js +1 -0
  30. package/dist/chunk-H2ORWIEY.js +1 -0
  31. package/dist/chunk-H4SV7FN4.js +1 -0
  32. package/dist/chunk-HS7X43XE.js +24 -0
  33. package/dist/{chunk-OQBBVTDG.js → chunk-I2DZGJRR.js} +6 -71
  34. package/dist/chunk-IZTIYR5Q.js +2 -0
  35. package/dist/chunk-JAPCCEKF.js +3 -0
  36. package/dist/chunk-JQTGQXUX.js +1 -0
  37. package/dist/chunk-KAF3CYRW.js +9 -0
  38. package/dist/chunk-KKDHD4XA.js +2 -0
  39. package/dist/chunk-KV325CXF.js +33 -0
  40. package/dist/chunk-MGHFDHHM.js +1 -0
  41. package/dist/chunk-MODXEGCU.js +1 -0
  42. package/dist/chunk-MVM6OGAF.js +4 -0
  43. package/dist/chunk-N7ODX6PO.js +1 -0
  44. package/dist/chunk-N7TGRFVZ.js +70 -0
  45. package/dist/chunk-NBTC5FNV.js +1 -0
  46. package/dist/chunk-NEACEHQD.js +1 -0
  47. package/dist/chunk-NJ5UED3H.js +1 -0
  48. package/dist/chunk-NVKX36YN.js +3 -0
  49. package/dist/chunk-O2SDD2WW.js +1 -0
  50. package/dist/chunk-O6C2UGBY.js +7 -0
  51. package/dist/chunk-OMXUK4M6.js +1 -0
  52. package/dist/chunk-PPKPCXJD.js +4 -0
  53. package/dist/{chunk-XZXS2W24.js → chunk-QFVGUZDO.js} +11 -57
  54. package/dist/chunk-RDET7CKR.js +1 -0
  55. package/dist/chunk-RQ424GI6.js +5 -0
  56. package/dist/chunk-RSKQRVPJ.js +1 -0
  57. package/dist/chunk-RTWRHIKY.js +7 -0
  58. package/dist/chunk-SZ62CP55.js +1 -0
  59. package/dist/chunk-TDD7IOV2.js +1 -0
  60. package/dist/chunk-TIOKY2IA.js +1 -0
  61. package/dist/chunk-TQMG647B.js +15 -0
  62. package/dist/chunk-TU2AR6XO.js +1 -0
  63. package/dist/chunk-U6ABMRT3.js +9 -0
  64. package/dist/chunk-U6XEU573.js +1 -0
  65. package/dist/chunk-UF6US7VU.js +1 -0
  66. package/dist/chunk-V44SRRYR.js +1 -0
  67. package/dist/chunk-V5U3E4BZ.js +1 -0
  68. package/dist/chunk-VAXRCSSH.js +2 -0
  69. package/dist/chunk-VLOX6KOM.js +1 -0
  70. package/dist/chunk-VUGRXM7R.js +1 -0
  71. package/dist/chunk-W2MOTOQE.js +1 -0
  72. package/dist/chunk-W2MV25SB.js +1 -0
  73. package/dist/chunk-WLVQJH4E.js +1 -0
  74. package/dist/chunk-WSCK4WNK.js +1 -0
  75. package/dist/chunk-XICLXXRH.js +1 -0
  76. package/dist/chunk-XXDZJ6YI.js +1 -0
  77. package/dist/chunk-ZL4MZMUK.js +34 -0
  78. package/dist/chunk-ZLLER3HP.js +1 -0
  79. package/dist/chunk-ZR3MUNLS.js +1 -0
  80. package/dist/chunk-ZXF5NE54.js +1 -0
  81. package/dist/commands/antigravity/backfill.js +2 -136
  82. package/dist/commands/auth/create-key.js +1 -52
  83. package/dist/commands/auth/login.js +1 -85
  84. package/dist/commands/auth/logout.js +1 -29
  85. package/dist/commands/auth/revoke-key.js +4 -33
  86. package/dist/commands/auth/signup.js +1 -89
  87. package/dist/commands/auth/status.js +1 -42
  88. package/dist/commands/catalog/index.js +2 -52
  89. package/dist/commands/catalog/recommend.js +3 -43
  90. package/dist/commands/convert.js +1 -75
  91. package/dist/commands/converters.js +1 -54
  92. package/dist/commands/crons/list.js +1 -41
  93. package/dist/commands/crons/run.js +2 -76
  94. package/dist/commands/dashboard.js +1 -46
  95. package/dist/commands/diagnostics.js +1 -117
  96. package/dist/commands/eval-targets/create.js +1 -53
  97. package/dist/commands/eval-targets/list.js +1 -54
  98. package/dist/commands/evals/agent.js +3 -310
  99. package/dist/commands/evals/benchmark.js +6 -73
  100. package/dist/commands/evals/compare.js +13 -96
  101. package/dist/commands/evals/create.js +1 -67
  102. package/dist/commands/evals/optimize-description.js +25 -239
  103. package/dist/commands/evals/optimize.js +5 -211
  104. package/dist/commands/evals/run.js +3 -183
  105. package/dist/commands/gateway/ensure.js +1 -104
  106. package/dist/commands/hooks/emit-instructions.js +1 -25
  107. package/dist/commands/hooks/install.js +1 -442
  108. package/dist/commands/hooks/run.js +3 -81
  109. package/dist/commands/hooks/uninstall.js +2 -156
  110. package/dist/commands/import.js +1 -66
  111. package/dist/commands/instructions/create.js +1 -74
  112. package/dist/commands/instructions/delete.js +1 -55
  113. package/dist/commands/instructions/fork.js +1 -34
  114. package/dist/commands/instructions/get.js +1 -68
  115. package/dist/commands/instructions/list.js +1 -65
  116. package/dist/commands/instructions/promote.js +1 -42
  117. package/dist/commands/instructions/pull.js +1 -39
  118. package/dist/commands/instructions/upstream.js +1 -38
  119. package/dist/commands/instructions/versions.js +1 -53
  120. package/dist/commands/launcher.js +1 -40
  121. package/dist/commands/org/current.js +1 -77
  122. package/dist/commands/org/list.js +1 -52
  123. package/dist/commands/org/switch.js +1 -71
  124. package/dist/commands/packs/add-instruction.js +1 -37
  125. package/dist/commands/packs/apply.js +1 -39
  126. package/dist/commands/packs/create.js +1 -50
  127. package/dist/commands/packs/fork.js +1 -34
  128. package/dist/commands/packs/get.js +3 -56
  129. package/dist/commands/packs/list.js +1 -66
  130. package/dist/commands/packs/remove-instruction.js +1 -35
  131. package/dist/commands/proxy/env.js +3 -131
  132. package/dist/commands/proxy/logs.js +3 -85
  133. package/dist/commands/proxy/restart.js +1 -35
  134. package/dist/commands/proxy/setup.js +17 -454
  135. package/dist/commands/proxy/start.js +10 -333
  136. package/dist/commands/proxy/status.js +1 -78
  137. package/dist/commands/proxy/stop.js +1 -94
  138. package/dist/commands/research/backfill.js +1 -59
  139. package/dist/commands/research/tail-transcript.js +1 -70
  140. package/dist/commands/service/install.js +57 -796
  141. package/dist/commands/service/status.js +1 -180
  142. package/dist/commands/service/uninstall.js +1 -119
  143. package/dist/commands/sessions/analyze.js +1 -48
  144. package/dist/commands/sessions/end.js +2 -85
  145. package/dist/commands/sessions/import.js +1 -46
  146. package/dist/commands/sessions/list.js +1 -48
  147. package/dist/commands/sessions/start.js +3 -90
  148. package/dist/commands/setup.js +3 -150
  149. package/dist/commands/skills/export-approved.js +1 -46
  150. package/dist/commands/skills/install.js +4 -107
  151. package/dist/commands/skills/list.js +4 -65
  152. package/dist/commands/skills/publish.js +2 -98
  153. package/dist/commands/skills/search.js +3 -72
  154. package/dist/commands/skills/update.js +3 -55
  155. package/dist/commands/suggestions/accept.js +8 -84
  156. package/dist/commands/suggestions/dismiss.js +1 -45
  157. package/dist/commands/suggestions/list.js +2 -61
  158. package/dist/commands/suggestions/refresh.js +1 -27
  159. package/dist/cursor-T7AMCMKS.js +13 -0
  160. package/dist/dashboard/Dashboard.js +1 -243
  161. package/dist/dashboard/data.js +1 -15
  162. package/dist/dashboard/launcher/ActiveJobsList.js +1 -10
  163. package/dist/dashboard/launcher/LauncherOverlay.js +1 -16
  164. package/dist/dashboard/launcher/NewLaunchForm.js +1 -10
  165. package/dist/dashboard/launcher/api.js +1 -16
  166. package/dist/dashboard/launcher/tool-labels.js +1 -10
  167. package/dist/dashboard/launcher/types.js +0 -1
  168. package/dist/dashboard/launcher/useLaunchJobs.js +1 -11
  169. package/dist/dashboard/panels/friction.js +1 -10
  170. package/dist/dashboard/panels/insights.js +1 -10
  171. package/dist/dashboard/panels/instructions.js +1 -10
  172. package/dist/dashboard/panels/outcomes.js +1 -10
  173. package/dist/dashboard/panels/overview.js +1 -10
  174. package/dist/dashboard/panels/shared.js +1 -19
  175. package/dist/dashboard/types.js +1 -24
  176. package/dist/dist-FAVALJ5C.js +1 -0
  177. package/dist/index.js +1 -8
  178. package/dist/lib/active-org-refresh.js +1 -15
  179. package/dist/lib/active-org.js +1 -16
  180. package/dist/lib/agent-loop.js +1 -47
  181. package/dist/lib/antigravity-transcript.js +1 -22
  182. package/dist/lib/api-client.js +1 -23
  183. package/dist/lib/auth.js +1 -30
  184. package/dist/lib/capture-hosts.js +1 -8
  185. package/dist/lib/detect-languages.js +1 -8
  186. package/dist/lib/detect-tmux.js +1 -9
  187. package/dist/lib/diagnostics.js +1 -12
  188. package/dist/lib/editor-proxy-pins.js +1 -14
  189. package/dist/lib/ensure-api-key.js +1 -11
  190. package/dist/lib/ensure-fresh-token.js +1 -0
  191. package/dist/lib/eval-analyzer.js +1 -9
  192. package/dist/lib/eval-benchmark.js +1 -12
  193. package/dist/lib/eval-conversation-handler.js +1 -13
  194. package/dist/lib/eval-executor.js +1 -8
  195. package/dist/lib/eval-grader.js +1 -9
  196. package/dist/lib/eval-meta-judge.js +1 -9
  197. package/dist/lib/eval-trigger-tester.js +1 -11
  198. package/dist/lib/eval-worktree.js +1 -8
  199. package/dist/lib/gateway-entry.js +1 -61
  200. package/dist/lib/gateway-identity.js +1 -16
  201. package/dist/lib/gateway-lifecycle.js +1 -32
  202. package/dist/lib/gateway.js +1 -14
  203. package/dist/lib/handlers/cron-refresh-pricing.js +1 -0
  204. package/dist/lib/handlers/cron-refresh-skills.js +1 -8
  205. package/dist/lib/handlers/cron-suggest-instructions.js +1 -16
  206. package/dist/lib/handlers/process-announcement.js +1 -11
  207. package/dist/lib/handlers/process-changelog.js +1 -11
  208. package/dist/lib/handlers/process-conversation.js +1 -14
  209. package/dist/lib/handlers/process-eval.js +1 -15
  210. package/dist/lib/handlers/process-insights.js +1 -15
  211. package/dist/lib/handlers/process-launch.js +1 -16
  212. package/dist/lib/handlers/process-run-cleanup.js +1 -13
  213. package/dist/lib/handlers/process-send-message.js +1 -10
  214. package/dist/lib/handlers/process-session-goal.js +1 -12
  215. package/dist/lib/hooks-config.js +1 -81
  216. package/dist/lib/insights-prompts.js +1 -12
  217. package/dist/lib/instruction-snapshot.js +1 -8
  218. package/dist/lib/job-helpers.js +0 -1
  219. package/dist/lib/llm-client.js +1 -20
  220. package/dist/lib/manual-tasks-meta.js +1 -8
  221. package/dist/lib/manual-tasks.js +1 -80
  222. package/dist/lib/output.js +1 -12
  223. package/dist/lib/permanent-job-error.js +1 -10
  224. package/dist/lib/pid-identity.js +1 -14
  225. package/dist/lib/proxy-respawn.js +1 -12
  226. package/dist/lib/research-client.js +1 -12
  227. package/dist/lib/setup-steps.js +1 -33
  228. package/dist/lib/skills-loader.js +1 -8
  229. package/dist/lib/statusline-shim.js +1 -20
  230. package/dist/lib/telemetry.js +1 -16
  231. package/dist/lib/terminal-target-heartbeat.js +1 -15
  232. package/dist/lib/tmux.js +1 -16
  233. package/dist/lib/transcript-rate-limit-watcher.js +1 -22
  234. package/dist/lib/types.js +1 -8
  235. package/dist/lib/version-check.js +1 -12
  236. package/dist/lib/which.js +1 -8
  237. package/dist/lib/worktree.js +1 -17
  238. package/dist/opencode-QRJ3BH23.js +1 -0
  239. package/oclif.manifest.json +12 -34
  240. package/package.json +9 -8
  241. package/dist/base-command.js.map +0 -7
  242. package/dist/chunk-2HK7RGZB.js +0 -82
  243. package/dist/chunk-2HK7RGZB.js.map +0 -7
  244. package/dist/chunk-2ORJWTNZ.js +0 -307
  245. package/dist/chunk-2ORJWTNZ.js.map +0 -7
  246. package/dist/chunk-37LN5O7M.js +0 -59
  247. package/dist/chunk-37LN5O7M.js.map +0 -7
  248. package/dist/chunk-3S7223UR.js +0 -81
  249. package/dist/chunk-3S7223UR.js.map +0 -7
  250. package/dist/chunk-3TIMQ3O6.js +0 -96
  251. package/dist/chunk-3TIMQ3O6.js.map +0 -7
  252. package/dist/chunk-42GFSAJP.js +0 -32
  253. package/dist/chunk-42GFSAJP.js.map +0 -7
  254. package/dist/chunk-4BHDHHKL.js +0 -48
  255. package/dist/chunk-4BHDHHKL.js.map +0 -7
  256. package/dist/chunk-4D537GXE.js +0 -99
  257. package/dist/chunk-4D537GXE.js.map +0 -7
  258. package/dist/chunk-4LYCDS2N.js +0 -139
  259. package/dist/chunk-4LYCDS2N.js.map +0 -7
  260. package/dist/chunk-4SCZK7AL.js +0 -129
  261. package/dist/chunk-4SCZK7AL.js.map +0 -7
  262. package/dist/chunk-4XAWK6S2.js +0 -161
  263. package/dist/chunk-4XAWK6S2.js.map +0 -7
  264. package/dist/chunk-52WIYRZH.js +0 -73
  265. package/dist/chunk-52WIYRZH.js.map +0 -7
  266. package/dist/chunk-5BAOGNUH.js +0 -79
  267. package/dist/chunk-5BAOGNUH.js.map +0 -7
  268. package/dist/chunk-5EDMGK3W.js +0 -39
  269. package/dist/chunk-5EDMGK3W.js.map +0 -7
  270. package/dist/chunk-6NBS5XFS.js +0 -99
  271. package/dist/chunk-6NBS5XFS.js.map +0 -7
  272. package/dist/chunk-7LVVKQMZ.js +0 -98
  273. package/dist/chunk-7LVVKQMZ.js.map +0 -7
  274. package/dist/chunk-7NNFYWKK.js +0 -243
  275. package/dist/chunk-7NNFYWKK.js.map +0 -7
  276. package/dist/chunk-7NYKWN7U.js +0 -12
  277. package/dist/chunk-7NYKWN7U.js.map +0 -7
  278. package/dist/chunk-BO76WKJR.js +0 -42
  279. package/dist/chunk-BO76WKJR.js.map +0 -7
  280. package/dist/chunk-BRD5RUGM.js +0 -53
  281. package/dist/chunk-BRD5RUGM.js.map +0 -7
  282. package/dist/chunk-BT6Z6545.js +0 -43
  283. package/dist/chunk-BT6Z6545.js.map +0 -7
  284. package/dist/chunk-BZDKEQKU.js +0 -39
  285. package/dist/chunk-BZDKEQKU.js.map +0 -7
  286. package/dist/chunk-DGHWRQXL.js +0 -17
  287. package/dist/chunk-DGHWRQXL.js.map +0 -7
  288. package/dist/chunk-DIQUV5FR.js +0 -257
  289. package/dist/chunk-DIQUV5FR.js.map +0 -7
  290. package/dist/chunk-DMX5YOTM.js +0 -167
  291. package/dist/chunk-DMX5YOTM.js.map +0 -7
  292. package/dist/chunk-DNKSVWMD.js +0 -108
  293. package/dist/chunk-DNKSVWMD.js.map +0 -7
  294. package/dist/chunk-DQ3KELXD.js +0 -74
  295. package/dist/chunk-DQ3KELXD.js.map +0 -7
  296. package/dist/chunk-DUJSRBLP.js +0 -122
  297. package/dist/chunk-DUJSRBLP.js.map +0 -7
  298. package/dist/chunk-E3BIT53W.js +0 -154
  299. package/dist/chunk-E3BIT53W.js.map +0 -7
  300. package/dist/chunk-EARWG4EV.js +0 -22
  301. package/dist/chunk-EARWG4EV.js.map +0 -7
  302. package/dist/chunk-EI5BHWXA.js +0 -1662
  303. package/dist/chunk-EI5BHWXA.js.map +0 -7
  304. package/dist/chunk-EJ3YAFDP.js +0 -37
  305. package/dist/chunk-EJ3YAFDP.js.map +0 -7
  306. package/dist/chunk-EKJ2CABV.js +0 -76
  307. package/dist/chunk-EKJ2CABV.js.map +0 -7
  308. package/dist/chunk-EKP32DLN.js +0 -16
  309. package/dist/chunk-EKP32DLN.js.map +0 -7
  310. package/dist/chunk-EYPAAGN5.js +0 -51
  311. package/dist/chunk-EYPAAGN5.js.map +0 -7
  312. package/dist/chunk-F5N6CLJJ.js +0 -1995
  313. package/dist/chunk-F5N6CLJJ.js.map +0 -7
  314. package/dist/chunk-GIUBARWS.js +0 -99
  315. package/dist/chunk-GIUBARWS.js.map +0 -7
  316. package/dist/chunk-GQNJO2P2.js +0 -102
  317. package/dist/chunk-GQNJO2P2.js.map +0 -7
  318. package/dist/chunk-IJGF2ETG.js +0 -68
  319. package/dist/chunk-IJGF2ETG.js.map +0 -7
  320. package/dist/chunk-ILYDELUE.js +0 -46
  321. package/dist/chunk-ILYDELUE.js.map +0 -7
  322. package/dist/chunk-J6QFW4LD.js +0 -55
  323. package/dist/chunk-J6QFW4LD.js.map +0 -7
  324. package/dist/chunk-J7N3DLH6.js +0 -117
  325. package/dist/chunk-J7N3DLH6.js.map +0 -7
  326. package/dist/chunk-JFDWKLQC.js +0 -23
  327. package/dist/chunk-JFDWKLQC.js.map +0 -7
  328. package/dist/chunk-JULOLTZS.js +0 -61
  329. package/dist/chunk-JULOLTZS.js.map +0 -7
  330. package/dist/chunk-KJKBDQ4D.js +0 -220
  331. package/dist/chunk-KJKBDQ4D.js.map +0 -7
  332. package/dist/chunk-KRBQLMOP.js +0 -41
  333. package/dist/chunk-KRBQLMOP.js.map +0 -7
  334. package/dist/chunk-LXKPNATC.js +0 -624
  335. package/dist/chunk-LXKPNATC.js.map +0 -7
  336. package/dist/chunk-NSBPE2FW.js +0 -17
  337. package/dist/chunk-NSBPE2FW.js.map +0 -7
  338. package/dist/chunk-OCKHW72U.js +0 -55
  339. package/dist/chunk-OCKHW72U.js.map +0 -7
  340. package/dist/chunk-OKWCKCPE.js +0 -414
  341. package/dist/chunk-OKWCKCPE.js.map +0 -7
  342. package/dist/chunk-OO7JDFS4.js +0 -157
  343. package/dist/chunk-OO7JDFS4.js.map +0 -7
  344. package/dist/chunk-OQBBVTDG.js.map +0 -7
  345. package/dist/chunk-OQSQC7VB.js +0 -77
  346. package/dist/chunk-OQSQC7VB.js.map +0 -7
  347. package/dist/chunk-PED7L5GX.js +0 -92
  348. package/dist/chunk-PED7L5GX.js.map +0 -7
  349. package/dist/chunk-QJQS6TUN.js +0 -44
  350. package/dist/chunk-QJQS6TUN.js.map +0 -7
  351. package/dist/chunk-QN34TGD3.js +0 -83
  352. package/dist/chunk-QN34TGD3.js.map +0 -7
  353. package/dist/chunk-QSN77T7C.js +0 -250
  354. package/dist/chunk-QSN77T7C.js.map +0 -7
  355. package/dist/chunk-R56PH7YE.js +0 -78
  356. package/dist/chunk-R56PH7YE.js.map +0 -7
  357. package/dist/chunk-RAXRZYOB.js +0 -299
  358. package/dist/chunk-RAXRZYOB.js.map +0 -7
  359. package/dist/chunk-RH7NHVSK.js +0 -16
  360. package/dist/chunk-RH7NHVSK.js.map +0 -7
  361. package/dist/chunk-RMTT4KDY.js +0 -191
  362. package/dist/chunk-RMTT4KDY.js.map +0 -7
  363. package/dist/chunk-RQ2TMLKG.js +0 -142
  364. package/dist/chunk-RQ2TMLKG.js.map +0 -7
  365. package/dist/chunk-SO3T35U7.js +0 -80
  366. package/dist/chunk-SO3T35U7.js.map +0 -7
  367. package/dist/chunk-UKMLICWS.js +0 -51
  368. package/dist/chunk-UKMLICWS.js.map +0 -7
  369. package/dist/chunk-VA5FFOS7.js +0 -243
  370. package/dist/chunk-VA5FFOS7.js.map +0 -7
  371. package/dist/chunk-W2YERO7E.js +0 -170
  372. package/dist/chunk-W2YERO7E.js.map +0 -7
  373. package/dist/chunk-W53GKIZQ.js +0 -50
  374. package/dist/chunk-W53GKIZQ.js.map +0 -7
  375. package/dist/chunk-WA4MWYRW.js +0 -254
  376. package/dist/chunk-WA4MWYRW.js.map +0 -7
  377. package/dist/chunk-XC6M4CSW.js +0 -44
  378. package/dist/chunk-XC6M4CSW.js.map +0 -7
  379. package/dist/chunk-XK42ZBDE.js +0 -23
  380. package/dist/chunk-XK42ZBDE.js.map +0 -7
  381. package/dist/chunk-XUV6DDBF.js +0 -124
  382. package/dist/chunk-XUV6DDBF.js.map +0 -7
  383. package/dist/chunk-XZXS2W24.js.map +0 -7
  384. package/dist/chunk-Y3WD5CSW.js +0 -49
  385. package/dist/chunk-Y3WD5CSW.js.map +0 -7
  386. package/dist/chunk-Y4BJXXYV.js +0 -148
  387. package/dist/chunk-Y4BJXXYV.js.map +0 -7
  388. package/dist/chunk-YNIH3KMU.js +0 -121
  389. package/dist/chunk-YNIH3KMU.js.map +0 -7
  390. package/dist/chunk-ZUJBM6HE.js +0 -125
  391. package/dist/chunk-ZUJBM6HE.js.map +0 -7
  392. package/dist/commands/antigravity/backfill.js.map +0 -7
  393. package/dist/commands/auth/create-key.js.map +0 -7
  394. package/dist/commands/auth/login.js.map +0 -7
  395. package/dist/commands/auth/logout.js.map +0 -7
  396. package/dist/commands/auth/revoke-key.js.map +0 -7
  397. package/dist/commands/auth/signup.js.map +0 -7
  398. package/dist/commands/auth/status.js.map +0 -7
  399. package/dist/commands/catalog/index.js.map +0 -7
  400. package/dist/commands/catalog/recommend.js.map +0 -7
  401. package/dist/commands/convert.js.map +0 -7
  402. package/dist/commands/converters.js.map +0 -7
  403. package/dist/commands/crons/list.js.map +0 -7
  404. package/dist/commands/crons/run.js.map +0 -7
  405. package/dist/commands/dashboard.js.map +0 -7
  406. package/dist/commands/diagnostics.js.map +0 -7
  407. package/dist/commands/eval-targets/create.js.map +0 -7
  408. package/dist/commands/eval-targets/list.js.map +0 -7
  409. package/dist/commands/evals/agent.js.map +0 -7
  410. package/dist/commands/evals/benchmark.js.map +0 -7
  411. package/dist/commands/evals/compare.js.map +0 -7
  412. package/dist/commands/evals/create.js.map +0 -7
  413. package/dist/commands/evals/optimize-description.js.map +0 -7
  414. package/dist/commands/evals/optimize.js.map +0 -7
  415. package/dist/commands/evals/run.js.map +0 -7
  416. package/dist/commands/gateway/ensure.js.map +0 -7
  417. package/dist/commands/hooks/emit-instructions.js.map +0 -7
  418. package/dist/commands/hooks/install.js.map +0 -7
  419. package/dist/commands/hooks/run.js.map +0 -7
  420. package/dist/commands/hooks/uninstall.js.map +0 -7
  421. package/dist/commands/import.js.map +0 -7
  422. package/dist/commands/instructions/create.js.map +0 -7
  423. package/dist/commands/instructions/delete.js.map +0 -7
  424. package/dist/commands/instructions/fork.js.map +0 -7
  425. package/dist/commands/instructions/get.js.map +0 -7
  426. package/dist/commands/instructions/list.js.map +0 -7
  427. package/dist/commands/instructions/promote.js.map +0 -7
  428. package/dist/commands/instructions/pull.js.map +0 -7
  429. package/dist/commands/instructions/upstream.js.map +0 -7
  430. package/dist/commands/instructions/versions.js.map +0 -7
  431. package/dist/commands/launcher.js.map +0 -7
  432. package/dist/commands/org/current.js.map +0 -7
  433. package/dist/commands/org/list.js.map +0 -7
  434. package/dist/commands/org/switch.js.map +0 -7
  435. package/dist/commands/packs/add-instruction.js.map +0 -7
  436. package/dist/commands/packs/apply.js.map +0 -7
  437. package/dist/commands/packs/create.js.map +0 -7
  438. package/dist/commands/packs/fork.js.map +0 -7
  439. package/dist/commands/packs/get.js.map +0 -7
  440. package/dist/commands/packs/list.js.map +0 -7
  441. package/dist/commands/packs/remove-instruction.js.map +0 -7
  442. package/dist/commands/proxy/env.js.map +0 -7
  443. package/dist/commands/proxy/logs.js.map +0 -7
  444. package/dist/commands/proxy/restart.js.map +0 -7
  445. package/dist/commands/proxy/setup.js.map +0 -7
  446. package/dist/commands/proxy/start.js.map +0 -7
  447. package/dist/commands/proxy/status.js.map +0 -7
  448. package/dist/commands/proxy/stop.js.map +0 -7
  449. package/dist/commands/research/backfill.js.map +0 -7
  450. package/dist/commands/research/tail-transcript.js.map +0 -7
  451. package/dist/commands/service/install.js.map +0 -7
  452. package/dist/commands/service/status.js.map +0 -7
  453. package/dist/commands/service/uninstall.js.map +0 -7
  454. package/dist/commands/sessions/analyze.js.map +0 -7
  455. package/dist/commands/sessions/end.js.map +0 -7
  456. package/dist/commands/sessions/import.js.map +0 -7
  457. package/dist/commands/sessions/list.js.map +0 -7
  458. package/dist/commands/sessions/start.js.map +0 -7
  459. package/dist/commands/setup.js.map +0 -7
  460. package/dist/commands/skills/export-approved.js.map +0 -7
  461. package/dist/commands/skills/install.js.map +0 -7
  462. package/dist/commands/skills/list.js.map +0 -7
  463. package/dist/commands/skills/publish.js.map +0 -7
  464. package/dist/commands/skills/search.js.map +0 -7
  465. package/dist/commands/skills/update.js.map +0 -7
  466. package/dist/commands/suggestions/accept.js.map +0 -7
  467. package/dist/commands/suggestions/dismiss.js.map +0 -7
  468. package/dist/commands/suggestions/list.js.map +0 -7
  469. package/dist/commands/suggestions/refresh.js.map +0 -7
  470. package/dist/cursor-BGQJ4CWI.js +0 -134
  471. package/dist/cursor-BGQJ4CWI.js.map +0 -7
  472. package/dist/dashboard/Dashboard.js.map +0 -7
  473. package/dist/dashboard/data.js.map +0 -7
  474. package/dist/dashboard/launcher/ActiveJobsList.js.map +0 -7
  475. package/dist/dashboard/launcher/LauncherOverlay.js.map +0 -7
  476. package/dist/dashboard/launcher/NewLaunchForm.js.map +0 -7
  477. package/dist/dashboard/launcher/api.js.map +0 -7
  478. package/dist/dashboard/launcher/tool-labels.js.map +0 -7
  479. package/dist/dashboard/launcher/types.js.map +0 -7
  480. package/dist/dashboard/launcher/useLaunchJobs.js.map +0 -7
  481. package/dist/dashboard/panels/friction.js.map +0 -7
  482. package/dist/dashboard/panels/insights.js.map +0 -7
  483. package/dist/dashboard/panels/instructions.js.map +0 -7
  484. package/dist/dashboard/panels/outcomes.js.map +0 -7
  485. package/dist/dashboard/panels/overview.js.map +0 -7
  486. package/dist/dashboard/panels/shared.js.map +0 -7
  487. package/dist/dashboard/types.js.map +0 -7
  488. package/dist/dist-UNYP5PJR.js +0 -56
  489. package/dist/dist-UNYP5PJR.js.map +0 -7
  490. package/dist/index.js.map +0 -7
  491. package/dist/lib/active-org-refresh.js.map +0 -7
  492. package/dist/lib/active-org.js.map +0 -7
  493. package/dist/lib/agent-loop.js.map +0 -7
  494. package/dist/lib/antigravity-transcript.js.map +0 -7
  495. package/dist/lib/api-client.js.map +0 -7
  496. package/dist/lib/auth.js.map +0 -7
  497. package/dist/lib/capture-hosts.js.map +0 -7
  498. package/dist/lib/detect-languages.js.map +0 -7
  499. package/dist/lib/detect-tmux.js.map +0 -7
  500. package/dist/lib/diagnostics.js.map +0 -7
  501. package/dist/lib/editor-proxy-pins.js.map +0 -7
  502. package/dist/lib/ensure-api-key.js.map +0 -7
  503. package/dist/lib/eval-analyzer.js.map +0 -7
  504. package/dist/lib/eval-benchmark.js.map +0 -7
  505. package/dist/lib/eval-conversation-handler.js.map +0 -7
  506. package/dist/lib/eval-executor.js.map +0 -7
  507. package/dist/lib/eval-grader.js.map +0 -7
  508. package/dist/lib/eval-meta-judge.js.map +0 -7
  509. package/dist/lib/eval-trigger-tester.js.map +0 -7
  510. package/dist/lib/eval-worktree.js.map +0 -7
  511. package/dist/lib/gateway-entry.js.map +0 -7
  512. package/dist/lib/gateway-identity.js.map +0 -7
  513. package/dist/lib/gateway-lifecycle.js.map +0 -7
  514. package/dist/lib/gateway.js.map +0 -7
  515. package/dist/lib/handlers/cron-refresh-skills.js.map +0 -7
  516. package/dist/lib/handlers/cron-suggest-instructions.js.map +0 -7
  517. package/dist/lib/handlers/process-announcement.js.map +0 -7
  518. package/dist/lib/handlers/process-changelog.js.map +0 -7
  519. package/dist/lib/handlers/process-conversation.js.map +0 -7
  520. package/dist/lib/handlers/process-eval.js.map +0 -7
  521. package/dist/lib/handlers/process-insights.js.map +0 -7
  522. package/dist/lib/handlers/process-launch.js.map +0 -7
  523. package/dist/lib/handlers/process-run-cleanup.js.map +0 -7
  524. package/dist/lib/handlers/process-send-message.js.map +0 -7
  525. package/dist/lib/handlers/process-session-goal.js.map +0 -7
  526. package/dist/lib/hooks-config.js.map +0 -7
  527. package/dist/lib/insights-prompts.js.map +0 -7
  528. package/dist/lib/instruction-snapshot.js.map +0 -7
  529. package/dist/lib/job-helpers.js.map +0 -7
  530. package/dist/lib/llm-client.js.map +0 -7
  531. package/dist/lib/manual-tasks-meta.js.map +0 -7
  532. package/dist/lib/manual-tasks.js.map +0 -7
  533. package/dist/lib/output.js.map +0 -7
  534. package/dist/lib/permanent-job-error.js.map +0 -7
  535. package/dist/lib/pid-identity.js.map +0 -7
  536. package/dist/lib/proxy-respawn.js.map +0 -7
  537. package/dist/lib/research-client.js.map +0 -7
  538. package/dist/lib/setup-steps.js.map +0 -7
  539. package/dist/lib/skills-loader.js.map +0 -7
  540. package/dist/lib/statusline-shim.js.map +0 -7
  541. package/dist/lib/telemetry.js.map +0 -7
  542. package/dist/lib/terminal-target-heartbeat.js.map +0 -7
  543. package/dist/lib/tmux.js.map +0 -7
  544. package/dist/lib/transcript-rate-limit-watcher.js.map +0 -7
  545. package/dist/lib/types.js.map +0 -7
  546. package/dist/lib/version-check.js.map +0 -7
  547. package/dist/lib/which.js.map +0 -7
  548. package/dist/lib/worktree.js.map +0 -7
  549. package/dist/opencode-IQ7X5YMJ.js +0 -190
  550. package/dist/opencode-IQ7X5YMJ.js.map +0 -7
@@ -1,99 +0,0 @@
1
- import {
2
- agentRuns,
3
- getDb,
4
- sessions
5
- } from "./chunk-EI5BHWXA.js";
6
- import {
7
- removeWorktree
8
- } from "./chunk-Y4BJXXYV.js";
9
- import {
10
- PermanentJobError
11
- } from "./chunk-DGHWRQXL.js";
12
-
13
- // src/lib/handlers/process-run-cleanup.ts
14
- import { and, eq, isNotNull } from "drizzle-orm";
15
- async function processRunCleanup(payload, deps = {}) {
16
- const db = deps.db ?? getDb();
17
- const doRemove = deps.removeWorktreeFn ?? removeWorktree;
18
- const log = deps.log ?? ((msg) => process.stderr.write(`[process_run_cleanup] ${msg}
19
- `));
20
- const { runId } = payload;
21
- const [run] = await db.select({
22
- id: agentRuns.id,
23
- userId: agentRuns.userId,
24
- projectPath: agentRuns.projectPath
25
- }).from(agentRuns).where(eq(agentRuns.id, runId)).limit(1);
26
- if (!run) {
27
- throw new PermanentJobError(`Run ${runId} not found`);
28
- }
29
- if (!run.projectPath) {
30
- throw new PermanentJobError(
31
- `Run ${runId} has no projectPath; cannot resolve a repo root for worktree cleanup`
32
- );
33
- }
34
- const repoRoot = run.projectPath;
35
- const endedSessions = await db.select({
36
- id: sessions.id,
37
- projectPath: sessions.projectPath
38
- }).from(sessions).where(
39
- and(
40
- eq(sessions.runId, runId),
41
- eq(sessions.userId, run.userId),
42
- isNotNull(sessions.endedAt)
43
- )
44
- );
45
- const worktrees = [];
46
- let removed = 0;
47
- let skippedDirty = 0;
48
- let absent = 0;
49
- let errored = 0;
50
- const seenPaths = /* @__PURE__ */ new Set();
51
- for (const s of endedSessions) {
52
- if (!s.projectPath || s.projectPath === repoRoot) continue;
53
- if (seenPaths.has(s.projectPath)) continue;
54
- seenPaths.add(s.projectPath);
55
- try {
56
- const result = await doRemove({ repoRoot, worktreePath: s.projectPath });
57
- if (result.removed) {
58
- removed++;
59
- worktrees.push({ sessionId: s.id, worktreePath: s.projectPath, status: "removed" });
60
- log(`removed worktree ${s.projectPath} (session ${s.id})`);
61
- } else if (result.reason === "dirty") {
62
- skippedDirty++;
63
- worktrees.push({ sessionId: s.id, worktreePath: s.projectPath, status: "skipped-dirty" });
64
- log(`skipped dirty worktree ${s.projectPath} (session ${s.id}) \u2014 uncommitted changes`);
65
- } else {
66
- absent++;
67
- worktrees.push({ sessionId: s.id, worktreePath: s.projectPath, status: "absent" });
68
- log(`worktree absent ${s.projectPath} (session ${s.id})`);
69
- }
70
- } catch (err) {
71
- const message = err instanceof Error ? err.message : String(err);
72
- errored++;
73
- worktrees.push({
74
- sessionId: s.id,
75
- worktreePath: s.projectPath,
76
- status: "error",
77
- error: message.slice(0, 1e3)
78
- });
79
- log(`error removing worktree ${s.projectPath} (session ${s.id}): ${message}`);
80
- }
81
- }
82
- log(
83
- `run ${runId} cleanup: removed=${removed} skippedDirty=${skippedDirty} absent=${absent} errored=${errored}`
84
- );
85
- return {
86
- runId,
87
- repoRoot,
88
- removed,
89
- skippedDirty,
90
- absent,
91
- errored,
92
- worktrees
93
- };
94
- }
95
-
96
- export {
97
- processRunCleanup
98
- };
99
- //# sourceMappingURL=chunk-6NBS5XFS.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../src/lib/handlers/process-run-cleanup.ts"],
4
- "sourcesContent": ["import { and, eq, isNotNull } from 'drizzle-orm';\nimport { agentRuns, sessions, getDb } from '@rulemetric/db';\n\nimport { removeWorktree } from '../worktree.js';\nimport { PermanentJobError } from '../permanent-job-error.js';\n\nexport interface ProcessRunCleanupPayload {\n runId: string;\n}\n\n/** Per-worktree cleanup outcome for the summary returned to the API. */\nexport interface RunCleanupWorktreeOutcome {\n sessionId: string;\n worktreePath: string;\n /** 'removed' | 'skipped-dirty' | 'absent' | 'error' */\n status: 'removed' | 'skipped-dirty' | 'absent' | 'error';\n /** Present only when status === 'error'. */\n error?: string;\n}\n\nexport interface ProcessRunCleanupResult {\n runId: string;\n /** Repo root the worktrees were pruned from (the run's projectPath). */\n repoRoot: string | null;\n removed: number;\n skippedDirty: number;\n absent: number;\n errored: number;\n worktrees: RunCleanupWorktreeOutcome[];\n}\n\nexport interface ProcessRunCleanupDeps {\n db?: any;\n removeWorktreeFn?: typeof removeWorktree;\n log?: (msg: string) => void;\n}\n\n/**\n * Worker handler for the `process_run_cleanup` task (Task 5.2).\n *\n * Prunes the git worktrees of a run's ENDED sessions, GUARDING against\n * destroying uncommitted work. Only ENDED sessions are touched \u2014 an active\n * session is still using its worktree, so removing it would break the live\n * agent. Each worktree is removed via `removeWorktree`, which refuses to delete\n * a checkout with uncommitted changes (returns `skipped-dirty`) \u2014 never a\n * silent clobber (research \"merge-review bottleneck\" finding).\n *\n * Repo root = the run's `projectPath`. Each ended session's `projectPath` is\n * its worktree path (the launcher sets `config.projectPath = wt.path` before\n * spawning the session, and capture stamps that cwd onto `sessions.projectPath`\n * \u2014 see process-launch.ts + the linkRunSessions reconcile in runs.ts).\n *\n * Idempotent: a worktree already removed (or never created) reports `absent`,\n * not an error, so a re-run after a partial cleanup is safe. Per-worktree\n * errors are collected, not fatal \u2014 one bad worktree must not abort cleanup of\n * the others. The job only fails terminally on a missing run / missing repo\n * root, where there's nothing actionable to retry.\n *\n * No mirror table \u2014 this is an `agent_jobs` kind (like process_announcement /\n * process_session_goal). The result blob is returned to /api/work/:id/complete\n * and stored on the agent_jobs row for the API/UI to read.\n */\nexport async function processRunCleanup(\n payload: ProcessRunCleanupPayload,\n deps: ProcessRunCleanupDeps = {},\n): Promise<ProcessRunCleanupResult> {\n const db = deps.db ?? getDb();\n const doRemove = deps.removeWorktreeFn ?? removeWorktree;\n const log =\n deps.log ?? ((msg: string) => process.stderr.write(`[process_run_cleanup] ${msg}\\n`));\n\n const { runId } = payload;\n\n const [run] = await db\n .select({\n id: agentRuns.id,\n userId: agentRuns.userId,\n projectPath: agentRuns.projectPath,\n })\n .from(agentRuns)\n .where(eq(agentRuns.id, runId))\n .limit(1);\n\n if (!run) {\n throw new PermanentJobError(`Run ${runId} not found`);\n }\n if (!run.projectPath) {\n // No repo root to prune from \u2014 nothing we can ever do. Don't requeue.\n throw new PermanentJobError(\n `Run ${runId} has no projectPath; cannot resolve a repo root for worktree cleanup`,\n );\n }\n const repoRoot = run.projectPath;\n\n // ENDED sessions only (endedAt IS NOT NULL). Active sessions keep their\n // worktree \u2014 removing it out from under a running agent would break it.\n const endedSessions = await db\n .select({\n id: sessions.id,\n projectPath: sessions.projectPath,\n })\n .from(sessions)\n .where(\n and(\n eq(sessions.runId, runId),\n eq(sessions.userId, run.userId),\n isNotNull(sessions.endedAt),\n ),\n );\n\n const worktrees: RunCleanupWorktreeOutcome[] = [];\n let removed = 0;\n let skippedDirty = 0;\n let absent = 0;\n let errored = 0;\n\n // De-dupe by path so we don't double-remove if two ended sessions somehow\n // share a worktree path (shouldn't happen for autoWorktree runs, but cheap\n // insurance \u2014 git worktree remove on a gone path would otherwise count as a\n // spurious second `absent`).\n const seenPaths = new Set<string>();\n\n for (const s of endedSessions) {\n // A session without a cwd (or pointed at the shared repo root for a\n // non-worktree run) has no per-session worktree to remove \u2014 skip it. We\n // never remove the repo root itself.\n if (!s.projectPath || s.projectPath === repoRoot) continue;\n if (seenPaths.has(s.projectPath)) continue;\n seenPaths.add(s.projectPath);\n\n try {\n const result = await doRemove({ repoRoot, worktreePath: s.projectPath });\n if (result.removed) {\n removed++;\n worktrees.push({ sessionId: s.id, worktreePath: s.projectPath, status: 'removed' });\n log(`removed worktree ${s.projectPath} (session ${s.id})`);\n } else if (result.reason === 'dirty') {\n skippedDirty++;\n worktrees.push({ sessionId: s.id, worktreePath: s.projectPath, status: 'skipped-dirty' });\n log(`skipped dirty worktree ${s.projectPath} (session ${s.id}) \u2014 uncommitted changes`);\n } else {\n // reason === 'absent' (already removed / never existed)\n absent++;\n worktrees.push({ sessionId: s.id, worktreePath: s.projectPath, status: 'absent' });\n log(`worktree absent ${s.projectPath} (session ${s.id})`);\n }\n } catch (err) {\n // A single bad worktree must not abort cleanup of the rest.\n const message = err instanceof Error ? err.message : String(err);\n errored++;\n worktrees.push({\n sessionId: s.id,\n worktreePath: s.projectPath,\n status: 'error',\n error: message.slice(0, 1000),\n });\n log(`error removing worktree ${s.projectPath} (session ${s.id}): ${message}`);\n }\n }\n\n log(\n `run ${runId} cleanup: removed=${removed} skippedDirty=${skippedDirty} ` +\n `absent=${absent} errored=${errored}`,\n );\n\n return {\n runId,\n repoRoot,\n removed,\n skippedDirty,\n absent,\n errored,\n worktrees,\n };\n}\n"],
5
- "mappings": "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",
6
- "names": []
7
- }
@@ -1,98 +0,0 @@
1
- // src/lib/gateway-identity.ts
2
- import { execFileSync } from "node:child_process";
3
- import * as http from "node:http";
4
- var GATEWAY_IDENTITY_PATH = "/__rulemetric_gateway__";
5
- var GATEWAY_IDENTITY_SERVICE = "rulemetric-gateway";
6
- var MAX_IDENTITY_BODY_BYTES = 4096;
7
- function probeGatewayIdentity(port, timeoutMs = 1500) {
8
- return new Promise((resolve) => {
9
- let settled = false;
10
- const finish = (result) => {
11
- if (settled) return;
12
- settled = true;
13
- resolve(result);
14
- };
15
- const req = http.get(
16
- { host: "127.0.0.1", port, path: GATEWAY_IDENTITY_PATH, timeout: timeoutMs },
17
- (res) => {
18
- let body = "";
19
- res.setEncoding("utf-8");
20
- res.on("data", (chunk) => {
21
- body += chunk;
22
- if (body.length > MAX_IDENTITY_BODY_BYTES) {
23
- req.destroy();
24
- finish({ status: "foreign", detail: "oversized identity response" });
25
- }
26
- });
27
- res.on("end", () => {
28
- if (res.statusCode === 200) {
29
- try {
30
- const parsed = JSON.parse(body);
31
- if (parsed?.service === GATEWAY_IDENTITY_SERVICE) {
32
- finish({
33
- status: "ours-live",
34
- version: typeof parsed.version === "string" ? parsed.version : null,
35
- pid: typeof parsed.pid === "number" ? parsed.pid : null
36
- });
37
- return;
38
- }
39
- } catch {
40
- }
41
- }
42
- finish({ status: "foreign", detail: `HTTP ${res.statusCode ?? "?"} without identity marker` });
43
- });
44
- res.on("error", () => finish({ status: "foreign", detail: "response stream error" }));
45
- }
46
- );
47
- req.on("timeout", () => {
48
- req.destroy();
49
- finish({ status: "foreign", detail: "accepted TCP but no identity response (timeout)" });
50
- });
51
- req.on("error", (err) => {
52
- const code = err.code;
53
- if (code === "ECONNREFUSED") {
54
- finish({ status: "dead" });
55
- } else {
56
- finish({ status: "foreign", detail: `socket error ${code ?? err.message}` });
57
- }
58
- });
59
- });
60
- }
61
- async function waitForGatewayIdentity(port, { timeoutMs = 3e3, intervalMs = 150 } = {}) {
62
- const deadline = Date.now() + timeoutMs;
63
- for (; ; ) {
64
- const identity = await probeGatewayIdentity(port, Math.min(1500, timeoutMs));
65
- if (identity.status !== "dead") return identity;
66
- if (Date.now() >= deadline) return identity;
67
- await new Promise((resolve) => setTimeout(resolve, intervalMs));
68
- }
69
- }
70
- function runLsofDefault(port) {
71
- try {
72
- return execFileSync("lsof", ["-nP", `-iTCP:${port}`, "-sTCP:LISTEN"], {
73
- encoding: "utf-8",
74
- stdio: ["ignore", "pipe", "ignore"]
75
- });
76
- } catch {
77
- return null;
78
- }
79
- }
80
- function describePortOwner(port, opts = {}) {
81
- const output = (opts.runLsof ?? runLsofDefault)(port);
82
- if (!output) return null;
83
- const rows = output.split("\n").filter((line) => line.trim().length > 0);
84
- const dataRow = rows.find((line) => !/^COMMAND\s/.test(line));
85
- if (!dataRow) return null;
86
- const [command, pid] = dataRow.trim().split(/\s+/);
87
- if (!command) return null;
88
- return pid ? `${command} (PID ${pid})` : command;
89
- }
90
-
91
- export {
92
- GATEWAY_IDENTITY_PATH,
93
- GATEWAY_IDENTITY_SERVICE,
94
- probeGatewayIdentity,
95
- waitForGatewayIdentity,
96
- describePortOwner
97
- };
98
- //# sourceMappingURL=chunk-7LVVKQMZ.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../src/lib/gateway-identity.ts"],
4
- "sourcesContent": ["/**\n * Gateway identity handshake \u2014 distinguishes OUR gateway from a foreign\n * process squatting on :8787.\n *\n * A bare TCP-accept probe cannot tell the difference, and pinning Claude\n * Code's HTTPS_PROXY at a port owned by some other app breaks ALL of its\n * HTTPS (the worst client-side failure we have). The gateway serves a JSON\n * marker at GATEWAY_IDENTITY_PATH; this module probes it and classifies the\n * port as ours-live / foreign / dead. HTTPS_PROXY may only be pinned on\n * ours-live.\n *\n * Kept free of oclif so gateway-entry (a standalone Node process) can import it.\n */\nimport { execFileSync } from 'node:child_process';\nimport * as http from 'node:http';\n\nexport const GATEWAY_IDENTITY_PATH = '/__rulemetric_gateway__';\nexport const GATEWAY_IDENTITY_SERVICE = 'rulemetric-gateway';\n// The probe reads at most this much of a response \u2014 a foreign server could\n// stream forever on an unknown path.\nconst MAX_IDENTITY_BODY_BYTES = 4096;\n\nexport type GatewayIdentity =\n /** The port answered with our JSON marker \u2014 safe to pin HTTPS_PROXY. */\n | { status: 'ours-live'; version: string | null; pid: number | null }\n /** Something accepts connections but is NOT our gateway \u2014 never pin. */\n | { status: 'foreign'; detail: string }\n /** Nothing is listening \u2014 safe to spawn a gateway, unsafe to pin. */\n | { status: 'dead' };\n\n/**\n * One-shot identity probe against 127.0.0.1:<port>. Connects directly\n * (node:http ignores HTTPS_PROXY env), requests the identity path, and\n * verifies the marker. Anything that accepts TCP but fails the handshake \u2014\n * wrong body, non-JSON, hang, mid-request reset \u2014 is classified foreign:\n * the conservative direction, since foreign means \"do not pin\".\n */\nexport function probeGatewayIdentity(port: number, timeoutMs = 1500): Promise<GatewayIdentity> {\n return new Promise((resolve) => {\n let settled = false;\n const finish = (result: GatewayIdentity) => {\n if (settled) return;\n settled = true;\n resolve(result);\n };\n\n const req = http.get(\n { host: '127.0.0.1', port, path: GATEWAY_IDENTITY_PATH, timeout: timeoutMs },\n (res) => {\n let body = '';\n res.setEncoding('utf-8');\n res.on('data', (chunk: string) => {\n body += chunk;\n if (body.length > MAX_IDENTITY_BODY_BYTES) {\n req.destroy();\n finish({ status: 'foreign', detail: 'oversized identity response' });\n }\n });\n res.on('end', () => {\n if (res.statusCode === 200) {\n try {\n const parsed = JSON.parse(body) as { service?: unknown; version?: unknown; pid?: unknown };\n if (parsed?.service === GATEWAY_IDENTITY_SERVICE) {\n finish({\n status: 'ours-live',\n version: typeof parsed.version === 'string' ? parsed.version : null,\n pid: typeof parsed.pid === 'number' ? parsed.pid : null,\n });\n return;\n }\n } catch {\n /* not our JSON \u2014 fall through to foreign */\n }\n }\n finish({ status: 'foreign', detail: `HTTP ${res.statusCode ?? '?'} without identity marker` });\n });\n res.on('error', () => finish({ status: 'foreign', detail: 'response stream error' }));\n },\n );\n\n req.on('timeout', () => {\n // The connection was accepted but nothing answered the handshake in\n // time \u2014 on loopback that is a listener that isn't our gateway.\n req.destroy();\n finish({ status: 'foreign', detail: 'accepted TCP but no identity response (timeout)' });\n });\n req.on('error', (err) => {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === 'ECONNREFUSED') {\n finish({ status: 'dead' });\n } else {\n // Accepted-then-reset (e.g. a TLS-only listener) and anything else\n // that isn't a clean refusal means SOMETHING owns the port.\n finish({ status: 'foreign', detail: `socket error ${code ?? err.message}` });\n }\n });\n });\n}\n\n/**\n * Poll probeGatewayIdentity() until it resolves to a terminal state or the\n * window elapses. 'dead' is the only retryable state (a just-spawned gateway\n * needs a moment to bind); 'ours-live' and 'foreign' can't change by waiting.\n */\nexport async function waitForGatewayIdentity(\n port: number,\n { timeoutMs = 3000, intervalMs = 150 }: { timeoutMs?: number; intervalMs?: number } = {},\n): Promise<GatewayIdentity> {\n const deadline = Date.now() + timeoutMs;\n for (;;) {\n const identity = await probeGatewayIdentity(port, Math.min(1500, timeoutMs));\n if (identity.status !== 'dead') return identity;\n if (Date.now() >= deadline) return identity;\n await new Promise((resolve) => setTimeout(resolve, intervalMs));\n }\n}\n\nexport interface DescribePortOwnerOptions {\n /** Override the `lsof` exec. Return raw lsof output, or null on failure. Used in tests. */\n runLsof?: (port: number) => string | null;\n}\n\nfunction runLsofDefault(port: number): string | null {\n try {\n return execFileSync('lsof', ['-nP', `-iTCP:${port}`, '-sTCP:LISTEN'], {\n encoding: 'utf-8',\n stdio: ['ignore', 'pipe', 'ignore'],\n });\n } catch {\n // lsof missing (some Linuxes) or no permission \u2014 the caller degrades to a\n // generic \"something else holds the port\" message.\n return null;\n }\n}\n\n/**\n * Best-effort \"what is holding this port\" description for user-facing\n * messages, e.g. `dev-server (PID 4242)`. Returns null when it can't tell.\n */\nexport function describePortOwner(port: number, opts: DescribePortOwnerOptions = {}): string | null {\n const output = (opts.runLsof ?? runLsofDefault)(port);\n if (!output) return null;\n // lsof output: header line, then `COMMAND PID USER ...` rows.\n const rows = output.split('\\n').filter((line) => line.trim().length > 0);\n const dataRow = rows.find((line) => !/^COMMAND\\s/.test(line));\n if (!dataRow) return null;\n const [command, pid] = dataRow.trim().split(/\\s+/);\n if (!command) return null;\n return pid ? `${command} (PID ${pid})` : command;\n}\n"],
5
- "mappings": "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",
6
- "names": []
7
- }
@@ -1,243 +0,0 @@
1
- import {
2
- MitmproxyRespawnMonitor
3
- } from "./chunk-ILYDELUE.js";
4
- import {
5
- GATEWAY_IDENTITY_PATH,
6
- GATEWAY_IDENTITY_SERVICE
7
- } from "./chunk-7LVVKQMZ.js";
8
-
9
- // src/lib/gateway.ts
10
- import { spawn } from "node:child_process";
11
- import * as fs from "node:fs";
12
- import * as http from "node:http";
13
- import * as net from "node:net";
14
- import * as os from "node:os";
15
- import * as path from "node:path";
16
- var GATEWAY_PORT = 8787;
17
- var MITMPROXY_PORT = 8788;
18
- var HEALTH_INTERVAL = 3e3;
19
- var HEALTH_TIMEOUT = 500;
20
- var RESTART_COOLDOWN_MS = 6e4;
21
- var VERSION_FILE = path.join(os.homedir(), ".config", "rulemetric", "proxy-addon.version");
22
- var PROXY_PID_FILE = path.join(os.homedir(), ".config", "rulemetric", "proxy.pid");
23
- var isProxyAlive = false;
24
- var lastSeenAddonVersion = null;
25
- var lastRestartAt = 0;
26
- var identityVersion = "unknown";
27
- var respawnMonitor = null;
28
- function log(msg) {
29
- const ts = (/* @__PURE__ */ new Date()).toISOString();
30
- console.log(`[${ts}] ${msg}`);
31
- }
32
- function readAddonVersion() {
33
- try {
34
- return fs.readFileSync(VERSION_FILE, "utf-8").trim() || null;
35
- } catch {
36
- return null;
37
- }
38
- }
39
- function maybeRestartOnDrift(gatewayCliVersion, cliEntry) {
40
- if (gatewayCliVersion === "unknown" || !cliEntry) return;
41
- const addonVersion = readAddonVersion();
42
- if (!addonVersion || addonVersion === "unknown") return;
43
- if (addonVersion === lastSeenAddonVersion) return;
44
- lastSeenAddonVersion = addonVersion;
45
- if (addonVersion === gatewayCliVersion) {
46
- log(`addon version matches gateway (${gatewayCliVersion})`);
47
- return;
48
- }
49
- const sinceLast = Date.now() - lastRestartAt;
50
- if (sinceLast < RESTART_COOLDOWN_MS) {
51
- log(
52
- `addon version drift (gateway=${gatewayCliVersion}, addon=${addonVersion}); restart cooldown active (${Math.round((RESTART_COOLDOWN_MS - sinceLast) / 1e3)}s left)`
53
- );
54
- return;
55
- }
56
- log(
57
- `addon version drift detected (gateway=${gatewayCliVersion}, addon=${addonVersion}). Restarting proxy to pick up latest code.`
58
- );
59
- lastRestartAt = Date.now();
60
- spawnProxyRestart(cliEntry);
61
- }
62
- function spawnProxyRestart(cliEntry) {
63
- if (!cliEntry) {
64
- log("cannot restart proxy: no CLI entry recorded (RULEMETRIC_CLI_ENTRY unset)");
65
- return false;
66
- }
67
- try {
68
- const child = spawn(process.execPath, [cliEntry, "proxy", "restart"], {
69
- detached: true,
70
- stdio: "ignore"
71
- });
72
- child.unref();
73
- return true;
74
- } catch (err) {
75
- log(`restart spawn failed: ${err.message}`);
76
- return false;
77
- }
78
- }
79
- function proxyCrashEvidence() {
80
- try {
81
- const content = fs.readFileSync(PROXY_PID_FILE, "utf-8").trim();
82
- return /^\d+$/.test(content);
83
- } catch {
84
- return false;
85
- }
86
- }
87
- function checkProxyHealth(mitmproxyPort) {
88
- const sock = net.connect({ port: mitmproxyPort, timeout: HEALTH_TIMEOUT });
89
- sock.on("connect", () => {
90
- sock.destroy();
91
- if (!isProxyAlive) {
92
- isProxyAlive = true;
93
- log(`mitmproxy up on :${mitmproxyPort}, routing through proxy`);
94
- }
95
- respawnMonitor?.onHealthCheck(true);
96
- });
97
- sock.on("error", () => {
98
- if (isProxyAlive) {
99
- isProxyAlive = false;
100
- log(`mitmproxy down on :${mitmproxyPort}, routing direct`);
101
- }
102
- respawnMonitor?.onHealthCheck(false);
103
- });
104
- sock.on("timeout", () => {
105
- sock.destroy();
106
- if (isProxyAlive) {
107
- isProxyAlive = false;
108
- log(`mitmproxy timeout on :${mitmproxyPort}, routing direct`);
109
- }
110
- respawnMonitor?.onHealthCheck(false);
111
- });
112
- }
113
- function handleConnect(req, clientSocket, head, mitmproxyPort) {
114
- const [targetHost, targetPortStr] = (req.url ?? "").split(":");
115
- const targetPort = parseInt(targetPortStr, 10) || 443;
116
- if (isProxyAlive) {
117
- const proxySocket = net.connect({ port: mitmproxyPort, host: "127.0.0.1" });
118
- proxySocket.on("connect", () => {
119
- proxySocket.write(
120
- `CONNECT ${req.url} HTTP/1.1\r
121
- Host: ${req.url}\r
122
- \r
123
- `
124
- );
125
- });
126
- let responseBuffer = Buffer.alloc(0);
127
- const onData = (chunk) => {
128
- responseBuffer = Buffer.concat([responseBuffer, chunk]);
129
- const responseStr = responseBuffer.toString();
130
- if (responseStr.includes("\r\n\r\n")) {
131
- proxySocket.removeListener("data", onData);
132
- clientSocket.write("HTTP/1.1 200 Connection Established\r\n\r\n");
133
- if (head.length > 0) proxySocket.write(head);
134
- clientSocket.pipe(proxySocket);
135
- proxySocket.pipe(clientSocket);
136
- }
137
- };
138
- proxySocket.on("data", onData);
139
- proxySocket.on("error", (err) => {
140
- log(`proxy socket error for ${req.url}: ${err.message}, falling back to direct`);
141
- connectDirect(req, clientSocket, head, targetHost, targetPort);
142
- });
143
- clientSocket.on("error", () => {
144
- proxySocket.destroy();
145
- });
146
- } else {
147
- connectDirect(req, clientSocket, head, targetHost, targetPort);
148
- }
149
- }
150
- function connectDirect(req, clientSocket, head, targetHost, targetPort) {
151
- const upstream = net.connect({ port: targetPort, host: targetHost });
152
- upstream.on("connect", () => {
153
- clientSocket.write("HTTP/1.1 200 Connection Established\r\n\r\n");
154
- if (head.length > 0) upstream.write(head);
155
- clientSocket.pipe(upstream);
156
- upstream.pipe(clientSocket);
157
- });
158
- upstream.on("error", (err) => {
159
- log(`upstream error for ${req.url}: ${err.message}`);
160
- clientSocket.end("HTTP/1.1 502 Bad Gateway\r\n\r\n");
161
- });
162
- clientSocket.on("error", () => {
163
- upstream.destroy();
164
- });
165
- }
166
- function handleRequest(req, res, mitmproxyPort) {
167
- if (req.url === GATEWAY_IDENTITY_PATH) {
168
- res.writeHead(200, { "content-type": "application/json" });
169
- res.end(JSON.stringify({
170
- service: GATEWAY_IDENTITY_SERVICE,
171
- version: identityVersion,
172
- pid: process.pid,
173
- mitmproxyAlive: isProxyAlive
174
- }));
175
- return;
176
- }
177
- const targetUrl = req.url ?? "";
178
- let parsedUrl;
179
- try {
180
- parsedUrl = new URL(targetUrl);
181
- } catch {
182
- res.writeHead(400);
183
- res.end("Bad Request");
184
- return;
185
- }
186
- const options = {
187
- hostname: isProxyAlive ? "127.0.0.1" : parsedUrl.hostname,
188
- port: isProxyAlive ? mitmproxyPort : parseInt(parsedUrl.port, 10) || 80,
189
- path: isProxyAlive ? targetUrl : parsedUrl.pathname + parsedUrl.search,
190
- method: req.method,
191
- headers: req.headers
192
- };
193
- const proxyReq = http.request(options, (proxyRes) => {
194
- res.writeHead(proxyRes.statusCode ?? 502, proxyRes.headers);
195
- proxyRes.pipe(res);
196
- });
197
- proxyReq.on("error", (err) => {
198
- log(`HTTP proxy error for ${targetUrl}: ${err.message}`);
199
- res.writeHead(502);
200
- res.end("Bad Gateway");
201
- });
202
- req.pipe(proxyReq);
203
- }
204
- function startGateway(port = GATEWAY_PORT, mitmproxyPort = MITMPROXY_PORT, options = {}) {
205
- const cliVersion = options.cliVersion ?? process.env.RULEMETRIC_CLI_VERSION ?? "unknown";
206
- const cliEntry = options.cliEntry ?? process.env.RULEMETRIC_CLI_ENTRY ?? null;
207
- identityVersion = cliVersion;
208
- respawnMonitor = new MitmproxyRespawnMonitor({
209
- hasCrashEvidence: proxyCrashEvidence,
210
- respawn: () => spawnProxyRestart(cliEntry),
211
- log
212
- });
213
- const server = http.createServer((req, res) => {
214
- handleRequest(req, res, mitmproxyPort);
215
- });
216
- server.on("connect", (req, clientSocket, head) => {
217
- handleConnect(req, clientSocket, head, mitmproxyPort);
218
- });
219
- server.on("clientError", (_err, socket) => {
220
- if (socket.writable) {
221
- socket.end("HTTP/1.1 400 Bad Request\r\n\r\n");
222
- }
223
- });
224
- const healthInterval = setInterval(() => {
225
- checkProxyHealth(mitmproxyPort);
226
- maybeRestartOnDrift(cliVersion, cliEntry);
227
- }, HEALTH_INTERVAL);
228
- checkProxyHealth(mitmproxyPort);
229
- maybeRestartOnDrift(cliVersion, cliEntry);
230
- server.listen(port, "127.0.0.1", () => {
231
- log(
232
- `gateway listening on 127.0.0.1:${port} (mitmproxy target: :${mitmproxyPort}, cli version: ${cliVersion})`
233
- );
234
- });
235
- return { server, healthInterval };
236
- }
237
-
238
- export {
239
- GATEWAY_PORT,
240
- MITMPROXY_PORT,
241
- startGateway
242
- };
243
- //# sourceMappingURL=chunk-7NNFYWKK.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../src/lib/gateway.ts"],
4
- "sourcesContent": ["/**\n * Resilient HTTP proxy gateway that always accepts connections on GATEWAY_PORT.\n * Routes through mitmproxy when it's alive, direct to upstream when it's not.\n */\nimport { spawn } from 'node:child_process';\nimport * as fs from 'node:fs';\nimport * as http from 'node:http';\nimport * as net from 'node:net';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport { GATEWAY_IDENTITY_PATH, GATEWAY_IDENTITY_SERVICE } from './gateway-identity.js';\nimport { MitmproxyRespawnMonitor } from './proxy-respawn.js';\n\nexport const GATEWAY_PORT = 8787;\nexport const MITMPROXY_PORT = 8788;\nconst HEALTH_INTERVAL = 3000;\nconst HEALTH_TIMEOUT = 500;\n// Floor on auto-restarts so a misconfigured drift can't trigger a restart\n// loop. Plenty long for the user to fix any underlying problem manually.\nconst RESTART_COOLDOWN_MS = 60_000;\nconst VERSION_FILE = path.join(os.homedir(), '.config', 'rulemetric', 'proxy-addon.version');\n// Crash evidence for the mitmproxy auto-restart: `proxy stop` removes this\n// file, a crash leaves it behind.\nconst PROXY_PID_FILE = path.join(os.homedir(), '.config', 'rulemetric', 'proxy.pid');\n\nlet isProxyAlive = false;\nlet lastState: boolean | null = null;\n// Drift state \u2014 tracked across health-check ticks. lastSeenAddonVersion is\n// what the file said last time we read it; lastRestartAt prevents loops.\nlet lastSeenAddonVersion: string | null = null;\nlet lastRestartAt = 0;\n// Set by startGateway; served on the identity endpoint so callers can verify\n// the thing on :8787 is actually us (and which build).\nlet identityVersion = 'unknown';\n// Mid-session mitmproxy crash recovery \u2014 constructed in startGateway.\nlet respawnMonitor: MitmproxyRespawnMonitor | null = null;\n\nfunction log(msg: string): void {\n const ts = new Date().toISOString();\n console.log(`[${ts}] ${msg}`);\n}\n\nfunction readAddonVersion(): string | null {\n try {\n return fs.readFileSync(VERSION_FILE, 'utf-8').trim() || null;\n } catch {\n // File may not exist yet (proxy not started, or older addon that doesn't\n // write the file). Returning null disables drift checks for this tick.\n return null;\n }\n}\n\nfunction maybeRestartOnDrift(gatewayCliVersion: string, cliEntry: string | null): void {\n // No reference version means we can't compare \u2014 skip.\n if (gatewayCliVersion === 'unknown' || !cliEntry) return;\n const addonVersion = readAddonVersion();\n if (!addonVersion || addonVersion === 'unknown') return;\n // Same as last tick \u2014 nothing changed, no need to log or act.\n if (addonVersion === lastSeenAddonVersion) return;\n lastSeenAddonVersion = addonVersion;\n\n if (addonVersion === gatewayCliVersion) {\n // Drift cleared (e.g. proxy was just restarted). Quiet log, no action.\n log(`addon version matches gateway (${gatewayCliVersion})`);\n return;\n }\n\n const sinceLast = Date.now() - lastRestartAt;\n if (sinceLast < RESTART_COOLDOWN_MS) {\n log(\n `addon version drift (gateway=${gatewayCliVersion}, addon=${addonVersion}); ` +\n `restart cooldown active (${Math.round((RESTART_COOLDOWN_MS - sinceLast) / 1000)}s left)`,\n );\n return;\n }\n\n log(\n `addon version drift detected (gateway=${gatewayCliVersion}, addon=${addonVersion}). ` +\n `Restarting proxy to pick up latest code.`,\n );\n lastRestartAt = Date.now();\n spawnProxyRestart(cliEntry);\n}\n\n/**\n * Fire one detached `rulemetric proxy restart` via the CLI entry the spawning\n * process recorded. Shared by the version-drift restart and the mid-session\n * crash auto-restart. Output goes to /dev/null; the proxy.log captures the\n * restart events from mitmproxy itself.\n */\nfunction spawnProxyRestart(cliEntry: string | null): boolean {\n if (!cliEntry) {\n log('cannot restart proxy: no CLI entry recorded (RULEMETRIC_CLI_ENTRY unset)');\n return false;\n }\n try {\n const child = spawn(process.execPath, [cliEntry, 'proxy', 'restart'], {\n detached: true,\n stdio: 'ignore',\n });\n child.unref();\n return true;\n } catch (err) {\n log(`restart spawn failed: ${(err as Error).message}`);\n return false;\n }\n}\n\n/**\n * True when the local proxy.pid file says a local-mode mitmproxy SHOULD be\n * running (numeric PID). `proxy stop` deletes the file, so its absence means\n * a deliberate stop \u2014 never auto-restart over that. A `docker:` marker means\n * Docker owns the lifecycle.\n */\nfunction proxyCrashEvidence(): boolean {\n try {\n const content = fs.readFileSync(PROXY_PID_FILE, 'utf-8').trim();\n return /^\\d+$/.test(content);\n } catch {\n return false;\n }\n}\n\nfunction checkProxyHealth(mitmproxyPort: number): void {\n const sock = net.connect({ port: mitmproxyPort, timeout: HEALTH_TIMEOUT });\n sock.on('connect', () => {\n sock.destroy();\n if (!isProxyAlive) {\n isProxyAlive = true;\n log(`mitmproxy up on :${mitmproxyPort}, routing through proxy`);\n }\n respawnMonitor?.onHealthCheck(true);\n });\n sock.on('error', () => {\n if (isProxyAlive) {\n isProxyAlive = false;\n log(`mitmproxy down on :${mitmproxyPort}, routing direct`);\n }\n respawnMonitor?.onHealthCheck(false);\n });\n sock.on('timeout', () => {\n sock.destroy();\n if (isProxyAlive) {\n isProxyAlive = false;\n log(`mitmproxy timeout on :${mitmproxyPort}, routing direct`);\n }\n respawnMonitor?.onHealthCheck(false);\n });\n}\n\nfunction handleConnect(\n req: http.IncomingMessage,\n clientSocket: net.Socket,\n head: Buffer,\n mitmproxyPort: number,\n): void {\n const [targetHost, targetPortStr] = (req.url ?? '').split(':');\n const targetPort = parseInt(targetPortStr, 10) || 443;\n\n if (isProxyAlive) {\n // Forward CONNECT to mitmproxy\n const proxySocket = net.connect({ port: mitmproxyPort, host: '127.0.0.1' });\n\n proxySocket.on('connect', () => {\n // Send the CONNECT request to mitmproxy\n proxySocket.write(\n `CONNECT ${req.url} HTTP/1.1\\r\\nHost: ${req.url}\\r\\n\\r\\n`,\n );\n });\n\n // Wait for mitmproxy's 200 response before piping\n let responseBuffer = Buffer.alloc(0);\n const onData = (chunk: Buffer) => {\n responseBuffer = Buffer.concat([responseBuffer, chunk]);\n const responseStr = responseBuffer.toString();\n if (responseStr.includes('\\r\\n\\r\\n')) {\n proxySocket.removeListener('data', onData);\n // Forward the 200 to client\n clientSocket.write('HTTP/1.1 200 Connection Established\\r\\n\\r\\n');\n // Pipe remaining data and head\n if (head.length > 0) proxySocket.write(head);\n clientSocket.pipe(proxySocket);\n proxySocket.pipe(clientSocket);\n }\n };\n proxySocket.on('data', onData);\n\n proxySocket.on('error', (err) => {\n log(`proxy socket error for ${req.url}: ${err.message}, falling back to direct`);\n // Mitmproxy failed mid-connect, fall back to direct\n connectDirect(req, clientSocket, head, targetHost, targetPort);\n });\n\n clientSocket.on('error', () => {\n proxySocket.destroy();\n });\n } else {\n connectDirect(req, clientSocket, head, targetHost, targetPort);\n }\n}\n\nfunction connectDirect(\n req: http.IncomingMessage,\n clientSocket: net.Socket,\n head: Buffer,\n targetHost: string,\n targetPort: number,\n): void {\n const upstream = net.connect({ port: targetPort, host: targetHost });\n\n upstream.on('connect', () => {\n clientSocket.write('HTTP/1.1 200 Connection Established\\r\\n\\r\\n');\n if (head.length > 0) upstream.write(head);\n clientSocket.pipe(upstream);\n upstream.pipe(clientSocket);\n });\n\n upstream.on('error', (err) => {\n log(`upstream error for ${req.url}: ${err.message}`);\n clientSocket.end('HTTP/1.1 502 Bad Gateway\\r\\n\\r\\n');\n });\n\n clientSocket.on('error', () => {\n upstream.destroy();\n });\n}\n\nfunction handleRequest(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n mitmproxyPort: number,\n): void {\n // Identity handshake (origin-form GET, not a proxy request): lets callers\n // distinguish OUR gateway from a foreign process squatting on the port \u2014\n // the gate for pinning HTTPS_PROXY and for idempotent double-spawns.\n if (req.url === GATEWAY_IDENTITY_PATH) {\n res.writeHead(200, { 'content-type': 'application/json' });\n res.end(JSON.stringify({\n service: GATEWAY_IDENTITY_SERVICE,\n version: identityVersion,\n pid: process.pid,\n mitmproxyAlive: isProxyAlive,\n }));\n return;\n }\n\n // Plain HTTP proxy (non-CONNECT)\n const targetUrl = req.url ?? '';\n let parsedUrl: URL;\n try {\n parsedUrl = new URL(targetUrl);\n } catch {\n res.writeHead(400);\n res.end('Bad Request');\n return;\n }\n\n const options: http.RequestOptions = {\n hostname: isProxyAlive ? '127.0.0.1' : parsedUrl.hostname,\n port: isProxyAlive ? mitmproxyPort : (parseInt(parsedUrl.port, 10) || 80),\n path: isProxyAlive ? targetUrl : parsedUrl.pathname + parsedUrl.search,\n method: req.method,\n headers: req.headers,\n };\n\n const proxyReq = http.request(options, (proxyRes) => {\n res.writeHead(proxyRes.statusCode ?? 502, proxyRes.headers);\n proxyRes.pipe(res);\n });\n\n proxyReq.on('error', (err) => {\n log(`HTTP proxy error for ${targetUrl}: ${err.message}`);\n res.writeHead(502);\n res.end('Bad Gateway');\n });\n\n req.pipe(proxyReq);\n}\n\nexport function startGateway(\n port: number = GATEWAY_PORT,\n mitmproxyPort: number = MITMPROXY_PORT,\n options: { cliVersion?: string; cliEntry?: string } = {},\n): { server: http.Server; healthInterval: NodeJS.Timeout } {\n const cliVersion = options.cliVersion ?? process.env.RULEMETRIC_CLI_VERSION ?? 'unknown';\n const cliEntry = options.cliEntry ?? process.env.RULEMETRIC_CLI_ENTRY ?? null;\n identityVersion = cliVersion;\n // Mid-session crash recovery: when the health check sees mitmproxy stay\n // dead, attempt a bounded, crash-evidence-gated `proxy restart` (see\n // proxy-respawn.ts for the guard rails).\n respawnMonitor = new MitmproxyRespawnMonitor({\n hasCrashEvidence: proxyCrashEvidence,\n respawn: () => spawnProxyRestart(cliEntry),\n log,\n });\n const server = http.createServer((req, res) => {\n handleRequest(req, res, mitmproxyPort);\n });\n\n server.on('connect', (req, clientSocket, head) => {\n handleConnect(req, clientSocket as net.Socket, head as Buffer, mitmproxyPort);\n });\n\n // Don't crash on client socket errors\n server.on('clientError', (_err, socket) => {\n if (socket.writable) {\n socket.end('HTTP/1.1 400 Bad Request\\r\\n\\r\\n');\n }\n });\n\n const healthInterval = setInterval(() => {\n checkProxyHealth(mitmproxyPort);\n maybeRestartOnDrift(cliVersion, cliEntry);\n }, HEALTH_INTERVAL);\n\n // Do an immediate check\n checkProxyHealth(mitmproxyPort);\n maybeRestartOnDrift(cliVersion, cliEntry);\n\n server.listen(port, '127.0.0.1', () => {\n log(\n `gateway listening on 127.0.0.1:${port} (mitmproxy target: :${mitmproxyPort}, ` +\n `cli version: ${cliVersion})`,\n );\n });\n\n return { server, healthInterval };\n}\n"],
5
- "mappings": "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",
6
- "names": []
7
- }
@@ -1,12 +0,0 @@
1
- // src/lib/types.ts
2
- var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
3
- function validateUuid(value, label = "ID") {
4
- if (!UUID_RE.test(value)) {
5
- throw new Error(`Invalid ${label}: "${value}" is not a valid UUID`);
6
- }
7
- }
8
-
9
- export {
10
- validateUuid
11
- };
12
- //# sourceMappingURL=chunk-7NYKWN7U.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../src/lib/types.ts"],
4
- "sourcesContent": ["const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\nexport function validateUuid(value: string, label = 'ID'): void {\n if (!UUID_RE.test(value)) {\n throw new Error(`Invalid ${label}: \"${value}\" is not a valid UUID`);\n }\n}\n\n/** API response type for an instruction */\nexport interface Instruction {\n id: string;\n name: string;\n description: string;\n scope: string;\n version: string;\n tags: string[];\n content: string;\n createdAt: string;\n updatedAt: string;\n}\n\n/** Subset for list views where not all fields are needed */\nexport type InstructionSummary = Pick<Instruction, 'id' | 'name' | 'scope' | 'version' | 'tags' | 'updatedAt'>;\n\nexport interface InstructionVersion {\n id: string;\n versionNumber: number;\n changeSummary: string | null;\n createdAt: string;\n}\n\nexport interface ConvertResult {\n output: string;\n format: string;\n outputPath: string;\n warnings: string[];\n score?: { overall: number; details: Record<string, number> };\n}\n\nexport interface ConverterEntry {\n id: string;\n name: string;\n description: string;\n tier: number;\n outputPath: string;\n toolUrl: string;\n}\n\nexport interface ImportResult {\n instruction: { id: string; name: string };\n sourceFormat: string;\n parseWarnings: string[];\n}\n"],
5
- "mappings": ";AAAA,IAAM,UAAU;AAET,SAAS,aAAa,OAAe,QAAQ,MAAY;AAC9D,MAAI,CAAC,QAAQ,KAAK,KAAK,GAAG;AACxB,UAAM,IAAI,MAAM,WAAW,KAAK,MAAM,KAAK,uBAAuB;AAAA,EACpE;AACF;",
6
- "names": []
7
- }
@@ -1,42 +0,0 @@
1
- import {
2
- tmuxSpawnEnv
3
- } from "./chunk-KRBQLMOP.js";
4
-
5
- // src/lib/detect-tmux.ts
6
- import { spawn } from "node:child_process";
7
- function detectTmux() {
8
- return new Promise((resolve) => {
9
- let child;
10
- try {
11
- child = spawn("tmux", ["-V"], { stdio: ["ignore", "pipe", "pipe"], env: tmuxSpawnEnv() });
12
- } catch {
13
- resolve({ available: false });
14
- return;
15
- }
16
- let stdout = "";
17
- child.stdout?.on("data", (chunk) => {
18
- stdout += chunk.toString();
19
- });
20
- child.stderr?.on("data", () => {
21
- });
22
- child.on("error", () => {
23
- resolve({ available: false });
24
- });
25
- child.on("close", (code) => {
26
- if (code !== 0) {
27
- resolve({ available: false });
28
- return;
29
- }
30
- const match = stdout.trim().match(/^tmux\s+(\S+)/);
31
- resolve({
32
- available: true,
33
- version: match ? match[1] : void 0
34
- });
35
- });
36
- });
37
- }
38
-
39
- export {
40
- detectTmux
41
- };
42
- //# sourceMappingURL=chunk-BO76WKJR.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../src/lib/detect-tmux.ts"],
4
- "sourcesContent": ["import { spawn } from 'node:child_process';\nimport { tmuxSpawnEnv } from './tmux.js';\n\nexport interface TmuxDetection {\n available: boolean;\n version?: string;\n path?: string;\n}\n\n/**\n * Detect whether `tmux` is installed and runnable.\n *\n * Uses `tmux -V` with stdout/stderr captured so we never block waiting on a\n * TTY. ENOENT (binary missing) and any non-zero exit code both resolve as\n * `{ available: false }`. We never reject \u2014 callers print a one-line user\n * hint and continue; tmux is a soft dependency for live-send.\n */\nexport function detectTmux(): Promise<TmuxDetection> {\n return new Promise((resolve) => {\n let child: ReturnType<typeof spawn>;\n try {\n child = spawn('tmux', ['-V'], { stdio: ['ignore', 'pipe', 'pipe'], env: tmuxSpawnEnv() });\n } catch {\n resolve({ available: false });\n return;\n }\n\n let stdout = '';\n child.stdout?.on('data', (chunk: Buffer) => {\n stdout += chunk.toString();\n });\n child.stderr?.on('data', () => {\n // discard\n });\n child.on('error', () => {\n resolve({ available: false });\n });\n child.on('close', (code) => {\n if (code !== 0) {\n resolve({ available: false });\n return;\n }\n // `tmux -V` prints e.g. \"tmux 3.4\\n\"\n const match = stdout.trim().match(/^tmux\\s+(\\S+)/);\n resolve({\n available: true,\n version: match ? match[1] : undefined,\n });\n });\n });\n}\n"],
5
- "mappings": ";;;;;AAAA,SAAS,aAAa;AAiBf,SAAS,aAAqC;AACnD,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,QAAI;AACJ,QAAI;AACF,cAAQ,MAAM,QAAQ,CAAC,IAAI,GAAG,EAAE,OAAO,CAAC,UAAU,QAAQ,MAAM,GAAG,KAAK,aAAa,EAAE,CAAC;AAAA,IAC1F,QAAQ;AACN,cAAQ,EAAE,WAAW,MAAM,CAAC;AAC5B;AAAA,IACF;AAEA,QAAI,SAAS;AACb,UAAM,QAAQ,GAAG,QAAQ,CAAC,UAAkB;AAC1C,gBAAU,MAAM,SAAS;AAAA,IAC3B,CAAC;AACD,UAAM,QAAQ,GAAG,QAAQ,MAAM;AAAA,IAE/B,CAAC;AACD,UAAM,GAAG,SAAS,MAAM;AACtB,cAAQ,EAAE,WAAW,MAAM,CAAC;AAAA,IAC9B,CAAC;AACD,UAAM,GAAG,SAAS,CAAC,SAAS;AAC1B,UAAI,SAAS,GAAG;AACd,gBAAQ,EAAE,WAAW,MAAM,CAAC;AAC5B;AAAA,MACF;AAEA,YAAM,QAAQ,OAAO,KAAK,EAAE,MAAM,eAAe;AACjD,cAAQ;AAAA,QACN,WAAW;AAAA,QACX,SAAS,QAAQ,MAAM,CAAC,IAAI;AAAA,MAC9B,CAAC;AAAA,IACH,CAAC;AAAA,EACH,CAAC;AACH;",
6
- "names": []
7
- }