@rulemetric/cli 0.7.32 → 0.7.33
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-E3MQVVH6.js +24 -0
- package/dist/{chunk-DTMLVFNM.js → chunk-H4EVJK4P.js} +1 -1
- package/dist/commands/evals/agent.js +1 -1
- package/dist/lib/agent-loop.js +1 -1
- package/dist/lib/handlers/distill-memories.js +1 -1
- package/oclif.manifest.json +1 -1
- package/package.json +6 -6
- package/dist/chunk-Q76LGSIU.js +0 -24
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import{f as E}from"./chunk-MODFTCZY.js";import{b,e as y,f as k,h as M}from"./chunk-H2ORWIEY.js";import{a as u}from"./chunk-ZLLER3HP.js";var v=50,I=24e3,P=3,R=3,C=40,N=4e3,x=new Set(["fact","decision","correction","convention"]),L=`You are distilling DURABLE, PROJECT-SPECIFIC knowledge from an AI coding session so a future agent working on the SAME project starts smarter.
|
|
2
|
+
|
|
3
|
+
Extract ONLY facts / decisions / corrections / conventions that will STILL be true and useful in FUTURE sessions \u2014 architecture facts, deliberate design decisions, corrections of a wrong approach, or project conventions.
|
|
4
|
+
|
|
5
|
+
Do NOT extract:
|
|
6
|
+
- what the user asked for in THIS session, or the step-by-step actions taken
|
|
7
|
+
- anything specific to this one task that will not recur
|
|
8
|
+
- anything already covered by the existing memories listed below
|
|
9
|
+
|
|
10
|
+
Existing memories for this project (do NOT duplicate these):
|
|
11
|
+
{{EXISTING}}
|
|
12
|
+
|
|
13
|
+
Prefer FEWER, higher-quality memories \u2014 most sessions yield 0-2, many yield 0. A weak or redundant memory is worse than none.
|
|
14
|
+
|
|
15
|
+
Each memory has: "kind" (one of: fact, decision, correction, convention), a short "title" (<= 120 chars), and a 1-3 sentence "body".
|
|
16
|
+
|
|
17
|
+
Return STRICT JSON: {"memories": [{"kind": "...", "title": "...", "body": "..."}]} \u2014 use an empty array if nothing durable was learned.`;function A(t){return t.toLowerCase().replace(/[^a-z0-9]+/g," ").trim()}u(A,"normalizeTitle");function O(t,n,f=R){let l=Array.isArray(t?.memories)?t.memories:[],g=new Set(n.map(A)),d=[];for(let m of l){if(d.length>=f)break;if(!m||typeof m!="object")continue;let o=m,r=typeof o.kind=="string"?o.kind.trim().toLowerCase():"",s=typeof o.title=="string"?o.title.trim():"",p=typeof o.body=="string"?o.body.trim():"";if(!x.has(r)||!s||!p||s.length>300||p.length>N)continue;let a=A(s);!a||g.has(a)||(g.add(a),d.push({kind:r,title:s,body:p}))}return d}u(O,"selectNewMemories");async function $(t,n){await M(`/api/sessions/${t}/enrich`,{analysis:{distilledAt:n}})}u($,"stampDistilledViaApi");async function F(t,n={}){let f=n.llm??E,l=n.now??Date.now,g=n.getSession??(async e=>{try{return await y(`/api/sessions/${e}`)}catch(i){if(i instanceof b&&i.statusCode===404)return null;throw i}}),d=n.getTurns??((e,i)=>y(`/api/sessions/${e}/events?limit=${i}&sort=desc&eventType=user_message,assistant_response&hasContent=true`)),m=n.getExistingTitles??(async(e,i)=>{let{memories:_}=await y(`/api/memories?projectId=${e}&status=active&limit=${i}`);return(_??[]).map(j=>j.title)}),o=n.createMemory??(async e=>{await k("/api/memories",{kind:e.kind,title:e.title,body:e.body,projectId:e.projectId,source:"distilled"})}),r=n.stamp??$,s=await g(t.sessionId);if(!s)return{skipped:"not_found"};if((s.analysis??{}).distilledAt)return{skipped:"already_distilled"};if(!s.projectId)return await r(t.sessionId,new Date(l()).toISOString()),{skipped:"no_project"};let a=s.projectId,S=(await d(t.sessionId,v)).reverse().map(e=>`${e.eventType==="user_message"?"USER":"ASSISTANT"}: ${e.content}`);if(S.length<P)return await r(t.sessionId,new Date(l()).toISOString()),{skipped:"too_short"};let c=S.join(`
|
|
18
|
+
|
|
19
|
+
`);if(c.length>I){let e=c.slice(0,Math.floor(I*.45)),i=c.slice(c.length-Math.floor(I*.45));c=`${e}
|
|
20
|
+
|
|
21
|
+
[... middle of session omitted ...]
|
|
22
|
+
|
|
23
|
+
${i}`}let h=await m(a,C),D=L.replace("{{EXISTING}}",h.length?h.map(e=>`- ${e}`).join(`
|
|
24
|
+
`):"(none yet)"),T=await f(D,c,700);if(T===null)throw new Error("distill_memories: LLM backend unavailable or returned unparseable output");let w=O(T,h);for(let e of w)await o({...e,projectId:a});return await r(t.sessionId,new Date(l()).toISOString()),{created:w.length,candidates:w.length}}u(F,"distillMemories");export{O as a,F as b};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{c as C}from"./chunk-TIOKY2IA.js";import{b as I}from"./chunk-W2MOTOQE.js";import{a as R}from"./chunk-3FJT6LL4.js";import{a as T}from"./chunk-DAGDGAPU.js";import{a as A}from"./chunk-RSKQRVPJ.js";import{a as y}from"./chunk-JEBHSV2M.js";import{a as _}from"./chunk-L5ORQB25.js";import{b as H}from"./chunk-
|
|
1
|
+
import{c as C}from"./chunk-TIOKY2IA.js";import{b as I}from"./chunk-W2MOTOQE.js";import{a as R}from"./chunk-3FJT6LL4.js";import{a as T}from"./chunk-DAGDGAPU.js";import{a as A}from"./chunk-RSKQRVPJ.js";import{a as y}from"./chunk-JEBHSV2M.js";import{a as _}from"./chunk-L5ORQB25.js";import{b as H}from"./chunk-E3MQVVH6.js";import{a as M}from"./chunk-WEF5LPGS.js";import{a as S}from"./chunk-ZAWAPLIE.js";import{a as h}from"./chunk-AIEM6VXO.js";import{a as E}from"./chunk-BZUIMHHT.js";import{b}from"./chunk-5RBLIVBF.js";import{a as L}from"./chunk-LEXVC7VH.js";import{a as N}from"./chunk-5W55CRBJ.js";import{d as P}from"./chunk-JR4CWY3J.js";import{a as x}from"./chunk-UR6GZGFK.js";import{a as k}from"./chunk-UF6US7VU.js";import{d as w}from"./chunk-OPUI7CM2.js";import{b as f,e as v,f as p}from"./chunk-H2ORWIEY.js";import{a as s}from"./chunk-ZLLER3HP.js";var W={process_eval:h,process_insights:E,process_launch:I,process_send_message:A,process_conversation:S,process_session_goal:y,distill_memories:H,memory_ab:R,process_announcement:M,process_run_cleanup:T,cron_suggest_instructions:_,cron_refresh_skills:k,cron_refresh_pricing:x,cron_eval_autorun:N,cron_instruction_evolution:P,process_judge_review:L},D=Object.keys(W),F=new Set(["process_announcement","process_run_cleanup","memory_ab"]);function J(e=process.env){return e.DATABASE_URL?D:D.filter(n=>!F.has(n))}s(J,"availableCapabilities");var U=3e4,K=3e4,G=3e4,V=250,B=5e3,q=`thin-agent-${process.pid}`,g=null;function Q(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:q,clientVersion:l,workerVersion:"0.1.0",currentJobId:null,inFlightCount:0,lastError:null,status:d,metadata:{capabilities:e,mode:"thin-agent",llmEngines:c}}).then(u=>{let t=u?.advisory;t&&t.message!==g?(g=t.message,a(r,{event:"worker_advisory",code:t.code,message:t.message})):t||(g=null)}).catch(u=>{a(r,{event:"presence_heartbeat_error",error:u instanceof Error?u.message:String(u)})})},"send");i("alive");let o=setInterval(()=>i("alive"),G);n.addEventListener("abort",()=>{clearInterval(o),i("shutting_down")},{once:!0})}s(Q,"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 O(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(O,"abortableSleep");async function X(e,n){let r=`capabilities=${encodeURIComponent(e.join(","))}&waitMs=${n}`,l=await v(`/api/work/next?${r}`);return l==null||typeof l=="string"?null:l}s(X,"pollForWork");function z(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(z,"makeHelpers");async function Y(e,n,r){let l=W[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=z(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),u=o instanceof Error?o.message:String(o);a(r,{event:"fail",jobId:e.id,kind:e.kind,durationMs:Date.now()-c,terminal:d,error:u}),await p(`/api/work/${e.id}/fail`,{leaseToken:e.leaseToken,error:u,terminal:d}).catch(t=>{a(r,{event:"fail_post_error",jobId:e.id,error:t instanceof Error?t.message:String(t)})})}}s(Y,"runOne");async function we(e){let n=e.log??(()=>{}),r=e.pollWaitMs??U,l=e.heartbeatIntervalMs??K,c=e.capabilities??J(),i=V;a(n,{event:"agent_start",capabilities:c,pollWaitMs:r,heartbeatIntervalMs:l}),Q(c,e.signal,n,e.version),C({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,u=s(()=>{if(!e.readInstalledVersion||!e.version)return!1;let t=Date.now();if(t-d<o)return!1;d=t;let m=e.readInstalledVersion();return!!(m&&m!==e.version)},"versionDrifted");for(;!e.signal.aborted;){if(u()){a(n,{event:"agent_version_drift",bootVersion:e.version,installedVersion:e.readInstalledVersion?.()??null}),e.onVersionDrift?.();break}let t=null;try{t=await X(c,r)}catch(m){let $=m instanceof f?m.statusCode:void 0;if(a(n,{event:"poll_error",status:$,error:m instanceof Error?m.message:String(m)}),!await O(i,e.signal))break;i=Math.min(i*2,B);continue}if(!t){if(a(n,{event:"poll_204"}),!await O(i,e.signal))break;i=Math.min(i*2,B);continue}i=V,await Y(t,l,n)}a(n,{event:"agent_stop"})}s(we,"runAgentLoop");export{W as a,D as b,J as c,X as d,we as e};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{a as k,b as A,c as I}from"../../chunk-47HDPK73.js";import{e as O}from"../../chunk-
|
|
1
|
+
import{a as k,b as A,c as I}from"../../chunk-47HDPK73.js";import{e as O}from"../../chunk-H4EVJK4P.js";import"../../chunk-TIOKY2IA.js";import"../../chunk-W2MOTOQE.js";import"../../chunk-3FJT6LL4.js";import"../../chunk-DAGDGAPU.js";import"../../chunk-6QKI756T.js";import"../../chunk-RSKQRVPJ.js";import"../../chunk-JEBHSV2M.js";import"../../chunk-L5ORQB25.js";import"../../chunk-E3MQVVH6.js";import"../../chunk-WEF5LPGS.js";import"../../chunk-N7TGRFVZ.js";import{j as u}from"../../chunk-3DLVY7LD.js";import"../../chunk-ZAWAPLIE.js";import"../../chunk-AIEM6VXO.js";import"../../chunk-BZUIMHHT.js";import"../../chunk-QFVGUZDO.js";import"../../chunk-ZL4MZMUK.js";import"../../chunk-5RBLIVBF.js";import"../../chunk-LEXVC7VH.js";import"../../chunk-5W55CRBJ.js";import"../../chunk-JR4CWY3J.js";import"../../chunk-ZERPMWRT.js";import"../../chunk-UR6GZGFK.js";import"../../chunk-UF6US7VU.js";import"../../chunk-YQ56FQEO.js";import"../../chunk-JGYCLDYF.js";import"../../chunk-ZWKKFAIX.js";import"../../chunk-TDD7IOV2.js";import"../../chunk-MODXEGCU.js";import"../../chunk-7DFNBRLY.js";import"../../chunk-4VZLIGMS.js";import"../../chunk-3VYV6ZYB.js";import"../../chunk-OZQV5CDT.js";import"../../chunk-6UEFCMR2.js";import"../../chunk-CJRYYV76.js";import"../../chunk-BSJBNOJT.js";import"../../chunk-L2CFSMBC.js";import"../../chunk-Z72VHGV7.js";import"../../chunk-7AZKPX2J.js";import"../../chunk-CDY7TQFZ.js";import"../../chunk-V5MJ4ICC.js";import"../../chunk-WKXTY5AM.js";import"../../chunk-HMMO27U4.js";import"../../chunk-OPUI7CM2.js";import"../../chunk-MODFTCZY.js";import"../../chunk-PJ3WHQ67.js";import"../../chunk-N7ODX6PO.js";import{a as b}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{e as P,l as g}from"../../chunk-O6C2UGBY.js";import{a as e}from"../../chunk-ZLLER3HP.js";import{trace as te,context as re}from"@opentelemetry/api";import{NodeSDK as M}from"@opentelemetry/sdk-node";import{OTLPTraceExporter as V}from"@opentelemetry/exporter-trace-otlp-http";import{BatchSpanProcessor as $,ConsoleSpanExporter as j,SimpleSpanProcessor as q}from"@opentelemetry/sdk-trace-node";import{Resource as F}from"@opentelemetry/resources";import{ATTR_SERVICE_NAME as G,ATTR_SERVICE_VERSION as U}from"@opentelemetry/semantic-conventions";function L(t){if(!t)return{};let r={};for(let n of t.split(",")){let o=n.indexOf("=");if(o===-1)continue;let i=n.slice(0,o).trim(),a=n.slice(o+1).trim();i&&(r[i]=a)}return r}e(L,"parseOtlpHeaders");var l=null;function y(){return process.env.TELEMETRY_ENABLED!=="false"}e(y,"isTelemetryEnabled");function h(t){if(!y()||l!==null)return"off";let r=new F({[G]:t.serviceName,[U]:t.serviceVersion??"0.1.0"}),n=process.env.OTEL_EXPORTER_OTLP_ENDPOINT,o,i;if(n){let a=L(process.env.OTEL_EXPORTER_OTLP_HEADERS),d=new V({url:`${n}/v1/traces`,headers:a});i=new $(d),o="otlp"}else if(process.env.OTEL_SPAN_EXPORT==="none")i=void 0,o="silent";else{let a=new j;i=new q(a),o="console"}return l=new M({resource:r,spanProcessors:i?[i]:[]}),l.start(),o}e(h,"initTelemetry");async function f(){l&&(await l.shutdown(),l=null)}e(f,"shutdownTelemetry");import{SpanKind as fe,SpanStatusCode as me}from"@opentelemetry/api";import{trace as Ee,context as Se}from"@opentelemetry/api";import*as p from"@sentry/node";var E=!1;function S(t){if(E)return!1;let r=process.env.SENTRY_DSN;return r?(p.init({dsn:r,serverName:t.serviceName,environment:process.env.NODE_ENV??"development",tracesSampleRate:0}),E=!0,!0):!1}e(S,"initSentry");async function m(t){E&&await p.flush(t)}e(m,"flushSentry");import{existsSync as B,mkdirSync as H,readFileSync as w,unlinkSync as D,writeFileSync as C}from"node:fs";import{dirname as K,join as v}from"node:path";import{execFileSync as Y}from"node:child_process";var c=v(g(),"evals-agent.lock");function J(t){try{return process.kill(t,0),!0}catch(r){return r.code==="EPERM"}}e(J,"pidAlive");function z(t){if(!J(t))return!1;try{let r=Y("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(z,"isLiveAgent");function Q(){try{H(K(c),{recursive:!0})}catch{}for(let t=0;t<2;t++)try{return C(c,String(process.pid),{flag:"wx"}),{ok:!0}}catch(r){if(r.code!=="EEXIST")throw r;let n=0;try{n=Number(w(c,"utf-8").trim())}catch{}if(n&&n!==process.pid&&z(n))return{ok:!1,holder:n};try{D(c)}catch{}}try{C(c,String(process.pid))}catch{}return{ok:!0}}e(Q,"acquireAgentLock");function T(){try{B(c)&&Number(w(c,"utf-8").trim())===process.pid&&D(c)}catch{}}e(T,"releaseAgentLock");var x=class t extends b{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=Q();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",S({serviceName:"rulemetric-agent"})&&this.log("[sentry] error capture enabled");let o=h({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)"),!P()&&!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 a=new AbortController,d=new k({providers:[A()],statePath:v(g(),"transcript-sync-state.json"),importTranscript:e(s=>N("/api/sessions/import",s),"importTranscript"),log:e(s=>this.log(`[transcript-sync] ${s}`),"log")});I(d,{signal:a.signal,log:e(s=>this.log(`[transcript-sync] ${s}`),"log")});let R=e(async s=>{this.log(`
|
|
3
3
|
[${s}] shutting down agent...`),a.abort(),await Promise.allSettled([m(2e3),f(),u()]),T(),process.exit(0)},"shutdown");process.on("SIGINT",()=>{R("SIGINT")}),process.on("SIGTERM",()=>{R("SIGTERM")});let _=!1;try{await O({signal:a.signal,log:e(s=>this.log(s),"log"),version:this.config.version,readInstalledVersion:e(()=>{try{return JSON.parse(w(v(this.config.root,"package.json"),"utf-8")).version??null}catch{return null}},"readInstalledVersion"),onVersionDrift:e(()=>{_=!0},"onVersionDrift")}),_&&(this.log("[upgrade] Installed CLI version changed \u2014 restarting worker onto the new code."),await Promise.allSettled([m(2e3),f(),u()]),T(),process.exit(1))}finally{T(),await u()}}};export{x 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-H4EVJK4P.js";import"../chunk-TIOKY2IA.js";import"../chunk-W2MOTOQE.js";import"../chunk-3FJT6LL4.js";import"../chunk-DAGDGAPU.js";import"../chunk-6QKI756T.js";import"../chunk-RSKQRVPJ.js";import"../chunk-JEBHSV2M.js";import"../chunk-L5ORQB25.js";import"../chunk-E3MQVVH6.js";import"../chunk-WEF5LPGS.js";import"../chunk-N7TGRFVZ.js";import"../chunk-3DLVY7LD.js";import"../chunk-ZAWAPLIE.js";import"../chunk-AIEM6VXO.js";import"../chunk-BZUIMHHT.js";import"../chunk-QFVGUZDO.js";import"../chunk-ZL4MZMUK.js";import"../chunk-5RBLIVBF.js";import"../chunk-LEXVC7VH.js";import"../chunk-5W55CRBJ.js";import"../chunk-JR4CWY3J.js";import"../chunk-ZERPMWRT.js";import"../chunk-UR6GZGFK.js";import"../chunk-UF6US7VU.js";import"../chunk-YQ56FQEO.js";import"../chunk-JGYCLDYF.js";import"../chunk-ZWKKFAIX.js";import"../chunk-TDD7IOV2.js";import"../chunk-MODXEGCU.js";import"../chunk-7DFNBRLY.js";import"../chunk-4VZLIGMS.js";import"../chunk-3VYV6ZYB.js";import"../chunk-OZQV5CDT.js";import"../chunk-6UEFCMR2.js";import"../chunk-CJRYYV76.js";import"../chunk-BSJBNOJT.js";import"../chunk-L2CFSMBC.js";import"../chunk-Z72VHGV7.js";import"../chunk-7AZKPX2J.js";import"../chunk-CDY7TQFZ.js";import"../chunk-V5MJ4ICC.js";import"../chunk-WKXTY5AM.js";import"../chunk-HMMO27U4.js";import"../chunk-OPUI7CM2.js";import"../chunk-MODFTCZY.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};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a,b}from"../../chunk-
|
|
1
|
+
import{a,b}from"../../chunk-E3MQVVH6.js";import"../../chunk-MODFTCZY.js";import"../../chunk-PJ3WHQ67.js";import"../../chunk-N7ODX6PO.js";import"../../chunk-H2ORWIEY.js";import"../../chunk-O6C2UGBY.js";import"../../chunk-ZLLER3HP.js";export{b as distillMemories,a as selectNewMemories};
|
package/oclif.manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rulemetric/cli",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.33",
|
|
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/proxy": "0.7.
|
|
79
|
-
"@rulemetric/skills-registry": "0.7.
|
|
77
|
+
"@rulemetric/hooks": "0.7.33",
|
|
78
|
+
"@rulemetric/proxy": "0.7.33",
|
|
79
|
+
"@rulemetric/skills-registry": "0.7.33"
|
|
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": {
|
|
@@ -97,11 +97,11 @@
|
|
|
97
97
|
"@rulemetric/api": "0.0.1",
|
|
98
98
|
"@rulemetric/core": "0.0.1",
|
|
99
99
|
"@rulemetric/db": "0.0.1",
|
|
100
|
-
"@rulemetric/effectiveness": "0.0.1",
|
|
101
100
|
"@rulemetric/email": "0.0.1",
|
|
102
101
|
"@rulemetric/session": "0.2.1",
|
|
102
|
+
"@rulemetric/telemetry": "0.0.1",
|
|
103
103
|
"@rulemetric/typescript-config": "0.0.0",
|
|
104
|
-
"@rulemetric/
|
|
104
|
+
"@rulemetric/effectiveness": "0.0.1"
|
|
105
105
|
},
|
|
106
106
|
"scripts": {
|
|
107
107
|
"build": "node scripts/build.mjs",
|
package/dist/chunk-Q76LGSIU.js
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import{f as E}from"./chunk-MODFTCZY.js";import{b,e as y,f as k,h as M}from"./chunk-H2ORWIEY.js";import{a as u}from"./chunk-ZLLER3HP.js";var j=50,I=24e3,v=3,P=3,R=40,C=4e3,N=new Set(["fact","decision","correction","convention"]),x=`You are distilling DURABLE, PROJECT-SPECIFIC knowledge from an AI coding session so a future agent working on the SAME project starts smarter.
|
|
2
|
-
|
|
3
|
-
Extract ONLY facts / decisions / corrections / conventions that will STILL be true and useful in FUTURE sessions \u2014 architecture facts, deliberate design decisions, corrections of a wrong approach, or project conventions.
|
|
4
|
-
|
|
5
|
-
Do NOT extract:
|
|
6
|
-
- what the user asked for in THIS session, or the step-by-step actions taken
|
|
7
|
-
- anything specific to this one task that will not recur
|
|
8
|
-
- anything already covered by the existing memories listed below
|
|
9
|
-
|
|
10
|
-
Existing memories for this project (do NOT duplicate these):
|
|
11
|
-
{{EXISTING}}
|
|
12
|
-
|
|
13
|
-
Prefer FEWER, higher-quality memories \u2014 most sessions yield 0-2, many yield 0. A weak or redundant memory is worse than none.
|
|
14
|
-
|
|
15
|
-
Each memory has: "kind" (one of: fact, decision, correction, convention), a short "title" (<= 120 chars), and a 1-3 sentence "body".
|
|
16
|
-
|
|
17
|
-
Return STRICT JSON: {"memories": [{"kind": "...", "title": "...", "body": "..."}]} \u2014 use an empty array if nothing durable was learned.`;function A(e){return e.toLowerCase().replace(/[^a-z0-9]+/g," ").trim()}u(A,"normalizeTitle");function L(e,n,f=P){let l=Array.isArray(e?.memories)?e.memories:[],g=new Set(n.map(A)),d=[];for(let m of l){if(d.length>=f)break;if(!m||typeof m!="object")continue;let o=m,r=typeof o.kind=="string"?o.kind.trim().toLowerCase():"",s=typeof o.title=="string"?o.title.trim():"",p=typeof o.body=="string"?o.body.trim():"";if(!N.has(r)||!s||!p||s.length>300||p.length>C)continue;let a=A(s);!a||g.has(a)||(g.add(a),d.push({kind:r,title:s,body:p}))}return d}u(L,"selectNewMemories");async function O(e,n){await M(`/api/sessions/${e}/enrich`,{analysis:{distilledAt:n}})}u(O,"stampDistilledViaApi");async function F(e,n={}){let f=n.llm??E,l=n.now??Date.now,g=n.getSession??(async t=>{try{return await y(`/api/sessions/${t}`)}catch(i){if(i instanceof b&&i.statusCode===404)return null;throw i}}),d=n.getTurns??((t,i)=>y(`/api/sessions/${t}/events?limit=${i}&sort=desc&eventType=user_message,assistant_response&hasContent=true`)),m=n.getExistingTitles??(async(t,i)=>(await y(`/api/memories?projectId=${t}&status=active&limit=${i}`)).map(_=>_.title)),o=n.createMemory??(async t=>{await k("/api/memories",{kind:t.kind,title:t.title,body:t.body,projectId:t.projectId,source:"distilled"})}),r=n.stamp??O,s=await g(e.sessionId);if(!s)return{skipped:"not_found"};if((s.analysis??{}).distilledAt)return{skipped:"already_distilled"};if(!s.projectId)return await r(e.sessionId,new Date(l()).toISOString()),{skipped:"no_project"};let a=s.projectId,S=(await d(e.sessionId,j)).reverse().map(t=>`${t.eventType==="user_message"?"USER":"ASSISTANT"}: ${t.content}`);if(S.length<v)return await r(e.sessionId,new Date(l()).toISOString()),{skipped:"too_short"};let c=S.join(`
|
|
18
|
-
|
|
19
|
-
`);if(c.length>I){let t=c.slice(0,Math.floor(I*.45)),i=c.slice(c.length-Math.floor(I*.45));c=`${t}
|
|
20
|
-
|
|
21
|
-
[... middle of session omitted ...]
|
|
22
|
-
|
|
23
|
-
${i}`}let h=await m(a,R),D=x.replace("{{EXISTING}}",h.length?h.map(t=>`- ${t}`).join(`
|
|
24
|
-
`):"(none yet)"),T=await f(D,c,700);if(T===null)throw new Error("distill_memories: LLM backend unavailable or returned unparseable output");let w=L(T,h);for(let t of w)await o({...t,projectId:a});return await r(e.sessionId,new Date(l()).toISOString()),{created:w.length,candidates:w.length}}u(F,"distillMemories");export{L as a,F as b};
|