@rulemetric/cli 0.7.4 → 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 (163) hide show
  1. package/README.md +10 -8
  2. package/dist/base-command.js +1 -1
  3. package/dist/{chunk-O7ZMHCMG.js → chunk-2JRDG4LJ.js} +14 -14
  4. package/dist/chunk-2WLVDSAP.js +2 -0
  5. package/dist/{chunk-F2VP4B4J.js → chunk-32EEBARV.js} +1 -1
  6. package/dist/chunk-43YBXX7R.js +1 -0
  7. package/dist/{chunk-HOHD5HY2.js → chunk-AYUJY37O.js} +1 -1
  8. package/dist/{chunk-VAFAH6QL.js → chunk-DCLWFGEA.js} +1 -1
  9. package/dist/{chunk-IY5NXR3N.js → chunk-DPFNJZUO.js} +1 -1
  10. package/dist/chunk-G63KMH6U.js +1 -0
  11. package/dist/{chunk-T3W5N3BP.js → chunk-G6XGDHGC.js} +1 -1
  12. package/dist/{chunk-TIQ7DQ3M.js → chunk-H2ORWIEY.js} +1 -1
  13. package/dist/chunk-H4SV7FN4.js +1 -0
  14. package/dist/chunk-HS7X43XE.js +24 -0
  15. package/dist/{chunk-Y65CSJFF.js → chunk-JAPCCEKF.js} +1 -1
  16. package/dist/chunk-JQTGQXUX.js +1 -0
  17. package/dist/{chunk-V5QFOF4F.js → chunk-KAF3CYRW.js} +1 -1
  18. package/dist/{chunk-EUHNCVJQ.js → chunk-KV325CXF.js} +3 -3
  19. package/dist/{chunk-FHVBTDBM.js → chunk-N7TGRFVZ.js} +13 -12
  20. package/dist/{chunk-I4YJ7NTX.js → chunk-NEACEHQD.js} +1 -1
  21. package/dist/chunk-O2SDD2WW.js +1 -0
  22. package/dist/chunk-O6C2UGBY.js +7 -0
  23. package/dist/chunk-PPKPCXJD.js +4 -0
  24. package/dist/{chunk-VWEXKDWG.js → chunk-QFVGUZDO.js} +1 -1
  25. package/dist/{chunk-VMWY7KHH.js → chunk-RDET7CKR.js} +1 -1
  26. package/dist/chunk-RQ424GI6.js +5 -0
  27. package/dist/{chunk-PZS2KOU7.js → chunk-TIOKY2IA.js} +1 -1
  28. package/dist/chunk-TQMG647B.js +15 -0
  29. package/dist/{chunk-WJUQBMTF.js → chunk-U6ABMRT3.js} +1 -1
  30. package/dist/chunk-U6XEU573.js +1 -0
  31. package/dist/{chunk-CRAKDQ4H.js → chunk-V44SRRYR.js} +1 -1
  32. package/dist/{chunk-7XQ4VPLC.js → chunk-VAXRCSSH.js} +1 -1
  33. package/dist/{chunk-WPJ2BND4.js → chunk-VLOX6KOM.js} +1 -1
  34. package/dist/chunk-W2MOTOQE.js +1 -0
  35. package/dist/chunk-XICLXXRH.js +1 -0
  36. package/dist/{chunk-2UC3ULIG.js → chunk-XXDZJ6YI.js} +1 -1
  37. package/dist/{chunk-SBILN45P.js → chunk-ZR3MUNLS.js} +1 -1
  38. package/dist/commands/antigravity/backfill.js +1 -1
  39. package/dist/commands/auth/create-key.js +1 -1
  40. package/dist/commands/auth/login.js +1 -1
  41. package/dist/commands/auth/logout.js +1 -1
  42. package/dist/commands/auth/revoke-key.js +4 -1
  43. package/dist/commands/auth/signup.js +1 -1
  44. package/dist/commands/auth/status.js +1 -1
  45. package/dist/commands/catalog/index.js +1 -1
  46. package/dist/commands/catalog/recommend.js +1 -1
  47. package/dist/commands/convert.js +1 -1
  48. package/dist/commands/converters.js +1 -1
  49. package/dist/commands/crons/list.js +1 -1
  50. package/dist/commands/crons/run.js +1 -1
  51. package/dist/commands/dashboard.js +1 -1
  52. package/dist/commands/diagnostics.js +1 -1
  53. package/dist/commands/eval-targets/create.js +1 -1
  54. package/dist/commands/eval-targets/list.js +1 -1
  55. package/dist/commands/evals/agent.js +1 -1
  56. package/dist/commands/evals/benchmark.js +1 -1
  57. package/dist/commands/evals/compare.js +1 -1
  58. package/dist/commands/evals/create.js +1 -1
  59. package/dist/commands/evals/optimize-description.js +15 -15
  60. package/dist/commands/evals/optimize.js +5 -5
  61. package/dist/commands/evals/run.js +1 -1
  62. package/dist/commands/gateway/ensure.js +1 -1
  63. package/dist/commands/hooks/install.js +1 -1
  64. package/dist/commands/hooks/run.js +1 -1
  65. package/dist/commands/hooks/uninstall.js +1 -1
  66. package/dist/commands/import.js +1 -1
  67. package/dist/commands/instructions/create.js +1 -1
  68. package/dist/commands/instructions/delete.js +1 -1
  69. package/dist/commands/instructions/fork.js +1 -1
  70. package/dist/commands/instructions/get.js +1 -1
  71. package/dist/commands/instructions/list.js +1 -1
  72. package/dist/commands/instructions/promote.js +1 -1
  73. package/dist/commands/instructions/pull.js +1 -1
  74. package/dist/commands/instructions/upstream.js +1 -1
  75. package/dist/commands/instructions/versions.js +1 -1
  76. package/dist/commands/launcher.js +1 -1
  77. package/dist/commands/org/current.js +1 -1
  78. package/dist/commands/org/list.js +1 -1
  79. package/dist/commands/org/switch.js +1 -1
  80. package/dist/commands/packs/add-instruction.js +1 -1
  81. package/dist/commands/packs/apply.js +1 -1
  82. package/dist/commands/packs/create.js +1 -1
  83. package/dist/commands/packs/fork.js +1 -1
  84. package/dist/commands/packs/get.js +1 -1
  85. package/dist/commands/packs/list.js +1 -1
  86. package/dist/commands/packs/remove-instruction.js +1 -1
  87. package/dist/commands/proxy/env.js +1 -1
  88. package/dist/commands/proxy/logs.js +1 -1
  89. package/dist/commands/proxy/restart.js +1 -1
  90. package/dist/commands/proxy/setup.js +13 -11
  91. package/dist/commands/proxy/start.js +1 -1
  92. package/dist/commands/proxy/status.js +1 -1
  93. package/dist/commands/proxy/stop.js +1 -1
  94. package/dist/commands/research/backfill.js +1 -1
  95. package/dist/commands/research/tail-transcript.js +1 -1
  96. package/dist/commands/service/install.js +5 -5
  97. package/dist/commands/service/status.js +1 -1
  98. package/dist/commands/service/uninstall.js +1 -1
  99. package/dist/commands/sessions/analyze.js +1 -3
  100. package/dist/commands/sessions/end.js +2 -2
  101. package/dist/commands/sessions/import.js +1 -1
  102. package/dist/commands/sessions/list.js +1 -1
  103. package/dist/commands/sessions/start.js +1 -1
  104. package/dist/commands/setup.js +1 -1
  105. package/dist/commands/skills/export-approved.js +1 -1
  106. package/dist/commands/skills/install.js +1 -1
  107. package/dist/commands/skills/list.js +1 -1
  108. package/dist/commands/skills/publish.js +1 -1
  109. package/dist/commands/skills/search.js +1 -1
  110. package/dist/commands/skills/update.js +1 -1
  111. package/dist/commands/suggestions/accept.js +3 -3
  112. package/dist/commands/suggestions/dismiss.js +1 -1
  113. package/dist/commands/suggestions/list.js +2 -1
  114. package/dist/commands/suggestions/refresh.js +1 -1
  115. package/dist/dashboard/Dashboard.js +1 -1
  116. package/dist/dashboard/data.js +1 -1
  117. package/dist/dashboard/launcher/LauncherOverlay.js +1 -1
  118. package/dist/dashboard/launcher/api.js +1 -1
  119. package/dist/dashboard/launcher/useLaunchJobs.js +1 -1
  120. package/dist/dashboard/panels/insights.js +1 -1
  121. package/dist/lib/active-org-refresh.js +1 -1
  122. package/dist/lib/agent-loop.js +1 -1
  123. package/dist/lib/antigravity-transcript.js +1 -1
  124. package/dist/lib/api-client.js +1 -1
  125. package/dist/lib/auth.js +1 -1
  126. package/dist/lib/editor-proxy-pins.js +1 -1
  127. package/dist/lib/ensure-api-key.js +1 -1
  128. package/dist/lib/ensure-fresh-token.js +1 -0
  129. package/dist/lib/eval-benchmark.js +1 -1
  130. package/dist/lib/eval-conversation-handler.js +1 -1
  131. package/dist/lib/eval-trigger-tester.js +1 -1
  132. package/dist/lib/handlers/cron-refresh-pricing.js +1 -1
  133. package/dist/lib/handlers/cron-suggest-instructions.js +1 -1
  134. package/dist/lib/handlers/process-announcement.js +1 -1
  135. package/dist/lib/handlers/process-changelog.js +1 -1
  136. package/dist/lib/handlers/process-conversation.js +1 -1
  137. package/dist/lib/handlers/process-eval.js +1 -1
  138. package/dist/lib/handlers/process-insights.js +1 -1
  139. package/dist/lib/handlers/process-launch.js +1 -1
  140. package/dist/lib/handlers/process-run-cleanup.js +1 -1
  141. package/dist/lib/handlers/process-session-goal.js +1 -1
  142. package/dist/lib/hooks-config.js +1 -1
  143. package/dist/lib/insights-prompts.js +1 -1
  144. package/dist/lib/manual-tasks.js +1 -1
  145. package/dist/lib/research-client.js +1 -1
  146. package/dist/lib/setup-steps.js +1 -1
  147. package/dist/lib/telemetry.js +1 -1
  148. package/dist/lib/terminal-target-heartbeat.js +1 -1
  149. package/oclif.manifest.json +145 -167
  150. package/package.json +7 -7
  151. package/dist/chunk-72XLQE3X.js +0 -2
  152. package/dist/chunk-AHRHCERJ.js +0 -1
  153. package/dist/chunk-DT4GKEP5.js +0 -5
  154. package/dist/chunk-E4SFUPYR.js +0 -15
  155. package/dist/chunk-FEHM5OKW.js +0 -1
  156. package/dist/chunk-HP2BUPGS.js +0 -24
  157. package/dist/chunk-LQRYQE6Q.js +0 -4
  158. package/dist/chunk-M6AJDVCL.js +0 -5
  159. package/dist/chunk-ML36XQW7.js +0 -1
  160. package/dist/chunk-NVOTOQBA.js +0 -1
  161. package/dist/chunk-RTEATXTP.js +0 -1
  162. package/dist/chunk-RVO4HV3M.js +0 -1
  163. package/dist/chunk-WJ3H73G6.js +0 -1
