@rulemetric/cli 0.7.26 → 0.7.27
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.
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{a as o}from"./chunk-ZLLER3HP.js";import{createHash as T}from"node:crypto";import{mkdir as w,open as M,readFile as h,readdir as b,rename as x,stat as P,writeFile as C}from"node:fs/promises";import{homedir as _}from"node:os";import{basename as A,dirname as z,join as l}from"node:path";var F=3e4,$=5,E=8*1024*1024;function f(i){return T("sha256").update(`${i.externalSessionId}:${Math.round(i.mtimeMs)}:${i.size}`).digest("hex")}o(f,"fingerprint");async function I(i){try{return{fingerprints:JSON.parse(await h(i,"utf8")).fingerprints??{}}}catch{return{fingerprints:{}}}}o(I,"readState");async function O(i,e){let s=`${i}.${process.pid}.tmp`;await w(z(i),{recursive:!0}),await C(s,JSON.stringify(e)),await x(s,i)}o(O,"persistState");var g=class{constructor(e){this.options=e}static{o(this,"TranscriptSync")}lastSeenSize=new Map;lastSyncAt=new Map;inFlight=!1;async scan(){if(this.inFlight)return{discovered:0,imported:0,skipped:0};this.inFlight=!0;try{let e=await I(this.options.statePath),s=(await Promise.all(this.options.providers.map(t=>t.discover()))).flat().sort((t,c)=>c.mtimeMs-t.mtimeMs),r=Date.now(),n=[],a=0;for(let t of s){let c=f(t),d=this.lastSeenSize.get(t.path);if(this.lastSeenSize.set(t.path,t.size),e.fingerprints[t.path]===c){a++;continue}let m=this.options.minStableAgeMs??3e3;if(m>0&&r-t.mtimeMs<m){a++;continue}let S=d!==void 0&&d===t.size,u=this.lastSyncAt.get(t.path),v=u===void 0||r-u>=(this.options.activeResyncMs??F);if(!S&&!v){a++;continue}if(n.push(t),n.length>=(this.options.maxImportsPerScan??$))break}let p=0;for(let t of n){let c=f(t);if(t.size>(this.options.maxContentBytes??E)){e.fingerprints[t.path]=c,a++,this.options.log?.(`Transcript sync skipped oversized file: ${t.path}`);continue}let d=await h(t.path,"utf8");await this.options.importTranscript({content:d,tool:t.tool}),e.fingerprints[t.path]=c,this.lastSyncAt.set(t.path,Date.now()),p++,this.options.log?.(`Transcript sync imported ${t.tool} ${A(t.path)} (${t.externalSessionId}).`)}return n.length>0&&await O(this.options.statePath,e),{discovered:s.length,imported:p,skipped:a}}finally{this.inFlight=!1}}};async function k(i){let e;try{e=await M(i,"r");let s=Buffer.alloc(64*1024),{bytesRead:r}=await e.read(s,0,s.length,0),n=s.subarray(0,r).toString("utf8").split(`
|
|
2
|
+
`)[0];return n?JSON.parse(n):null}catch{return null}finally{await e?.close()}}o(k,"readFirstJsonLine");async function y(i,e,s){let r=await b(i,{withFileTypes:!0}).catch(()=>[]);for(let n of r){let a=l(i,n.name);if(n.isDirectory()){await y(a,e,s);continue}if(!n.isFile()||!n.name.startsWith("rollout-")||!n.name.endsWith(".jsonl"))continue;let[p,t]=await Promise.all([P(a).catch(()=>null),k(a)]);if(!p||p.mtimeMs<s||t?.type!=="session_meta")continue;let c=t.payload?.originator,d=t.payload?.id??t.payload?.session_id;!c?.toLowerCase().startsWith("codex")||!d||e.push({path:a,tool:"codex",externalSessionId:d,projectPath:t.payload?.cwd??null,mtimeMs:p.mtimeMs,size:p.size})}}o(y,"walkCodexSessions");function j(i=process.env.CODEX_HOME??l(_(),".codex"),e=14){return{name:"codex",async discover(){let s=[],r=Date.now()-Math.max(1,e)*24*60*60*1e3;return await y(l(i,"sessions"),s,r),s}}}o(j,"createCodexTranscriptProvider");function B(i,e){let s=o(async()=>{try{let n=await i.scan();n.imported>0&&e.log?.(`Transcript sync imported/updated ${n.imported} session${n.imported===1?"":"s"}.`)}catch(n){e.log?.(`Transcript sync failed: ${n instanceof Error?n.message:String(n)}`)}},"run"),r=setInterval(()=>void s(),e.intervalMs??3e4);e.signal.addEventListener("abort",()=>clearInterval(r),{once:!0}),s()}o(B,"startTranscriptSync");export{g as a,j as b,B as c};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{e as
|
|
2
|
-
`);let
|
|
3
|
-
[${
|
|
1
|
+
import{a as k,b as A,c as I}from"../../chunk-47HDPK73.js";import{e as O}from"../../chunk-QYKLIRMY.js";import"../../chunk-TIOKY2IA.js";import"../../chunk-35ST2BX7.js";import"../../chunk-MYPDODRJ.js";import"../../chunk-O23Z6LTP.js";import"../../chunk-PRDYXO6Z.js";import"../../chunk-QFVGUZDO.js";import"../../chunk-KG3TW5QB.js";import"../../chunk-W2MOTOQE.js";import"../../chunk-WNAYTVCO.js";import"../../chunk-ARZJNTMV.js";import"../../chunk-6QKI756T.js";import"../../chunk-RSKQRVPJ.js";import"../../chunk-DO3KHK2X.js";import"../../chunk-UF6US7VU.js";import"../../chunk-MSTF7A7D.js";import"../../chunk-4HZWSFSY.js";import"../../chunk-LVOLDUFC.js";import"../../chunk-5RBLIVBF.js";import"../../chunk-ZL4MZMUK.js";import"../../chunk-N7TGRFVZ.js";import{k as u}from"../../chunk-KZ65LEUH.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-BSXUH5FD.js";import"../../chunk-6UEFCMR2.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 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
|
+
`);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
|
+
[${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};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{a,b,c}from"../chunk-47HDPK73.js";import"../chunk-ZLLER3HP.js";export{a as TranscriptSync,b as createCodexTranscriptProvider,c as startTranscriptSync};
|
package/oclif.manifest.json
CHANGED
|
@@ -405,6 +405,88 @@
|
|
|
405
405
|
"setup.js"
|
|
406
406
|
]
|
|
407
407
|
},
|
|
408
|
+
"antigravity:backfill": {
|
|
409
|
+
"aliases": [],
|
|
410
|
+
"args": {
|
|
411
|
+
"conversationId": {
|
|
412
|
+
"description": "Antigravity conversationId (UUID) — the directory name under ~/.gemini/antigravity-ide/brain/",
|
|
413
|
+
"name": "conversationId",
|
|
414
|
+
"required": true
|
|
415
|
+
}
|
|
416
|
+
},
|
|
417
|
+
"description": "Backfill historical events from an Antigravity conversation transcript into a RuleMetric session. Useful for seeding a conversation that existed before hooks were installed — the live hook intentionally only captures forward.",
|
|
418
|
+
"examples": [
|
|
419
|
+
"<%= config.bin %> antigravity backfill 26fd215d-f43b-4ea5-b177-dc2c0e696f97 --session 158db9aa-68ee-43fc-961b-f3a180578694",
|
|
420
|
+
"<%= config.bin %> antigravity backfill 26fd215d-f43b-4ea5-b177-dc2c0e696f97 --dry-run"
|
|
421
|
+
],
|
|
422
|
+
"flags": {
|
|
423
|
+
"api-url": {
|
|
424
|
+
"description": "Override API base URL",
|
|
425
|
+
"env": "RULEMETRIC_API_URL",
|
|
426
|
+
"hidden": true,
|
|
427
|
+
"name": "api-url",
|
|
428
|
+
"hasDynamicHelp": false,
|
|
429
|
+
"multiple": false,
|
|
430
|
+
"type": "option"
|
|
431
|
+
},
|
|
432
|
+
"session": {
|
|
433
|
+
"char": "s",
|
|
434
|
+
"description": "RuleMetric session UUID to POST events into. If omitted, resolved from the hook tmp file ($TMPDIR/rulemetric/<conversationId>) — fails if neither is present.",
|
|
435
|
+
"name": "session",
|
|
436
|
+
"hasDynamicHelp": false,
|
|
437
|
+
"multiple": false,
|
|
438
|
+
"type": "option"
|
|
439
|
+
},
|
|
440
|
+
"transcript": {
|
|
441
|
+
"description": "Path to the transcript.jsonl file. Defaults to ~/.gemini/antigravity-ide/brain/<conversationId>/.system_generated/logs/transcript.jsonl",
|
|
442
|
+
"name": "transcript",
|
|
443
|
+
"hasDynamicHelp": false,
|
|
444
|
+
"multiple": false,
|
|
445
|
+
"type": "option"
|
|
446
|
+
},
|
|
447
|
+
"after-step": {
|
|
448
|
+
"description": "Only emit records with step_index > this value. Default: read from existing state file, else -1 (everything).",
|
|
449
|
+
"name": "after-step",
|
|
450
|
+
"hasDynamicHelp": false,
|
|
451
|
+
"multiple": false,
|
|
452
|
+
"type": "option"
|
|
453
|
+
},
|
|
454
|
+
"limit": {
|
|
455
|
+
"description": "Cap on the number of records to process this run.",
|
|
456
|
+
"name": "limit",
|
|
457
|
+
"hasDynamicHelp": false,
|
|
458
|
+
"multiple": false,
|
|
459
|
+
"type": "option"
|
|
460
|
+
},
|
|
461
|
+
"dry-run": {
|
|
462
|
+
"description": "Classify records without POSTing. Reports counts only.",
|
|
463
|
+
"name": "dry-run",
|
|
464
|
+
"allowNo": false,
|
|
465
|
+
"type": "boolean"
|
|
466
|
+
},
|
|
467
|
+
"save-state": {
|
|
468
|
+
"description": "After backfill, persist the highest step_index so the live hook resumes from there.",
|
|
469
|
+
"name": "save-state",
|
|
470
|
+
"allowNo": true,
|
|
471
|
+
"type": "boolean"
|
|
472
|
+
}
|
|
473
|
+
},
|
|
474
|
+
"hasDynamicHelp": false,
|
|
475
|
+
"hiddenAliases": [],
|
|
476
|
+
"id": "antigravity:backfill",
|
|
477
|
+
"pluginAlias": "@rulemetric/cli",
|
|
478
|
+
"pluginName": "@rulemetric/cli",
|
|
479
|
+
"pluginType": "core",
|
|
480
|
+
"strict": true,
|
|
481
|
+
"enableJsonFlag": false,
|
|
482
|
+
"isESM": true,
|
|
483
|
+
"relativePath": [
|
|
484
|
+
"dist",
|
|
485
|
+
"commands",
|
|
486
|
+
"antigravity",
|
|
487
|
+
"backfill.js"
|
|
488
|
+
]
|
|
489
|
+
},
|
|
408
490
|
"auth:create-key": {
|
|
409
491
|
"aliases": [],
|
|
410
492
|
"args": {},
|
|
@@ -846,88 +928,6 @@
|
|
|
846
928
|
"run.js"
|
|
847
929
|
]
|
|
848
930
|
},
|
|
849
|
-
"antigravity:backfill": {
|
|
850
|
-
"aliases": [],
|
|
851
|
-
"args": {
|
|
852
|
-
"conversationId": {
|
|
853
|
-
"description": "Antigravity conversationId (UUID) — the directory name under ~/.gemini/antigravity-ide/brain/",
|
|
854
|
-
"name": "conversationId",
|
|
855
|
-
"required": true
|
|
856
|
-
}
|
|
857
|
-
},
|
|
858
|
-
"description": "Backfill historical events from an Antigravity conversation transcript into a RuleMetric session. Useful for seeding a conversation that existed before hooks were installed — the live hook intentionally only captures forward.",
|
|
859
|
-
"examples": [
|
|
860
|
-
"<%= config.bin %> antigravity backfill 26fd215d-f43b-4ea5-b177-dc2c0e696f97 --session 158db9aa-68ee-43fc-961b-f3a180578694",
|
|
861
|
-
"<%= config.bin %> antigravity backfill 26fd215d-f43b-4ea5-b177-dc2c0e696f97 --dry-run"
|
|
862
|
-
],
|
|
863
|
-
"flags": {
|
|
864
|
-
"api-url": {
|
|
865
|
-
"description": "Override API base URL",
|
|
866
|
-
"env": "RULEMETRIC_API_URL",
|
|
867
|
-
"hidden": true,
|
|
868
|
-
"name": "api-url",
|
|
869
|
-
"hasDynamicHelp": false,
|
|
870
|
-
"multiple": false,
|
|
871
|
-
"type": "option"
|
|
872
|
-
},
|
|
873
|
-
"session": {
|
|
874
|
-
"char": "s",
|
|
875
|
-
"description": "RuleMetric session UUID to POST events into. If omitted, resolved from the hook tmp file ($TMPDIR/rulemetric/<conversationId>) — fails if neither is present.",
|
|
876
|
-
"name": "session",
|
|
877
|
-
"hasDynamicHelp": false,
|
|
878
|
-
"multiple": false,
|
|
879
|
-
"type": "option"
|
|
880
|
-
},
|
|
881
|
-
"transcript": {
|
|
882
|
-
"description": "Path to the transcript.jsonl file. Defaults to ~/.gemini/antigravity-ide/brain/<conversationId>/.system_generated/logs/transcript.jsonl",
|
|
883
|
-
"name": "transcript",
|
|
884
|
-
"hasDynamicHelp": false,
|
|
885
|
-
"multiple": false,
|
|
886
|
-
"type": "option"
|
|
887
|
-
},
|
|
888
|
-
"after-step": {
|
|
889
|
-
"description": "Only emit records with step_index > this value. Default: read from existing state file, else -1 (everything).",
|
|
890
|
-
"name": "after-step",
|
|
891
|
-
"hasDynamicHelp": false,
|
|
892
|
-
"multiple": false,
|
|
893
|
-
"type": "option"
|
|
894
|
-
},
|
|
895
|
-
"limit": {
|
|
896
|
-
"description": "Cap on the number of records to process this run.",
|
|
897
|
-
"name": "limit",
|
|
898
|
-
"hasDynamicHelp": false,
|
|
899
|
-
"multiple": false,
|
|
900
|
-
"type": "option"
|
|
901
|
-
},
|
|
902
|
-
"dry-run": {
|
|
903
|
-
"description": "Classify records without POSTing. Reports counts only.",
|
|
904
|
-
"name": "dry-run",
|
|
905
|
-
"allowNo": false,
|
|
906
|
-
"type": "boolean"
|
|
907
|
-
},
|
|
908
|
-
"save-state": {
|
|
909
|
-
"description": "After backfill, persist the highest step_index so the live hook resumes from there.",
|
|
910
|
-
"name": "save-state",
|
|
911
|
-
"allowNo": true,
|
|
912
|
-
"type": "boolean"
|
|
913
|
-
}
|
|
914
|
-
},
|
|
915
|
-
"hasDynamicHelp": false,
|
|
916
|
-
"hiddenAliases": [],
|
|
917
|
-
"id": "antigravity:backfill",
|
|
918
|
-
"pluginAlias": "@rulemetric/cli",
|
|
919
|
-
"pluginName": "@rulemetric/cli",
|
|
920
|
-
"pluginType": "core",
|
|
921
|
-
"strict": true,
|
|
922
|
-
"enableJsonFlag": false,
|
|
923
|
-
"isESM": true,
|
|
924
|
-
"relativePath": [
|
|
925
|
-
"dist",
|
|
926
|
-
"commands",
|
|
927
|
-
"antigravity",
|
|
928
|
-
"backfill.js"
|
|
929
|
-
]
|
|
930
|
-
},
|
|
931
931
|
"eval-targets:create": {
|
|
932
932
|
"aliases": [],
|
|
933
933
|
"args": {},
|
|
@@ -4323,5 +4323,5 @@
|
|
|
4323
4323
|
]
|
|
4324
4324
|
}
|
|
4325
4325
|
},
|
|
4326
|
-
"version": "0.7.
|
|
4326
|
+
"version": "0.7.27"
|
|
4327
4327
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rulemetric/cli",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.27",
|
|
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.27",
|
|
78
|
+
"@rulemetric/proxy": "0.7.27",
|
|
79
|
+
"@rulemetric/skills-registry": "0.7.27"
|
|
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,14 +94,14 @@
|
|
|
94
94
|
"tsx": "^4.19.0",
|
|
95
95
|
"typescript": "^5.9.0",
|
|
96
96
|
"vitest": "^3.2.0",
|
|
97
|
-
"@rulemetric/api": "0.0.1",
|
|
98
97
|
"@rulemetric/core": "0.0.1",
|
|
98
|
+
"@rulemetric/api": "0.0.1",
|
|
99
99
|
"@rulemetric/db": "0.0.1",
|
|
100
100
|
"@rulemetric/effectiveness": "0.0.1",
|
|
101
101
|
"@rulemetric/email": "0.0.1",
|
|
102
|
-
"@rulemetric/session": "0.2.1",
|
|
103
102
|
"@rulemetric/telemetry": "0.0.1",
|
|
104
|
-
"@rulemetric/typescript-config": "0.0.0"
|
|
103
|
+
"@rulemetric/typescript-config": "0.0.0",
|
|
104
|
+
"@rulemetric/session": "0.2.1"
|
|
105
105
|
},
|
|
106
106
|
"scripts": {
|
|
107
107
|
"build": "node scripts/build.mjs",
|