@rulemetric/cli 0.7.22 → 0.7.23
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.
- package/dist/chunk-35ZDT2VL.js +11 -0
- package/dist/chunk-TAWDHGWW.js +1 -0
- package/dist/commands/diagnostics.js +1 -1
- package/dist/commands/evals/agent.js +1 -1
- package/dist/commands/setup.js +1 -1
- package/dist/lib/agent-loop.js +1 -1
- package/dist/lib/setup-steps.js +1 -1
- package/oclif.manifest.json +2 -2
- package/package.json +5 -5
- package/dist/chunk-FS2Q2J7V.js +0 -1
- package/dist/chunk-U6ABMRT3.js +0 -9
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import{a as I,g as _,h as x,j as C,m as T}from"./chunk-2JRDG4LJ.js";import{c as d}from"./chunk-MVM6OGAF.js";import{d as g}from"./chunk-3BVHPQZW.js";import{e as v}from"./chunk-H2ORWIEY.js";import{g as m,l as E}from"./chunk-O6C2UGBY.js";import{a as s}from"./chunk-ZLLER3HP.js";import{execSync as j}from"node:child_process";import{existsSync as p,readFileSync as y}from"node:fs";import{homedir as f}from"node:os";import{join as a}from"node:path";var P=["install","auth","hooks","worker"],$=["judge"],M=[...P,...$];function O(){return{projectPath:process.cwd(),configDir:E()}}s(O,"defaultContext");var A=a(f(),".mitmproxy","mitmproxy-ca-cert.pem");function S(e){if(!e)return"";if(e.length<=8)return"*".repeat(e.length);let t=e.slice(0,4),n=e.slice(-4);return`${t}${"*".repeat(Math.max(4,e.length-8))}${n}`}s(S,"maskToken");function te(e,t){let n=e===null?[]:e.replace(/\n$/,"").split(`
|
|
2
|
+
`),o=t===null?[]:t.replace(/\n$/,"").split(`
|
|
3
|
+
`),i=[],u=Math.max(n.length,o.length);for(let c=0;c<u;c++){let l=n[c],r=o[c];l===r?i.push(` ${l}`):(l!==void 0&&i.push(`-${l}`),r!==void 0&&i.push(`+${r}`))}return i.join(`
|
|
4
|
+
`)}s(te,"renderDiff");function b(e,t){let n=a(e,"env");if(!p(n))return null;try{let i=y(n,"utf-8").match(new RegExp(`^${t}=(.+)$`,"m"));return i?i[1]:null}catch{return null}}s(b,"readEnvValue");async function R(){if(!m())return!1;try{return(await Promise.race([v("/api/setup/status"),new Promise((t,n)=>setTimeout(()=>n(new Error("setup/status timeout")),2500))]))?.workerActive===!0}catch{return!1}}s(R,"workerActive");function k(e,t){let n=a(e,".claude",t),o={},i=null;if(p(n))try{i=y(n,"utf-8").replace(/\n$/,""),o=JSON.parse(i)}catch{o={}}return{settings:o,before:i}}s(k,"readProjectSettings");function D(e){let{settings:t,before:n}=k(e,"settings.local.json");return _(t),{before:n,after:JSON.stringify(t,null,2)}}s(D,"projectHooksSettings");function N(e){let{settings:t,before:n}=k(e,"settings.local.json"),o={...t.env??{}};return o.HTTPS_PROXY=`http://localhost:${d}`,o.NO_PROXY=C,o.NODE_EXTRA_CA_CERTS=A,{before:n,after:JSON.stringify({...t,env:o},null,2)}}s(N,"projectProxyEnvSettings");function U(e){let{settings:t,before:n}=k(e,"settings.json");if(n===null)return null;let{removed:o}=T(t,d);return o?{before:n,after:JSON.stringify(t,null,2)}:null}s(U,"projectSharedSettingsMigration");var H=a(f(),"Library","LaunchAgents","com.rulemetric.worker.plist"),K=a(f(),".config","systemd","user","rulemetric-worker.service");function h(e){j(e,{stdio:"inherit"})}s(h,"runCommand");var w=[{id:"install",title:"Install the CLI",command:"npm install -g @rulemetric/cli",async detect(){return m()||await R()},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(e){let t=a(e.configDir,"env"),n=null;if(p(t))try{n=G(y(t,"utf-8"))}catch{n="(unreadable)"}let o=b(e.configDir,"RULEMETRIC_ACCESS_TOKEN"),u=[`RULEMETRIC_ACCESS_TOKEN=${S(o||"<token-from-login>")}`],c=b(e.configDir,"RULEMETRIC_API_KEY");c&&u.push(`RULEMETRIC_API_KEY=${S(c)}`);let l=process.env.RULEMETRIC_API_URL;l&&u.push(`RULEMETRIC_API_URL=${l}`);let r=u.join(`
|
|
5
|
+
`);return{id:"auth",title:"Authenticate",command:"rulemetric auth login",artifacts:[{path:t,kind:"file",before:n,after:r,masked:!0},{path:a(e.configDir,"auth.json"),kind:"file",before:p(a(e.configDir,"auth.json"))?"(existing session tokens)":null,after:"{ accessToken, refreshToken, expiresAt, email } \u2014 OAuth session tokens (secret)",masked:!0}]}},async apply(){h("rulemetric auth login")}},{id:"hooks",title:"Install hooks + capture proxy",command:"rulemetric hooks install",async detect(e){for(let t of["settings.local.json","settings.json"]){let n=a(e.projectPath,".claude",t);if(p(n))try{let o=JSON.parse(y(n,"utf-8"));if(x(o))return!0}catch{}}return!1},async plan(e){let t=a(e.projectPath,".claude","settings.local.json"),{before:n,after:o}=D(e.projectPath),i=[{path:t,kind:"file",before:n,after:o},{path:"what these hooks capture",kind:"service",before:null,after:"session-end reimports the FULL transcript to the API; post-tool-use records each tool call and snapshots the working tree to a LOCAL shadow git ref (paper-trail, never pushed); user-prompt posts prompt text. All scoped to sessions in this project."},{path:`${t} (proxy env block)`,kind:"file",...N(e.projectPath)},{path:"system keychain \u2014 mitmproxy root CA",kind:"service",before:p(A)?"(CA generated; trust state unchanged)":"(no CA yet)",after:"Installs + trusts the mitmproxy CA (requires sudo). This lets the proxy DECRYPT Claude Code HTTPS request/response bodies \u2014 the capability that powers rendered-system-prompt / instruction linking. Decline the sudo prompt and setup stays hooks-only (still fully onboarded)."},{path:"launchctl setenv HTTPS_PROXY (machine-wide, all GUI apps)",kind:"command",before:null,after:`http://localhost:${d} \u2014 routes every GUI app's HTTPS through the local gateway (only when the CA is trusted AND :${d} is live)`},{path:"VS Code + Cursor user settings (http.proxy)",kind:"file",before:null,after:`http.proxy \u2192 http://localhost:${d} (+ http.proxyStrictSSL=false)`},{path:`gateway process on :${d}`,kind:"service",before:null,after:"started (routes Claude Code \u2192 mitmproxy \u2192 Anthropic; falls back to direct if mitmproxy is down)"}],u=U(e.projectPath);u&&i.push({path:`${a(e.projectPath,".claude","settings.json")} (removes RuleMetric machine-local state left by an older install \u2014 see the local-file artifacts above for where it moves)`,kind:"file",...u});for(let c of I(e.projectPath).filter(l=>l==="cursor"||l==="copilot_agent"))i.push({path:`${e.projectPath} (${c} workspace proxy config)`,kind:"file",before:null,after:`proxy \u2192 http://localhost:${d}`});for(let[c,l,r]of[["Cursor",a(f(),".cursor"),a(f(),".cursor","hooks.json")],["Antigravity/Gemini",a(f(),".gemini"),a(f(),".gemini","config","hooks.json")]])p(l)&&i.push({path:`${r} (${c} user hooks)`,kind:"file",before:p(r)?"(existing config)":null,after:"adds RuleMetric session-capture hooks for this tool"});return{id:"hooks",title:"Install hooks + capture proxy",command:"rulemetric hooks install",artifacts:i}},async apply(){h("rulemetric hooks install")}},{id:"worker",title:"Run the worker",command:"rulemetric service install --worker-only",async detect(){return R()},async plan(){let e=process.platform==="darwin",t=e?H:K,n=p(t)?`(service already installed at ${t})`:null,o=e?["Label: com.rulemetric.worker","ProgramArguments: <node> <cli>/bin/run.js evals agent","RunAtLoad: true, KeepAlive: true"].join(`
|
|
6
|
+
`):["[Service]","ExecStart=<node> <cli>/bin/run.js evals agent","Restart=on-failure"].join(`
|
|
7
|
+
`);return{id:"worker",title:"Run the worker",command:"rulemetric service install --worker-only",artifacts:[{path:t,kind:"service",before:n,after:o}]}},async apply(){h("rulemetric service install --worker-only")}},{id:"judge",title:"Judge validation engine (optional)",command:"npm install -g @openai/codex",optional:!0,async detect(){let e=g();return e.claudeBin!=null&&e.codexBin!=null},async plan(){let e=g();return{id:"judge",title:"Judge validation engine (optional)",command:"npm install -g @openai/codex",artifacts:[{path:"installed LLM engines",kind:"command",before:[`claude CLI: ${e.claudeBin??"not found"}`,`codex CLI: ${e.codexBin??"not found"}`].join(`
|
|
8
|
+
`),after:["claude CLI + codex CLI both installed.","Hand labels + one judge already give calibrated verdicts; a second","engine additionally unlocks cross-vendor judge validation","(`rulemetric evals validate-judge`)."].join(`
|
|
9
|
+
`)}]}},async apply(){let e=g();if(e.claudeBin!=null&&e.codexBin!=null){console.log("[OK] Both engines already installed \u2014 nothing to do.");return}let t=e.codexBin==null?"codex":"claude";console.log(`[..] Second engine not detected (missing: ${t} CLI).`),console.log(t==="codex"?" Install it yourself when ready: npm install -g @openai/codex":" Install it yourself when ready: npm install -g @anthropic-ai/claude-code"),console.log(" Then re-run: rulemetric setup judge --show")}}],Y=new Map(w.map(e=>[e.id,e]));function ne(e){let t=Y.get(e);if(!t)throw new Error(`Unknown setup step: ${e}`);return t}s(ne,"getStep");function oe(e){return M.includes(e)}s(oe,"isStepId");var B=new Set(["RULEMETRIC_API_URL","RULEMETRIC_USER_ID","RULEMETRIC_CLIENT_NAME","RESEND_FROM_EMAIL","SENTRY_DSN","PG_POOL_MAX","PG_IDLE_TIMEOUT","PG_STATEMENT_TIMEOUT_MS","NODE_ENV"]);function G(e){return e.replace(/\n$/,"").split(`
|
|
10
|
+
`).map(t=>{let n=t.match(/^([A-Z0-9_]+)=(.+)$/);if(!n)return t;let[,o,i]=n;return B.has(o)?t:`${o}=${S(i)}`}).join(`
|
|
11
|
+
`)}s(G,"maskEnvFile");async function re(e=O()){let t=[];for(let r of w){let L=await r.detect(e);t.push({id:r.id,done:L})}let n=new Set(P),o=t.find(r=>r.id==="install");o&&!o.done&&(o.done=t.some(r=>r.id!=="install"&&n.has(r.id)&&r.done));let i=new Set(P),u=t.filter(r=>i.has(r.id)),c=u.find(r=>!r.done)?.id??null,l=u.every(r=>r.done);return{steps:t,coreComplete:l,currentStepId:c}}s(re,"computeStatus");export{P as a,$ as b,M as c,O as d,S as e,te as f,w as g,ne as h,oe as i,re as j};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{c as x}from"./chunk-TIOKY2IA.js";import{a as S}from"./chunk-MYPDODRJ.js";import{a as h}from"./chunk-O23Z6LTP.js";import{a as I}from"./chunk-PRDYXO6Z.js";import{b as E}from"./chunk-W2MOTOQE.js";import{a as R}from"./chunk-F53QW6VG.js";import{a as H}from"./chunk-EXUPWAVK.js";import{a as A}from"./chunk-RSKQRVPJ.js";import{a as y}from"./chunk-AW6LN6ZU.js";import{a as L}from"./chunk-DO3KHK2X.js";import{a as k}from"./chunk-UF6US7VU.js";import{a as v}from"./chunk-MSTF7A7D.js";import{b as M}from"./chunk-TSS6ESRK.js";import{a as T}from"./chunk-SD4SGJZY.js";import{b}from"./chunk-5RBLIVBF.js";import{d as w}from"./chunk-3BVHPQZW.js";import{b as f,e as _,f as p}from"./chunk-H2ORWIEY.js";import{a as s}from"./chunk-ZLLER3HP.js";var V={process_eval:h,process_insights:I,process_launch:E,process_send_message:A,process_conversation:S,process_session_goal:y,distill_memories:M,memory_ab:R,process_announcement:T,process_run_cleanup:H,cron_suggest_instructions:v,cron_refresh_skills:k,cron_refresh_pricing:L},N=Object.keys(V),O=new Set(["process_session_goal","process_announcement","process_run_cleanup","distill_memories","memory_ab"]);function W(e=process.env){return e.DATABASE_URL?N:N.filter(n=>!O.has(n))}s(W,"availableCapabilities");var $=3e4,F=3e4,J=3e4,P=250,C=5e3,U=`thin-agent-${process.pid}`,g=null;function K(e,n,r,l){let c;try{let d=w();c={claude:d.claudeBin!=null,codex:d.codexBin!=null,codexModel:d.codexConfiguredModel}}catch{}let i=s(d=>{p("/api/workers/heartbeat",{workerType:"cli-worker",clientName:U,clientVersion:l,workerVersion:"0.1.0",currentJobId:null,inFlightCount:0,lastError:null,status:d,metadata:{capabilities:e,mode:"thin-agent",llmEngines:c}}).then(m=>{let t=m?.advisory;t&&t.message!==g?(g=t.message,a(r,{event:"worker_advisory",code:t.code,message:t.message})):t||(g=null)}).catch(m=>{a(r,{event:"presence_heartbeat_error",error:m instanceof Error?m.message:String(m)})})},"send");i("alive");let o=setInterval(()=>i("alive"),J);n.addEventListener("abort",()=>{clearInterval(o),i("shutting_down")},{once:!0})}s(K,"startPresenceHeartbeat");function a(e,n){try{e(JSON.stringify({ts:new Date().toISOString(),...n}))}catch{e(`[agent-loop] log_error event=${n.event}`)}}s(a,"structuredLog");function D(e,n){return n.aborted?Promise.resolve(!1):e<=0?Promise.resolve(!0):new Promise(r=>{let l=setTimeout(()=>{n.removeEventListener("abort",c),r(!0)},e),c=s(()=>{clearTimeout(l),n.removeEventListener("abort",c),r(!1)},"onAbort");n.addEventListener("abort",c,{once:!0})})}s(D,"abortableSleep");async function G(e,n){let r=`capabilities=${encodeURIComponent(e.join(","))}&waitMs=${n}`,l=await _(`/api/work/next?${r}`);return l==null||typeof l=="string"?null:l}s(G,"pollForWork");function q(e,n){return{logger:{info:s(r=>n(r),"info"),warn:s(r=>n(r),"warn"),error:s(r=>n(r),"error")},job:{attempts:e}}}s(q,"makeHelpers");async function Q(e,n,r){let l=V[e.kind],c=Date.now();if(a(r,{event:"claim",jobId:e.id,kind:e.kind,attempts:e.attempts}),!l){let o=`unknown kind: ${e.kind}`;a(r,{event:"fail",jobId:e.id,kind:e.kind,terminal:!0,error:o}),await p(`/api/work/${e.id}/fail`,{leaseToken:e.leaseToken,error:o,terminal:!0}).catch(()=>{});return}let i=setInterval(()=>{a(r,{event:"heartbeat",jobId:e.id}),p(`/api/work/${e.id}/heartbeat`,{leaseToken:e.leaseToken}).catch(o=>{a(r,{event:"heartbeat_error",jobId:e.id,error:o instanceof Error?o.message:String(o)})})},n);try{let o=q(e.attempts,r),d=await l(e.payload,o)??{};clearInterval(i),a(r,{event:"complete",jobId:e.id,kind:e.kind,durationMs:Date.now()-c}),await p(`/api/work/${e.id}/complete`,{leaseToken:e.leaseToken,result:d})}catch(o){clearInterval(i);let d=b(o),m=o instanceof Error?o.message:String(o);a(r,{event:"fail",jobId:e.id,kind:e.kind,durationMs:Date.now()-c,terminal:d,error:m}),await p(`/api/work/${e.id}/fail`,{leaseToken:e.leaseToken,error:m,terminal:d}).catch(t=>{a(r,{event:"fail_post_error",jobId:e.id,error:t instanceof Error?t.message:String(t)})})}}s(Q,"runOne");async function pe(e){let n=e.log??(()=>{}),r=e.pollWaitMs??$,l=e.heartbeatIntervalMs??F,c=e.capabilities??W(),i=P;a(n,{event:"agent_start",capabilities:c,pollWaitMs:r,heartbeatIntervalMs:l}),K(c,e.signal,n,e.version),x({signal:e.signal,log:n}).catch(t=>{a(n,{event:"tt_heartbeat_fatal",error:t instanceof Error?t.message:String(t)})});let o=5*6e4,d=0,m=s(()=>{if(!e.readInstalledVersion||!e.version)return!1;let t=Date.now();if(t-d<o)return!1;d=t;let u=e.readInstalledVersion();return!!(u&&u!==e.version)},"versionDrifted");for(;!e.signal.aborted;){if(m()){a(n,{event:"agent_version_drift",bootVersion:e.version,installedVersion:e.readInstalledVersion?.()??null}),e.onVersionDrift?.();break}let t=null;try{t=await G(c,r)}catch(u){let B=u instanceof f?u.statusCode:void 0;if(a(n,{event:"poll_error",status:B,error:u instanceof Error?u.message:String(u)}),!await D(i,e.signal))break;i=Math.min(i*2,C);continue}if(!t){if(a(n,{event:"poll_204"}),!await D(i,e.signal))break;i=Math.min(i*2,C);continue}i=P,await Q(t,l,n)}a(n,{event:"agent_stop"})}s(pe,"runAgentLoop");export{V as a,N as b,W as c,G as d,pe as e};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{b as f,c as O}from"../chunk-V5U3E4BZ.js";import{
|
|
1
|
+
import{b as f,c as O}from"../chunk-V5U3E4BZ.js";import{c as g,d as h,e as P}from"../chunk-MVM6OGAF.js";import"../chunk-KKDHD4XA.js";import"../chunk-SZ62CP55.js";import{d as R}from"../chunk-3BVHPQZW.js";import"../chunk-SMGSLY5N.js";import"../chunk-PJ3WHQ67.js";import"../chunk-N7ODX6PO.js";import{a as x}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 y}from"../chunk-H2ORWIEY.js";import{a as T,g as p}from"../chunk-O6C2UGBY.js";import{a as u}from"../chunk-ZLLER3HP.js";import{spawnSync as H}from"node:child_process";import{existsSync as S,readFileSync as X}from"node:fs";import{join as $}from"node:path";var m=class b extends x{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??T().apiUrl??y}async checkDirect(){let t=process.env.HTTPS_PROXY,e=process.env.HTTP_PROXY;delete process.env.HTTPS_PROXY,delete process.env.HTTP_PROXY;let o=new AbortController,i=setTimeout(()=>o.abort(),8e3);try{return(await globalThis.fetch(`${this.baseUrl()}/health`,{signal:o.signal})).ok}catch{return!1}finally{clearTimeout(i),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=$(process.cwd(),".claude",t);if(S(e))try{let o=JSON.parse(X(e,"utf8"));if(o.env?.HTTPS_PROXY)return o.env.HTTPS_PROXY}catch{}}return null}checkThroughProxy(t){let e=H("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(b);let t=process.version,e=this.configuredProxy(),o=e!=null,[i,s,c]=await Promise.all([this.checkDirect(),P(g),P(h)]),l=o&&e?this.checkThroughProxy(e):null,n=u((d,v,A)=>{let w=v===null?"\u2013":v?"[OK]":"[!!]";this.log(` ${w} ${d.padEnd(22)} ${A}`)},"line");this.log("RuleMetric diagnostics"),this.log(""),n("Node",!f(t),`${t}${f(t)?" (< 20.11 \u2014 breaks the bundled proxy)":""}`),n("API (direct)",i,`${this.baseUrl()}/health ${i?"reachable":"UNREACHABLE"}`),n("Authenticated",p(),p()?"yes":"no \u2014 run `rulemetric auth login`"),n("Proxy configured",o?!0:null,o?e:"no HTTPS_PROXY set"),o&&(n("Gateway :"+g,s,s?"listening":"NOT listening"),n("mitmproxy :"+h,c,c?"listening":"not listening (gateway should route direct)"),n("API (via proxy)",l,l===null?"inconclusive (curl unavailable)":l?"reachable":"FAILED \u2014 502/blocked through your proxy"));let r=R();n("claude CLI",r.claudeBin!=null,r.claudeBin??"not found \u2014 LLM features (grading, distill) will no-op"),n("codex CLI",r.codexBin!=null?!0:null,r.codexBin?`${r.codexBin}${r.codexConfiguredModel?` (model ${r.codexConfiguredModel})`:""}`:"not found \u2014 optional; enables the cross-vendor reviewer (evals validate-judge)");let a=O({nodeVersion:t,directApiOk:i,httpsProxySet:o,gatewayAlive:s,mitmproxyAlive:c,proxyPathOk:l});this.log("");let _=a.severity==="ok"?"[OK]":a.severity==="warn"?"[!!]":"[XX]";this.log(`${_} ${a.headline}`);for(let d of a.hints)this.log(` \u2022 ${d}`)}};export{m as default};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{e as N}from"../../chunk-
|
|
1
|
+
import{e as N}from"../../chunk-TAWDHGWW.js";import"../../chunk-TIOKY2IA.js";import"../../chunk-MYPDODRJ.js";import"../../chunk-O23Z6LTP.js";import"../../chunk-PRDYXO6Z.js";import"../../chunk-QFVGUZDO.js";import"../../chunk-W2MOTOQE.js";import"../../chunk-F53QW6VG.js";import"../../chunk-EXUPWAVK.js";import"../../chunk-6QKI756T.js";import"../../chunk-RSKQRVPJ.js";import"../../chunk-AW6LN6ZU.js";import"../../chunk-DO3KHK2X.js";import"../../chunk-UF6US7VU.js";import"../../chunk-MSTF7A7D.js";import"../../chunk-TSS6ESRK.js";import"../../chunk-SD4SGJZY.js";import"../../chunk-5RBLIVBF.js";import"../../chunk-ZL4MZMUK.js";import"../../chunk-N7TGRFVZ.js";import{k as f}from"../../chunk-KXW3IWKQ.js";import"../../chunk-GTOEWPIM.js";import"../../chunk-6V4WM73L.js";import"../../chunk-JUF4JLZQ.js";import"../../chunk-TDD7IOV2.js";import"../../chunk-7DFNBRLY.js";import"../../chunk-MODXEGCU.js";import"../../chunk-GQRCSR2A.js";import"../../chunk-UUMW6X2W.js";import"../../chunk-YDRZDBHG.js";import"../../chunk-S6B2R2LL.js";import"../../chunk-K25S2MGU.js";import"../../chunk-CHA5SX4Y.js";import"../../chunk-WQ2BJQYB.js";import"../../chunk-3BVHPQZW.js";import"../../chunk-SMGSLY5N.js";import"../../chunk-PJ3WHQ67.js";import"../../chunk-N7ODX6PO.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};
|
package/dist/commands/setup.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{c as l,d as h,f as m,g as p,h as f,i as y,j as r}from"../chunk-
|
|
1
|
+
import{c as l,d as h,f as m,g as p,h as f,i as y,j as r}from"../chunk-35ZDT2VL.js";import"../chunk-2JRDG4LJ.js";import"../chunk-I2DZGJRR.js";import"../chunk-MVM6OGAF.js";import"../chunk-KKDHD4XA.js";import"../chunk-SZ62CP55.js";import"../chunk-3BVHPQZW.js";import"../chunk-SMGSLY5N.js";import"../chunk-PJ3WHQ67.js";import"../chunk-N7ODX6PO.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"../chunk-O6C2UGBY.js";import{a as u}from"../chunk-ZLLER3HP.js";import{Args as b,Flags as c}from"@oclif/core";import*as w from"node:readline/promises";var d=class v extends g{static{u(this,"Setup")}static description="Agentic, transparent setup: plan / show diffs / apply the four core onboarding steps";static examples=["<%= config.bin %> setup # interactive walk (TTY)","<%= config.bin %> setup plan # read-only: every remaining artifact + diff","<%= config.bin %> setup hooks --show # print one step's diff","<%= config.bin %> setup hooks --apply # apply one step","<%= config.bin %> setup --json # machine-readable status (exit 0 iff complete)"];static args={target:b.string({description:`"plan" or a step id (${l.join(", ")})`,required:!1})};static flags={json:c.boolean({description:"Machine-readable output",default:!1}),show:c.boolean({description:"Print the step diff (read-only)",default:!1}),apply:c.boolean({description:"Apply the step",default:!1})};async run(){let{args:t,flags:e}=await this.parse(v),i=h();if(t.target==="plan"){await this.runPlan(i,e.json);return}if(t.target&&y(t.target)){if(e.apply){await f(t.target).apply(i);return}let n=await f(t.target).plan(i);this.printPlan(n);return}if(t.target&&this.error(`Unknown target "${t.target}". Use "plan" or one of: ${l.join(", ")}.`),e.json){let n=await r(i);this.log(JSON.stringify(n,null,2)),n.coreComplete||this.exit(1);return}await this.runInteractive(i)}async runPlan(t,e){let i=await r(t),n=p.filter(s=>!i.steps.find(a=>a.id===s.id)?.done),o=[];for(let s of n)o.push(await s.plan(t));if(e){this.log(JSON.stringify({...i,plans:o},null,2));return}if(o.length===0){this.log("[OK] All core steps complete \u2014 nothing to install.");return}this.log(`The following steps would be applied:
|
|
2
2
|
`);for(let s of o)this.printPlan(s),this.log("")}printPlan(t){this.log(`[..] ${t.title} (${t.id})`),t.command&&this.log(` command: ${t.command}`);for(let e of t.artifacts){this.log(` ${e.kind}: ${e.path}${e.masked?" (secret masked)":""}`);let i=m(e.before,e.after);for(let n of i.split(`
|
|
3
3
|
`))this.log(` ${n}`)}}async runInteractive(t){if(!process.stdin.isTTY){this.log("Not a TTY \u2014 interactive walk needs a terminal."),this.log("Use one of:"),this.log(" rulemetric setup plan \u2014 see every remaining artifact + diff"),this.log(" rulemetric setup <step> --show \u2014 print one step diff"),this.log(" rulemetric setup <step> --apply \u2014 apply one step"),this.log(" rulemetric setup --json \u2014 machine-readable status");return}let e=await r(t),i=p.filter(o=>!e.steps.find(s=>s.id===o.id)?.done);if(i.length===0){this.log("[OK] All core steps complete.");return}let n=w.createInterface({input:process.stdin,output:process.stdout});try{for(let o of i){let s=await o.plan(t);this.printPlan(s);let a=(await n.question(`Apply "${s.title}"? [y/N] `)).trim().toLowerCase();a==="y"||a==="yes"?(await o.apply(t),this.log(`[OK] Applied ${s.title}.`)):this.log(`[..] Skipped ${s.title}.`),this.log("")}}finally{n.close()}}};export{d as default};
|
package/dist/lib/agent-loop.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a,b,c,d,e}from"../chunk-
|
|
1
|
+
import{a,b,c,d,e}from"../chunk-TAWDHGWW.js";import"../chunk-TIOKY2IA.js";import"../chunk-MYPDODRJ.js";import"../chunk-O23Z6LTP.js";import"../chunk-PRDYXO6Z.js";import"../chunk-QFVGUZDO.js";import"../chunk-W2MOTOQE.js";import"../chunk-F53QW6VG.js";import"../chunk-EXUPWAVK.js";import"../chunk-6QKI756T.js";import"../chunk-RSKQRVPJ.js";import"../chunk-AW6LN6ZU.js";import"../chunk-DO3KHK2X.js";import"../chunk-UF6US7VU.js";import"../chunk-MSTF7A7D.js";import"../chunk-TSS6ESRK.js";import"../chunk-SD4SGJZY.js";import"../chunk-5RBLIVBF.js";import"../chunk-ZL4MZMUK.js";import"../chunk-N7TGRFVZ.js";import"../chunk-KXW3IWKQ.js";import"../chunk-GTOEWPIM.js";import"../chunk-6V4WM73L.js";import"../chunk-JUF4JLZQ.js";import"../chunk-TDD7IOV2.js";import"../chunk-7DFNBRLY.js";import"../chunk-MODXEGCU.js";import"../chunk-GQRCSR2A.js";import"../chunk-UUMW6X2W.js";import"../chunk-YDRZDBHG.js";import"../chunk-S6B2R2LL.js";import"../chunk-K25S2MGU.js";import"../chunk-CHA5SX4Y.js";import"../chunk-WQ2BJQYB.js";import"../chunk-3BVHPQZW.js";import"../chunk-SMGSLY5N.js";import"../chunk-PJ3WHQ67.js";import"../chunk-N7ODX6PO.js";import"../chunk-H2ORWIEY.js";import"../chunk-O6C2UGBY.js";import"../chunk-ZLLER3HP.js";export{b as CAPABILITIES,a as HANDLERS,c as availableCapabilities,d as pollForWork,e as runAgentLoop};
|
package/dist/lib/setup-steps.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a,b,c,d,e,f,g,h,i,j}from"../chunk-
|
|
1
|
+
import{a,b,c,d,e,f,g,h,i,j}from"../chunk-35ZDT2VL.js";import"../chunk-2JRDG4LJ.js";import"../chunk-I2DZGJRR.js";import"../chunk-MVM6OGAF.js";import"../chunk-KKDHD4XA.js";import"../chunk-SZ62CP55.js";import"../chunk-3BVHPQZW.js";import"../chunk-SMGSLY5N.js";import"../chunk-PJ3WHQ67.js";import"../chunk-N7ODX6PO.js";import"../chunk-H2ORWIEY.js";import"../chunk-O6C2UGBY.js";import"../chunk-ZLLER3HP.js";export{c as ALL_STEP_IDS,a as CORE_STEP_IDS,b as OPTIONAL_STEP_IDS,g as STEPS,j as computeStatus,d as defaultContext,h as getStep,i as isStepId,e as maskToken,f as renderDiff};
|
package/oclif.manifest.json
CHANGED
|
@@ -348,7 +348,7 @@
|
|
|
348
348
|
"aliases": [],
|
|
349
349
|
"args": {
|
|
350
350
|
"target": {
|
|
351
|
-
"description": "\"plan\" or a step id (install, auth, hooks, worker)",
|
|
351
|
+
"description": "\"plan\" or a step id (install, auth, hooks, worker, judge)",
|
|
352
352
|
"name": "target",
|
|
353
353
|
"required": false
|
|
354
354
|
}
|
|
@@ -4317,5 +4317,5 @@
|
|
|
4317
4317
|
]
|
|
4318
4318
|
}
|
|
4319
4319
|
},
|
|
4320
|
-
"version": "0.7.
|
|
4320
|
+
"version": "0.7.23"
|
|
4321
4321
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rulemetric/cli",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.23",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -74,9 +74,9 @@
|
|
|
74
74
|
"postgres": "^3.4.0",
|
|
75
75
|
"react": "^19.0.0",
|
|
76
76
|
"zod": "^3.24.0",
|
|
77
|
-
"@rulemetric/hooks": "0.7.
|
|
78
|
-
"@rulemetric/
|
|
79
|
-
"@rulemetric/
|
|
77
|
+
"@rulemetric/hooks": "0.7.23",
|
|
78
|
+
"@rulemetric/proxy": "0.7.23",
|
|
79
|
+
"@rulemetric/skills-registry": "0.7.23"
|
|
80
80
|
},
|
|
81
81
|
"//deps": "Worker (`evals agent`) runtime deps: the @opentelemetry/* set, @sentry/node, and postgres are STATIC top-level imports loaded at worker startup (via bundled @rulemetric/{telemetry,db}) — they MUST be runtime deps or a clean `npm i -g` crashes with ModuleLoadError. `better-sqlite3` is optionalDependencies (below): it's a native module, lazy `require()`'d inside a try/catch (packages/session providers cursor/opencode) so a missing binary degrades gracefully — making it a hard dep would break `npm i -g` on platforms without prebuilt binaries. `resend` stays a devDep: lazy `await import('resend')` guarded by RESEND_API_KEY, which end-user workers never set (provider falls back to noop). Classification verified via import-graph scan of dist/commands/evals/agent.js + per-importer static/lazy check.",
|
|
82
82
|
"optionalDependencies": {
|
|
@@ -94,10 +94,10 @@
|
|
|
94
94
|
"tsx": "^4.19.0",
|
|
95
95
|
"typescript": "^5.9.0",
|
|
96
96
|
"vitest": "^3.2.0",
|
|
97
|
+
"@rulemetric/api": "0.0.1",
|
|
97
98
|
"@rulemetric/core": "0.0.1",
|
|
98
99
|
"@rulemetric/db": "0.0.1",
|
|
99
100
|
"@rulemetric/effectiveness": "0.0.1",
|
|
100
|
-
"@rulemetric/api": "0.0.1",
|
|
101
101
|
"@rulemetric/email": "0.0.1",
|
|
102
102
|
"@rulemetric/session": "0.2.1",
|
|
103
103
|
"@rulemetric/telemetry": "0.0.1",
|
package/dist/chunk-FS2Q2J7V.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{c as L}from"./chunk-TIOKY2IA.js";import{a as E}from"./chunk-MYPDODRJ.js";import{a as b}from"./chunk-O23Z6LTP.js";import{a as h}from"./chunk-PRDYXO6Z.js";import{b as I}from"./chunk-W2MOTOQE.js";import{a as R}from"./chunk-F53QW6VG.js";import{a as H}from"./chunk-EXUPWAVK.js";import{a as S}from"./chunk-RSKQRVPJ.js";import{a as A}from"./chunk-AW6LN6ZU.js";import{a as M}from"./chunk-DO3KHK2X.js";import{a as k}from"./chunk-UF6US7VU.js";import{a as v}from"./chunk-MSTF7A7D.js";import{b as y}from"./chunk-TSS6ESRK.js";import{a as T}from"./chunk-SD4SGJZY.js";import{b as w}from"./chunk-5RBLIVBF.js";import{b as f,e as _,f as p}from"./chunk-H2ORWIEY.js";import{a as s}from"./chunk-ZLLER3HP.js";var V={process_eval:b,process_insights:h,process_launch:I,process_send_message:S,process_conversation:E,process_session_goal:A,distill_memories:y,memory_ab:R,process_announcement:T,process_run_cleanup:H,cron_suggest_instructions:v,cron_refresh_skills:k,cron_refresh_pricing:M},N=Object.keys(V),O=new Set(["process_session_goal","process_announcement","process_run_cleanup","distill_memories","memory_ab"]);function W(e=process.env){return e.DATABASE_URL?N:N.filter(n=>!O.has(n))}s(W,"availableCapabilities");var $=3e4,B=3e4,F=3e4,P=250,D=5e3,J=`thin-agent-${process.pid}`,g=null;function U(e,n,r,l){let a=s(t=>{p("/api/workers/heartbeat",{workerType:"cli-worker",clientName:J,clientVersion:l,workerVersion:"0.1.0",currentJobId:null,inFlightCount:0,lastError:null,status:t,metadata:{capabilities:e,mode:"thin-agent"}}).then(c=>{let m=c?.advisory;m&&m.message!==g?(g=m.message,o(r,{event:"worker_advisory",code:m.code,message:m.message})):m||(g=null)}).catch(c=>{o(r,{event:"presence_heartbeat_error",error:c instanceof Error?c.message:String(c)})})},"send");a("alive");let d=setInterval(()=>a("alive"),F);n.addEventListener("abort",()=>{clearInterval(d),a("shutting_down")},{once:!0})}s(U,"startPresenceHeartbeat");function o(e,n){try{e(JSON.stringify({ts:new Date().toISOString(),...n}))}catch{e(`[agent-loop] log_error event=${n.event}`)}}s(o,"structuredLog");function C(e,n){return n.aborted?Promise.resolve(!1):e<=0?Promise.resolve(!0):new Promise(r=>{let l=setTimeout(()=>{n.removeEventListener("abort",a),r(!0)},e),a=s(()=>{clearTimeout(l),n.removeEventListener("abort",a),r(!1)},"onAbort");n.addEventListener("abort",a,{once:!0})})}s(C,"abortableSleep");async function K(e,n){let r=`capabilities=${encodeURIComponent(e.join(","))}&waitMs=${n}`,l=await _(`/api/work/next?${r}`);return l==null||typeof l=="string"?null:l}s(K,"pollForWork");function G(e,n){return{logger:{info:s(r=>n(r),"info"),warn:s(r=>n(r),"warn"),error:s(r=>n(r),"error")},job:{attempts:e}}}s(G,"makeHelpers");async function q(e,n,r){let l=V[e.kind],a=Date.now();if(o(r,{event:"claim",jobId:e.id,kind:e.kind,attempts:e.attempts}),!l){let t=`unknown kind: ${e.kind}`;o(r,{event:"fail",jobId:e.id,kind:e.kind,terminal:!0,error:t}),await p(`/api/work/${e.id}/fail`,{leaseToken:e.leaseToken,error:t,terminal:!0}).catch(()=>{});return}let d=setInterval(()=>{o(r,{event:"heartbeat",jobId:e.id}),p(`/api/work/${e.id}/heartbeat`,{leaseToken:e.leaseToken}).catch(t=>{o(r,{event:"heartbeat_error",jobId:e.id,error:t instanceof Error?t.message:String(t)})})},n);try{let t=G(e.attempts,r),c=await l(e.payload,t)??{};clearInterval(d),o(r,{event:"complete",jobId:e.id,kind:e.kind,durationMs:Date.now()-a}),await p(`/api/work/${e.id}/complete`,{leaseToken:e.leaseToken,result:c})}catch(t){clearInterval(d);let c=w(t),m=t instanceof Error?t.message:String(t);o(r,{event:"fail",jobId:e.id,kind:e.kind,durationMs:Date.now()-a,terminal:c,error:m}),await p(`/api/work/${e.id}/fail`,{leaseToken:e.leaseToken,error:m,terminal:c}).catch(i=>{o(r,{event:"fail_post_error",jobId:e.id,error:i instanceof Error?i.message:String(i)})})}}s(q,"runOne");async function me(e){let n=e.log??(()=>{}),r=e.pollWaitMs??$,l=e.heartbeatIntervalMs??B,a=e.capabilities??W(),d=P;o(n,{event:"agent_start",capabilities:a,pollWaitMs:r,heartbeatIntervalMs:l}),U(a,e.signal,n,e.version),L({signal:e.signal,log:n}).catch(i=>{o(n,{event:"tt_heartbeat_fatal",error:i instanceof Error?i.message:String(i)})});let t=5*6e4,c=0,m=s(()=>{if(!e.readInstalledVersion||!e.version)return!1;let i=Date.now();if(i-c<t)return!1;c=i;let u=e.readInstalledVersion();return!!(u&&u!==e.version)},"versionDrifted");for(;!e.signal.aborted;){if(m()){o(n,{event:"agent_version_drift",bootVersion:e.version,installedVersion:e.readInstalledVersion?.()??null}),e.onVersionDrift?.();break}let i=null;try{i=await K(a,r)}catch(u){let x=u instanceof f?u.statusCode:void 0;if(o(n,{event:"poll_error",status:x,error:u instanceof Error?u.message:String(u)}),!await C(d,e.signal))break;d=Math.min(d*2,D);continue}if(!i){if(o(n,{event:"poll_204"}),!await C(d,e.signal))break;d=Math.min(d*2,D);continue}d=P,await q(i,l,n)}o(n,{event:"agent_stop"})}s(me,"runAgentLoop");export{V as a,N as b,W as c,K as d,me as e};
|
package/dist/chunk-U6ABMRT3.js
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
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
|
-
`),r=e===null?[]:e.replace(/\n$/,"").split(`
|
|
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
|
-
`)}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(`
|
|
5
|
-
`);return{id:"auth",title:"Authenticate",command:"rulemetric auth login",artifacts:[{path:e,kind:"file",before:n,after:u,masked:!0},{path:a(t.configDir,"auth.json"),kind:"file",before:p(a(t.configDir,"auth.json"))?"(existing session tokens)":null,after:"{ accessToken, refreshToken, expiresAt, email } \u2014 OAuth session tokens (secret)",masked:!0}]}},async apply(){h("rulemetric auth login")}},{id:"hooks",title:"Install hooks + capture proxy",command:"rulemetric hooks install",async detect(t){for(let e of["settings.local.json","settings.json"]){let n=a(t.projectPath,".claude",e);if(p(n))try{let r=JSON.parse(S(n,"utf-8"));if(R(r))return!0}catch{}}return!1},async plan(t){let e=a(t.projectPath,".claude","settings.local.json"),{before:n,after:r}=M(t.projectPath),s=[{path:e,kind:"file",before:n,after:r},{path:"what these hooks capture",kind:"service",before:null,after:"session-end reimports the FULL transcript to the API; post-tool-use records each tool call and snapshots the working tree to a LOCAL shadow git ref (paper-trail, never pushed); user-prompt posts prompt text. All scoped to sessions in this project."},{path:`${e} (proxy env block)`,kind:"file",...O(t.projectPath)},{path:"system keychain \u2014 mitmproxy root CA",kind:"service",before:p(b)?"(CA generated; trust state unchanged)":"(no CA yet)",after:"Installs + trusts the mitmproxy CA (requires sudo). This lets the proxy DECRYPT Claude Code HTTPS request/response bodies \u2014 the capability that powers rendered-system-prompt / instruction linking. Decline the sudo prompt and setup stays hooks-only (still fully onboarded)."},{path:"launchctl setenv HTTPS_PROXY (machine-wide, all GUI apps)",kind:"command",before:null,after:`http://localhost:${f} \u2014 routes every GUI app's HTTPS through the local gateway (only when the CA is trusted AND :${f} is live)`},{path:"VS Code + Cursor user settings (http.proxy)",kind:"file",before:null,after:`http.proxy \u2192 http://localhost:${f} (+ http.proxyStrictSSL=false)`},{path:`gateway process on :${f}`,kind:"service",before:null,after:"started (routes Claude Code \u2192 mitmproxy \u2192 Anthropic; falls back to direct if mitmproxy is down)"}],c=D(t.projectPath);c&&s.push({path:`${a(t.projectPath,".claude","settings.json")} (removes RuleMetric machine-local state left by an older install \u2014 see the local-file artifacts above for where it moves)`,kind:"file",...c});for(let l of E(t.projectPath).filter(o=>o==="cursor"||o==="copilot_agent"))s.push({path:`${t.projectPath} (${l} workspace proxy config)`,kind:"file",before:null,after:`proxy \u2192 http://localhost:${f}`});for(let[l,o,u]of[["Cursor",a(d(),".cursor"),a(d(),".cursor","hooks.json")],["Antigravity/Gemini",a(d(),".gemini"),a(d(),".gemini","config","hooks.json")]])p(o)&&s.push({path:`${u} (${l} user hooks)`,kind:"file",before:p(u)?"(existing config)":null,after:"adds RuleMetric session-capture hooks for this tool"});return{id:"hooks",title:"Install hooks + capture proxy",command:"rulemetric hooks install",artifacts:s}},async apply(){h("rulemetric hooks install")}},{id:"worker",title:"Run the worker",command:"rulemetric service install --worker-only",async detect(){return C()},async plan(){let t=process.platform==="darwin",e=t?N:U,n=p(e)?`(service already installed at ${e})`:null,r=t?["Label: com.rulemetric.worker","ProgramArguments: <node> <cli>/bin/run.js evals agent","RunAtLoad: true, KeepAlive: true"].join(`
|
|
6
|
-
`):["[Service]","ExecStart=<node> <cli>/bin/run.js evals agent","Restart=on-failure"].join(`
|
|
7
|
-
`);return{id:"worker",title:"Run the worker",command:"rulemetric service install --worker-only",artifacts:[{path:e,kind:"service",before:n,after:r}]}},async apply(){h("rulemetric service install --worker-only")}}],Y=new Map(w.map(t=>[t.id,t]));function Q(t){let e=Y.get(t);if(!e)throw new Error(`Unknown setup step: ${t}`);return e}i(Q,"getStep");function tt(t){return j.includes(t)}i(tt,"isStepId");var H=new Set(["RULEMETRIC_API_URL","RULEMETRIC_USER_ID","RULEMETRIC_CLIENT_NAME","RESEND_FROM_EMAIL","SENTRY_DSN","PG_POOL_MAX","PG_IDLE_TIMEOUT","PG_STATEMENT_TIMEOUT_MS","NODE_ENV"]);function K(t){return t.replace(/\n$/,"").split(`
|
|
8
|
-
`).map(e=>{let n=e.match(/^([A-Z0-9_]+)=(.+)$/);if(!n)return e;let[,r,s]=n;return H.has(r)?e:`${r}=${g(s)}`}).join(`
|
|
9
|
-
`)}i(K,"maskEnvFile");async function et(t=$()){let e=[];for(let o of w){let u=await o.detect(t);e.push({id:o.id,done:u})}let n=e.find(o=>o.id==="install");n&&!n.done&&(n.done=e.some(o=>o.id!=="install"&&o.done));let r=new Set(I),s=e.filter(o=>r.has(o.id)),c=s.find(o=>!o.done)?.id??null,l=s.every(o=>o.done);return{steps:e,coreComplete:l,currentStepId:c}}i(et,"computeStatus");export{I as a,L as b,j as c,$ as d,g as e,z as f,w as g,Q as h,tt as i,et as j};
|