@@ -1,9 +1,9 @@
1
- import{a as o}from"./chunk-ZLLER3HP.js";var R="#5b6cff",l="#1a1a1a",d="#666666",w="#f5f5f7",z="#ffffff",v="#e5e5e9",C=["Added","Changed","Fixed","Removed","Deprecated","Security"];function k(e){let t=["January","February","March","April","May","June","July","August","September","October","November","December"],[r,n,i]=e.split("-").map(p=>parseInt(p,10));return!r||!n||!i||n<1||n>12?e:`${t[n-1]} ${i}, ${r}`}o(k,"formatIsoDate");function s(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}o(s,"escapeHtml");function N(e){let t=[];for(let r of C){let n=e[r];n&&n.length>0&&t.push({name:r,items:n})}return t}o(N,"orderedSections");function U(e){let{version:t,date:r,sections:n,unsubscribeUrl:i,productUrl:p,recipientName:a}=e,f=k(r),y=`What's new in RuleMetric \u2014 ${f}`,$=a?`Hi ${a},`:"Hi there,",b=N(n),E=new Date().getUTCFullYear(),T=b.map(({name:g,items:h})=>{let m=h.map(D=>` <li style="margin:0 0 6px 0;font-size:15px;line-height:1.5;color:${l};">${s(D)}</li>`).join(`
2
- `);return` <h3 style="margin:24px 0 8px 0;font-size:16px;line-height:1.3;font-weight:600;color:${l};">${g}</h3>
1
+ import{a as n}from"./chunk-ZLLER3HP.js";var R="#0d9488",l="#1a1a1a",d="#666666",w="#f5f5f7",C="#ffffff",v="#e5e5e9",O=["Added","Changed","Fixed","Removed","Deprecated","Security"];function z(e){let t=["January","February","March","April","May","June","July","August","September","October","November","December"],[r,o,i]=e.split("-").map(p=>parseInt(p,10));return!r||!o||!i||o<1||o>12?e:`${t[o-1]} ${i}, ${r}`}n(z,"formatIsoDate");function s(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}n(s,"escapeHtml");function U(e){let t=[];for(let r of O){let o=e[r];o&&o.length>0&&t.push({name:r,items:o})}return t}n(U,"orderedSections");function k(e){let{version:t,date:r,sections:o,unsubscribeUrl:i,productUrl:p,recipientName:a}=e,f=z(r),y=`What's new in RuleMetric \u2014 ${f}`,$=a?`Hi ${a},`:"Hi there,",E=U(o),b=new Date().getUTCFullYear(),I=E.map(({name:h,items:m})=>{let g=m.map(S=>` <li style="margin:0 0 6px 0;font-size:15px;line-height:1.5;color:${l};">${s(S)}</li>`).join(`
2
+ `);return` <h3 style="margin:24px 0 8px 0;font-size:16px;line-height:1.3;font-weight:600;color:${l};">${h}</h3>
3
3
  <ul style="margin:0 0 8px 0;padding-left:20px;">
4
- ${m}
4
+ ${g}
5
5
  </ul>`}).join(`
6
- `),I=`<!doctype html>
6
+ `),T=`<!doctype html>
7
7
  <html lang="en">
8
8
  <head>
9
9
  <meta charset="utf-8" />
@@ -14,7 +14,7 @@ ${m}
14
14
  <table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0" style="background:${w};padding:32px 16px;">
15
15
  <tr>
16
16
  <td align="center">
17
- <table role="presentation" width="560" cellspacing="0" cellpadding="0" border="0" style="max-width:560px;background:${z};border:1px solid ${v};border-radius:8px;overflow:hidden;">
17
+ <table role="presentation" width="560" cellspacing="0" cellpadding="0" border="0" style="max-width:560px;background:${C};border:1px solid ${v};border-radius:8px;overflow:hidden;">
18
18
  <tr>
19
19
  <td style="padding:24px 32px 8px 32px;">
20
20
  <a href="${s(p)}" style="text-decoration:none;color:${R};font-size:14px;font-weight:600;">RuleMetric</a>
@@ -38,7 +38,7 @@ ${m}
38
38
  </tr>
39
39
  <tr>
40
40
  <td style="padding:0 32px 16px 32px;">
41
- ${T}
41
+ ${I}
42
42
  </td>
43
43
  </tr>
44
44
  <tr>
@@ -53,7 +53,7 @@ ${T}
53
53
  ${s(i)}
54
54
  </p>
55
55
  <p style="margin:0;font-size:11px;line-height:1.5;color:${d};">
56
- RuleMetric \u2022 ${E}
56
+ RuleMetric \u2022 ${b}
57
57
  </p>
58
58
  </td>
59
59
  </tr>
@@ -62,8 +62,9 @@ ${T}
62
62
  </tr>
63
63
  </table>
64
64
  </body>
65
- </html>`,c=[`What's new in RuleMetric \u2014 ${f}`,`Release ${t}`,"",$,"","Here's what shipped in the latest RuleMetric release.",""];for(let{name:g,items:h}of b){c.push(`${g}:`);for(let m of h)c.push(` - ${m}`);c.push("")}c.push("--","You're receiving this because you signed up for RuleMetric product updates.",`Unsubscribe: ${i}`,"",`RuleMetric \u2022 ${E}`);let S=c.join(`
66
- `);return{subject:y,html:I,text:S}}o(U,"renderChangelogAnnouncement");import{randomBytes as O}from"node:crypto";async function x(e){let t=e.idempotencyKey?` idempotencyKey=${e.idempotencyKey}`:"";return process.stderr.write(`[email:noop] would send to=${e.to} subject=${JSON.stringify(e.subject)}${t}
67
- `),{id:`noop-${O(8).toString("hex")}`,provider:"noop"}}o(x,"sendNoopEmail");var u=null;async function j(){if(u)return u;let e=process.env.RESEND_API_KEY;if(!e)throw new Error("RESEND_API_KEY is not set");let{Resend:t}=await import("resend");return u=new t(e),u}o(j,"getClient");async function M(e){let t=e.fromName??"RuleMetric",r=process.env.RESEND_FROM_EMAIL??"onboarding@resend.dev",n=`${t} <${r}>`,i=await j(),p=e.idempotencyKey?{idempotencyKey:e.idempotencyKey}:void 0,a=await i.emails.send({from:n,to:e.to,subject:e.subject,html:e.html,text:e.text},p);if(a.error)throw new Error(`Resend send failed: ${a.error.message}`);if(!a.data)throw new Error("Resend send returned no data and no error");return{id:a.data.id,provider:"resend"}}o(M,"sendResendEmail");async function A(e){throw new Error("SMTP provider not implemented. Set RESEND_API_KEY to use Resend, or unset RULEMETRIC_EMAIL_PROVIDER to fall back to noop.")}o(A,"sendSmtpEmail");function Y(){let e=process.env.RULEMETRIC_EMAIL_PROVIDER;return e==="resend"||e==="smtp"||e==="noop"?e:process.env.RESEND_API_KEY?"resend":"noop"}o(Y,"selectEmailProvider");var H=new Set(["test","example","invalid","localhost"]),K=/^example\.(com|net|org)$/;function L(e){let t=e.trim().toLowerCase(),r=t.lastIndexOf("@");if(r<0)return!1;let n=t.slice(r+1);if(!n)return!1;let i=n.slice(n.lastIndexOf(".")+1);return!!(H.has(i)||K.test(n))}o(L,"isUndeliverableRecipient");var _=!1;async function re(e){let t=Y();switch(_||(_=!0,process.stderr.write(`[email] active provider: ${t}
68
- `)),t){case"resend":return L(e.to)?(process.stderr.write(`[email] skipping real send to reserved/undeliverable address ${e.to} (RFC 2606/6761) \u2014 routed to noop to protect sender reputation
69
- `),x(e)):M(e);case"smtp":return A(e);case"noop":return x(e)}}o(re,"sendEmail");export{U as a,re as b};
65
+ </html>`,c=[`What's new in RuleMetric \u2014 ${f}`,`Release ${t}`,"",$,"","Here's what shipped in the latest RuleMetric release.",""];for(let{name:h,items:m}of E){c.push(`${h}:`);for(let g of m)c.push(` - ${g}`);c.push("")}c.push("--","You're receiving this because you signed up for RuleMetric product updates.",`Unsubscribe: ${i}`,"",`RuleMetric \u2022 ${b}`);let N=c.join(`
66
+ `);return{subject:y,html:T,text:N}}n(k,"renderChangelogAnnouncement");import{randomBytes as L}from"node:crypto";async function x(e){let t=e.idempotencyKey?` idempotencyKey=${e.idempotencyKey}`:"";return process.stderr.write(`[email:noop] would send to=${e.to} subject=${JSON.stringify(e.subject)}${t}
67
+ `),{id:`noop-${L(8).toString("hex")}`,provider:"noop"}}n(x,"sendNoopEmail");var u=null;async function P(){if(u)return u;let e=process.env.RESEND_API_KEY;if(!e)throw new Error("RESEND_API_KEY is not set");let{Resend:t}=await import("resend");return u=new t(e),u}n(P,"getClient");var _=!1;function F(){let e=process.env.RESEND_FROM_EMAIL;if(e)return e;if(!_){_=!0;let t=process.env.NODE_ENV==="production"?"PRODUCTION":"dev";process.stderr.write(`[email:resend] ${t}: RESEND_FROM_EMAIL not set \u2014 sending from the shared sandbox sender onboarding@resend.dev, which Gmail spam-filters. Set RESEND_FROM_EMAIL to an address on a verified domain.
68
+ `)}return"onboarding@resend.dev"}n(F,"resolveFromEmail");async function M(e){let t=e.fromName??"RuleMetric",r=F(),o=`${t} <${r}>`,i=await P(),p=e.idempotencyKey?{idempotencyKey:e.idempotencyKey}:void 0,a=await i.emails.send({from:o,to:e.to,subject:e.subject,html:e.html,text:e.text,...e.headers?{headers:e.headers}:{}},p);if(a.error)throw new Error(`Resend send failed: ${a.error.message}`);if(!a.data)throw new Error("Resend send returned no data and no error");return{id:a.data.id,provider:"resend"}}n(M,"sendResendEmail");async function A(e){throw new Error("SMTP provider not implemented. Set RESEND_API_KEY to use Resend, or unset RULEMETRIC_EMAIL_PROVIDER to fall back to noop.")}n(A,"sendSmtpEmail");function K(){let e=process.env.RULEMETRIC_EMAIL_PROVIDER;return e==="resend"||e==="smtp"||e==="noop"?e:process.env.RESEND_API_KEY?"resend":"noop"}n(K,"selectEmailProvider");var Y=new Set(["test","example","invalid","localhost"]),j=/^example\.(com|net|org)$/;function B(e){let t=e.trim().toLowerCase(),r=t.lastIndexOf("@");if(r<0)return!1;let o=t.slice(r+1);if(!o)return!1;let i=o.slice(o.lastIndexOf(".")+1);return!!(Y.has(i)||j.test(o))}n(B,"isUndeliverableRecipient");var D=!1;async function se(e){let t=K();switch(D||(D=!0,process.stderr.write(`[email] active provider: ${t}
69
+ `)),t){case"resend":return B(e.to)?(process.stderr.write(`[email] skipping real send to reserved/undeliverable address ${e.to} (RFC 2606/6761) \u2014 routed to noop to protect sender reputation
70
+ `),x(e)):M(e);case"smtp":return A(e);case"noop":if(process.env.NODE_ENV==="production"&&process.env.RULEMETRIC_EMAIL_PROVIDER!=="noop")throw new Error("email provider unconfigured in production: RESEND_API_KEY is not set (set it, or force RULEMETRIC_EMAIL_PROVIDER=noop to intentionally disable email)");return x(e)}}n(se,"sendEmail");export{k as a,se as b};
@@ -1 +1 @@
1
- import{a as i}from"./chunk-HP2BUPGS.js";import{g as s}from"./chunk-TIQ7DQ3M.js";import{a as n}from"./chunk-ZLLER3HP.js";async function l(a,c){let{mirrorId:g,evalTargetId:p,config:r}=a,e=n(o=>c.logger.info(o),"log");await i(r,p,e);let t={type:"conversation",conversationId:r.conversationId};return await s(`/api/eval-jobs/${g}/state`,{result:t}).catch(o=>{e(`result persist failed: ${o instanceof Error?o.message:String(o)}`)}),t}n(l,"processConversation");export{l as a};
1
+ import{a as i}from"./chunk-HS7X43XE.js";import{h as s}from"./chunk-H2ORWIEY.js";import{a as n}from"./chunk-ZLLER3HP.js";async function l(a,c){let{mirrorId:g,evalTargetId:p,config:r}=a,e=n(o=>c.logger.info(o),"log");await i(r,p,e);let t={type:"conversation",conversationId:r.conversationId};return await s(`/api/eval-jobs/${g}/state`,{result:t}).catch(o=>{e(`result persist failed: ${o instanceof Error?o.message:String(o)}`)}),t}n(l,"processConversation");export{l as a};
@@ -0,0 +1 @@
1
+ import{a as h,c as _}from"./chunk-ARNZQBMX.js";import{d as p,e as m,g as S,i as w}from"./chunk-NJ5UED3H.js";import{a as u,b as M}from"./chunk-ZLLER3HP.js";import{useState as B,useMemo as P}from"react";import{Box as g,Text as r,useInput as E}from"ink";import{jsx as o,jsxs as d}from"react/jsx-runtime";function D(n){let t=n.recommendations;if(!t)return[];let s=[];for(let e of t.suggestions?.features_to_try??[])e.example_code&&s.push({label:e.feature,description:e.why_for_you||e.one_liner,command:e.example_code});for(let e of t.suggestions?.usage_patterns??[])e.copyable_prompt&&s.push({label:e.title,description:e.suggestion,command:e.copyable_prompt});for(let e of t.on_the_horizon?.opportunities??[])e.copyable_prompt&&s.push({label:e.title,description:e.whats_possible,command:e.copyable_prompt});return s}u(D,"extractSuggestions");function R(n){let t=n.trim();return/^(claude|rulemetric|pnpm|npm|npx|git)\s/.test(t)?t:`claude -p '${t.replace(/'/g,"'\\''")}'`}u(R,"toCliCommand");function v(n){try{let{execSync:t}=M("node:child_process");return process.platform==="darwin"?t("pbcopy",{input:n,stdio:["pipe","ignore","ignore"]}):t("xclip -selection clipboard",{input:n,stdio:["pipe","ignore","ignore"]}),!0}catch{return!1}}u(v,"copyToClipboard");function q({api:n,width:t,focused:s,onSelect:e}){let[b,I]=B(0),[C,y]=B(null),a=P(()=>n?D(n):[],[n]),f=n?.recommendations?.at_a_glance;if(E((l,c)=>{if(!(!s||a.length===0)){if(c.upArrow)I(i=>Math.max(0,i-1));else if(c.downArrow)I(i=>Math.min(a.length-1,i+1));else if(c.return){let i=a[b];if(i){let x=R(i.command);v(x)&&(y(b),setTimeout(()=>y(null),2e3)),e?.(x)}}}}),!n)return o(h,{title:"Insights",color:p,width:t,children:o(r,{dimColor:!0,children:"API offline \u2014 no insights"})});if(!f&&a.length===0)return o(h,{title:"Insights",color:p,width:t,children:o(r,{dimColor:!0,children:"No recommendations yet. Ensure the worker is running: rulemetric evals agent"})});let T=Math.min(30,Math.max(...a.map(l=>l.label.length),10)),A=Math.max(10,t-T-12);return d(h,{title:s?"\u25B8 Insights & Suggestions":"Insights & Suggestions",color:s?p:m,width:t,children:[f&&Object.entries(f).length>0&&o(g,{flexDirection:"column",marginBottom:1,children:Object.entries(f).map(([l,c])=>d(g,{flexDirection:"column",children:[o(r,{color:m,bold:!0,children:l.replace(/_/g," ").toUpperCase()}),o(r,{wrap:"wrap",children:String(c).slice(0,200)})]},l))}),a.length>0&&d(g,{flexDirection:"column",children:[d(g,{marginBottom:0,children:[o(r,{color:p,bold:!0,children:"Suggestions"}),s&&o(r,{dimColor:!0,children:" \u2191\u2193 navigate \u23CE copy command"})]}),a.map((l,c)=>{let i=s&&c===b,x=c===C;return d(g,{children:[o(r,{color:i?p:m,children:i?"\u25B8 ":" "}),o(r,{color:i?p:w,bold:i,children:_(l.label,T)}),o(r,{color:m,children:" \u2502 "}),o(r,{color:i?void 0:m,wrap:"truncate-end",children:_(l.description,A)}),x&&o(r,{color:S,children:" \u2713 copied"})]},c)})]})]})}u(q,"InsightsPanel");export{q as a};
@@ -0,0 +1,7 @@
1
+ import{a as e}from"./chunk-ZLLER3HP.js";import*as i from"node:fs";import*as u from"node:path";import*as R from"node:os";function m(){return process.env.RULEMETRIC_CONFIG_DIR||u.join(R.homedir(),".config","rulemetric")}e(m,"getConfigDir");var l;function F(){if(l!==void 0)return l;try{let n=u.join(m(),"env");if(!i.existsSync(n))return l={};let s=i.readFileSync(n,"utf-8"),E=e(h=>s.match(new RegExp(`^${h}=(.+)$`,"m"))?.[1]?.trim(),"read");return l={apiKey:E("RULEMETRIC_API_KEY"),accessToken:E("RULEMETRIC_ACCESS_TOKEN"),apiUrl:E("RULEMETRIC_API_URL")},l}catch{return l={}}}e(F,"loadEnvFileAuth");function U(){l=void 0}e(U,"__resetEnvFileAuthCache");function S(n=m()){let s=u.join(n,"auth.json");function E(o){i.mkdirSync(n,{recursive:!0,mode:448}),i.writeFileSync(s,JSON.stringify(o,null,2),{encoding:"utf-8",mode:384})}e(E,"saveToken");function h(){try{let o=i.readFileSync(s,"utf-8"),t=JSON.parse(o);return t&&typeof t=="object"&&"accessToken"in t&&"expiresAt"in t&&"email"in t&&typeof t.accessToken=="string"&&typeof t.expiresAt=="string"?t:null}catch{return null}}e(h,"loadToken");function y(){try{i.unlinkSync(s)}catch{}}e(y,"clearToken");function _(){let o=h();if(!o)return!1;let t=new Date(o.expiresAt).getTime();return Number.isNaN(t)?!1:Date.now()<t}e(_,"isAuthenticated");function g(o=0){let t=h();if(!t?.refreshToken)return!1;let r=new Date(t.expiresAt).getTime();return Number.isNaN(r)?!0:Date.now()>=r-o}e(g,"isRefreshable");function k(o,t){i.mkdirSync(n,{recursive:!0,mode:448});let r=u.join(n,"env"),c="",p="";try{let d=i.readFileSync(r,"utf-8"),T=d.match(/^RULEMETRIC_API_KEY=(.+)$/m);T&&(c=T[1]);let A=d.match(/^RULEMETRIC_API_URL=(.+)$/m);A&&(p=A[1])}catch{}let f=[`RULEMETRIC_ACCESS_TOKEN=${o}`];c&&f.push(`RULEMETRIC_API_KEY=${c}`);let v=t??p;v&&f.push(`RULEMETRIC_API_URL=${v}`),i.writeFileSync(r,f.join(`
2
+ `)+`
3
+ `,{encoding:"utf-8",mode:384})}e(k,"saveEnvFile");function x(o,t){i.mkdirSync(n,{recursive:!0,mode:448});let r=u.join(n,"env"),c="",p="";try{let d=i.readFileSync(r,"utf-8"),T=d.match(/^RULEMETRIC_ACCESS_TOKEN=(.+)$/m);T&&(c=T[1]);let A=d.match(/^RULEMETRIC_API_URL=(.+)$/m);A&&(p=A[1])}catch{}let f=[`RULEMETRIC_API_KEY=${o}`];c&&f.push(`RULEMETRIC_ACCESS_TOKEN=${c}`);let v=t??p;v&&f.push(`RULEMETRIC_API_URL=${v}`),i.writeFileSync(r,f.join(`
4
+ `)+`
5
+ `,{encoding:"utf-8",mode:384})}e(x,"saveApiKeyToEnv");function I(){let o=u.join(n,"env");try{i.unlinkSync(o)}catch{}}e(I,"clearEnvFile");function C(){let o=u.join(n,"env");try{let t=i.readFileSync(o,"utf-8"),r=t.split(`
6
+ `).filter(c=>!c.startsWith("RULEMETRIC_API_KEY=")).join(`
7
+ `);r!==t&&i.writeFileSync(o,r,{encoding:"utf-8",mode:384})}catch{}}return e(C,"removeApiKeyFromEnvFile"),{saveToken:E,loadToken:h,clearToken:y,isAuthenticated:_,isRefreshable:g,saveEnvFile:k,saveApiKeyToEnv:x,clearEnvFile:I,removeApiKeyFromEnvFile:C,configDir:n,authFile:s}}e(S,"createAuthStore");function a(){return S()}e(a,"getStore");function L(n){a().saveToken(n)}e(L,"saveToken");function K(){return a().loadToken()}e(K,"loadToken");function M(){a().clearToken()}e(M,"clearToken");function P(){if(process.env.RULEMETRIC_API_KEY||a().isAuthenticated())return!0;let n=F();return!!(n.apiKey||n.accessToken)}e(P,"isAuthenticated");function N(n,s){a().saveEnvFile(n,s)}e(N,"saveEnvFile");function j(n,s){a().saveApiKeyToEnv(n,s)}e(j,"saveApiKey");function $(){a().clearEnvFile()}e($,"clearEnvFile");function w(){a().removeApiKeyFromEnvFile()}e(w,"removeApiKeyFromEnv");function O(){return m()}e(O,"getDefaultConfigDir");var b=m();export{F as a,U as b,S as c,L as d,K as e,M as f,P as g,N as h,j as i,$ as j,w as k,O as l,b as m};
@@ -0,0 +1,4 @@
1
+ import{a as c,c as d}from"./chunk-IZTIYR5Q.js";import{d as u}from"./chunk-V44SRRYR.js";import{a}from"./chunk-U6XEU573.js";import{a as n}from"./chunk-VLOX6KOM.js";import{b as i}from"./chunk-H2ORWIEY.js";import{g as r}from"./chunk-O6C2UGBY.js";import{a as s}from"./chunk-ZLLER3HP.js";import{Command as f,Flags as h}from"@oclif/core";function p(t){return t instanceof i?t.statusCode>=500||t.statusCode===408||t.statusCode===0:/fetch failed|ECONNREFUSED|ECONNRESET|ETIMEDOUT|EAI_AGAIN|bad gateway|timed out/i.test(t.message??"")}s(p,"isAvailabilityError");var m=class extends f{static{s(this,"BaseCommand")}static baseFlags={"api-url":h.string({description:"Override API base URL",env:"RULEMETRIC_API_URL",hidden:!0})};async init(){await super.init();let{flags:e}=await this.parse(this.constructor);e["api-url"]&&(process.env.RULEMETRIC_API_URL=e["api-url"]);let o=d(this.config.version);o&&!this.argv.includes("--quiet")&&!process.env.RULEMETRIC_QUIET&&process.stderr.write(`
2
+ ${o}
3
+
4
+ `),c();try{await a()}catch{}}requireAuth(){r()||this.error("Not logged in. Run `rulemetric auth login` to authenticate."),n()}async catch(e){throw p(e)&&await u({command:this.id,statusCode:e instanceof i?e.statusCode:void 0,message:e.message,cliVersion:this.config.version}),e instanceof i&&(e.statusCode===401&&this.error("Session expired. Run `rulemetric auth login` to re-authenticate."),this.error(e.message)),(e.message?.includes("fetch failed")||e.message?.includes("ECONNREFUSED"))&&this.error("Could not connect to the API server. Is it running?"),e}};export{m as a};
@@ -86,7 +86,7 @@ RESPOND WITH ONLY A VALID JSON OBJECT:
86
86
  "goal_categories": {"category": count},
87
87
  "outcome": "achieved|mostly_achieved|partially_achieved|not_achieved|abandoned",
88
88
  "session_type": "quick_task|iterative_refinement|exploration|debugging|greenfield",
89
- "friction_counts": {"wrong_approach": 0, "tool_failure": 0, "excessive_changes": 0, "misunderstanding": 0},
89
+ "friction": {"wrong_approach": 0, "tool_failure": 0, "excessive_changes": 0, "misunderstanding": 0},
90
90
  "friction_detail": "Brief description of any friction encountered, or empty string",
91
91
  "primary_success": "Brief description of main achievement, or empty string",
92
92
  "brief_summary": "2-3 sentence summary of the session"
@@ -1 +1 @@
1
- import{a as i}from"./chunk-SBILN45P.js";import{a as f}from"./chunk-ZLLER3HP.js";import{useEffect as J,useState as u,useCallback as m,useRef as s}from"react";var y=5e3;function T(a=20){let[d,b]=u([]),[g,l]=u(null),[h,p]=u(!0),r=s(!1),e=s(null),c=s(0),t=m(async()=>{let o=++c.current;try{let n=await i({limit:a});if(r.current||o!==c.current)return;b(n),l(null)}catch(n){if(r.current||o!==c.current)return;l(n instanceof Error?n.message:String(n))}finally{if(r.current||o!==c.current)return;p(!1),e.current=setTimeout(()=>{t()},y)}},[a]),L=m(()=>{e.current&&clearTimeout(e.current),t()},[t]);return J(()=>(r.current=!1,t(),()=>{r.current=!0,e.current&&clearTimeout(e.current)}),[t]),{jobs:d,error:g,loading:h,refetch:L}}f(T,"useLaunchJobs");export{T as a};
1
+ import{a as i}from"./chunk-ZR3MUNLS.js";import{a as f}from"./chunk-ZLLER3HP.js";import{useEffect as J,useState as u,useCallback as m,useRef as s}from"react";var y=5e3;function T(a=20){let[d,b]=u([]),[g,l]=u(null),[h,p]=u(!0),r=s(!1),e=s(null),c=s(0),t=m(async()=>{let o=++c.current;try{let n=await i({limit:a});if(r.current||o!==c.current)return;b(n),l(null)}catch(n){if(r.current||o!==c.current)return;l(n instanceof Error?n.message:String(n))}finally{if(r.current||o!==c.current)return;p(!1),e.current=setTimeout(()=>{t()},y)}},[a]),L=m(()=>{e.current&&clearTimeout(e.current),t()},[t]);return J(()=>(r.current=!1,t(),()=>{r.current=!0,e.current&&clearTimeout(e.current)}),[t]),{jobs:d,error:g,loading:h,refetch:L}}f(T,"useLaunchJobs");export{T as a};
@@ -0,0 +1,5 @@
1
+ import{b as E,d as R}from"./chunk-H2ORWIEY.js";import{a as o}from"./chunk-ZLLER3HP.js";import{createHash as C}from"node:crypto";import{existsSync as A,mkdirSync as I,readFileSync as p,renameSync as L,rmdirSync as M,writeFileSync as m}from"node:fs";import{homedir as U,tmpdir as x}from"node:os";import{join as c}from"node:path";var $=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;function v(t){return $.test(t)?t:`antigravity-${C("sha256").update(t).digest("hex").slice(0,16)}`}o(v,"hookSessionKey");var _=100,F=new Set(["RUN_COMMAND","VIEW_FILE","LIST_DIRECTORY","CODE_ACTION","GREP_SEARCH","SEARCH_WEB"]),H=new Set(["CONVERSATION_HISTORY","KNOWLEDGE_ARTIFACTS","CHECKPOINT"]);function T(){return process.env.RULEMETRIC_CONFIG_DIR??c(U(),".config","rulemetric")}o(T,"configDir");function O(){return c(T(),"antigravity-state")}o(O,"stateDir");function P(t){return c(O(),`${t}.json`)}o(P,"stateFile");function k(){let t=c(T(),"env");if(A(t))try{let n=p(t,"utf-8");for(let r of n.split(/\r?\n/)){let e=r.match(/^([A-Z_][A-Z0-9_]*)=(.*)$/);if(!e)continue;let i=e[1];if(process.env[i]!==void 0)continue;let s=e[2];(s.startsWith('"')&&s.endsWith('"')||s.startsWith("'")&&s.endsWith("'"))&&(s=s.slice(1,-1)),process.env[i]=s}}catch{}}o(k,"loadEnvFile");function b(t){try{let n=p(P(t),"utf-8"),r=JSON.parse(n);if(r&&typeof r=="object"&&"lastStepIdx"in r){let e=r.lastStepIdx;if(typeof e=="number"&&Number.isFinite(e))return{lastStepIdx:e}}}catch{}return null}o(b,"loadState");function g(t,n){I(O(),{recursive:!0});let r=P(t),e=`${r}.tmp`;m(e,JSON.stringify(n),{mode:384});try{L(e,r)}catch{m(r,JSON.stringify(n),{mode:384})}}o(g,"saveState");function N(t){let n=process.env.TMPDIR??x(),r=c(n,"rulemetric"),e=c(r,v(t));try{return p(e,"utf-8").trim()||null}catch{return null}}o(N,"resolveRwSessionId");function W(t){let n=process.env.TMPDIR??x(),r=c(n,"rulemetric"),e=v(t),i=c(r,`${e}.seq`),s=c(r,`${e}.seqlock`),l=Date.now()+5e3;for(;Date.now()<l;)try{I(s);break}catch{}let a=1;try{a=parseInt(p(i,"utf-8").trim(),10)+1,(!Number.isFinite(a)||a<1)&&(a=1)}catch{a=1}try{m(i,String(a))}catch{}try{M(s)}catch{}return a}o(W,"nextSequence");function Y(t,n){let r;try{r=p(t,"utf-8")}catch{return[]}let e=[];for(let i of r.split(/\r?\n/))if(i.trim())try{let s=JSON.parse(i);typeof s.step_index=="number"&&s.step_index>n&&e.push(s)}catch{}return e.sort((i,s)=>i.step_index-s.step_index),e}o(Y,"readNewRecords");function G(t){let n;try{n=p(t,"utf-8")}catch{return-1}let r=-1;for(let e of n.split(/\r?\n/))if(e.trim())try{let i=JSON.parse(e);typeof i.step_index=="number"&&i.step_index>r&&(r=i.step_index)}catch{}return r}o(G,"findMaxStepIndex");function J(t){let n=t.match(/<USER_REQUEST>\s*([\s\S]*?)\s*<\/USER_REQUEST>/);return n?n[1].trim():t.trim()}o(J,"extractUserPrompt");function j(t,n){let r=t.created_at??new Date().toISOString(),e={antigravityStepIndex:t.step_index,antigravitySource:t.source,antigravityType:t.type};if(H.has(t.type)||F.has(t.type))return null;if(t.source==="USER_EXPLICIT"&&t.type==="USER_INPUT")return{sequence:n,eventType:"user_message",content:J(t.content??""),timestamp:r,metadata:e};if(t.source==="MODEL"&&t.type==="PLANNER_RESPONSE"){let i=[];return t.thinking&&t.thinking.trim()&&i.push(`[thinking]
2
+ ${t.thinking.trim()}`),t.content&&t.content.trim()&&i.push(t.content.trim()),t.tool_calls&&t.tool_calls.length>0&&(e.antigravityToolCalls=t.tool_calls.map(s=>s.name).filter(Boolean)),{sequence:n,eventType:"assistant_response",content:i.join(`
3
+
4
+ `)||null,timestamp:r,metadata:e}}return t.source==="MODEL"&&t.type==="GENERIC"?{sequence:n,eventType:"tool_result",content:t.content??null,timestamp:r,metadata:e}:t.source==="SYSTEM"&&(t.type==="SYSTEM_MESSAGE"||t.type==="ERROR_MESSAGE")?null:{sequence:n,eventType:`antigravity_${t.type.toLowerCase()}`,content:t.content??null,timestamp:r,metadata:e}}o(j,"classifyRecord");function q(t){try{let n=JSON.parse(t);return n&&typeof n=="object"?n:null}catch{return null}}o(q,"parseHookPayload");async function K(t,n,r,e,i={}){let s=i.errorSink??(u=>process.stderr.write(u)),l=0,a=0,d=0,S=0,f=e;for(let u of t){l++,i.onProgress?.({attempted:l,total:t.length,record:u});let w=W(r),y=j(u,w);if(!y)S++;else try{await R(`/api/sessions/${n}/events`,{method:"POST",body:y}),a++}catch(h){d++;let D=h instanceof E?h.statusCode:"unknown";s(`[antigravity-tailer] failed step=${u.step_index} type=${u.type} status=${D}
5
+ `)}u.step_index>f&&(f=u.step_index)}return{attempted:l,emitted:a,failed:d,skipped:S,highestStepIdx:f}}o(K,"emitRecordsAsEvents");async function z(t){let n=q(t);if(!n?.conversationId||!n?.transcriptPath||(k(),!process.env.RULEMETRIC_API_URL))return;let r=N(n.conversationId);if(!r)return;let e=b(n.conversationId);if(e===null){let l=G(n.transcriptPath);g(n.conversationId,{lastStepIdx:l});return}let i=Y(n.transcriptPath,e.lastStepIdx);if(i.length===0)return;i.length>_&&(i=i.slice(0,_));let s=await K(i,r,n.conversationId,e.lastStepIdx);g(n.conversationId,{lastStepIdx:s.highestStepIdx})}o(z,"tailAntigravityTranscript");var tt={load:b,save:g,resolveRwSessionId:N,loadEnvFile:k};export{Y as a,G as b,J as c,j as d,K as e,z as f,tt as g};
@@ -1 +1 @@
1
- import{b as g,c as m}from"./chunk-N7ODX6PO.js";import{d as s,g as c}from"./chunk-TIQ7DQ3M.js";import{a as i}from"./chunk-ZLLER3HP.js";var u=6e4;function o(t,e){try{t(JSON.stringify({ts:new Date().toISOString(),...e}))}catch{t(`[tt-heartbeat] log_error event=${e.event}`)}}i(o,"structuredLog");function d(t,e){return e.aborted?Promise.resolve(!1):t<=0?Promise.resolve(!0):new Promise(r=>{let a=setTimeout(()=>{e.removeEventListener("abort",n),r(!0)},t),n=i(()=>{clearTimeout(a),e.removeEventListener("abort",n),r(!1)},"onAbort");e.addEventListener("abort",n,{once:!0})})}i(d,"abortableSleep");async function l(t,e){if(t.kind!=="tmux")return;let a=(await g(m(t.target))).code===0?"active":"missing";try{await c(`/api/terminal-targets/${t.id}/status`,{status:a,lastSeenAt:new Date().toISOString()}),o(e,{event:"tt_heartbeat",targetId:t.id,target:t.target,status:a})}catch(n){o(e,{event:"tt_heartbeat_error",targetId:t.id,target:t.target,error:n instanceof Error?n.message:String(n)})}}i(l,"probeAndReport");async function b(t){let e;try{e=await s("/api/terminal-targets?status=active")}catch(r){o(t,{event:"tt_heartbeat_list_error",error:r instanceof Error?r.message:String(r)});return}for(let r of e.targets??[])try{await l(r,t)}catch(a){o(t,{event:"tt_heartbeat_probe_error",targetId:r.id,error:a instanceof Error?a.message:String(a)})}}i(b,"runOneHeartbeatCycle");async function p(t){let e=t.log??(()=>{}),r=t.intervalMs??u;for(o(e,{event:"tt_heartbeat_start",intervalMs:r});!t.signal.aborted&&(await b(e),!!await d(r,t.signal)););o(e,{event:"tt_heartbeat_stop"})}i(p,"startTerminalTargetHeartbeat");export{l as a,b,p as c};
1
+ import{b as g,c as m}from"./chunk-N7ODX6PO.js";import{e as s,h as c}from"./chunk-H2ORWIEY.js";import{a as i}from"./chunk-ZLLER3HP.js";var u=6e4;function o(t,e){try{t(JSON.stringify({ts:new Date().toISOString(),...e}))}catch{t(`[tt-heartbeat] log_error event=${e.event}`)}}i(o,"structuredLog");function d(t,e){return e.aborted?Promise.resolve(!1):t<=0?Promise.resolve(!0):new Promise(r=>{let a=setTimeout(()=>{e.removeEventListener("abort",n),r(!0)},t),n=i(()=>{clearTimeout(a),e.removeEventListener("abort",n),r(!1)},"onAbort");e.addEventListener("abort",n,{once:!0})})}i(d,"abortableSleep");async function l(t,e){if(t.kind!=="tmux")return;let a=(await g(m(t.target))).code===0?"active":"missing";try{await c(`/api/terminal-targets/${t.id}/status`,{status:a,lastSeenAt:new Date().toISOString()}),o(e,{event:"tt_heartbeat",targetId:t.id,target:t.target,status:a})}catch(n){o(e,{event:"tt_heartbeat_error",targetId:t.id,target:t.target,error:n instanceof Error?n.message:String(n)})}}i(l,"probeAndReport");async function b(t){let e;try{e=await s("/api/terminal-targets?status=active")}catch(r){o(t,{event:"tt_heartbeat_list_error",error:r instanceof Error?r.message:String(r)});return}for(let r of e.targets??[])try{await l(r,t)}catch(a){o(t,{event:"tt_heartbeat_probe_error",targetId:r.id,error:a instanceof Error?a.message:String(a)})}}i(b,"runOneHeartbeatCycle");async function p(t){let e=t.log??(()=>{}),r=t.intervalMs??u;for(o(e,{event:"tt_heartbeat_start",intervalMs:r});!t.signal.aborted&&(await b(e),!!await d(r,t.signal)););o(e,{event:"tt_heartbeat_stop"})}i(p,"startTerminalTargetHeartbeat");export{l as a,b,p as c};
@@ -0,0 +1,15 @@
1
+ import{a as S,b as z,c as T}from"./chunk-QFVGUZDO.js";import{c as A,d as C,f as b}from"./chunk-RTWRHIKY.js";import{a as O}from"./chunk-ZL4MZMUK.js";import{a as j}from"./chunk-5RBLIVBF.js";import{e as _,f as I,h as u}from"./chunk-H2ORWIEY.js";import{a as $}from"./chunk-ZLLER3HP.js";async function D(f,m){let{mirrorId:o,projectPath:s,projectId:i,config:p}=f,e=$(n=>m.logger.info(n),"log");if(p?.sessionId)return M({mirrorId:o,sessionId:p.sessionId},e);e(`Processing insights job ${o}...`),await u(`/api/insights-jobs/${o}/progress`,{status:"running",progress:{step:"reading_data"}});try{let{repaired:n}=await I("/api/sessions/repair-analyzed-at",{});n>0&&e(` Repaired analyzed_at on ${n} orphan session(s).`)}catch(n){e(` Warning: analyzed_at repair failed: ${n instanceof Error?n.message:String(n)}`)}let a=await J(s,i);if(!a)throw new j("No session data found \u2014 ensure sessions are captured and enriched.");e(` Found ${a.stats.sessions} sessions, generating recommendations...`);let w=20,c=200;if(C()!=="none"){let n=0,t=0;try{for(;n<c;){let l=await _(`/api/sessions?hasAnalysis=false&limit=${w}&offset=${t}`);if(l.length===0)break;e(` Generating facets for ${l.length} un-analyzed sessions (drained ${n} so far)...`);for(let g of l){if(n>=c)break;try{let d=await _(`/api/sessions/${g.id}/events?limit=100`);if(d.length<2){n++,t++;continue}let P=d.filter(h=>h.eventType==="user_message"||h.eventType==="human").map(h=>h.content?.slice(0,200)??"").filter(Boolean).join(`
2
+ ---
3
+ `);if(!P){n++,t++;continue}let E=await b(T,P,4096);if(E){let h=d.filter(R=>R.eventType==="user_message"||R.eventType==="human").length;await u(`/api/sessions/${g.id}/enrich`,{analysis:{source:"generated_facets",...E},analyzedEventCount:d.length,analyzedTurnCount:h}),e(` Generated facets for session ${g.id} (${g.tool})`)}else t++;n++}catch(d){e(` Failed to generate facets for session ${g.id}: ${d instanceof Error?d.message:String(d)}`),n++,t++}}if(l.length<w)break}}catch(l){e(` Warning: facet generation failed after ${n} sessions: ${l instanceof Error?l.message:String(l)}`)}}let r={},y=S.length+1;for(let n=0;n<S.length;n++){let t=S[n];e(` [${n+1}/${y}] Generating ${t.name}...`);try{await u(`/api/insights-jobs/${o}/progress`,{status:"running",progress:{step:t.name,current:n+1,total:y,partial:{...r}}})}catch(g){e(` Warning: progress update failed for ${t.name}: ${g instanceof Error?g.message:String(g)}`)}e(` Running LLM prompt for ${t.name}...`);let l=await b(t.prompt,a.summary,t.maxTokens);l?(r[t.name]=l,e(` Got result for ${t.name}`)):e(` No result for ${t.name} (LLM returned null)`)}e(` [${y}/${y}] Generating at_a_glance...`),await u(`/api/insights-jobs/${o}/progress`,{status:"running",progress:{step:"at_a_glance",current:y,total:y,partial:{...r}}});let N=[a.summary,r.what_works?`
4
+ ## What Works
5
+ ${JSON.stringify(r.what_works)}`:"",r.friction_analysis?`
6
+ ## Friction
7
+ ${JSON.stringify(r.friction_analysis)}`:"",r.suggestions?`
8
+ ## Suggestions
9
+ ${JSON.stringify(r.suggestions)}`:"",r.on_the_horizon?`
10
+ ## On the Horizon
11
+ ${JSON.stringify(r.on_the_horizon)}`:""].join(`
12
+ `),k=await b(z,N,8192);k&&(r.at_a_glance=k),e(" Uploading results..."),e(` Done! Recommendations generated for job ${o}`),O(r);let v={recommendations:r};return await u(`/api/insights-jobs/${o}/state`,{result:v}).catch(n=>{e(`result persist failed: ${n instanceof Error?n.message:String(n)}`)}),v}$(D,"processInsights");async function M(f,m){let{mirrorId:o,sessionId:s}=f;m(`Analyzing session ${s} via tool CLI...`),await u(`/api/insights-jobs/${o}/progress`,{status:"running",progress:{step:"fetching_session"}});let i=await _(`/api/sessions/${s}`);if(i.analysis&&i.analysis.source==="session_analysis")return m(` Session ${s} already analyzed \u2014 skipping (idempotency guard)`),{sessionId:s,skipped:!0,reason:"already_analyzed"};let p=await _(`/api/sessions/${s}/events?limit=100`);if(p.length<2)throw new j("Session has too few events to analyze");let e=p.filter(c=>c.eventType==="user_message"||c.eventType==="human").map(c=>c.content?.slice(0,200)??"").filter(Boolean).join(`
13
+ ---
14
+ `);if(!e)throw new j("No user messages found in session");await u(`/api/insights-jobs/${o}/progress`,{status:"running",progress:{step:"running_analysis",tool:i.tool}});let a=A(i.tool,T,e);if(!a)throw new Error(`Analysis failed \u2014 ${i.tool} CLI returned no result`);let w=p.filter(c=>c.eventType==="user_message"||c.eventType==="human").length;return await u(`/api/sessions/${s}/enrich`,{analysis:{source:"session_analysis",tool:i.tool,...a},analyzedEventCount:p.length,analyzedTurnCount:w}),m(` Session ${s} analyzed via ${i.tool}`),{sessionId:s,tool:i.tool,facets:a}}$(M,"processSessionAnalysisInline");async function J(f,m){try{let o=new URLSearchParams;m?o.set("projectId",m):f&&o.set("projectPath",f);let s=await _(`/api/insights/compute?${o}`);if(!s||s.total_sessions===0)return null;let i=Object.entries(s.tool_counts??{}).sort((e,a)=>a[1]-e[1]).slice(0,10).map(([e,a])=>`${e}: ${a}`).join(", ");return{summary:[`Sessions: ${s.total_sessions}, Messages: ${s.total_messages}, Hours: ${Math.round(s.total_duration_hours)}`,`Top tools: ${i}`,s.goal_categories&&Object.keys(s.goal_categories).length>0?`Goals: ${JSON.stringify(s.goal_categories)}`:"",s.friction&&Object.keys(s.friction).length>0?`Friction: ${JSON.stringify(s.friction)}`:"",s.outcomes&&Object.keys(s.outcomes).length>0?`Outcomes: ${JSON.stringify(s.outcomes)}`:"",s.projects&&Object.keys(s.projects).length>0?`Projects: ${JSON.stringify(s.projects)}`:""].filter(Boolean).join(`
15
+ `),stats:{sessions:s.total_sessions,totalMessages:s.total_messages,totalHours:s.total_duration_hours,toolCounts:s.tool_counts,goalCounts:s.goal_categories,frictionCounts:s.friction}}}catch{return null}}$(J,"buildDataSummaryFromApi");export{D as a};
@@ -1,4 +1,4 @@
1
- import{a as E,g as _,h as R,j as T,m as A}from"./chunk-O7ZMHCMG.js";import{c as f}from"./chunk-MVM6OGAF.js";import{d as k}from"./chunk-TIQ7DQ3M.js";import{g as m,k as P}from"./chunk-M6AJDVCL.js";import{a as i}from"./chunk-ZLLER3HP.js";import{execSync as x}from"node:child_process";import{existsSync as p,readFileSync as S}from"node:fs";import{homedir as d}from"node:os";import{join as a}from"node:path";var I=["install","auth","hooks","worker"],L=[],j=[...I,...L];function $(){return{projectPath:process.cwd(),configDir:P()}}i($,"defaultContext");var b=a(d(),".mitmproxy","mitmproxy-ca-cert.pem");function g(t){if(!t)return"";if(t.length<=8)return"*".repeat(t.length);let e=t.slice(0,4),n=t.slice(-4);return`${e}${"*".repeat(Math.max(4,t.length-8))}${n}`}i(g,"maskToken");function z(t,e){let n=t===null?[]:t.replace(/\n$/,"").split(`
1
+ import{a as E,g as _,h as R,j as T,m as A}from"./chunk-2JRDG4LJ.js";import{c as f}from"./chunk-MVM6OGAF.js";import{e as k}from"./chunk-H2ORWIEY.js";import{g as m,l as P}from"./chunk-O6C2UGBY.js";import{a as i}from"./chunk-ZLLER3HP.js";import{execSync as x}from"node:child_process";import{existsSync as p,readFileSync as S}from"node:fs";import{homedir as d}from"node:os";import{join as a}from"node:path";var I=["install","auth","hooks","worker"],L=[],j=[...I,...L];function $(){return{projectPath:process.cwd(),configDir:P()}}i($,"defaultContext");var b=a(d(),".mitmproxy","mitmproxy-ca-cert.pem");function g(t){if(!t)return"";if(t.length<=8)return"*".repeat(t.length);let e=t.slice(0,4),n=t.slice(-4);return`${e}${"*".repeat(Math.max(4,t.length-8))}${n}`}i(g,"maskToken");function z(t,e){let n=t===null?[]:t.replace(/\n$/,"").split(`
2
2
  `),r=e===null?[]:e.replace(/\n$/,"").split(`
3
3
  `),s=[],c=Math.max(n.length,r.length);for(let l=0;l<c;l++){let o=n[l],u=r[l];o===u?s.push(` ${o}`):(o!==void 0&&s.push(`-${o}`),u!==void 0&&s.push(`+${u}`))}return s.join(`
4
4
  `)}i(z,"renderDiff");function v(t,e){let n=a(t,"env");if(!p(n))return null;try{let s=S(n,"utf-8").match(new RegExp(`^${e}=(.+)$`,"m"));return s?s[1]:null}catch{return null}}i(v,"readEnvValue");async function C(){if(!m())return!1;try{return(await Promise.race([k("/api/setup/status"),new Promise((e,n)=>setTimeout(()=>n(new Error("setup/status timeout")),2500))]))?.workerActive===!0}catch{return!1}}i(C,"workerActive");function y(t,e){let n=a(t,".claude",e),r={},s=null;if(p(n))try{s=S(n,"utf-8").replace(/\n$/,""),r=JSON.parse(s)}catch{r={}}return{settings:r,before:s}}i(y,"readProjectSettings");function M(t){let{settings:e,before:n}=y(t,"settings.local.json");return _(e),{before:n,after:JSON.stringify(e,null,2)}}i(M,"projectHooksSettings");function O(t){let{settings:e,before:n}=y(t,"settings.local.json"),r={...e.env??{}};return r.HTTPS_PROXY=`http://localhost:${f}`,r.NO_PROXY=T,r.NODE_EXTRA_CA_CERTS=b,{before:n,after:JSON.stringify({...e,env:r},null,2)}}i(O,"projectProxyEnvSettings");function D(t){let{settings:e,before:n}=y(t,"settings.json");if(n===null)return null;let{removed:r}=A(e,f);return r?{before:n,after:JSON.stringify(e,null,2)}:null}i(D,"projectSharedSettingsMigration");var N=a(d(),"Library","LaunchAgents","com.rulemetric.worker.plist"),U=a(d(),".config","systemd","user","rulemetric-worker.service");function h(t){x(t,{stdio:"inherit"})}i(h,"runCommand");var w=[{id:"install",title:"Install the CLI",command:"npm install -g @rulemetric/cli",async detect(){return m()||await C()},async plan(){return{id:"install",title:"Install the CLI",command:"npm install -g @rulemetric/cli",artifacts:[{path:"npm install -g @rulemetric/cli",kind:"command",before:null,after:"rulemetric --version # verifies the binary is on PATH"}]}},async apply(){h("npm install -g @rulemetric/cli")}},{id:"auth",title:"Authenticate",command:"rulemetric auth login",async detect(){return m()},async plan(t){let e=a(t.configDir,"env"),n=null;if(p(e))try{n=K(S(e,"utf-8"))}catch{n="(unreadable)"}let r=v(t.configDir,"RULEMETRIC_ACCESS_TOKEN"),c=[`RULEMETRIC_ACCESS_TOKEN=${g(r||"<token-from-login>")}`],l=v(t.configDir,"RULEMETRIC_API_KEY");l&&c.push(`RULEMETRIC_API_KEY=${g(l)}`);let o=process.env.RULEMETRIC_API_URL;o&&c.push(`RULEMETRIC_API_URL=${o}`);let u=c.join(`
@@ -0,0 +1 @@
1
+ import{c as l}from"./chunk-H2ORWIEY.js";import{c as a,l as u}from"./chunk-O6C2UGBY.js";import{a as o}from"./chunk-ZLLER3HP.js";var c=120*1e3,t=null;async function k(){if(process.env.RULEMETRIC_API_KEY)return!0;let e=a(u());if(!e.isRefreshable(c))return!0;let r=e.loadToken();return r?.refreshToken?t||(t=f(e,r).finally(()=>{t=null}),t):!0}o(k,"ensureFreshToken");async function f(e,r){let s;try{s=await fetch(`${l()}/auth/refresh`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:r.refreshToken})})}catch{return!0}if(s.status===401)return e.clearToken(),!1;if(!s.ok)return!0;let n=await s.json().catch(()=>null);if(!n?.accessToken||!n.refreshToken)return!0;let i={accessToken:n.accessToken,refreshToken:n.refreshToken,expiresAt:n.expiresAt??r.expiresAt,email:n.email??r.email};return e.saveToken(i),e.saveEnvFile(i.accessToken),!0}o(f,"doRefresh");export{k as a};
@@ -1 +1 @@
1
- import{a as d,c as m}from"./chunk-TIQ7DQ3M.js";import{a as c,k as a}from"./chunk-M6AJDVCL.js";import{a as o}from"./chunk-ZLLER3HP.js";import{createHash as g,randomUUID as v}from"node:crypto";import{hostname as y,platform as p}from"node:os";import{existsSync as P,mkdirSync as _,readFileSync as h,writeFileSync as R}from"node:fs";import{join as E}from"node:path";var O="device-id";function u(){let e=o(t=>t==="1"||t==="true","off");return e(process.env.RULEMETRIC_NO_TELEMETRY)||e(process.env.DO_NOT_TRACK)}o(u,"telemetryDisabled");function l(){let e=a(),t=E(e,O);try{if(P(t)){let r=h(t,"utf-8").trim();if(r)return r}}catch{}let n=g("sha256").update(`${v()}:${y()}`).digest("hex").slice(0,32);try{_(e,{recursive:!0}),R(t,n,{mode:384})}catch{}return n}o(l,"getDeviceId");async function U(e,t={},n){if(!u())try{await m("/api/telemetry/cli-events",{method:"POST",body:{event:e,deviceId:l(),cliVersion:n,os:p(),props:t},timeoutMs:5e3})}catch{}}o(U,"emitSetupEvent");async function w(e){if(u())return;let n=`${process.env.RULEMETRIC_API_URL??c().apiUrl??d}/api/telemetry/cli-error`,r=process.env.HTTPS_PROXY,s=process.env.HTTP_PROXY,T=r!==void 0||s!==void 0;delete process.env.HTTPS_PROXY,delete process.env.HTTP_PROXY;let i=new AbortController,f=setTimeout(()=>i.abort(),4e3);try{await globalThis.fetch(n,{method:"POST",headers:{"Content-Type":"application/json","User-Agent":`rulemetric-cli/${e.cliVersion??"unknown"}`},body:JSON.stringify({event:e.event??"onboarding_error",deviceId:l(),command:e.command,statusCode:e.statusCode,message:e.message?e.message.slice(0,500):void 0,cliVersion:e.cliVersion,os:p(),nodeVersion:process.version,proxied:T,props:e.props}),signal:i.signal})}catch{}finally{clearTimeout(f),r!==void 0&&(process.env.HTTPS_PROXY=r),s!==void 0&&(process.env.HTTP_PROXY=s)}}o(w,"emitErrorBeacon");export{u as a,l as b,U as c,w as d};
1
+ import{a as d,d as m}from"./chunk-H2ORWIEY.js";import{a as c,l as a}from"./chunk-O6C2UGBY.js";import{a as o}from"./chunk-ZLLER3HP.js";import{createHash as g,randomUUID as v}from"node:crypto";import{hostname as y,platform as p}from"node:os";import{existsSync as P,mkdirSync as _,readFileSync as h,writeFileSync as R}from"node:fs";import{join as E}from"node:path";var O="device-id";function u(){let e=o(t=>t==="1"||t==="true","off");return e(process.env.RULEMETRIC_NO_TELEMETRY)||e(process.env.DO_NOT_TRACK)}o(u,"telemetryDisabled");function l(){let e=a(),t=E(e,O);try{if(P(t)){let r=h(t,"utf-8").trim();if(r)return r}}catch{}let n=g("sha256").update(`${v()}:${y()}`).digest("hex").slice(0,32);try{_(e,{recursive:!0}),R(t,n,{mode:384})}catch{}return n}o(l,"getDeviceId");async function U(e,t={},n){if(!u())try{await m("/api/telemetry/cli-events",{method:"POST",body:{event:e,deviceId:l(),cliVersion:n,os:p(),props:t},timeoutMs:5e3})}catch{}}o(U,"emitSetupEvent");async function w(e){if(u())return;let n=`${process.env.RULEMETRIC_API_URL??c().apiUrl??d}/api/telemetry/cli-error`,r=process.env.HTTPS_PROXY,s=process.env.HTTP_PROXY,T=r!==void 0||s!==void 0;delete process.env.HTTPS_PROXY,delete process.env.HTTP_PROXY;let i=new AbortController,f=setTimeout(()=>i.abort(),4e3);try{await globalThis.fetch(n,{method:"POST",headers:{"Content-Type":"application/json","User-Agent":`rulemetric-cli/${e.cliVersion??"unknown"}`},body:JSON.stringify({event:e.event??"onboarding_error",deviceId:l(),command:e.command,statusCode:e.statusCode,message:e.message?e.message.slice(0,500):void 0,cliVersion:e.cliVersion,os:p(),nodeVersion:process.version,proxied:T,props:e.props}),signal:i.signal})}catch{}finally{clearTimeout(f),r!==void 0&&(process.env.HTTPS_PROXY=r),s!==void 0&&(process.env.HTTP_PROXY=s)}}o(w,"emitErrorBeacon");export{u as a,l as b,U as c,w as d};
@@ -1,2 +1,2 @@
1
- import{c as R}from"./chunk-6QKI756T.js";import{b as s,c as r,h as j}from"./chunk-NVOTOQBA.js";import{a as P}from"./chunk-5RBLIVBF.js";import{a as g}from"./chunk-ZLLER3HP.js";import{and as y,eq as l,isNotNull as I}from"drizzle-orm";async function O($,p={}){let k=p.db??j(),b=p.removeWorktreeFn??R,n=p.log??(e=>process.stderr.write(`[process_run_cleanup] ${e}
1
+ import{c as R}from"./chunk-6QKI756T.js";import{b as s,c as r,h as j}from"./chunk-H4SV7FN4.js";import{a as P}from"./chunk-5RBLIVBF.js";import{a as g}from"./chunk-ZLLER3HP.js";import{and as y,eq as l,isNotNull as I}from"drizzle-orm";async function O($,p={}){let k=p.db??j(),b=p.removeWorktreeFn??R,n=p.log??(e=>process.stderr.write(`[process_run_cleanup] ${e}
2
2
  `)),{runId:t}=$,[i]=await k.select({id:s.id,userId:s.userId,projectPath:s.projectPath}).from(s).where(l(s.id,t)).limit(1);if(!i)throw new P(`Run ${t} not found`);if(!i.projectPath)throw new P(`Run ${t} has no projectPath; cannot resolve a repo root for worktree cleanup`);let c=i.projectPath,v=await k.select({id:r.id,projectPath:r.projectPath}).from(r).where(y(l(r.runId,t),l(r.userId,i.userId),I(r.endedAt))),a=[],u=0,d=0,h=0,m=0,w=new Set;for(let e of v)if(!(!e.projectPath||e.projectPath===c)&&!w.has(e.projectPath)){w.add(e.projectPath);try{let o=await b({repoRoot:c,worktreePath:e.projectPath});o.removed?(u++,a.push({sessionId:e.id,worktreePath:e.projectPath,status:"removed"}),n(`removed worktree ${e.projectPath} (session ${e.id})`)):o.reason==="dirty"?(d++,a.push({sessionId:e.id,worktreePath:e.projectPath,status:"skipped-dirty"}),n(`skipped dirty worktree ${e.projectPath} (session ${e.id}) \u2014 uncommitted changes`)):(h++,a.push({sessionId:e.id,worktreePath:e.projectPath,status:"absent"}),n(`worktree absent ${e.projectPath} (session ${e.id})`))}catch(o){let f=o instanceof Error?o.message:String(o);m++,a.push({sessionId:e.id,worktreePath:e.projectPath,status:"error",error:f.slice(0,1e3)}),n(`error removing worktree ${e.projectPath} (session ${e.id}): ${f}`)}}return n(`run ${t} cleanup: removed=${u} skippedDirty=${d} absent=${h} errored=${m}`),{runId:t,repoRoot:c,removed:u,skippedDirty:d,absent:h,errored:m,worktrees:a}}g(O,"processRunCleanup");export{O as a};
@@ -1 +1 @@
1
- import{a as s,b as n,c as a,d as g}from"./chunk-3AV3GTMP.js";import{d as o}from"./chunk-TIQ7DQ3M.js";import{a as e}from"./chunk-ZLLER3HP.js";var i=!1;async function c(){if(process.env.RULEMETRIC_ORG_ID)return;let r=s();if(!(r&&!g(r)))try{let t=await o("/api/profile");if(!t.activeOrgId){a();return}if(r&&t.activeOrgId===r.orgId){n({orgId:r.orgId,orgSlug:r.orgSlug,syncedAt:Date.now()});return}let d=(await o("/api/orgs")).find(l=>l.id===t.activeOrgId);n({orgId:t.activeOrgId,orgSlug:d?.slug,syncedAt:Date.now()})}catch{}}e(c,"syncActiveOrgFromServer");async function p(){i||(i=!0,await c())}e(p,"maybeRefreshActiveOrg");async function v(){i=!0,await c()}e(v,"bootstrapActiveOrg");function O(){i=!1}e(O,"_resetRefreshAttempt");export{p as a,v as b,O as c};
1
+ import{a as s,b as n,c as a,d as g}from"./chunk-3AV3GTMP.js";import{e as o}from"./chunk-H2ORWIEY.js";import{a as e}from"./chunk-ZLLER3HP.js";var i=!1;async function c(){if(process.env.RULEMETRIC_ORG_ID)return;let r=s();if(!(r&&!g(r)))try{let t=await o("/api/profile");if(!t.activeOrgId){a();return}if(r&&t.activeOrgId===r.orgId){n({orgId:r.orgId,orgSlug:r.orgSlug,syncedAt:Date.now()});return}let d=(await o("/api/orgs")).find(l=>l.id===t.activeOrgId);n({orgId:t.activeOrgId,orgSlug:d?.slug,syncedAt:Date.now()})}catch{}}e(c,"syncActiveOrgFromServer");async function p(){i||(i=!0,await c())}e(p,"maybeRefreshActiveOrg");async function v(){i=!0,await c()}e(v,"bootstrapActiveOrg");function O(){i=!1}e(O,"_resetRefreshAttempt");export{p as a,v as b,O as c};
@@ -0,0 +1 @@
1
+ import{b as l}from"./chunk-6QKI756T.js";import{a as p}from"./chunk-5RBLIVBF.js";import{h}from"./chunk-H2ORWIEY.js";import{a as c}from"./chunk-ZLLER3HP.js";async function g(t){if(!t.worktree?.create)return t;let{branch:e,baseRef:s}=t.worktree,n=await l({repoRoot:t.projectPath,branch:e,baseRef:s});return{...t,projectPath:n.path,gitBranch:n.branch}}c(g,"resolveWorktreeForLaunch");async function L(t,e){let{mirrorId:s,tool:n}=t,{config:r}=t,a=c(o=>e.logger.info(o),"log");if(e.job.attempts>1)throw new p(`process_launch is not safe to retry (attempt ${e.job.attempts}). Re-launch manually.`);r=await g(r),r.worktree?.create&&a(`Worktree resolved: ${r.projectPath} (branch ${r.gitBranch})`),a(`Launching ${n}...`);let{getLauncher:f}=await import("./dist-FAVALJ5C.js"),i=await f(n).launch(r);a(`Launch completed: sessionId=${i.sessionId}`);let u={...i,worktreePath:r.worktree?.create?r.projectPath:void 0,runId:r.runId};return await h(`/api/launch-jobs/${s}/state`,{result:u}).catch(o=>{a(`result persist failed: ${o instanceof Error?o.message:String(o)}`)}),u}c(L,"processLaunch");export{g as a,L as b};
@@ -0,0 +1 @@
1
+ import{c as u}from"./chunk-V44SRRYR.js";import{b as c,e as y,f as m}from"./chunk-H2ORWIEY.js";import{a as n,b as t,i as s,k as p}from"./chunk-O6C2UGBY.js";import{a}from"./chunk-ZLLER3HP.js";import{hostname as l}from"node:os";async function R(f,r,h){t();let o=process.env.RULEMETRIC_API_KEY,d=n().apiKey;if(o||d)try{await y("/api/profile");return}catch(e){if(!(e instanceof c)||e.statusCode!==401)return;if(o){r('Your exported RULEMETRIC_API_KEY was rejected (revoked?). Unset it or replace it with a fresh key (`rulemetric auth create-key --name "my-laptop"`).');return}p(),t(),r("Stored API key was rejected (revoked?) \u2014 replacing it with a fresh one.")}let i=`${l()} (auto)`;try{let e=await m("/api/auth/api-keys",{name:i});s(e.key,process.env.RULEMETRIC_API_URL),t(),f(`Created API key "${i}" for hooks + proxy auth (saved to your config).`),u("key_created",{},h)}catch(e){let k=e instanceof Error?e.message:String(e);r(`Could not auto-create an API key (${k}). Hooks/proxy will work via your session token for ABOUT AN HOUR \u2014 the token expires, and capture then stops until a key exists. Run \`rulemetric auth create-key --name "my-laptop"\` (or \`rulemetric auth login\` again) to fix this permanently.`)}}a(R,"ensureDeviceApiKey");export{R as a};
@@ -1 +1 @@
1
- import{b as o,e as a}from"./chunk-TIQ7DQ3M.js";import{a as n}from"./chunk-ZLLER3HP.js";function c(e){return e==null?e??null:e instanceof Date?e.toISOString():e}n(c,"serializeDate");async function d(e){let r={provider:e.provider,plan:e.plan,limitType:e.limitType,value:e.value,unit:e.unit,comparator:e.comparator,resetsAt:c(e.resetsAt),sourceType:e.sourceType,sourceUrl:e.sourceUrl,sourceEvidence:e.sourceEvidence,confidence:e.confidence,observedAt:c(e.observedAt)};return a("/api/internal/research/observe",r)}n(d,"postObservation");async function f(e){let r=0,i=0,s=[];for(let u of e)try{await d(u),r++}catch(t){i++;let p=t instanceof o?`HTTP ${t.statusCode}: ${t.message}`:String(t);s.length<5&&s.push(p)}return{posted:r,failed:i,errors:s}}n(f,"postObservations");export{d as a,f as b};
1
+ import{b as o,f as a}from"./chunk-H2ORWIEY.js";import{a as n}from"./chunk-ZLLER3HP.js";function c(e){return e==null?e??null:e instanceof Date?e.toISOString():e}n(c,"serializeDate");async function d(e){let r={provider:e.provider,plan:e.plan,limitType:e.limitType,value:e.value,unit:e.unit,comparator:e.comparator,resetsAt:c(e.resetsAt),sourceType:e.sourceType,sourceUrl:e.sourceUrl,sourceEvidence:e.sourceEvidence,confidence:e.confidence,observedAt:c(e.observedAt)};return a("/api/internal/research/observe",r)}n(d,"postObservation");async function f(e){let r=0,i=0,s=[];for(let u of e)try{await d(u),r++}catch(t){i++;let p=t instanceof o?`HTTP ${t.statusCode}: ${t.message}`:String(t);s.length<5&&s.push(p)}return{posted:r,failed:i,errors:s}}n(f,"postObservations");export{d as a,f as b};
@@ -1 +1 @@
1
- import{a}from"./chunk-TIQ7DQ3M.js";import{a as e}from"./chunk-ZLLER3HP.js";function i(){return process.env.RULEMETRIC_API_URL??a}e(i,"apiUrl");function u(){let n=process.env.RULEMETRIC_API_KEY??process.env.RULEMETRIC_ACCESS_TOKEN;if(!n)throw new Error("not signed in \u2014 run `rulemetric auth login`");return n}e(u,"authToken");async function t(n,o){let r=await fetch(`${i()}${n}`,{...o,headers:{Authorization:`Bearer ${u()}`,"Content-Type":"application/json",...o?.headers??{}},signal:AbortSignal.timeout(1e4)});if(!r.ok)throw new Error(`${r.status} ${r.statusText}`);return await r.json()}e(t,"request");function c({limit:n}){return t(`/api/launch-jobs?limit=${n}`)}e(c,"fetchLaunchJobs");function h(n){return t("/api/launch-jobs",{method:"POST",body:JSON.stringify(n)})}e(h,"createLaunchJob");function l(n){return t(`/api/launch-jobs/${n}/cancel`,{method:"POST"})}e(l,"cancelLaunchJob");function p(){return t("/api/launchers")}e(p,"listLaunchers");export{c as a,h as b,l as c,p as d};
1
+ import{a}from"./chunk-H2ORWIEY.js";import{a as e}from"./chunk-ZLLER3HP.js";function i(){return process.env.RULEMETRIC_API_URL??a}e(i,"apiUrl");function u(){let n=process.env.RULEMETRIC_API_KEY??process.env.RULEMETRIC_ACCESS_TOKEN;if(!n)throw new Error("not signed in \u2014 run `rulemetric auth login`");return n}e(u,"authToken");async function t(n,o){let r=await fetch(`${i()}${n}`,{...o,headers:{Authorization:`Bearer ${u()}`,"Content-Type":"application/json",...o?.headers??{}},signal:AbortSignal.timeout(1e4)});if(!r.ok)throw new Error(`${r.status} ${r.statusText}`);return await r.json()}e(t,"request");function c({limit:n}){return t(`/api/launch-jobs?limit=${n}`)}e(c,"fetchLaunchJobs");function h(n){return t("/api/launch-jobs",{method:"POST",body:JSON.stringify(n)})}e(h,"createLaunchJob");function l(n){return t(`/api/launch-jobs/${n}/cancel`,{method:"POST"})}e(l,"cancelLaunchJob");function p(){return t("/api/launchers")}e(p,"listLaunchers");export{c as a,h as b,l as c,p as d};
@@ -1,2 +1,2 @@
1
- import{a as v,b as u,e as y,g as d}from"../../chunk-DT4GKEP5.js";import{a as h}from"../../chunk-LQRYQE6Q.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-CRAKDQ4H.js";import"../../chunk-WPJ2BND4.js";import"../../chunk-3AV3GTMP.js";import"../../chunk-TIQ7DQ3M.js";import"../../chunk-M6AJDVCL.js";import{a as p}from"../../chunk-ZLLER3HP.js";import{Args as k,Flags as o}from"@oclif/core";import{existsSync as T}from"node:fs";import{homedir as P}from"node:os";import{join as I}from"node:path";var A=I(P(),".gemini","antigravity-ide","brain"),g=class x extends h{static{p(this,"AntigravityBackfill")}static description="Backfill historical events from an Antigravity conversation transcript into a RuleMetric session. Useful for seeding a conversation that existed before hooks were installed \u2014 the live hook intentionally only captures forward.";static examples=["<%= config.bin %> antigravity backfill 26fd215d-f43b-4ea5-b177-dc2c0e696f97 --session 158db9aa-68ee-43fc-961b-f3a180578694","<%= config.bin %> antigravity backfill 26fd215d-f43b-4ea5-b177-dc2c0e696f97 --dry-run"];static args={conversationId:k.string({description:"Antigravity conversationId (UUID) \u2014 the directory name under ~/.gemini/antigravity-ide/brain/",required:!0})};static flags={session:o.string({char:"s",description:"RuleMetric session UUID to POST events into. If omitted, resolved from the hook tmp file ($TMPDIR/rulemetric/<conversationId>) \u2014 fails if neither is present."}),transcript:o.string({description:"Path to the transcript.jsonl file. Defaults to ~/.gemini/antigravity-ide/brain/<conversationId>/.system_generated/logs/transcript.jsonl"}),"after-step":o.integer({description:"Only emit records with step_index > this value. Default: read from existing state file, else -1 (everything)."}),limit:o.integer({description:"Cap on the number of records to process this run."}),"dry-run":o.boolean({default:!1,description:"Classify records without POSTing. Reports counts only."}),"save-state":o.boolean({default:!0,allowNo:!0,description:"After backfill, persist the highest step_index so the live hook resumes from there."})};async run(){let{args:b,flags:e}=await this.parse(x),t=b.conversationId;d.loadEnvFile(),process.env.RULEMETRIC_API_URL||this.error("RULEMETRIC_API_URL is not set. Configure it via env or ~/.config/rulemetric/env.");let l=e.transcript??I(A,t,".system_generated","logs","transcript.jsonl");T(l)||this.error(`Transcript not found: ${l}`);let m=e.session??d.resolveRwSessionId(t);m||this.error(`No RuleMetric session resolved. Pass --session <uuid>, or run the Antigravity hook at least once so $TMPDIR/rulemetric/${t} is populated.`);let n=e["after-step"];n===void 0&&(n=d.load(t)?.lastStepIdx??-1);let i=v(l,n);e.limit!==void 0&&i.length>e.limit&&(i=i.slice(0,e.limit));let R=u(l);if(this.log(`Conversation ${t}: transcript max step = ${R}, after-step = ${n}, records to process = ${i.length}`),i.length===0){this.log("Nothing to backfill.");return}if(e["dry-run"]){let r=0,a=0,c={};for(let S of i){let f=(await import("../../lib/antigravity-transcript.js")).classifyRecord(S,0);f?(r++,c[f.eventType]=(c[f.eventType]??0)+1):a++}this.log(`Dry run: would emit ${r}, skip ${a}. By eventType: ${JSON.stringify(c)}`);return}let w=Date.now(),s=await y(i,m,t,n,{onProgress:p(({attempted:r,total:a})=>{(r%100===0||r===a)&&process.stderr.write(` \u2026${r}/${a}
1
+ import{a as v,b as u,e as y,g as d}from"../../chunk-RQ424GI6.js";import{a as h}from"../../chunk-PPKPCXJD.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-V44SRRYR.js";import"../../chunk-U6XEU573.js";import"../../chunk-VLOX6KOM.js";import"../../chunk-3AV3GTMP.js";import"../../chunk-H2ORWIEY.js";import"../../chunk-O6C2UGBY.js";import{a as p}from"../../chunk-ZLLER3HP.js";import{Args as k,Flags as o}from"@oclif/core";import{existsSync as T}from"node:fs";import{homedir as P}from"node:os";import{join as I}from"node:path";var A=I(P(),".gemini","antigravity-ide","brain"),g=class x extends h{static{p(this,"AntigravityBackfill")}static description="Backfill historical events from an Antigravity conversation transcript into a RuleMetric session. Useful for seeding a conversation that existed before hooks were installed \u2014 the live hook intentionally only captures forward.";static examples=["<%= config.bin %> antigravity backfill 26fd215d-f43b-4ea5-b177-dc2c0e696f97 --session 158db9aa-68ee-43fc-961b-f3a180578694","<%= config.bin %> antigravity backfill 26fd215d-f43b-4ea5-b177-dc2c0e696f97 --dry-run"];static args={conversationId:k.string({description:"Antigravity conversationId (UUID) \u2014 the directory name under ~/.gemini/antigravity-ide/brain/",required:!0})};static flags={session:o.string({char:"s",description:"RuleMetric session UUID to POST events into. If omitted, resolved from the hook tmp file ($TMPDIR/rulemetric/<conversationId>) \u2014 fails if neither is present."}),transcript:o.string({description:"Path to the transcript.jsonl file. Defaults to ~/.gemini/antigravity-ide/brain/<conversationId>/.system_generated/logs/transcript.jsonl"}),"after-step":o.integer({description:"Only emit records with step_index > this value. Default: read from existing state file, else -1 (everything)."}),limit:o.integer({description:"Cap on the number of records to process this run."}),"dry-run":o.boolean({default:!1,description:"Classify records without POSTing. Reports counts only."}),"save-state":o.boolean({default:!0,allowNo:!0,description:"After backfill, persist the highest step_index so the live hook resumes from there."})};async run(){let{args:b,flags:e}=await this.parse(x),t=b.conversationId;d.loadEnvFile(),process.env.RULEMETRIC_API_URL||this.error("RULEMETRIC_API_URL is not set. Configure it via env or ~/.config/rulemetric/env.");let l=e.transcript??I(A,t,".system_generated","logs","transcript.jsonl");T(l)||this.error(`Transcript not found: ${l}`);let m=e.session??d.resolveRwSessionId(t);m||this.error(`No RuleMetric session resolved. Pass --session <uuid>, or run the Antigravity hook at least once so $TMPDIR/rulemetric/${t} is populated.`);let n=e["after-step"];n===void 0&&(n=d.load(t)?.lastStepIdx??-1);let i=v(l,n);e.limit!==void 0&&i.length>e.limit&&(i=i.slice(0,e.limit));let R=u(l);if(this.log(`Conversation ${t}: transcript max step = ${R}, after-step = ${n}, records to process = ${i.length}`),i.length===0){this.log("Nothing to backfill.");return}if(e["dry-run"]){let r=0,a=0,c={};for(let S of i){let f=(await import("../../lib/antigravity-transcript.js")).classifyRecord(S,0);f?(r++,c[f.eventType]=(c[f.eventType]??0)+1):a++}this.log(`Dry run: would emit ${r}, skip ${a}. By eventType: ${JSON.stringify(c)}`);return}let w=Date.now(),s=await y(i,m,t,n,{onProgress:p(({attempted:r,total:a})=>{(r%100===0||r===a)&&process.stderr.write(` \u2026${r}/${a}
2
2
  `)},"onProgress")}),$=((Date.now()-w)/1e3).toFixed(1);this.log(`Backfill complete in ${$}s. attempted=${s.attempted} emitted=${s.emitted} skipped=${s.skipped} failed=${s.failed} highestStepIdx=${s.highestStepIdx}`),e["save-state"]?(d.save(t,{lastStepIdx:s.highestStepIdx}),this.log(`State saved \u2192 live hook will resume from step_index > ${s.highestStepIdx}.`)):this.log("State NOT saved (--no-save-state). Live hook will re-emit any new records from after-step.")}};export{g as default};
@@ -1 +1 @@
1
- import{a as n}from"../../chunk-LQRYQE6Q.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-CRAKDQ4H.js";import"../../chunk-WPJ2BND4.js";import"../../chunk-3AV3GTMP.js";import{e as r}from"../../chunk-TIQ7DQ3M.js";import{i as o,k as s}from"../../chunk-M6AJDVCL.js";import{a}from"../../chunk-ZLLER3HP.js";import*as c from"node:path";import{Flags as l}from"@oclif/core";var t=class g extends n{static{a(this,"AuthCreateKey")}static description="Create a long-lived API key for CLI and proxy authentication";static examples=['<%= config.bin %> auth create-key --name "laptop"','<%= config.bin %> auth create-key --name "work proxy" --save'];static flags={name:l.string({char:"n",description:"Name for this key",required:!0}),save:l.boolean({char:"s",description:"Save key to ~/.config/rulemetric/env for hooks/proxy",default:!0})};async run(){let{flags:i}=await this.parse(g),e=await r("/api/auth/api-keys",{name:i.name});this.log(""),this.log("API key created successfully:"),this.log(""),this.log(` Name: ${e.name}`),this.log(` Key: ${e.key}`),this.log(` Prefix: ${e.keyPrefix}`),this.log(""),this.warn("Save this key now \u2014 it will not be shown again."),i.save&&(o(e.key,process.env.RULEMETRIC_API_URL),this.log(""),this.log(`Key saved to ${c.join(s(),"env")} (RULEMETRIC_API_KEY)`),this.log("Hooks and proxy will use this key automatically."))}};export{t as default};
1
+ import{a as n}from"../../chunk-PPKPCXJD.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-V44SRRYR.js";import"../../chunk-U6XEU573.js";import"../../chunk-VLOX6KOM.js";import"../../chunk-3AV3GTMP.js";import{f as r}from"../../chunk-H2ORWIEY.js";import{i as o,l as s}from"../../chunk-O6C2UGBY.js";import{a}from"../../chunk-ZLLER3HP.js";import*as c from"node:path";import{Flags as l}from"@oclif/core";var t=class g extends n{static{a(this,"AuthCreateKey")}static description="Create a long-lived API key for CLI and proxy authentication";static examples=['<%= config.bin %> auth create-key --name "laptop"','<%= config.bin %> auth create-key --name "ci token" --no-save'];static flags={name:l.string({char:"n",description:"Name for this key",required:!0}),save:l.boolean({char:"s",description:"Save key to ~/.config/rulemetric/env for hooks/proxy",default:!0,allowNo:!0})};async run(){let{flags:i}=await this.parse(g),e=await r("/api/auth/api-keys",{name:i.name});this.log(""),this.log("API key created successfully:"),this.log(""),this.log(` Name: ${e.name}`),this.log(` Key: ${e.key}`),this.log(` Prefix: ${e.keyPrefix}`),this.log(""),this.warn("Save this key now \u2014 it will not be shown again."),i.save&&(o(e.key,process.env.RULEMETRIC_API_URL),this.log(""),this.log(`Key saved to ${c.join(s(),"env")} (RULEMETRIC_API_KEY)`),this.log("Hooks and proxy will use this key automatically."))}};export{t as default};
@@ -1 +1 @@
1
- import{a as f}from"../../chunk-AHRHCERJ.js";import{a as g}from"../../chunk-LQRYQE6Q.js";import"../../chunk-IZTIYR5Q.js";import{c as d}from"../../chunk-CRAKDQ4H.js";import{b as l}from"../../chunk-WPJ2BND4.js";import"../../chunk-3AV3GTMP.js";import{b as m,c as p}from"../../chunk-TIQ7DQ3M.js";import{d as n,h as c}from"../../chunk-M6AJDVCL.js";import{a}from"../../chunk-ZLLER3HP.js";import{Flags as h}from"@oclif/core";var r=class w extends g{static{a(this,"AuthLogin")}static description="Log in to RuleMetric";static examples=["<%= config.bin %> auth login","<%= config.bin %> auth login -e user@example.com"];static flags={email:h.string({char:"e",description:"Email address"}),password:h.string({char:"p",description:"Password (for non-interactive use)"})};async run(){let{flags:o}=await this.parse(w),s=o.email,t=o.password;if(!s||!t){process.stdin.isTTY||this.error("Missing credentials in a non-interactive shell. Pass --email/-e and --password/-p, or set RULEMETRIC_API_KEY (create a key at https://rulemetric.com/settings).");let{input:i,password:u}=await import("@inquirer/prompts");s||(s=await i({message:"Email:"})),t||(t=await u({message:"Password:"}))}let e;try{e=await p("/auth/login",{method:"POST",body:{email:s,password:t},timeoutMs:2e4})}catch(i){throw i instanceof m&&i.statusCode===401&&this.error("Invalid email or password."),i}let v=e.expiresAt??new Date(Date.now()+3600*1e3).toISOString();n({accessToken:e.accessToken,refreshToken:e.refreshToken,expiresAt:v,email:e.email}),c(e.accessToken,process.env.RULEMETRIC_API_URL),await l(),await f(this.log.bind(this),this.warn.bind(this),this.config.version),d("auth_login",{},this.config.version),this.log(`Logged in as ${e.email}`)}};export{r as default};
1
+ import{a as f}from"../../chunk-XICLXXRH.js";import{a as g}from"../../chunk-PPKPCXJD.js";import"../../chunk-IZTIYR5Q.js";import{c as d}from"../../chunk-V44SRRYR.js";import"../../chunk-U6XEU573.js";import{b as l}from"../../chunk-VLOX6KOM.js";import"../../chunk-3AV3GTMP.js";import{b as m,d as p}from"../../chunk-H2ORWIEY.js";import{d as n,h as c}from"../../chunk-O6C2UGBY.js";import{a}from"../../chunk-ZLLER3HP.js";import{Flags as h}from"@oclif/core";var o=class w extends g{static{a(this,"AuthLogin")}static description="Log in to RuleMetric";static examples=["<%= config.bin %> auth login","<%= config.bin %> auth login -e user@example.com"];static flags={email:h.string({char:"e",description:"Email address"}),password:h.string({char:"p",description:"Password (for non-interactive use)"})};async run(){let{flags:r}=await this.parse(w),s=r.email,t=r.password;if(!s||!t){process.stdin.isTTY||this.error("Missing credentials in a non-interactive shell. Pass --email/-e and --password/-p, or set RULEMETRIC_API_KEY (create a key at https://rulemetric.com/connect).");let{input:i,password:u}=await import("@inquirer/prompts");s||(s=await i({message:"Email:"})),t||(t=await u({message:"Password:"}))}let e;try{e=await p("/auth/login",{method:"POST",body:{email:s,password:t},timeoutMs:2e4})}catch(i){throw i instanceof m&&i.statusCode===401&&this.error("Invalid email or password."),i}let v=e.expiresAt??new Date(Date.now()+3600*1e3).toISOString();n({accessToken:e.accessToken,refreshToken:e.refreshToken,expiresAt:v,email:e.email}),c(e.accessToken,process.env.RULEMETRIC_API_URL),await l(),await f(this.log.bind(this),this.warn.bind(this),this.config.version),d("auth_login",{},this.config.version),this.log(`Logged in as ${e.email}`)}};export{o as default};
@@ -1 +1 @@
1
- import{a as s}from"../../chunk-LQRYQE6Q.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-CRAKDQ4H.js";import"../../chunk-WPJ2BND4.js";import"../../chunk-3AV3GTMP.js";import"../../chunk-TIQ7DQ3M.js";import{f as i,j as r}from"../../chunk-M6AJDVCL.js";import{a as o}from"../../chunk-ZLLER3HP.js";var e=class t extends s{static{o(this,"AuthLogout")}static description="Log out of RuleMetric";static examples=["<%= config.bin %> auth logout"];async run(){await this.parse(t),i(),r(),this.log("Logged out successfully.")}};export{e as default};
1
+ import{a as s}from"../../chunk-PPKPCXJD.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-V44SRRYR.js";import"../../chunk-U6XEU573.js";import"../../chunk-VLOX6KOM.js";import"../../chunk-3AV3GTMP.js";import"../../chunk-H2ORWIEY.js";import{f as i,j as r}from"../../chunk-O6C2UGBY.js";import{a as o}from"../../chunk-ZLLER3HP.js";var e=class t extends s{static{o(this,"AuthLogout")}static description="Log out of RuleMetric";static examples=["<%= config.bin %> auth logout"];async run(){await this.parse(t),i(),r(),this.log("Logged out successfully.")}};export{e as default};
@@ -1 +1,4 @@
1
- import{a}from"../../chunk-LQRYQE6Q.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-CRAKDQ4H.js";import"../../chunk-WPJ2BND4.js";import"../../chunk-3AV3GTMP.js";import{h as t}from"../../chunk-TIQ7DQ3M.js";import"../../chunk-M6AJDVCL.js";import{a as r}from"../../chunk-ZLLER3HP.js";import{Args as s}from"@oclif/core";var e=class o extends a{static{r(this,"AuthRevokeKey")}static description="Revoke an API key";static examples=["<%= config.bin %> auth revoke-key <key-id>"];static args={id:s.string({description:"API key ID to revoke",required:!0})};async run(){let{args:i}=await this.parse(o);await t(`/api/auth/api-keys/${i.id}`),this.log(`API key ${i.id} revoked.`)}};export{e as default};
1
+ import{a as k}from"../../chunk-PPKPCXJD.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-V44SRRYR.js";import"../../chunk-U6XEU573.js";import"../../chunk-VLOX6KOM.js";import"../../chunk-3AV3GTMP.js";import{e as n,i as c}from"../../chunk-H2ORWIEY.js";import"../../chunk-O6C2UGBY.js";import{a as s}from"../../chunk-ZLLER3HP.js";import{Args as y}from"@oclif/core";var a=class m extends k{static{s(this,"AuthRevokeKey")}static description="Revoke an API key (run with no argument to list active keys)";static examples=["<%= config.bin %> auth revoke-key","<%= config.bin %> auth revoke-key rm_abc12345",'<%= config.bin %> auth revoke-key "my-laptop (auto)"'];static args={id:y.string({description:"API key ID, prefix (rm_xxxxxxxx), or name"})};async run(){let{args:o}=await this.parse(m),r=(await n("/api/auth/api-keys")).filter(e=>!e.revokedAt);if(!o.id){if(r.length===0){this.log("No active API keys.");return}this.log(`Active API keys \u2014 pass an id, prefix, or name to revoke one:
2
+ `);for(let e of r)this.log(` ${e.id} ${e.keyPrefix}... ${e.name}`);return}let i=o.id,t=r.filter(e=>e.id===i||e.name===i||i.startsWith("rm_")&&i.startsWith(e.keyPrefix));t.length===0&&this.error(`No active API key matches "${i}". Run \`rulemetric auth revoke-key\` with no argument to list keys.`),t.length>1&&this.error(`"${i}" matches ${t.length} keys \u2014 use the exact key ID:
3
+ `+t.map(e=>` ${e.id} ${e.keyPrefix}... ${e.name}`).join(`
4
+ `)),await c(`/api/auth/api-keys/${t[0].id}`),this.log(`API key ${t[0].keyPrefix}... ("${t[0].name}") revoked.`)}};export{a as default};
@@ -1 +1 @@
1
- import{a as g}from"../../chunk-AHRHCERJ.js";import{a as h}from"../../chunk-LQRYQE6Q.js";import"../../chunk-IZTIYR5Q.js";import{c as d}from"../../chunk-CRAKDQ4H.js";import{b as l}from"../../chunk-WPJ2BND4.js";import"../../chunk-3AV3GTMP.js";import{b as m,c as p}from"../../chunk-TIQ7DQ3M.js";import{d as n,h as c}from"../../chunk-M6AJDVCL.js";import{a as o}from"../../chunk-ZLLER3HP.js";import{Flags as u}from"@oclif/core";var t=class f extends h{static{o(this,"AuthSignup")}static description="Create a RuleMetric account from the CLI";static examples=["<%= config.bin %> auth signup","<%= config.bin %> auth signup -e user@example.com"];static flags={email:u.string({char:"e",description:"Email address"}),password:u.string({char:"p",description:"Password (min 8 chars; for non-interactive use)"})};async run(){let{flags:a}=await this.parse(f),i=a.email,r=a.password;if(!i||!r){process.stdin.isTTY||this.error("Missing credentials in a non-interactive shell. Pass --email/-e and --password/-p.");let{input:s,password:v}=await import("@inquirer/prompts");i||(i=await s({message:"Email:"})),r||(r=await v({message:"Password (min 8 chars):"}))}let e;try{e=await p("/auth/signup",{method:"POST",body:{email:i,password:r},timeoutMs:2e4})}catch(s){throw s instanceof m&&s.statusCode===409&&this.error(`An account with ${i} already exists. Run: rulemetric auth login -e ${i}`),s}if(e.confirmationRequired||!e.accessToken||!e.refreshToken){this.log(`Account created for ${e.email}.`),this.log("Check your email and click the confirmation link, then run:"),this.log(` rulemetric auth login -e ${e.email}`);return}let w=e.expiresAt??new Date(Date.now()+3600*1e3).toISOString();n({accessToken:e.accessToken,refreshToken:e.refreshToken,expiresAt:w,email:e.email}),c(e.accessToken,process.env.RULEMETRIC_API_URL),await l(),await g(this.log.bind(this),this.warn.bind(this),this.config.version),d("auth_signup",{},this.config.version),this.log(`Signed up and logged in as ${e.email}`)}};export{t as default};
1
+ import{a as g}from"../../chunk-XICLXXRH.js";import{a as h}from"../../chunk-PPKPCXJD.js";import"../../chunk-IZTIYR5Q.js";import{c as d}from"../../chunk-V44SRRYR.js";import"../../chunk-U6XEU573.js";import{b as l}from"../../chunk-VLOX6KOM.js";import"../../chunk-3AV3GTMP.js";import{b as m,d as p}from"../../chunk-H2ORWIEY.js";import{d as n,h as c}from"../../chunk-O6C2UGBY.js";import{a as o}from"../../chunk-ZLLER3HP.js";import{Flags as u}from"@oclif/core";var t=class f extends h{static{o(this,"AuthSignup")}static description="Create a RuleMetric account from the CLI";static examples=["<%= config.bin %> auth signup","<%= config.bin %> auth signup -e user@example.com"];static flags={email:u.string({char:"e",description:"Email address"}),password:u.string({char:"p",description:"Password (min 8 chars; for non-interactive use)"})};async run(){let{flags:a}=await this.parse(f),i=a.email,r=a.password;if(!i||!r){process.stdin.isTTY||this.error("Missing credentials in a non-interactive shell. Pass --email/-e and --password/-p.");let{input:s,password:v}=await import("@inquirer/prompts");i||(i=await s({message:"Email:"})),r||(r=await v({message:"Password (min 8 chars):"}))}let e;try{e=await p("/auth/signup",{method:"POST",body:{email:i,password:r},timeoutMs:2e4})}catch(s){throw s instanceof m&&s.statusCode===409&&this.error(`An account with ${i} already exists. Run: rulemetric auth login -e ${i}`),s}if(e.confirmationRequired||!e.accessToken||!e.refreshToken){this.log(`Account created for ${e.email}.`),this.log("Check your email and click the confirmation link, then run:"),this.log(` rulemetric auth login -e ${e.email}`);return}let w=e.expiresAt??new Date(Date.now()+3600*1e3).toISOString();n({accessToken:e.accessToken,refreshToken:e.refreshToken,expiresAt:w,email:e.email}),c(e.accessToken,process.env.RULEMETRIC_API_URL),await l(),await g(this.log.bind(this),this.warn.bind(this),this.config.version),d("auth_signup",{},this.config.version),this.log(`Signed up and logged in as ${e.email}`)}};export{t as default};
@@ -1 +1 @@
1
- import{a as n}from"../../chunk-W2MV25SB.js";import{a}from"../../chunk-LQRYQE6Q.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-CRAKDQ4H.js";import"../../chunk-WPJ2BND4.js";import"../../chunk-3AV3GTMP.js";import"../../chunk-TIQ7DQ3M.js";import{e as o,g as r,k as s}from"../../chunk-M6AJDVCL.js";import{a as i}from"../../chunk-ZLLER3HP.js";var e=class u extends a{static{i(this,"AuthStatus")}static description="Show current authentication status";static examples=["<%= config.bin %> auth status"];async run(){await this.parse(u);let t=o();if(!t){this.log("Not logged in. Run `rulemetric auth login` to authenticate.");return}if(!r()){this.log("Session expired. Run `rulemetric auth login` to re-authenticate.");return}this.log(`Logged in as: ${t.email}`),this.log(`Session expires: ${n(t.expiresAt)}`),this.log(`Config: ${s()}`)}};export{e as default};
1
+ import{a as c}from"../../chunk-W2MV25SB.js";import{a as g}from"../../chunk-PPKPCXJD.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-V44SRRYR.js";import"../../chunk-U6XEU573.js";import"../../chunk-VLOX6KOM.js";import"../../chunk-3AV3GTMP.js";import"../../chunk-H2ORWIEY.js";import{a,e as l,l as t}from"../../chunk-O6C2UGBY.js";import{a as r}from"../../chunk-ZLLER3HP.js";import*as u from"node:path";var o=class h extends g{static{r(this,"AuthStatus")}static description="Show current authentication status";static examples=["<%= config.bin %> auth status"];async run(){await this.parse(h);let e=l(),i=process.env.RULEMETRIC_API_KEY,s=a().apiKey;if(i||s){let m=i||s,p=i?"RULEMETRIC_API_KEY env var":u.join(t(),"env");this.log(`Authenticated via API key ${m.slice(0,11)}... (${p})`),e&&this.log(`Logged in as: ${e.email}`),this.log(`Config: ${t()}`);return}if(!e){this.log("Not logged in. Run `rulemetric auth login` to authenticate.");return}let n=new Date(e.expiresAt).getTime();if(Number.isNaN(n)||Date.now()>=n){this.log("Session expired. Run `rulemetric auth login` to re-authenticate.");return}this.log(`Logged in as: ${e.email}`),this.log(`Session expires: ${c(e.expiresAt)}`),this.log(`Config: ${t()}`)}};export{o as default};
@@ -1,2 +1,2 @@
1
- import{a as g,b as d,c as p}from"../../chunk-W2MV25SB.js";import{a as c}from"../../chunk-LQRYQE6Q.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-CRAKDQ4H.js";import"../../chunk-WPJ2BND4.js";import"../../chunk-3AV3GTMP.js";import{d as n}from"../../chunk-TIQ7DQ3M.js";import"../../chunk-M6AJDVCL.js";import{a}from"../../chunk-ZLLER3HP.js";import{Flags as i}from"@oclif/core";var o=class m extends c{static{a(this,"Catalog")}static description="Browse the org instruction catalog";static flags={badge:i.string({description:"Filter by badge",options:["recommended","required"]}),scope:i.string({description:"Filter by scope",options:["org","team"]}),search:i.string({description:"Search by name or description"})};async run(){let{flags:e}=await this.parse(m);this.requireAuth();let s=new URLSearchParams;e.badge&&s.set("badge",e.badge),e.scope&&s.set("scope",e.scope),e.search&&s.set("search",e.search);let r=await n(`/api/catalog?${s.toString()}`);if(r.length===0){this.log("No instructions found in catalog.");return}for(let t of r){let l=t.badge?` [${t.badge}]`:"",f=t.tags?.length?` (${t.tags.join(", ")})`:"";this.log(` ${d(t.name,40)} \u2014 ${p(t.scope)}${l} v${t.version}${f} ${g(t.updatedAt)}`)}this.log(`
1
+ import{a as g,b as d,c as p}from"../../chunk-W2MV25SB.js";import{a as c}from"../../chunk-PPKPCXJD.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-V44SRRYR.js";import"../../chunk-U6XEU573.js";import"../../chunk-VLOX6KOM.js";import"../../chunk-3AV3GTMP.js";import{e as n}from"../../chunk-H2ORWIEY.js";import"../../chunk-O6C2UGBY.js";import{a}from"../../chunk-ZLLER3HP.js";import{Flags as i}from"@oclif/core";var o=class m extends c{static{a(this,"Catalog")}static description="Browse the org instruction catalog";static flags={badge:i.string({description:"Filter by badge",options:["recommended","required"]}),scope:i.string({description:"Filter by scope",options:["org","team"]}),search:i.string({description:"Search by name or description"})};async run(){let{flags:e}=await this.parse(m);this.requireAuth();let s=new URLSearchParams;e.badge&&s.set("badge",e.badge),e.scope&&s.set("scope",e.scope),e.search&&s.set("search",e.search);let r=await n(`/api/catalog?${s.toString()}`);if(r.length===0){this.log("No instructions found in catalog.");return}for(let t of r){let l=t.badge?` [${t.badge}]`:"",f=t.tags?.length?` (${t.tags.join(", ")})`:"";this.log(` ${d(t.name,40)} \u2014 ${p(t.scope)}${l} v${t.version}${f} ${g(t.updatedAt)}`)}this.log(`
2
2
  ${r.length} instruction(s) found.`)}};export{o as default};
@@ -1,3 +1,3 @@
1
- import{a as i}from"../../chunk-LQRYQE6Q.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-CRAKDQ4H.js";import"../../chunk-WPJ2BND4.js";import"../../chunk-3AV3GTMP.js";import{e as n}from"../../chunk-TIQ7DQ3M.js";import"../../chunk-M6AJDVCL.js";import{a as t}from"../../chunk-ZLLER3HP.js";import{Args as c}from"@oclif/core";var o=class s extends i{static{t(this,"CatalogRecommend")}static description="Get AI-powered instruction recommendations for a project";static args={projectId:c.string({description:"ID of the project",required:!0})};async run(){let{args:a}=await this.parse(s);this.requireAuth(),this.log(`Analyzing project and generating recommendations...
1
+ import{a as i}from"../../chunk-PPKPCXJD.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-V44SRRYR.js";import"../../chunk-U6XEU573.js";import"../../chunk-VLOX6KOM.js";import"../../chunk-3AV3GTMP.js";import{f as n}from"../../chunk-H2ORWIEY.js";import"../../chunk-O6C2UGBY.js";import{a as t}from"../../chunk-ZLLER3HP.js";import{Args as c}from"@oclif/core";var o=class s extends i{static{t(this,"CatalogRecommend")}static description="Get AI-powered instruction recommendations for a project";static args={projectId:c.string({description:"ID of the project",required:!0})};async run(){let{args:a}=await this.parse(s);this.requireAuth(),this.log(`Analyzing project and generating recommendations...
2
2
  `);let r=await n(`/api/projects/${a.projectId}/recommendations`,{});if(r.error&&this.warn(`Note: ${r.error}`),r.recommendations.length===0){this.log("No recommendations found.");return}for(let e of r.recommendations)this.log(` ${(e.score*100).toFixed(0)}% \u2014 ${e.instructionId}`),this.log(` ${e.reason}
3
3
  `)}};export{o as default};
@@ -1 +1 @@
1
- import{a as l}from"../chunk-WLVQJH4E.js";import{a as u}from"../chunk-LQRYQE6Q.js";import"../chunk-IZTIYR5Q.js";import"../chunk-CRAKDQ4H.js";import"../chunk-WPJ2BND4.js";import"../chunk-3AV3GTMP.js";import{a as n,e as c}from"../chunk-TIQ7DQ3M.js";import"../chunk-M6AJDVCL.js";import{a}from"../chunk-ZLLER3HP.js";import*as d from"node:fs";import{Args as p,Flags as i}from"@oclif/core";var e=class f extends u{static{a(this,"Convert")}static description="Convert an instruction to a target format";static examples=["<%= config.bin %> convert <id> --format claude-md","<%= config.bin %> convert <id> -f cursorrules --score","<%= config.bin %> convert <id> -f copilot -o .github/copilot-instructions.md"];static args={id:p.string({description:"Instruction ID",required:!0})};static flags={format:i.string({char:"f",description:"Target format (e.g., claude-md, cursorrules)",required:!0}),score:i.boolean({description:"Include quality score",default:!1}),output:i.string({char:"o",description:"Write output to file"})};async run(){let{args:s,flags:t}=await this.parse(f);this.requireAuth(),l(s.id,"instruction ID");let o=new URL(`${process.env.RULEMETRIC_API_URL??n}/api/instructions/${encodeURIComponent(s.id)}/convert`);o.searchParams.set("format",t.format),o.searchParams.set("score",String(t.score));let r=await c(`${o.pathname}${o.search}`,{});t.output?(d.writeFileSync(t.output,r.output,"utf-8"),this.log(`Written to ${t.output}`)):this.log(r.output),t.score&&r.score&&(this.log(""),this.log(`Quality Score: ${r.score.overall}/100`)),r.warnings.length>0&&this.warn(`Warnings: ${r.warnings.join(", ")}`)}};export{e as default};
1
+ import{a as l}from"../chunk-WLVQJH4E.js";import{a as u}from"../chunk-PPKPCXJD.js";import"../chunk-IZTIYR5Q.js";import"../chunk-V44SRRYR.js";import"../chunk-U6XEU573.js";import"../chunk-VLOX6KOM.js";import"../chunk-3AV3GTMP.js";import{a as n,f as c}from"../chunk-H2ORWIEY.js";import"../chunk-O6C2UGBY.js";import{a}from"../chunk-ZLLER3HP.js";import*as d from"node:fs";import{Args as p,Flags as i}from"@oclif/core";var e=class f extends u{static{a(this,"Convert")}static description="Convert an instruction to a target format";static examples=["<%= config.bin %> convert <id> --format claude-md","<%= config.bin %> convert <id> -f cursorrules --score","<%= config.bin %> convert <id> -f copilot -o .github/copilot-instructions.md"];static args={id:p.string({description:"Instruction ID",required:!0})};static flags={format:i.string({char:"f",description:"Target format (e.g., claude-md, cursorrules)",required:!0}),score:i.boolean({description:"Include quality score",default:!1}),output:i.string({char:"o",description:"Write output to file"})};async run(){let{args:s,flags:t}=await this.parse(f);this.requireAuth(),l(s.id,"instruction ID");let o=new URL(`${process.env.RULEMETRIC_API_URL??n}/api/instructions/${encodeURIComponent(s.id)}/convert`);o.searchParams.set("format",t.format),o.searchParams.set("score",String(t.score));let r=await c(`${o.pathname}${o.search}`,{});t.output?(d.writeFileSync(t.output,r.output,"utf-8"),this.log(`Written to ${t.output}`)):this.log(r.output),t.score&&r.score&&(this.log(""),this.log(`Quality Score: ${r.score.overall}/100`)),r.warnings.length>0&&this.warn(`Warnings: ${r.warnings.join(", ")}`)}};export{e as default};
@@ -1 +1 @@
1
- import{a as s}from"../chunk-LQRYQE6Q.js";import"../chunk-IZTIYR5Q.js";import"../chunk-CRAKDQ4H.js";import"../chunk-WPJ2BND4.js";import"../chunk-3AV3GTMP.js";import{d as a}from"../chunk-TIQ7DQ3M.js";import"../chunk-M6AJDVCL.js";import{a as o}from"../chunk-ZLLER3HP.js";import{Flags as m}from"@oclif/core";import{printTable as c}from"@oclif/table";var e=class n extends s{static{o(this,"Converters")}static description="List all supported conversion formats";static examples=["<%= config.bin %> converters","<%= config.bin %> converters --tier 1"];static enableJsonFlag=!0;static flags={tier:m.string({char:"t",description:"Filter by tier",options:["1","2","3"]})};async run(){let{flags:i}=await this.parse(n);this.requireAuth();let r=await a("/api/converters");if(i.tier){let t=Number.parseInt(i.tier,10);r=r.filter(p=>p.tier===t)}return c({data:r.map(t=>({ID:t.id,Name:t.name,Tier:String(t.tier),"Output Path":t.outputPath})),columns:["ID","Name","Tier","Output Path"]}),r}};export{e as default};
1
+ import{a as s}from"../chunk-PPKPCXJD.js";import"../chunk-IZTIYR5Q.js";import"../chunk-V44SRRYR.js";import"../chunk-U6XEU573.js";import"../chunk-VLOX6KOM.js";import"../chunk-3AV3GTMP.js";import{e as a}from"../chunk-H2ORWIEY.js";import"../chunk-O6C2UGBY.js";import{a as o}from"../chunk-ZLLER3HP.js";import{Flags as m}from"@oclif/core";import{printTable as c}from"@oclif/table";var e=class n extends s{static{o(this,"Converters")}static description="List all supported conversion formats";static examples=["<%= config.bin %> converters","<%= config.bin %> converters --tier 1"];static enableJsonFlag=!0;static flags={tier:m.string({char:"t",description:"Filter by tier",options:["1","2","3"]})};async run(){let{flags:i}=await this.parse(n);this.requireAuth();let r=await a("/api/converters");if(i.tier){let t=Number.parseInt(i.tier,10);r=r.filter(p=>p.tier===t)}return c({data:r.map(t=>({ID:t.id,Name:t.name,Tier:String(t.tier),"Output Path":t.outputPath})),columns:["ID","Name","Tier","Output Path"]}),r}};export{e as default};
@@ -1 +1 @@
1
- import{a as o}from"../../chunk-GY5IJ4RS.js";import{a as n}from"../../chunk-LQRYQE6Q.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-CRAKDQ4H.js";import"../../chunk-WPJ2BND4.js";import"../../chunk-3AV3GTMP.js";import"../../chunk-TIQ7DQ3M.js";import"../../chunk-M6AJDVCL.js";import{a as i}from"../../chunk-ZLLER3HP.js";import{printTable as t}from"@oclif/table";var a=class s extends n{static{i(this,"CronsList")}static description="List manually-runnable maintenance tasks";static examples=["<%= config.bin %> crons list"];async run(){await this.parse(s),t({data:o.map(e=>({Name:e.name,"Scheduled by":e.scheduledBy,Description:e.description})),columns:["Name","Scheduled by","Description"]}),this.log(""),this.log("Scheduled crons run in Supabase pg_cron \u2014 audit them with:"),this.log(` psql "$DATABASE_URL" -c 'select jobname, schedule, active from cron.job;'`),this.log("Run any task above on demand with: rulemetric crons run <name>")}};export{a as default};
1
+ import{a as o}from"../../chunk-GY5IJ4RS.js";import{a as n}from"../../chunk-PPKPCXJD.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-V44SRRYR.js";import"../../chunk-U6XEU573.js";import"../../chunk-VLOX6KOM.js";import"../../chunk-3AV3GTMP.js";import"../../chunk-H2ORWIEY.js";import"../../chunk-O6C2UGBY.js";import{a as i}from"../../chunk-ZLLER3HP.js";import{printTable as t}from"@oclif/table";var a=class s extends n{static{i(this,"CronsList")}static description="List manually-runnable maintenance tasks";static examples=["<%= config.bin %> crons list"];async run(){await this.parse(s),t({data:o.map(e=>({Name:e.name,"Scheduled by":e.scheduledBy,Description:e.description})),columns:["Name","Scheduled by","Description"]}),this.log(""),this.log("Scheduled crons run in Supabase pg_cron \u2014 audit them with:"),this.log(` psql "$DATABASE_URL" -c 'select jobname, schedule, active from cron.job;'`),this.log("Run any task above on demand with: rulemetric crons run <name>")}};export{a as default};
@@ -1,2 +1,2 @@
1
- import{a as u}from"../../chunk-GY5IJ4RS.js";import{a as c}from"../../chunk-LQRYQE6Q.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-CRAKDQ4H.js";import"../../chunk-WPJ2BND4.js";import"../../chunk-3AV3GTMP.js";import"../../chunk-TIQ7DQ3M.js";import"../../chunk-M6AJDVCL.js";import{a as l}from"../../chunk-ZLLER3HP.js";import{Args as g,Flags as f}from"@oclif/core";var i=class m extends c{static{l(this,"CronsRun")}static description="Run a maintenance task synchronously, right now";static examples=["<%= config.bin %> crons run cron_check_changelog","<%= config.bin %> crons run cron_suggest_instructions --quiet"];static args={name:g.string({description:"Task name (run `rulemetric crons list` to see all)",required:!0})};static flags={quiet:f.boolean({char:"q",description:"Suppress per-line log output; print summary only"})};async run(){let{args:s,flags:d}=await this.parse(m);this.requireAuth();let n=u.find(e=>e.name===s.name);n||this.error(`Unknown task: ${s.name}
1
+ import{a as u}from"../../chunk-GY5IJ4RS.js";import{a as c}from"../../chunk-PPKPCXJD.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-V44SRRYR.js";import"../../chunk-U6XEU573.js";import"../../chunk-VLOX6KOM.js";import"../../chunk-3AV3GTMP.js";import"../../chunk-H2ORWIEY.js";import"../../chunk-O6C2UGBY.js";import{a as l}from"../../chunk-ZLLER3HP.js";import{Args as g,Flags as f}from"@oclif/core";var i=class m extends c{static{l(this,"CronsRun")}static description="Run a maintenance task synchronously, right now";static examples=["<%= config.bin %> crons run cron_check_changelog","<%= config.bin %> crons run cron_suggest_instructions --quiet"];static args={name:g.string({description:"Task name (run `rulemetric crons list` to see all)",required:!0})};static flags={quiet:f.boolean({char:"q",description:"Suppress per-line log output; print summary only"})};async run(){let{args:s,flags:d}=await this.parse(m);this.requireAuth();let n=u.find(e=>e.name===s.name);n||this.error(`Unknown task: ${s.name}
2
2
  Run \`rulemetric crons list\` to see available tasks.`);let o;try{({runManualTask:o}=await import("../../lib/manual-tasks.js"))}catch(e){let r=e?.code;throw(r==="ERR_MODULE_NOT_FOUND"||r==="MODULE_NOT_FOUND")&&this.error("`crons run` needs the worker runtime, which isn't available in this install.\nThese maintenance tasks connect to the database directly \u2014 run them from a full RuleMetric checkout with DATABASE_URL and the worker dependencies installed."),e}this.log(`\u25B6 Running ${n.name} \u2026`);let h=Date.now(),t=await o(s.name);if(!d.quiet)for(let e of t.logs){let r=e.level==="error"||e.level==="warn"?`[${e.level}]`:"";this.log(` ${r} ${e.message}`)}let a=((t.durationMs??Date.now()-h)/1e3).toFixed(1);t.ok?this.log(`\u2713 ${n.name} completed in ${a}s (${t.logs.length} log line${t.logs.length===1?"":"s"})`):this.error(`\u2717 ${n.name} failed after ${a}s: ${t.error}`)}};export{i as default};
@@ -1 +1 @@
1
- import{a as o}from"../chunk-LQRYQE6Q.js";import"../chunk-IZTIYR5Q.js";import"../chunk-CRAKDQ4H.js";import"../chunk-WPJ2BND4.js";import"../chunk-3AV3GTMP.js";import"../chunk-TIQ7DQ3M.js";import"../chunk-M6AJDVCL.js";import{a as i}from"../chunk-ZLLER3HP.js";import{Flags as r}from"@oclif/core";var a=class s extends o{static{i(this,"Dashboard")}static description="Interactive TUI dashboard showing session analytics, outcomes, friction, and insights";static examples=["<%= config.bin %> dashboard","<%= config.bin %> dashboard --period 30days","<%= config.bin %> dashboard --launcher"];static flags={period:r.string({char:"p",default:"week",options:["today","week","30days","month","all"],description:"Initial time period"}),launcher:r.boolean({char:"l",default:!1,description:"Open the launcher overlay immediately"})};async run(){let{flags:e}=await this.parse(s),{renderDashboard:t}=await import("../dashboard/Dashboard.js");await t(e.period,{openLauncher:e.launcher})}};export{a as default};
1
+ import{a as o}from"../chunk-PPKPCXJD.js";import"../chunk-IZTIYR5Q.js";import"../chunk-V44SRRYR.js";import"../chunk-U6XEU573.js";import"../chunk-VLOX6KOM.js";import"../chunk-3AV3GTMP.js";import"../chunk-H2ORWIEY.js";import"../chunk-O6C2UGBY.js";import{a as i}from"../chunk-ZLLER3HP.js";import{Flags as r}from"@oclif/core";var a=class s extends o{static{i(this,"Dashboard")}static description="Interactive TUI dashboard showing session analytics, outcomes, friction, and insights";static examples=["<%= config.bin %> dashboard","<%= config.bin %> dashboard --period 30days","<%= config.bin %> dashboard --launcher"];static flags={period:r.string({char:"p",default:"week",options:["today","week","30days","month","all"],description:"Initial time period"}),launcher:r.boolean({char:"l",default:!1,description:"Open the launcher overlay immediately"})};async run(){let{flags:e}=await this.parse(s),{renderDashboard:t}=await import("../dashboard/Dashboard.js");await t(e.period,{openLauncher:e.launcher})}};export{a as default};
@@ -1 +1 @@
1
- import{b as P,c as x}from"../chunk-V5U3E4BZ.js";import{c as p,d as h,e as g}from"../chunk-MVM6OGAF.js";import"../chunk-KKDHD4XA.js";import"../chunk-SZ62CP55.js";import{a as v}from"../chunk-LQRYQE6Q.js";import"../chunk-IZTIYR5Q.js";import"../chunk-CRAKDQ4H.js";import"../chunk-WPJ2BND4.js";import"../chunk-3AV3GTMP.js";import{a as f}from"../chunk-TIQ7DQ3M.js";import{a as y,g as d}from"../chunk-M6AJDVCL.js";import{a as u}from"../chunk-ZLLER3HP.js";import{spawnSync as A}from"node:child_process";import{existsSync as H,readFileSync as S}from"node:fs";import{join as X}from"node:path";var m=class O extends v{static{u(this,"Diagnostics")}static description='Diagnose capture / proxy / connectivity problems (e.g. a client-side "502 Bad Gateway")';static examples=["<%= config.bin %> diagnostics"];baseUrl(){return process.env.RULEMETRIC_API_URL??y().apiUrl??f}async checkDirect(){let t=process.env.HTTPS_PROXY,e=process.env.HTTP_PROXY;delete process.env.HTTPS_PROXY,delete process.env.HTTP_PROXY;let r=new AbortController,n=setTimeout(()=>r.abort(),8e3);try{return(await globalThis.fetch(`${this.baseUrl()}/health`,{signal:r.signal})).ok}catch{return!1}finally{clearTimeout(n),t!==void 0&&(process.env.HTTPS_PROXY=t),e!==void 0&&(process.env.HTTP_PROXY=e)}}configuredProxy(){if(process.env.HTTPS_PROXY)return process.env.HTTPS_PROXY;for(let t of["settings.local.json","settings.json"]){let e=X(process.cwd(),".claude",t);if(H(e))try{let r=JSON.parse(S(e,"utf8"));if(r.env?.HTTPS_PROXY)return r.env.HTTPS_PROXY}catch{}}return null}checkThroughProxy(t){let e=A("curl",["-sS","-x",t,"--max-time","8","-o","/dev/null","-w","%{http_code}",`${this.baseUrl()}/health`],{encoding:"utf8",stdio:["ignore","pipe","ignore"]});return e.error||typeof e.stdout!="string"?null:e.stdout.trim()==="200"}async run(){await this.parse(O);let t=process.version,e=this.configuredProxy(),r=e!=null,[n,s,l]=await Promise.all([this.checkDirect(),g(p),g(h)]),i=r&&e?this.checkThroughProxy(e):null,o=u((c,T,b)=>{let _=T===null?"\u2013":T?"[OK]":"[!!]";this.log(` ${_} ${c.padEnd(22)} ${b}`)},"line");this.log("RuleMetric diagnostics"),this.log(""),o("Node",!P(t),`${t}${P(t)?" (< 20.11 \u2014 breaks the bundled proxy)":""}`),o("API (direct)",n,`${this.baseUrl()}/health ${n?"reachable":"UNREACHABLE"}`),o("Authenticated",d(),d()?"yes":"no \u2014 run `rulemetric auth login`"),o("Proxy configured",r?!0:null,r?e:"no HTTPS_PROXY set"),r&&(o("Gateway :"+p,s,s?"listening":"NOT listening"),o("mitmproxy :"+h,l,l?"listening":"not listening (gateway should route direct)"),o("API (via proxy)",i,i===null?"inconclusive (curl unavailable)":i?"reachable":"FAILED \u2014 502/blocked through your proxy"));let a=x({nodeVersion:t,directApiOk:n,httpsProxySet:r,gatewayAlive:s,mitmproxyAlive:l,proxyPathOk:i});this.log("");let R=a.severity==="ok"?"[OK]":a.severity==="warn"?"[!!]":"[XX]";this.log(`${R} ${a.headline}`);for(let c of a.hints)this.log(` \u2022 ${c}`)}};export{m as default};
1
+ import{b as P,c as x}from"../chunk-V5U3E4BZ.js";import{c as p,d as h,e as g}from"../chunk-MVM6OGAF.js";import"../chunk-KKDHD4XA.js";import"../chunk-SZ62CP55.js";import{a as v}from"../chunk-PPKPCXJD.js";import"../chunk-IZTIYR5Q.js";import"../chunk-V44SRRYR.js";import"../chunk-U6XEU573.js";import"../chunk-VLOX6KOM.js";import"../chunk-3AV3GTMP.js";import{a as f}from"../chunk-H2ORWIEY.js";import{a as y,g as d}from"../chunk-O6C2UGBY.js";import{a as u}from"../chunk-ZLLER3HP.js";import{spawnSync as A}from"node:child_process";import{existsSync as H,readFileSync as S}from"node:fs";import{join as X}from"node:path";var m=class O extends v{static{u(this,"Diagnostics")}static description='Diagnose capture / proxy / connectivity problems (e.g. a client-side "502 Bad Gateway")';static examples=["<%= config.bin %> diagnostics"];baseUrl(){return process.env.RULEMETRIC_API_URL??y().apiUrl??f}async checkDirect(){let t=process.env.HTTPS_PROXY,e=process.env.HTTP_PROXY;delete process.env.HTTPS_PROXY,delete process.env.HTTP_PROXY;let r=new AbortController,n=setTimeout(()=>r.abort(),8e3);try{return(await globalThis.fetch(`${this.baseUrl()}/health`,{signal:r.signal})).ok}catch{return!1}finally{clearTimeout(n),t!==void 0&&(process.env.HTTPS_PROXY=t),e!==void 0&&(process.env.HTTP_PROXY=e)}}configuredProxy(){if(process.env.HTTPS_PROXY)return process.env.HTTPS_PROXY;for(let t of["settings.local.json","settings.json"]){let e=X(process.cwd(),".claude",t);if(H(e))try{let r=JSON.parse(S(e,"utf8"));if(r.env?.HTTPS_PROXY)return r.env.HTTPS_PROXY}catch{}}return null}checkThroughProxy(t){let e=A("curl",["-sS","-x",t,"--max-time","8","-o","/dev/null","-w","%{http_code}",`${this.baseUrl()}/health`],{encoding:"utf8",stdio:["ignore","pipe","ignore"]});return e.error||typeof e.stdout!="string"?null:e.stdout.trim()==="200"}async run(){await this.parse(O);let t=process.version,e=this.configuredProxy(),r=e!=null,[n,s,l]=await Promise.all([this.checkDirect(),g(p),g(h)]),i=r&&e?this.checkThroughProxy(e):null,o=u((c,T,b)=>{let _=T===null?"\u2013":T?"[OK]":"[!!]";this.log(` ${_} ${c.padEnd(22)} ${b}`)},"line");this.log("RuleMetric diagnostics"),this.log(""),o("Node",!P(t),`${t}${P(t)?" (< 20.11 \u2014 breaks the bundled proxy)":""}`),o("API (direct)",n,`${this.baseUrl()}/health ${n?"reachable":"UNREACHABLE"}`),o("Authenticated",d(),d()?"yes":"no \u2014 run `rulemetric auth login`"),o("Proxy configured",r?!0:null,r?e:"no HTTPS_PROXY set"),r&&(o("Gateway :"+p,s,s?"listening":"NOT listening"),o("mitmproxy :"+h,l,l?"listening":"not listening (gateway should route direct)"),o("API (via proxy)",i,i===null?"inconclusive (curl unavailable)":i?"reachable":"FAILED \u2014 502/blocked through your proxy"));let a=x({nodeVersion:t,directApiOk:n,httpsProxySet:r,gatewayAlive:s,mitmproxyAlive:l,proxyPathOk:i});this.log("");let R=a.severity==="ok"?"[OK]":a.severity==="warn"?"[!!]":"[XX]";this.log(`${R} ${a.headline}`);for(let c of a.hints)this.log(` \u2022 ${c}`)}};export{m as default};
@@ -1 +1 @@
1
- import{a}from"../../chunk-LQRYQE6Q.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-CRAKDQ4H.js";import"../../chunk-WPJ2BND4.js";import"../../chunk-3AV3GTMP.js";import{e as s}from"../../chunk-TIQ7DQ3M.js";import"../../chunk-M6AJDVCL.js";import{a as o}from"../../chunk-ZLLER3HP.js";import{Flags as e}from"@oclif/core";import{readFileSync as p}from"node:fs";var n=class c extends a{static{o(this,"EvalTargetCreate")}static description="Create an eval target (instruction, skill, prompt, or plan to test)";static examples=["<%= config.bin %> eval-targets create --name my-rules --type instruction --file ./CLAUDE.md",'<%= config.bin %> eval-targets create --name my-prompt --type prompt --content "Always use TypeScript"'];static flags={name:e.string({char:"n",description:"Name for the eval target",required:!0}),type:e.string({char:"t",description:"Target type",options:["instruction","skill","prompt","plan"],required:!0}),file:e.string({char:"f",description:"Path to content file"}),content:e.string({char:"c",description:"Content string (alternative to --file)"}),description:e.string({char:"d",description:"Description of the target",default:""})};async run(){let{flags:t}=await this.parse(c);this.requireAuth();let i;t.file?i=p(t.file,"utf-8"):t.content?i=t.content:this.error("Provide either --file or --content");let r=await s("/api/eval-targets",{name:t.name,type:t.type,content:i,description:t.description});this.log(`Created eval target: ${r.name} (${r.id}) v${r.version}`)}};export{n as default};
1
+ import{a}from"../../chunk-PPKPCXJD.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-V44SRRYR.js";import"../../chunk-U6XEU573.js";import"../../chunk-VLOX6KOM.js";import"../../chunk-3AV3GTMP.js";import{f as s}from"../../chunk-H2ORWIEY.js";import"../../chunk-O6C2UGBY.js";import{a as o}from"../../chunk-ZLLER3HP.js";import{Flags as e}from"@oclif/core";import{readFileSync as p}from"node:fs";var n=class c extends a{static{o(this,"EvalTargetCreate")}static description="Create an eval target (instruction, skill, prompt, or plan to test)";static examples=["<%= config.bin %> eval-targets create --name my-rules --type instruction --file ./CLAUDE.md",'<%= config.bin %> eval-targets create --name my-prompt --type prompt --content "Always use TypeScript"'];static flags={name:e.string({char:"n",description:"Name for the eval target",required:!0}),type:e.string({char:"t",description:"Target type",options:["instruction","skill","prompt","plan"],required:!0}),file:e.string({char:"f",description:"Path to content file"}),content:e.string({char:"c",description:"Content string (alternative to --file)"}),description:e.string({char:"d",description:"Description of the target",default:""})};async run(){let{flags:t}=await this.parse(c);this.requireAuth();let i;t.file?i=p(t.file,"utf-8"):t.content?i=t.content:this.error("Provide either --file or --content");let r=await s("/api/eval-targets",{name:t.name,type:t.type,content:i,description:t.description});this.log(`Created eval target: ${r.name} (${r.id}) v${r.version}`)}};export{n as default};
@@ -1 +1 @@
1
- import{a as p,b as e}from"../../chunk-W2MV25SB.js";import{a as o}from"../../chunk-LQRYQE6Q.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-CRAKDQ4H.js";import"../../chunk-WPJ2BND4.js";import"../../chunk-3AV3GTMP.js";import{d as n}from"../../chunk-TIQ7DQ3M.js";import"../../chunk-M6AJDVCL.js";import{a as s}from"../../chunk-ZLLER3HP.js";import{Flags as m}from"@oclif/core";import{printTable as d}from"@oclif/table";var r=class l extends o{static{s(this,"EvalTargetList")}static description="List eval targets";static examples=["<%= config.bin %> eval-targets list","<%= config.bin %> eval-targets list --type instruction"];static flags={type:m.string({char:"t",description:"Filter by type",options:["instruction","skill","prompt","plan"]})};async run(){let{flags:i}=await this.parse(l);this.requireAuth();let c=i.type?`?type=${i.type}`:"",a=await n(`/api/eval-targets${c}`);if(a.length===0){this.log("No eval targets found. Create one with `rulemetric eval-targets create`.");return}d({data:a.map(t=>({Name:e(t.name,30),Type:t.type,Version:`v${t.version}`,Description:e(t.description,40),Updated:p(t.updatedAt)})),columns:["Name","Type","Version","Description","Updated"]})}};export{r as default};
1
+ import{a as p,b as e}from"../../chunk-W2MV25SB.js";import{a as o}from"../../chunk-PPKPCXJD.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-V44SRRYR.js";import"../../chunk-U6XEU573.js";import"../../chunk-VLOX6KOM.js";import"../../chunk-3AV3GTMP.js";import{e as n}from"../../chunk-H2ORWIEY.js";import"../../chunk-O6C2UGBY.js";import{a as s}from"../../chunk-ZLLER3HP.js";import{Flags as m}from"@oclif/core";import{printTable as d}from"@oclif/table";var r=class l extends o{static{s(this,"EvalTargetList")}static description="List eval targets";static examples=["<%= config.bin %> eval-targets list","<%= config.bin %> eval-targets list --type instruction"];static flags={type:m.string({char:"t",description:"Filter by type",options:["instruction","skill","prompt","plan"]})};async run(){let{flags:i}=await this.parse(l);this.requireAuth();let c=i.type?`?type=${i.type}`:"",a=await n(`/api/eval-targets${c}`);if(a.length===0){this.log("No eval targets found. Create one with `rulemetric eval-targets create`.");return}d({data:a.map(t=>({Name:e(t.name,30),Type:t.type,Version:`v${t.version}`,Description:e(t.description,40),Updated:p(t.updatedAt)})),columns:["Name","Type","Version","Description","Updated"]})}};export{r as default};
@@ -1,3 +1,3 @@
1
- import{e as N}from"../../chunk-ML36XQW7.js";import"../../chunk-PZS2KOU7.js";import"../../chunk-RTEATXTP.js";import"../../chunk-7XQ4VPLC.js";import"../../chunk-6QKI756T.js";import"../../chunk-RSKQRVPJ.js";import"../../chunk-HOHD5HY2.js";import"../../chunk-V5QFOF4F.js";import"../../chunk-UF6US7VU.js";import"../../chunk-IY5NXR3N.js";import"../../chunk-72XLQE3X.js";import"../../chunk-FHVBTDBM.js";import{i as f}from"../../chunk-NVOTOQBA.js";import"../../chunk-I4YJ7NTX.js";import"../../chunk-F2VP4B4J.js";import"../../chunk-E4SFUPYR.js";import"../../chunk-VWEXKDWG.js";import"../../chunk-RTWRHIKY.js";import"../../chunk-ZL4MZMUK.js";import"../../chunk-5RBLIVBF.js";import"../../chunk-2TC6WCUT.js";import"../../chunk-6V4WM73L.js";import"../../chunk-HP2BUPGS.js";import"../../chunk-TDD7IOV2.js";import"../../chunk-MODXEGCU.js";import"../../chunk-7DFNBRLY.js";import"../../chunk-N7ODX6PO.js";import"../../chunk-67QCYUJU.js";import"../../chunk-DSO2U4Y6.js";import"../../chunk-CADKBP3D.js";import"../../chunk-MGHFDHHM.js";import{a as _}from"../../chunk-LQRYQE6Q.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-CRAKDQ4H.js";import"../../chunk-WPJ2BND4.js";import"../../chunk-3AV3GTMP.js";import"../../chunk-TIQ7DQ3M.js";import{e as R,k as w}from"../../chunk-M6AJDVCL.js";import{a as e}from"../../chunk-ZLLER3HP.js";import{trace as z,context as Q}from"@opentelemetry/api";import{NodeSDK as A}from"@opentelemetry/sdk-node";import{OTLPTraceExporter as I}from"@opentelemetry/exporter-trace-otlp-http";import{BatchSpanProcessor as L,ConsoleSpanExporter as C,SimpleSpanProcessor as D}from"@opentelemetry/sdk-trace-node";import{Resource as M}from"@opentelemetry/resources";import{ATTR_SERVICE_NAME as V,ATTR_SERVICE_VERSION as q}from"@opentelemetry/semantic-conventions";function b(t){if(!t)return{};let r={};for(let n of t.split(",")){let o=n.indexOf("=");if(o===-1)continue;let s=n.slice(0,o).trim(),i=n.slice(o+1).trim();s&&(r[s]=i)}return r}e(b,"parseOtlpHeaders");var c=null;function g(){return process.env.TELEMETRY_ENABLED!=="false"}e(g,"isTelemetryEnabled");function E(t){if(!g()||c!==null)return"off";let r=new M({[V]:t.serviceName,[q]:t.serviceVersion??"0.1.0"}),n=process.env.OTEL_EXPORTER_OTLP_ENDPOINT,o,s;if(n){let i=b(process.env.OTEL_EXPORTER_OTLP_HEADERS),u=new I({url:`${n}/v1/traces`,headers:i});s=new L(u),o="otlp"}else if(process.env.OTEL_SPAN_EXPORT==="none")s=void 0,o="silent";else{let i=new C;s=new D(i),o="console"}return c=new A({resource:r,spanProcessors:s?[s]:[]}),c.start(),o}e(E,"initTelemetry");async function d(){c&&(await c.shutdown(),c=null)}e(d,"shutdownTelemetry");import{SpanKind as ae,SpanStatusCode as ce}from"@opentelemetry/api";import{trace as de,context as me}from"@opentelemetry/api";import*as l from"@sentry/node";var h=!1;function y(t){if(h)return!1;let r=process.env.SENTRY_DSN;return r?(l.init({dsn:r,serverName:t.serviceName,environment:process.env.NODE_ENV??"development",tracesSampleRate:0}),h=!0,!0):!1}e(y,"initSentry");async function m(t){h&&await l.flush(t)}e(m,"flushSentry");import{existsSync as G,mkdirSync as U,readFileSync as v,unlinkSync as k,writeFileSync as O}from"node:fs";import{dirname as X,join as P}from"node:path";import{execFileSync as $}from"node:child_process";var a=P(w(),"evals-agent.lock");function j(t){try{return process.kill(t,0),!0}catch(r){return r.code==="EPERM"}}e(j,"pidAlive");function B(t){if(!j(t))return!1;try{let r=$("ps",["-p",String(t),"-o","command="],{encoding:"utf-8",stdio:["ignore","pipe","ignore"]});return/run\.js\s+evals\s+agent|evals\s+agent/.test(r)}catch{return!0}}e(B,"isLiveAgent");function H(){try{U(X(a),{recursive:!0})}catch{}for(let t=0;t<2;t++)try{return O(a,String(process.pid),{flag:"wx"}),{ok:!0}}catch(r){if(r.code!=="EEXIST")throw r;let n=0;try{n=Number(v(a,"utf-8").trim())}catch{}if(n&&n!==process.pid&&B(n))return{ok:!1,holder:n};try{k(a)}catch{}}try{O(a,String(process.pid))}catch{}return{ok:!0}}e(H,"acquireAgentLock");function S(){try{G(a)&&Number(v(a,"utf-8").trim())===process.pid&&k(a)}catch{}}e(S,"releaseAgentLock");var T=class t extends _{static{e(this,"EvalAgentCommand")}static description="The worker daemon: long-polls /api/work/next, claims jobs, and runs them locally. Installed as a launchd service by `rulemetric service install`.";static examples=["<%= config.bin %> evals agent"];async run(){await this.parse(t),this.requireAuth();let r=H();if(!r.ok){this.log(`Another rulemetric evals agent is already running (pid ${r.holder}). Refusing to start a second instance.`);return}process.env.PG_APPLICATION_NAME||="rulemetric-agent",y({serviceName:"rulemetric-agent"})&&this.log("[sentry] error capture enabled");let o=E({serviceName:"rulemetric-agent"});o==="otlp"?this.log(`[otel] traces exporting to ${process.env.OTEL_EXPORTER_OTLP_ENDPOINT}`):o==="console"?this.log("[otel] cron spans printing to stdout (set OTEL_EXPORTER_OTLP_ENDPOINT to ship to a backend)"):this.log("[otel] disabled (TELEMETRY_ENABLED=false)"),!R()&&!process.env.RULEMETRIC_API_KEY&&this.error("No auth token found. Run `rulemetric auth login` first."),this.log("Starting thin agent (Phase 4b parallel-run)..."),this.log(`Long-polling /api/work/next. Press Ctrl+C to stop.
1
+ import{e as N}from"../../chunk-43YBXX7R.js";import"../../chunk-TIOKY2IA.js";import"../../chunk-TQMG647B.js";import"../../chunk-W2MOTOQE.js";import"../../chunk-VAXRCSSH.js";import"../../chunk-6QKI756T.js";import"../../chunk-RSKQRVPJ.js";import"../../chunk-AYUJY37O.js";import"../../chunk-QFVGUZDO.js";import"../../chunk-KAF3CYRW.js";import"../../chunk-UF6US7VU.js";import"../../chunk-DPFNJZUO.js";import"../../chunk-RTWRHIKY.js";import"../../chunk-2WLVDSAP.js";import"../../chunk-ZL4MZMUK.js";import"../../chunk-N7TGRFVZ.js";import{i as f}from"../../chunk-H4SV7FN4.js";import"../../chunk-NEACEHQD.js";import"../../chunk-32EEBARV.js";import"../../chunk-5RBLIVBF.js";import"../../chunk-2TC6WCUT.js";import"../../chunk-6V4WM73L.js";import"../../chunk-HS7X43XE.js";import"../../chunk-TDD7IOV2.js";import"../../chunk-MODXEGCU.js";import"../../chunk-7DFNBRLY.js";import"../../chunk-N7ODX6PO.js";import"../../chunk-67QCYUJU.js";import"../../chunk-DSO2U4Y6.js";import"../../chunk-CADKBP3D.js";import"../../chunk-MGHFDHHM.js";import{a as _}from"../../chunk-PPKPCXJD.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-V44SRRYR.js";import"../../chunk-U6XEU573.js";import"../../chunk-VLOX6KOM.js";import"../../chunk-3AV3GTMP.js";import"../../chunk-H2ORWIEY.js";import{e as R,l as w}from"../../chunk-O6C2UGBY.js";import{a as e}from"../../chunk-ZLLER3HP.js";import{trace as z,context as Q}from"@opentelemetry/api";import{NodeSDK as A}from"@opentelemetry/sdk-node";import{OTLPTraceExporter as I}from"@opentelemetry/exporter-trace-otlp-http";import{BatchSpanProcessor as L,ConsoleSpanExporter as C,SimpleSpanProcessor as D}from"@opentelemetry/sdk-trace-node";import{Resource as M}from"@opentelemetry/resources";import{ATTR_SERVICE_NAME as V,ATTR_SERVICE_VERSION as q}from"@opentelemetry/semantic-conventions";function b(t){if(!t)return{};let r={};for(let n of t.split(",")){let o=n.indexOf("=");if(o===-1)continue;let s=n.slice(0,o).trim(),i=n.slice(o+1).trim();s&&(r[s]=i)}return r}e(b,"parseOtlpHeaders");var c=null;function g(){return process.env.TELEMETRY_ENABLED!=="false"}e(g,"isTelemetryEnabled");function E(t){if(!g()||c!==null)return"off";let r=new M({[V]:t.serviceName,[q]:t.serviceVersion??"0.1.0"}),n=process.env.OTEL_EXPORTER_OTLP_ENDPOINT,o,s;if(n){let i=b(process.env.OTEL_EXPORTER_OTLP_HEADERS),u=new I({url:`${n}/v1/traces`,headers:i});s=new L(u),o="otlp"}else if(process.env.OTEL_SPAN_EXPORT==="none")s=void 0,o="silent";else{let i=new C;s=new D(i),o="console"}return c=new A({resource:r,spanProcessors:s?[s]:[]}),c.start(),o}e(E,"initTelemetry");async function d(){c&&(await c.shutdown(),c=null)}e(d,"shutdownTelemetry");import{SpanKind as ae,SpanStatusCode as ce}from"@opentelemetry/api";import{trace as de,context as me}from"@opentelemetry/api";import*as l from"@sentry/node";var h=!1;function y(t){if(h)return!1;let r=process.env.SENTRY_DSN;return r?(l.init({dsn:r,serverName:t.serviceName,environment:process.env.NODE_ENV??"development",tracesSampleRate:0}),h=!0,!0):!1}e(y,"initSentry");async function m(t){h&&await l.flush(t)}e(m,"flushSentry");import{existsSync as G,mkdirSync as U,readFileSync as v,unlinkSync as k,writeFileSync as O}from"node:fs";import{dirname as X,join as P}from"node:path";import{execFileSync as $}from"node:child_process";var a=P(w(),"evals-agent.lock");function j(t){try{return process.kill(t,0),!0}catch(r){return r.code==="EPERM"}}e(j,"pidAlive");function B(t){if(!j(t))return!1;try{let r=$("ps",["-p",String(t),"-o","command="],{encoding:"utf-8",stdio:["ignore","pipe","ignore"]});return/run\.js\s+evals\s+agent|evals\s+agent/.test(r)}catch{return!0}}e(B,"isLiveAgent");function H(){try{U(X(a),{recursive:!0})}catch{}for(let t=0;t<2;t++)try{return O(a,String(process.pid),{flag:"wx"}),{ok:!0}}catch(r){if(r.code!=="EEXIST")throw r;let n=0;try{n=Number(v(a,"utf-8").trim())}catch{}if(n&&n!==process.pid&&B(n))return{ok:!1,holder:n};try{k(a)}catch{}}try{O(a,String(process.pid))}catch{}return{ok:!0}}e(H,"acquireAgentLock");function S(){try{G(a)&&Number(v(a,"utf-8").trim())===process.pid&&k(a)}catch{}}e(S,"releaseAgentLock");var T=class t extends _{static{e(this,"EvalAgentCommand")}static description="The worker daemon: long-polls /api/work/next, claims jobs, and runs them locally. Installed as a launchd service by `rulemetric service install`.";static examples=["<%= config.bin %> evals agent"];async run(){await this.parse(t),this.requireAuth();let r=H();if(!r.ok){this.log(`Another rulemetric evals agent is already running (pid ${r.holder}). Refusing to start a second instance.`);return}process.env.PG_APPLICATION_NAME||="rulemetric-agent",y({serviceName:"rulemetric-agent"})&&this.log("[sentry] error capture enabled");let o=E({serviceName:"rulemetric-agent"});o==="otlp"?this.log(`[otel] traces exporting to ${process.env.OTEL_EXPORTER_OTLP_ENDPOINT}`):o==="console"?this.log("[otel] cron spans printing to stdout (set OTEL_EXPORTER_OTLP_ENDPOINT to ship to a backend)"):this.log("[otel] disabled (TELEMETRY_ENABLED=false)"),!R()&&!process.env.RULEMETRIC_API_KEY&&this.error("No auth token found. Run `rulemetric auth login` first."),this.log("Starting thin agent (Phase 4b parallel-run)..."),this.log(`Long-polling /api/work/next. Press Ctrl+C to stop.
2
2
  `);let i=new AbortController,u=e(async p=>{this.log(`
3
3
  [${p}] shutting down agent...`),i.abort(),await Promise.allSettled([m(2e3),d(),f()]),S(),process.exit(0)},"shutdown");process.on("SIGINT",()=>{u("SIGINT")}),process.on("SIGTERM",()=>{u("SIGTERM")});let x=!1;try{await N({signal:i.signal,log:e(p=>this.log(p),"log"),version:this.config.version,readInstalledVersion:e(()=>{try{return JSON.parse(v(P(this.config.root,"package.json"),"utf-8")).version??null}catch{return null}},"readInstalledVersion"),onVersionDrift:e(()=>{x=!0},"onVersionDrift")}),x&&(this.log("[upgrade] Installed CLI version changed \u2014 restarting worker onto the new code."),await Promise.allSettled([m(2e3),d(),f()]),S(),process.exit(1))}finally{S(),await f()}}};export{T as default};
@@ -1,4 +1,4 @@
1
- import{a as u,b as f}from"../../chunk-RVO4HV3M.js";import{a as d}from"../../chunk-LQRYQE6Q.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-CRAKDQ4H.js";import"../../chunk-WPJ2BND4.js";import"../../chunk-3AV3GTMP.js";import{d as l}from"../../chunk-TIQ7DQ3M.js";import"../../chunk-M6AJDVCL.js";import{a as m}from"../../chunk-ZLLER3HP.js";import{Args as b,Flags as $}from"@oclif/core";var o=class h extends d{static{m(this,"EvalBenchmarkCommand")}static description="Aggregate eval runs into a benchmark for a target";static examples=["<%= config.bin %> evals benchmark <target-id>","<%= config.bin %> evals benchmark <target-id> --iteration 2"];static args={targetId:b.string({description:"Eval target ID",required:!0})};static flags={iteration:$.integer({description:"Filter runs by iteration",default:1})};async run(){let{args:i,flags:a}=await this.parse(h);this.requireAuth();let g=await l(`/api/eval-targets/${i.targetId}`);this.log(`Aggregating benchmark for "${g.name}" v${g.version}, iteration ${a.iteration}`);let t=await u(i.targetId,a.iteration);t.totalRuns===0&&this.error("No completed runs found. Run evals first with `rulemetric evals run`."),this.log(`
1
+ import{a as u,b as f}from"../../chunk-G63KMH6U.js";import{a as d}from"../../chunk-PPKPCXJD.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-V44SRRYR.js";import"../../chunk-U6XEU573.js";import"../../chunk-VLOX6KOM.js";import"../../chunk-3AV3GTMP.js";import{e as l}from"../../chunk-H2ORWIEY.js";import"../../chunk-O6C2UGBY.js";import{a as m}from"../../chunk-ZLLER3HP.js";import{Args as b,Flags as $}from"@oclif/core";var o=class h extends d{static{m(this,"EvalBenchmarkCommand")}static description="Aggregate eval runs into a benchmark for a target";static examples=["<%= config.bin %> evals benchmark <target-id>","<%= config.bin %> evals benchmark <target-id> --iteration 2"];static args={targetId:b.string({description:"Eval target ID",required:!0})};static flags={iteration:$.integer({description:"Filter runs by iteration",default:1})};async run(){let{args:i,flags:a}=await this.parse(h);this.requireAuth();let g=await l(`/api/eval-targets/${i.targetId}`);this.log(`Aggregating benchmark for "${g.name}" v${g.version}, iteration ${a.iteration}`);let t=await u(i.targetId,a.iteration);t.totalRuns===0&&this.error("No completed runs found. Run evals first with `rulemetric evals run`."),this.log(`
2
2
  Aggregated ${t.totalRuns} runs
3
3
  `);for(let[e,c]of Object.entries(t.runSummary)){if(e==="delta"){this.log(`
4
4
  Delta (with_target - without_target):`);for(let[n,s]of Object.entries(c))this.log(` ${n}: ${s}`);continue}this.log(`${e}:`);for(let[n,s]of Object.entries(c)){let r=s;this.log(` ${n}: mean=${r.mean} stddev=${r.stddev} [${r.min}, ${r.max}]`)}}if(t.notes.length>0){this.log(`