@xerg/cli 0.0.1 → 0.1.1

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/README.md CHANGED
@@ -1,21 +1,73 @@
1
- # xerg
1
+ # xerg
2
2
 
3
- **Unit economics engine for AI agents. Know what your AI is worth.**
3
+ Xerg is a local-first CLI for OpenClaw waste intelligence.
4
4
 
5
- Xerg answers the question no existing tool answers well: *"What is the cost per outcome of my AI agents, and how do I improve it?"*
5
+ It does not try to be generic LLM observability. It reads your agent logs, shows
6
+ where money is leaking, and lets you re-run the same audit with `--compare` so
7
+ you can see what changed after a fix.
6
8
 
7
- ## Coming Soon
9
+ ## Install
8
10
 
9
- - `xerg audit` — Waste intelligence report from your AI agent logs
10
- - `xerg track` — Tag outcomes to compute cost per outcome
11
- - SDK wrapper for OpenAI, Anthropic, Google, and more
12
- - Team dashboard at xerg.ai
11
+ ```bash
12
+ npm install -g @xerg/cli
13
+ ```
13
14
 
14
- ## Links
15
+ Or run it without a global install:
15
16
 
16
- - Website: [xerg.ai](https://xerg.ai)
17
- - GitHub: [github.com/xerg/xerg](https://github.com/xerg/xerg)
17
+ ```bash
18
+ npx @xerg/cli audit
19
+ ```
18
20
 
19
- ## License
21
+ After a global install, run:
20
22
 
21
- MIT
23
+ ```bash
24
+ xerg audit
25
+ ```
26
+
27
+ ## Commands
28
+
29
+ Inspect local audit readiness:
30
+
31
+ ```bash
32
+ xerg doctor
33
+ ```
34
+
35
+ Run the first audit:
36
+
37
+ ```bash
38
+ xerg audit
39
+ ```
40
+
41
+ Compare the latest run against the newest compatible prior local snapshot:
42
+
43
+ ```bash
44
+ xerg audit --compare
45
+ ```
46
+
47
+ Audit a specific window:
48
+
49
+ ```bash
50
+ xerg audit --since 24h --compare
51
+ ```
52
+
53
+ ## What Xerg reports today
54
+
55
+ - total spend
56
+ - observed vs estimated spend
57
+ - workflow and model breakdowns
58
+ - high-confidence waste
59
+ - directional savings opportunities
60
+ - before/after re-audit deltas
61
+
62
+ ## Privacy
63
+
64
+ Xerg v0 stores economic metadata and audit summaries locally. It does not store
65
+ prompt or response content.
66
+
67
+ ## Support
68
+
69
+ For beta access and support, contact `query@xerg.ai`.
70
+
71
+ ## Website
72
+
73
+ [xerg.ai](https://xerg.ai)
package/dist/index.js ADDED
@@ -0,0 +1,209 @@
1
+ #!/usr/bin/env node
2
+ import{readFileSync as ct}from"fs";import{styleText as ut}from"util";import{readFileSync as Ae}from"fs";import{createHash as Oe}from"crypto";function U(e){return Oe("sha1").update(e).digest("hex")}function H(e){if(!e)return null;let t=e.trim().match(/^(\d+)([mhdw])$/i);if(!t)throw new Error(`Invalid --since value "${e}". Use values like 30m, 24h, 7d, 2w.`);let n=Number(t[1]),o=t[2].toLowerCase(),r={m:60*1e3,h:3600*1e3,d:1440*60*1e3,w:10080*60*1e3};return Date.now()-n*r[o]}function R(){return new Date().toISOString()}function v(e){if(typeof e=="string"){let t=new Date(e);if(!Number.isNaN(t.getTime()))return t.toISOString()}if(typeof e=="number"){let t=new Date(e);if(!Number.isNaN(t.getTime()))return t.toISOString()}return R()}import{mkdirSync as $e}from"fs";import{dirname as Le}from"path";import _e from"better-sqlite3";var Y=`
3
+ CREATE TABLE IF NOT EXISTS source_files (
4
+ id TEXT PRIMARY KEY,
5
+ path TEXT NOT NULL,
6
+ kind TEXT NOT NULL,
7
+ file_hash TEXT NOT NULL,
8
+ mtime_ms INTEGER NOT NULL,
9
+ size_bytes INTEGER NOT NULL,
10
+ imported_at TEXT NOT NULL
11
+ );
12
+
13
+ CREATE TABLE IF NOT EXISTS runs (
14
+ id TEXT PRIMARY KEY,
15
+ source_path TEXT NOT NULL,
16
+ source_kind TEXT NOT NULL,
17
+ timestamp TEXT NOT NULL,
18
+ workflow TEXT NOT NULL,
19
+ environment TEXT NOT NULL,
20
+ tags_json TEXT NOT NULL,
21
+ total_cost_usd REAL NOT NULL,
22
+ total_tokens INTEGER NOT NULL,
23
+ observed_cost_usd REAL NOT NULL,
24
+ estimated_cost_usd REAL NOT NULL
25
+ );
26
+
27
+ CREATE TABLE IF NOT EXISTS calls (
28
+ id TEXT PRIMARY KEY,
29
+ run_id TEXT NOT NULL,
30
+ timestamp TEXT NOT NULL,
31
+ provider TEXT NOT NULL,
32
+ model TEXT NOT NULL,
33
+ input_tokens INTEGER NOT NULL,
34
+ output_tokens INTEGER NOT NULL,
35
+ cost_usd REAL NOT NULL,
36
+ cost_source TEXT NOT NULL,
37
+ latency_ms INTEGER,
38
+ tool_calls INTEGER NOT NULL,
39
+ retries INTEGER NOT NULL,
40
+ attempt INTEGER,
41
+ iteration INTEGER,
42
+ status TEXT,
43
+ task_class TEXT,
44
+ cache_hit INTEGER NOT NULL,
45
+ cache_cost_usd REAL,
46
+ metadata_json TEXT NOT NULL
47
+ );
48
+
49
+ CREATE TABLE IF NOT EXISTS findings (
50
+ id TEXT PRIMARY KEY,
51
+ audit_id TEXT NOT NULL,
52
+ classification TEXT NOT NULL,
53
+ confidence TEXT NOT NULL,
54
+ kind TEXT NOT NULL,
55
+ title TEXT NOT NULL,
56
+ summary TEXT NOT NULL,
57
+ scope TEXT NOT NULL,
58
+ scope_id TEXT NOT NULL,
59
+ cost_impact_usd REAL NOT NULL,
60
+ details_json TEXT NOT NULL
61
+ );
62
+
63
+ CREATE TABLE IF NOT EXISTS pricing_catalog (
64
+ id TEXT PRIMARY KEY,
65
+ provider TEXT NOT NULL,
66
+ model TEXT NOT NULL,
67
+ effective_date TEXT NOT NULL,
68
+ input_per_1m REAL NOT NULL,
69
+ output_per_1m REAL NOT NULL,
70
+ cached_input_per_1m REAL
71
+ );
72
+
73
+ CREATE TABLE IF NOT EXISTS audit_snapshots (
74
+ id TEXT PRIMARY KEY,
75
+ created_at TEXT NOT NULL,
76
+ summary_json TEXT NOT NULL
77
+ );
78
+ `;function _(e){$e(Le(e),{recursive:!0});let t=new _e(e);return t.exec(Y),{sqlite:t}}function V(e,t){let{sqlite:n}=_(t),o=R(),r=e.pricingCatalog.map(s=>({...s,cachedInputPer1m:s.cachedInputPer1m??null})),a=e.summary.sourceFiles.map(s=>({id:U(`${s.path}:${s.mtimeMs}:${s.sizeBytes}`),path:s.path,kind:s.kind,fileHash:U(Ae(s.path,"utf8")),mtimeMs:Math.trunc(s.mtimeMs),sizeBytes:s.sizeBytes,importedAt:o})),i=e.runs.map(s=>({id:s.id,sourcePath:s.sourcePath,sourceKind:s.sourceKind,timestamp:s.timestamp,workflow:s.workflow,environment:s.environment,tagsJson:JSON.stringify(s.tags),totalCostUsd:s.totalCostUsd,totalTokens:s.totalTokens,observedCostUsd:s.observedCostUsd,estimatedCostUsd:s.estimatedCostUsd})),c=e.runs.flatMap(s=>s.calls.map(p=>({id:p.id,runId:p.runId,timestamp:p.timestamp,provider:p.provider,model:p.model,inputTokens:p.inputTokens,outputTokens:p.outputTokens,costUsd:p.costUsd,costSource:p.costSource,latencyMs:p.latencyMs,toolCalls:p.toolCalls,retries:p.retries,attempt:p.attempt,iteration:p.iteration,status:p.status,taskClass:p.taskClass,cacheHit:p.cacheHit,cacheCostUsd:p.cacheCostUsd,metadataJson:JSON.stringify(p.metadata)}))),u=e.summary.findings.map(s=>({id:s.id,auditId:e.summary.auditId,classification:s.classification,confidence:s.confidence,kind:s.kind,title:s.title,summary:s.summary,scope:s.scope,scopeId:s.scopeId,costImpactUsd:s.costImpactUsd,detailsJson:JSON.stringify(s.details)})),d=n.transaction(()=>{O(n,`
79
+ INSERT OR IGNORE INTO pricing_catalog (
80
+ id,
81
+ provider,
82
+ model,
83
+ effective_date,
84
+ input_per_1m,
85
+ output_per_1m,
86
+ cached_input_per_1m
87
+ ) VALUES (?, ?, ?, ?, ?, ?, ?)
88
+ `,r.map(s=>[s.id,s.provider,s.model,s.effectiveDate,s.inputPer1m,s.outputPer1m,s.cachedInputPer1m])),O(n,`
89
+ INSERT OR IGNORE INTO source_files (
90
+ id,
91
+ path,
92
+ kind,
93
+ file_hash,
94
+ mtime_ms,
95
+ size_bytes,
96
+ imported_at
97
+ ) VALUES (?, ?, ?, ?, ?, ?, ?)
98
+ `,a.map(s=>[s.id,s.path,s.kind,s.fileHash,s.mtimeMs,s.sizeBytes,s.importedAt])),O(n,`
99
+ INSERT OR IGNORE INTO runs (
100
+ id,
101
+ source_path,
102
+ source_kind,
103
+ timestamp,
104
+ workflow,
105
+ environment,
106
+ tags_json,
107
+ total_cost_usd,
108
+ total_tokens,
109
+ observed_cost_usd,
110
+ estimated_cost_usd
111
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
112
+ `,i.map(s=>[s.id,s.sourcePath,s.sourceKind,s.timestamp,s.workflow,s.environment,s.tagsJson,s.totalCostUsd,s.totalTokens,s.observedCostUsd,s.estimatedCostUsd])),O(n,`
113
+ INSERT OR IGNORE INTO calls (
114
+ id,
115
+ run_id,
116
+ timestamp,
117
+ provider,
118
+ model,
119
+ input_tokens,
120
+ output_tokens,
121
+ cost_usd,
122
+ cost_source,
123
+ latency_ms,
124
+ tool_calls,
125
+ retries,
126
+ attempt,
127
+ iteration,
128
+ status,
129
+ task_class,
130
+ cache_hit,
131
+ cache_cost_usd,
132
+ metadata_json
133
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
134
+ `,c.map(s=>[s.id,s.runId,s.timestamp,s.provider,s.model,s.inputTokens,s.outputTokens,s.costUsd,s.costSource,s.latencyMs??null,s.toolCalls,s.retries,s.attempt??null,s.iteration??null,s.status??null,s.taskClass??null,s.cacheHit?1:0,s.cacheCostUsd??null,s.metadataJson])),O(n,`
135
+ INSERT OR IGNORE INTO findings (
136
+ id,
137
+ audit_id,
138
+ classification,
139
+ confidence,
140
+ kind,
141
+ title,
142
+ summary,
143
+ scope,
144
+ scope_id,
145
+ cost_impact_usd,
146
+ details_json
147
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
148
+ `,u.map(s=>[s.id,s.auditId,s.classification,s.confidence,s.kind,s.title,s.summary,s.scope,s.scopeId,s.costImpactUsd,s.detailsJson])),n.prepare(`
149
+ INSERT OR IGNORE INTO audit_snapshots (
150
+ id,
151
+ created_at,
152
+ summary_json
153
+ ) VALUES (?, ?, ?)
154
+ `).run(e.summary.auditId,e.summary.generatedAt,JSON.stringify(e.summary))});try{d()}finally{n.close()}}function O(e,t,n){if(n.length===0)return;let o=e.prepare(t);for(let r of n)o.run(...r)}var xe={"retry-waste":"Retry waste","context-outlier":"Context bloat","loop-waste":"Loop waste","candidate-downgrade":"Downgrade candidates","idle-spend":"Idle waste"};function w(e){return Number(e.toFixed(6))}function ve(e){if(!e)return"all";let t=e.trim().toLowerCase().match(/^(\d+)([mhdw])$/);return t?`${Number(t[1])}${t[2]}`:e.trim().toLowerCase()}function ee(e){return e.replace(/\\/g,"/")}function De(e){let t=ee(e),n="/sessions/",o=t.lastIndexOf(n);return o>=0?t.slice(0,o+n.length-1):t.slice(0,t.lastIndexOf("/"))||t}function Fe(e){let t=ee(e);return t.slice(0,t.lastIndexOf("/"))||t}function Pe(e){return xe[e]??e}function Me(e){return e.kind==="sessions"?De(e.path):Fe(e.path)}function F(e){let t=Array.from(new Set(e.sources.map(o=>o.kind))).sort(),n=Array.from(new Set(e.sources.map(o=>`${o.kind}:${Me(o)}`))).sort();return U(JSON.stringify({kinds:t,roots:n,since:ve(e.since)}))}function $(e,t){let n=new Map;for(let o of e){if(o.classification!==t)continue;let r=n.get(o.kind)??{kind:o.kind,label:Pe(o.kind),classification:t,spendUsd:0,findingCount:0};r.spendUsd=w(r.spendUsd+o.costImpactUsd),r.findingCount+=1,n.set(o.kind,r)}return Array.from(n.values()).sort((o,r)=>r.spendUsd-o.spendUsd)}function q(e){return new Map(e.map(t=>[t.key,t.spendUsd]))}function Q(e,t){let n=q(e),o=q(t);return Array.from(new Set([...n.keys(),...o.keys()])).map(a=>{let i=o.get(a)??0,c=n.get(a)??0;return{key:a,baselineSpendUsd:w(i),currentSpendUsd:w(c),deltaSpendUsd:w(c-i)}}).filter(a=>a.deltaSpendUsd!==0).sort((a,i)=>Math.abs(i.deltaSpendUsd)-Math.abs(a.deltaSpendUsd)).slice(0,3)}function Z(e){return`${e.kind}:${e.scope}:${e.scopeId}`}function D(e){return e.sort((t,n)=>Math.abs(n.deltaCostImpactUsd)-Math.abs(t.deltaCostImpactUsd))}function Be(e,t){let n=e.filter(d=>d.classification==="waste"&&d.confidence==="high"),o=t.filter(d=>d.classification==="waste"&&d.confidence==="high"),r=new Map(n.map(d=>[Z(d),d])),a=new Map(o.map(d=>[Z(d),d])),i=[],c=[],u=[];for(let[d,s]of r.entries()){let p=a.get(d);if(!p){i.push({kind:s.kind,title:s.title,scope:s.scope,scopeId:s.scopeId,currentCostImpactUsd:s.costImpactUsd,deltaCostImpactUsd:w(s.costImpactUsd)});continue}let l=w(s.costImpactUsd-p.costImpactUsd);l>0&&u.push({kind:s.kind,title:s.title,scope:s.scope,scopeId:s.scopeId,baselineCostImpactUsd:p.costImpactUsd,currentCostImpactUsd:s.costImpactUsd,deltaCostImpactUsd:l})}for(let[d,s]of a.entries())r.has(d)||c.push({kind:s.kind,title:s.title,scope:s.scope,scopeId:s.scopeId,baselineCostImpactUsd:s.costImpactUsd,deltaCostImpactUsd:w(-s.costImpactUsd)});return{newHighConfidenceWaste:D(i),resolvedHighConfidenceWaste:D(c),worsenedHighConfidenceWaste:D(u)}}function te(e){return{...e,comparisonKey:e.comparisonKey??F({sources:e.sourceFiles,since:e.since}),comparison:e.comparison??null,wasteByKind:e.wasteByKind?.length>0?e.wasteByKind:$(e.findings,"waste"),opportunityByKind:e.opportunityByKind?.length>0?e.opportunityByKind:$(e.findings,"opportunity"),notes:e.notes??[]}}function ne(e,t){let n=Q(e.spendByWorkflow,t.spendByWorkflow),o=Q(e.spendByModel,t.spendByModel);return{baselineAuditId:t.auditId,baselineGeneratedAt:t.generatedAt,baselineRunCount:t.runCount,baselineCallCount:t.callCount,baselineTotalSpendUsd:t.totalSpendUsd,baselineObservedSpendUsd:t.observedSpendUsd,baselineEstimatedSpendUsd:t.estimatedSpendUsd,baselineWasteSpendUsd:t.wasteSpendUsd,baselineOpportunitySpendUsd:t.opportunitySpendUsd,baselineStructuralWasteRate:t.structuralWasteRate,deltaTotalSpendUsd:w(e.totalSpendUsd-t.totalSpendUsd),deltaObservedSpendUsd:w(e.observedSpendUsd-t.observedSpendUsd),deltaEstimatedSpendUsd:w(e.estimatedSpendUsd-t.estimatedSpendUsd),deltaWasteSpendUsd:w(e.wasteSpendUsd-t.wasteSpendUsd),deltaOpportunitySpendUsd:w(e.opportunitySpendUsd-t.opportunitySpendUsd),deltaStructuralWasteRate:w(e.structuralWasteRate-t.structuralWasteRate),deltaRunCount:e.runCount-t.runCount,deltaCallCount:e.callCount-t.callCount,workflowDeltas:n,modelDeltas:o,findingChanges:Be(e.findings,t.findings)}}function We(e){try{return te(JSON.parse(e))}catch{return null}}function Xe(e){let{sqlite:t}=_(e);try{return t.prepare(`
155
+ SELECT summary_json AS summaryJson
156
+ FROM audit_snapshots
157
+ ORDER BY created_at DESC
158
+ `).all().map(o=>We(o.summaryJson)).filter(o=>o!==null)}finally{t.close()}}function se(e){return Xe(e.dbPath).find(t=>e.currentAuditId&&t.auditId===e.currentAuditId?!1:t.comparisonKey===e.comparisonKey)}import{statSync as Ge}from"fs";import{glob as Je}from"fs/promises";import{resolve as Ke}from"path";import{mkdirSync as P}from"fs";import{homedir as re}from"os";import{join as h}from"path";import{platform as oe}from"process";function je(){let e=re(),t=oe==="darwin"?{data:h(e,"Library","Application Support","xerg"),config:h(e,"Library","Preferences","xerg"),cache:h(e,"Library","Caches","xerg")}:oe==="win32"?{data:h(process.env.LOCALAPPDATA??h(e,"AppData","Local"),"xerg","Data"),config:h(process.env.APPDATA??h(e,"AppData","Roaming"),"xerg","Config"),cache:h(process.env.LOCALAPPDATA??h(e,"AppData","Local"),"xerg","Cache")}:{data:h(process.env.XDG_DATA_HOME??h(e,".local","share"),"xerg"),config:h(process.env.XDG_CONFIG_HOME??h(e,".config"),"xerg"),cache:h(process.env.XDG_CACHE_HOME??h(e,".cache"),"xerg")};return P(t.data,{recursive:!0}),P(t.config,{recursive:!0}),P(t.cache,{recursive:!0}),t}function ie(){return h(je().data,"xerg.db")}function M(){return h(re(),".openclaw","agents","*","sessions","*.jsonl")}function B(){return"/tmp/openclaw/openclaw-*.log"}function A(e,t){try{let n=Ge(e);return n.isFile()?{kind:t,path:e,sizeBytes:n.size,mtimeMs:n.mtimeMs}:null}catch{return null}}async function X(e){let t=[];if(e.logFile){let a=A(e.logFile,"gateway");a&&t.push(a)}if(e.sessionsDir){let a=await W("**/*.jsonl",{cwd:e.sessionsDir,resolveWith:e.sessionsDir});for(let i of a){let c=A(i,"sessions");c&&t.push(c)}}if(t.length>0)return t.sort((a,i)=>i.mtimeMs-a.mtimeMs);let[n,o]=await Promise.all([W(B()),W(M())]);return[...n.map(a=>A(a,"gateway")).filter(Boolean),...o.map(a=>A(a,"sessions")).filter(Boolean)].sort((a,i)=>i.mtimeMs-a.mtimeMs)}async function W(e,t){let n=[];for await(let o of Je(e,{cwd:t?.cwd}))n.push(t?.resolveWith?Ke(t.resolveWith,o):o);return n}async function ae(e){let t=await X(e),n=[];return t.length===0&&(n.push("No OpenClaw gateway logs or session files were detected."),n.push("Use --log-file or --sessions-dir if your OpenClaw data lives outside the defaults.")),t.some(o=>o.kind==="gateway")&&n.push("Gateway logs detected. These are preferred when cost metadata is present."),t.some(o=>o.kind==="sessions")&&n.push("Session transcript fallback detected. Xerg will extract usage metadata only."),{canAudit:t.length>0,sources:t,defaults:{gatewayPattern:B(),sessionsPattern:M()},notes:n}}function L(e){return{...e,id:U(`${e.kind}:${e.scope}:${e.scopeId}:${e.title}:${e.costImpactUsd}:${e.summary}`)}}function b(e){return Number(e.toFixed(6))}function de(e){let t=[],o=e.flatMap(i=>i.calls.map(c=>({run:i,call:c}))).filter(({call:i})=>{let c=(i.status??"").toLowerCase();return c.includes("error")||c.includes("fail")}),r=o.reduce((i,c)=>i+c.call.costUsd,0);r>0&&t.push(L({classification:"waste",confidence:"high",kind:"retry-waste",title:"Retry waste is consuming measurable spend",summary:`${o.length} failed call${o.length===1?"":"s"} were followed by additional work, making their spend pure retry overhead.`,scope:"global",scopeId:"all",costImpactUsd:b(r),details:{failedCallCount:o.length}}));for(let i of e){let c=Math.max(...i.calls.map(u=>u.iteration??0));if(c>=7){let d=i.calls.filter(s=>(s.iteration??0)>5).reduce((s,p)=>s+p.costUsd,0);t.push(L({classification:"waste",confidence:"high",kind:"loop-waste",title:`Workflow "${i.workflow}" ran beyond efficient loop bounds`,summary:`This run reached ${c} iterations. Xerg treats the spend after iteration 5 as likely loop waste.`,scope:"run",scopeId:i.id,costImpactUsd:b(d),details:{workflow:i.workflow,maxIteration:c}}))}}let a=new Map;for(let i of e){let c=a.get(i.workflow)??[];c.push(i),a.set(i.workflow,c)}for(let[i,c]of a.entries()){if(c.length>=3){let s=c.map(g=>g.calls.reduce((k,y)=>k+y.inputTokens,0)),p=s.reduce((g,k)=>g+k,0)/s.length,l=c.filter(g=>{let k=g.calls.reduce((y,Re)=>y+Re.inputTokens,0);return k>p*1.75&&k>1500});if(l.length>0){let g=l.reduce((k,y)=>k+y.totalCostUsd,0);t.push(L({classification:"opportunity",confidence:"medium",kind:"context-outlier",title:`Context usage in "${i}" is well above its baseline`,summary:`Xerg found ${l.length} run${l.length===1?"":"s"} in this workflow with input token volume far above the workflow average.`,scope:"workflow",scopeId:i,costImpactUsd:b(g),details:{workflow:i,averageInputTokens:b(p),outlierRunCount:l.length}}))}}let u=c.filter(s=>/(heartbeat|cron|monitor|poll)/i.test(s.workflow));if(u.length>0){let s=u.reduce((p,l)=>p+l.totalCostUsd,0);t.push(L({classification:"opportunity",confidence:"medium",kind:"idle-spend",title:`Idle or monitoring spend detected in "${i}"`,summary:"This workflow name looks like a recurring heartbeat or monitoring loop. Review whether the cadence and model tier are justified.",scope:"workflow",scopeId:i,costImpactUsd:b(s),details:{workflow:i}}))}let d=c.flatMap(s=>s.calls).filter(s=>/(opus|gpt-4o|sonnet)/i.test(s.model)&&/(heartbeat|cron|monitor|summary|tag|triage)/i.test(s.taskClass??i));if(d.length>0){let s=d.reduce((p,l)=>p+l.costUsd,0);t.push(L({classification:"opportunity",confidence:"low",kind:"candidate-downgrade",title:`Candidate model downgrade opportunity in "${i}"`,summary:"An expensive model is being used on a workflow that looks operationally simple. Treat this as an A/B test candidate, not proven waste.",scope:"workflow",scopeId:i,costImpactUsd:b(s*.3),details:{workflow:i,expensiveCallCount:d.length,inspectedSpendUsd:b(s)}}))}}return t.sort((i,c)=>c.costImpactUsd-i.costImpactUsd)}import{readFileSync as He}from"fs";import{basename as Ye}from"path";var j=[{id:"anthropic-claude-haiku-4-5-2026-03-01",provider:"anthropic",model:"claude-haiku-4-5",effectiveDate:"2026-03-01",inputPer1m:.8,outputPer1m:4},{id:"anthropic-claude-sonnet-4-5-2026-03-01",provider:"anthropic",model:"claude-sonnet-4-5",effectiveDate:"2026-03-01",inputPer1m:3,outputPer1m:15},{id:"anthropic-claude-opus-4-2026-03-01",provider:"anthropic",model:"claude-opus-4",effectiveDate:"2026-03-01",inputPer1m:15,outputPer1m:75},{id:"openai-gpt-4o-2026-03-01",provider:"openai",model:"gpt-4o",effectiveDate:"2026-03-01",inputPer1m:2.5,outputPer1m:10},{id:"openai-gpt-4.1-mini-2026-03-01",provider:"openai",model:"gpt-4.1-mini",effectiveDate:"2026-03-01",inputPer1m:.4,outputPer1m:1.6},{id:"google-gemini-2.0-flash-2026-03-01",provider:"google",model:"gemini-2.0-flash",effectiveDate:"2026-03-01",inputPer1m:.35,outputPer1m:1.4},{id:"meta-llama-3.3-70b-2026-03-01",provider:"meta",model:"llama-3.3-70b-instruct",effectiveDate:"2026-03-01",inputPer1m:.9,outputPer1m:.9}];function ze(e,t){let n=e.trim().toLowerCase(),o=t.trim().toLowerCase();return j.find(r=>r.provider.toLowerCase()===n&&r.model.toLowerCase()===o)}function ce(e,t,n,o){let r=ze(e,t);if(!r)return null;let a=Math.max(n,0)/1e6*r.inputPer1m,i=Math.max(o,0)/1e6*r.outputPer1m;return Number((a+i).toFixed(8))}function f(e,t){if(!e||typeof e!="object")return null;let n=e;for(let o of t){let r=n;for(let a of o){if(!r||typeof r!="object"||!(a in r)){r=void 0;break}r=r[a]}if(r!==void 0)return r}return null}function S(e){if(typeof e=="number"&&Number.isFinite(e))return e;if(typeof e=="string"&&e.trim()!==""){let t=Number(e);return Number.isFinite(t)?t:null}return null}function C(e){return typeof e=="string"&&e.trim()!==""?e.trim():null}function ue(e){return typeof e=="boolean"?e:typeof e=="string"?["true","1","yes"].includes(e.trim().toLowerCase()):typeof e=="number"?e>0:!1}function pe(e,t){let n={};for(let o of t){let r=e[o];(typeof r=="string"||typeof r=="number"||typeof r=="boolean")&&(n[o]=r)}return n}function Ve(e){let n=He(e,"utf8").split(/\r?\n/).map(r=>r.trim()).filter(Boolean),o=[];for(let r of n)try{let a=JSON.parse(r);o.push(a)}catch{}return o}function qe(e){return C(f(e,[["provider"],["message","provider"],["usage","provider"]]))??"unknown"}function Qe(e){return C(f(e,[["model"],["message","model"],["usage","model"]]))??"unknown-model"}function le(e,t){return C(f(e,[["workflow"],["session","workflow"],["metadata","workflow"],["agent","name"],["agentId"],["sessionId"]]))??Ye(t,".jsonl")}function Ze(e){return C(f(e,[["environment"],["env"],["metadata","environment"]]))??"local"}function et(e,t,n,o){return C(f(e,[["run_id"],["runId"],["trace_id"],["traceId"],["sessionId"],["thread_id"]]))??`${o}:${t}:${n}`}function tt(e,t){return C(f(e,[["task_class"],["taskClass"],["metadata","taskClass"]]))??t.toLowerCase()}function x(e){let t=S(f(e,[["input_tokens"],["inputTokens"],["usage","input_tokens"],["usage","inputTokens"],["message","usage","input_tokens"],["message","usage","inputTokens"],["usage","prompt_tokens"],["message","usage","prompt_tokens"]]))??0,n=S(f(e,[["output_tokens"],["outputTokens"],["usage","output_tokens"],["usage","outputTokens"],["message","usage","output_tokens"],["message","usage","outputTokens"],["usage","completion_tokens"],["message","usage","completion_tokens"]]))??0,o=S(f(e,[["cost_usd"],["costUsd"],["usage","cost_usd"],["usage","costUsd"],["usage","cost","total"],["message","usage","cost","total"],["message","usage","cost_usd"],["pricing","total_usd"]]))??null;return{inputTokens:t,outputTokens:n,observedCost:o}}function nt(e,t,n,o){let r=qe(t),a=Qe(t),i=le(t,e.path),{inputTokens:c,outputTokens:u,observedCost:d}=x(t),s=ce(r,a,c,u),p=v(f(t,[["timestamp"],["createdAt"],["created_at"]])),l=S(f(t,[["attempt"],["usage","attempt"],["metadata","attempt"]]))??null,g=S(f(t,[["iteration"],["loop_iteration"],["metadata","iteration"]]))??null,k=S(f(t,[["retries"],["retry_count"],["metadata","retries"]]))??0,y=d??s??0;return{id:U(`${n}:${e.path}:${o}:${a}:${p}:${y}`),runId:n,timestamp:p,provider:r,model:a,inputTokens:c,outputTokens:u,costUsd:y,costSource:d!==null?"observed":"estimated",latencyMs:S(f(t,[["latency_ms"],["latencyMs"],["usage","latency_ms"]]))??null,toolCalls:S(f(t,[["tool_calls"],["toolCalls"],["usage","tool_calls"]]))??0,retries:k,attempt:l,iteration:g,status:C(f(t,[["status"],["level"],["result"],["error","type"]]))??null,taskClass:tt(t,i),cacheHit:ue(f(t,[["cache_hit"],["cacheHit"],["usage","cache_hit"]])),cacheCostUsd:S(f(t,[["cache_cost_usd"],["cacheCostUsd"],["usage","cache_cost_usd"]]))??null,metadata:pe(t,["event","type","sessionId","agentId"])}}function st(e){return x(e).inputTokens>0||x(e).outputTokens>0||x(e).observedCost!==null}function me(e,t){let n=H(t),o=new Map;for(let r of e)Ve(r.path).forEach((i,c)=>{if(!st(i))return;let u=le(i,r.path),d=v(f(i,[["timestamp"],["createdAt"],["created_at"]]));if(n&&new Date(d).getTime()<n)return;let s=et(i,u,c,r.path),p=U(`${r.path}:${s}`),l=nt(r,i,p,c),g=o.get(p);if(!g){o.set(p,{id:p,sourceKind:r.kind,sourcePath:r.path,timestamp:d,workflow:u,environment:Ze(i),tags:{sourceKind:r.kind},calls:[l],totalCostUsd:l.costUsd,totalTokens:l.inputTokens+l.outputTokens,observedCostUsd:l.costSource==="observed"?l.costUsd:0,estimatedCostUsd:l.costSource==="estimated"?l.costUsd:0});return}g.calls.push(l),g.totalCostUsd=Number((g.totalCostUsd+l.costUsd).toFixed(8)),g.totalTokens+=l.inputTokens+l.outputTokens,g.observedCostUsd+=l.costSource==="observed"?l.costUsd:0,g.estimatedCostUsd+=l.costSource==="estimated"?l.costUsd:0});return Array.from(o.values()).sort((r,a)=>new Date(r.timestamp).getTime()-new Date(a.timestamp).getTime())}function fe(e){let t=new Map;for(let n of e){let o=t.get(n.key)??{spendUsd:0,observedSpendUsd:0,callCount:0};o.spendUsd+=n.spendUsd,o.observedSpendUsd+=n.observedSpendUsd,o.callCount+=1,t.set(n.key,o)}return Array.from(t.entries()).map(([n,o])=>{let r=o.spendUsd===0?0:o.observedSpendUsd/o.spendUsd;return{key:n,spendUsd:Number(o.spendUsd.toFixed(6)),callCount:o.callCount,observedShare:Number(r.toFixed(4))}}).sort((n,o)=>o.spendUsd-n.spendUsd)}function ge(e){let t=e.runs.reduce((u,d)=>u+d.calls.length,0),n=e.runs.reduce((u,d)=>u+d.totalCostUsd,0),o=e.runs.reduce((u,d)=>u+d.observedCostUsd,0),r=e.runs.reduce((u,d)=>u+d.estimatedCostUsd,0),a=e.findings.filter(u=>u.classification==="waste").reduce((u,d)=>u+d.costImpactUsd,0),i=e.findings.filter(u=>u.classification==="opportunity").reduce((u,d)=>u+d.costImpactUsd,0),c=R();return{auditId:U(`${c}:${e.runs.length}:${e.sources.map(u=>u.path).join("|")}`),generatedAt:c,comparisonKey:F({sources:e.sources,since:e.since}),comparison:null,since:e.since,runCount:e.runs.length,callCount:t,totalSpendUsd:Number(n.toFixed(6)),observedSpendUsd:Number(o.toFixed(6)),estimatedSpendUsd:Number(r.toFixed(6)),wasteSpendUsd:Number(a.toFixed(6)),opportunitySpendUsd:Number(i.toFixed(6)),structuralWasteRate:Number((n===0?0:a/n).toFixed(4)),wasteByKind:$(e.findings,"waste"),opportunityByKind:$(e.findings,"opportunity"),spendByWorkflow:fe(e.runs.map(u=>({key:u.workflow,spendUsd:u.totalCostUsd,observedSpendUsd:u.observedCostUsd}))),spendByModel:fe(e.runs.flatMap(u=>u.calls.map(d=>({key:`${d.provider}/${d.model}`,spendUsd:d.costUsd,observedSpendUsd:d.costSource==="observed"?d.costUsd:0})))),findings:e.findings,notes:["Cost per outcome is intentionally unavailable in v0. Xerg is measuring waste intelligence only.","Opportunity findings are directional recommendations, not proven waste."],sourceFiles:e.sources,dbPath:e.dbPath}}async function he(e){return ae(e)}async function we(e){if(e.compare&&e.noDb)throw new Error("The --compare flag needs local snapshot history. Remove --no-db or provide --db <path>.");let t=await X(e);if(t.length===0)throw new Error("No OpenClaw sources were detected. Run `xerg doctor` or provide --log-file / --sessions-dir.");let n=me(t,e.since),o=de(n),r=e.noDb?void 0:e.dbPath??ie(),a=ge({runs:n,findings:o,sources:t,since:e.since,dbPath:r});if(e.compare&&r){let i=se({dbPath:r,comparisonKey:a.comparisonKey,currentAuditId:a.auditId});i?a.comparison=ne(a,i):a.notes=[...a.notes,"No prior comparable audit was found. Run the same audit again after a fix to unlock before/after deltas."]}return r&&V({summary:a,runs:n,pricingCatalog:j},r),a}function m(e){return new Intl.NumberFormat("en-US",{style:"currency",currency:"USD",minimumFractionDigits:e>=1?2:4,maximumFractionDigits:4}).format(e)}function N(e){return`${(e*100).toFixed(0)}%`}function Se(e){let t=e*100;return`${t>0?"+":""}${t.toFixed(0)} pts`}function I(e){return`${e>0?"+":""}${m(e)}`}function K(e,t=5){return e.slice(0,t).map(n=>`- ${n.key}: ${m(n.spendUsd)} (${N(n.observedShare)} observed)`)}function Ue(e,t,n){return e.length===0?[`- ${t}`]:e.map(o=>{let r=`${o.findingCount} finding${o.findingCount===1?"":"s"}`,a=n?` ${n}`:"";return`- ${o.label}: ${m(o.spendUsd)} across ${r}${a}`})}function Te(e){return["## Waste taxonomy","Structural waste",...Ue(e.wasteByKind,"No confirmed waste buckets detected."),"Savings opportunities",...Ue(e.opportunityByKind,"No opportunity buckets detected.","(directional)")]}function ot(e,t){return e.findings.filter(n=>n.classification===t).sort((n,o)=>o.costImpactUsd-n.costImpactUsd)[0]}function rt(e){return e.findings.filter(t=>t.classification==="opportunity").sort((t,n)=>{let o=t.kind==="candidate-downgrade"?1:0,r=n.kind==="candidate-downgrade"?1:0;return o!==r?r-o:n.costImpactUsd-t.costImpactUsd})[0]??null}function ke(e,t){return e.length===0?[`- ${t}`]:e.slice(0,5).map(n=>`- ${n.title}: ${m(n.costImpactUsd)} (${n.confidence})`)}function G(e){return`${e.key} (${I(e.deltaSpendUsd)})`}function it(e){return e.filter(t=>t.deltaSpendUsd<0).sort((t,n)=>t.deltaSpendUsd-n.deltaSpendUsd)[0]}function at(e){return e.filter(t=>t.deltaSpendUsd>0).sort((t,n)=>n.deltaSpendUsd-t.deltaSpendUsd)[0]}function J(e,t){return t==="resolved"?`- Resolved: ${e.title} (${m(e.baselineCostImpactUsd??0)})`:t==="worsened"?`- Worsened: ${e.title} (${I(e.deltaCostImpactUsd)})`:`- New: ${e.title} (${m(e.currentCostImpactUsd??0)})`}function dt(e){if(!e.comparison)return[];let t=e.comparison,n=it(t.workflowDeltas),o=at(t.workflowDeltas),r=o?.key??e.spendByWorkflow[0]?.key??null,a=[...t.findingChanges.newHighConfidenceWaste.map(i=>J(i,"new")),...t.findingChanges.resolvedHighConfidenceWaste.map(i=>J(i,"resolved")),...t.findingChanges.worsenedHighConfidenceWaste.map(i=>J(i,"worsened"))].slice(0,5);return["## Before / after",`Compared against ${t.baselineGeneratedAt}`,`- Total spend: ${m(t.baselineTotalSpendUsd)} -> ${m(e.totalSpendUsd)} (${I(t.deltaTotalSpendUsd)})`,`- Structural waste: ${m(t.baselineWasteSpendUsd)} -> ${m(e.wasteSpendUsd)} (${I(t.deltaWasteSpendUsd)})`,`- Waste rate: ${N(t.baselineStructuralWasteRate)} -> ${N(e.structuralWasteRate)} (${Se(t.deltaStructuralWasteRate)})`,`- Runs analyzed: ${t.baselineRunCount} -> ${e.runCount} (${t.deltaRunCount>0?"+":""}${t.deltaRunCount})`,`- Model calls: ${t.baselineCallCount} -> ${e.callCount} (${t.deltaCallCount>0?"+":""}${t.deltaCallCount})`,n?`- Biggest improvement: ${G(n)}`:"- Biggest improvement: none detected",o?`- Biggest regression: ${G(o)}`:"- Biggest regression: none detected",r?`- First workflow to inspect now: ${r}`:"- First workflow to inspect now: no workflow delta available",...t.modelDeltas.length>0?[`- Model swing to inspect: ${G(t.modelDeltas[0])}`]:["- Model swing to inspect: none"],...a.length>0?a:["- High-confidence waste changes: none"]]}function ye(e){return["# Xerg doctor","",e.canAudit?"OpenClaw sources detected.":"No OpenClaw sources detected.","","## Defaults",`- gateway logs: ${e.defaults.gatewayPattern}`,`- session files: ${e.defaults.sessionsPattern}`,"","## Sources",...e.sources.length>0?e.sources.map(n=>`- [${n.kind}] ${n.path}`):["- none"],"","## Notes",...e.notes.map(n=>`- ${n}`)].join(`
159
+ `)}function Ce(e){let t=e.findings.filter(a=>a.classification==="waste"),n=e.findings.filter(a=>a.classification==="opportunity"),o=rt(e),r=ot(e,"waste");return["# Xerg audit","",`Total spend: ${m(e.totalSpendUsd)}`,`Observed spend: ${m(e.observedSpendUsd)}`,`Estimated spend: ${m(e.estimatedSpendUsd)}`,`Runs analyzed: ${e.runCount}`,`Model calls: ${e.callCount}`,`Structural waste identified: ${m(e.wasteSpendUsd)} (${N(e.structuralWasteRate)})`,`Potential impact surfaced: ${m(e.opportunitySpendUsd)}`,"",...Te(e),"","## Top workflows",...K(e.spendByWorkflow),"","## Top models",...K(e.spendByModel),"","## High-confidence waste",...ke(t,"none detected"),"","## Opportunities",...ke(n,"none detected"),"","## First savings test",...o?[`- Start with ${o.title}: ${m(o.costImpactUsd)} of potential impact`,`- Why this test first: ${o.summary}`]:["- No savings test surfaced yet"],...r?[`- Confirmed leak to close first: ${r.title}`]:["- Confirmed leak to close first: none"],...e.spendByWorkflow[0]?[`- Workflow to inspect first: ${e.spendByWorkflow[0].key}`]:["- Workflow to inspect first: none"],"",...dt(e),...e.comparison?[""]:[],"## Notes",...e.notes.map(a=>`- ${a}`)].join(`
160
+ `)}function be(e){let t=["# Xerg Audit Report","",`- Generated: ${e.generatedAt}`,`- Total spend: ${m(e.totalSpendUsd)}`,`- Observed spend: ${m(e.observedSpendUsd)}`,`- Estimated spend: ${m(e.estimatedSpendUsd)}`,`- Structural waste identified: ${m(e.wasteSpendUsd)} (${N(e.structuralWasteRate)})`,`- Potential impact surfaced: ${m(e.opportunitySpendUsd)}`,`- Runs analyzed: ${e.runCount}`,`- Model calls: ${e.callCount}`,"",...Te(e),"","## Top workflows",...K(e.spendByWorkflow),"","## Findings",...e.findings.slice(0,10).map(n=>`- **${n.title}** (${n.classification}, ${n.confidence}) \u2014 ${n.summary} Estimated impact: ${m(n.costImpactUsd)}.`)];if(e.comparison){let n=e.comparison;t.push("","## Before / after",`- Compared against: ${n.baselineGeneratedAt}`,`- Total spend: ${m(n.baselineTotalSpendUsd)} -> ${m(e.totalSpendUsd)} (${I(n.deltaTotalSpendUsd)})`,`- Structural waste: ${m(n.baselineWasteSpendUsd)} -> ${m(e.wasteSpendUsd)} (${I(n.deltaWasteSpendUsd)})`,`- Waste rate: ${N(n.baselineStructuralWasteRate)} -> ${N(e.structuralWasteRate)} (${Se(n.deltaStructuralWasteRate)})`)}return t.join(`
161
+ `)}async function Ne(e){let t=await we({logFile:e.logFile,sessionsDir:e.sessionsDir,since:e.since,compare:e.compare,dbPath:e.db,noDb:e.noDb});if(e.json){process.stdout.write(`${JSON.stringify(t,null,2)}
162
+ `);return}if(e.markdown){process.stdout.write(`${be(t)}
163
+ `);return}process.stdout.write(`${Ce(t)}
164
+ `)}async function Ie(e){let t=await he({logFile:e.logFile,sessionsDir:e.sessionsDir});process.stdout.write(`${ye(t)}
165
+ `)}var Ee=Ut(),z=process.argv.slice(2),T=z[0];(!T||T==="--help"||T==="-h"||T==="help")&&(process.stdout.write(ft()),process.exit(0));(T==="--version"||T==="-v"||T==="version")&&(process.stdout.write(`${Ee}
166
+ `),process.exit(0));pt().catch(e=>{let t=e instanceof Error?e.message:"Unknown error";process.stderr.write(`${wt(`xerg failed: ${t}`)}
167
+ `),process.exitCode=1});async function pt(){if(T==="audit"){let e=lt(z.slice(1));if(e.json&&e.markdown)throw new Error("Use either --json or --markdown, not both.");await Ne(e);return}if(T==="doctor"){let e=mt(z.slice(1));await Ie(e);return}throw new Error(`Unknown command "${T}". Run \`xerg --help\` to see available commands.`)}function lt(e){let t={};for(let n=0;n<e.length;n+=1){let o=e[n];switch(o){case"--help":case"-h":process.stdout.write(gt()),process.exit(0);break;case"--log-file":t.logFile=E(o,e[n+1]),n+=1;break;case"--sessions-dir":t.sessionsDir=E(o,e[n+1]),n+=1;break;case"--since":t.since=E(o,e[n+1]),n+=1;break;case"--db":t.db=E(o,e[n+1]),n+=1;break;case"--compare":t.compare=!0;break;case"--json":t.json=!0;break;case"--markdown":t.markdown=!0;break;case"--no-db":t.noDb=!0;break;default:throw new Error(`Unknown audit option "${o}". Run \`xerg audit --help\` for usage.`)}}return t}function mt(e){let t={};for(let n=0;n<e.length;n+=1){let o=e[n];switch(o){case"--help":case"-h":process.stdout.write(ht()),process.exit(0);break;case"--log-file":t.logFile=E(o,e[n+1]),n+=1;break;case"--sessions-dir":t.sessionsDir=E(o,e[n+1]),n+=1;break;default:throw new Error(`Unknown doctor option "${o}". Run \`xerg doctor --help\` for usage.`)}}return t}function E(e,t){if(!t||t.startsWith("-"))throw new Error(`The ${e} flag needs a value.`);return t}function ft(){return`xerg ${Ee}
168
+
169
+ Waste intelligence for OpenClaw workflows.
170
+
171
+ Usage:
172
+ xerg <command> [options]
173
+
174
+ Commands:
175
+ audit Analyze OpenClaw logs and produce a waste intelligence report.
176
+ doctor Inspect your machine for OpenClaw sources and audit readiness.
177
+
178
+ Global options:
179
+ -h, --help Show help
180
+ -v, --version Show version
181
+ `}function gt(){return`xerg audit
182
+
183
+ Analyze OpenClaw logs and produce a waste intelligence report.
184
+
185
+ Usage:
186
+ xerg audit [options]
187
+
188
+ Options:
189
+ --log-file <path> Explicit OpenClaw gateway log file to analyze
190
+ --sessions-dir <path> Explicit OpenClaw sessions directory to analyze
191
+ --since <duration> Look back window such as 24h, 7d, or 30m
192
+ --compare Compare this audit to the newest compatible prior local snapshot
193
+ --json Render the report as JSON
194
+ --markdown Render the report as Markdown
195
+ --db <path> Custom SQLite database path
196
+ --no-db Skip local persistence
197
+ -h, --help Show help
198
+ `}function ht(){return`xerg doctor
199
+
200
+ Inspect your machine for OpenClaw sources and audit readiness.
201
+
202
+ Usage:
203
+ xerg doctor [options]
204
+
205
+ Options:
206
+ --log-file <path> Explicit OpenClaw gateway log file to inspect
207
+ --sessions-dir <path> Explicit OpenClaw sessions directory to inspect
208
+ -h, --help Show help
209
+ `}function wt(e){return process.stderr.isTTY?ut("red",e):e}function Ut(){let e=new URL("../package.json",import.meta.url);return JSON.parse(ct(e,"utf8")).version??"0.0.0"}
package/package.json CHANGED
@@ -1,20 +1,46 @@
1
1
  {
2
2
  "name": "@xerg/cli",
3
- "version": "0.0.1",
4
- "description": "Unit economics engine for AI agents. Know what your AI is worth.",
5
- "keywords": ["ai", "llm", "cost", "unit-economics", "agents", "finops", "opentelemetry"],
3
+ "version": "0.1.1",
4
+ "description": "CLI waste intelligence for OpenClaw workflows.",
5
+ "keywords": ["ai", "agents", "finops", "llm", "openclaw", "cost", "cli"],
6
6
  "homepage": "https://xerg.ai",
7
7
  "repository": {
8
8
  "type": "git",
9
- "url": "https://github.com/xerg/xerg"
9
+ "url": "git+https://github.com/xergai/xerg.git",
10
+ "directory": "packages/cli"
10
11
  },
12
+ "bugs": {
13
+ "email": "query@xerg.ai",
14
+ "url": "https://xerg.ai"
15
+ },
16
+ "author": "Xerg <query@xerg.ai>",
11
17
  "license": "MIT",
12
- "author": "Xerg <jason@xerg.ai>",
18
+ "type": "module",
13
19
  "bin": {
14
- "xerg": "./bin/xerg.js"
20
+ "xerg": "dist/index.js"
21
+ },
22
+ "publishConfig": {
23
+ "access": "public"
24
+ },
25
+ "files": ["dist", "README.md", "LICENSE"],
26
+ "main": "./dist/index.js",
27
+ "exports": {
28
+ ".": {
29
+ "default": "./dist/index.js"
30
+ }
15
31
  },
16
- "files": ["bin", "README.md", "LICENSE"],
17
32
  "engines": {
18
- "node": ">=18"
33
+ "node": "24.x"
34
+ },
35
+ "scripts": {
36
+ "build": "tsup",
37
+ "dev": "tsx src/index.ts",
38
+ "typecheck": "tsc --noEmit -p tsconfig.json"
39
+ },
40
+ "dependencies": {
41
+ "better-sqlite3": "^11.10.0"
42
+ },
43
+ "devDependencies": {
44
+ "@xergai/core": "workspace:*"
19
45
  }
20
46
  }
package/bin/xerg.js DELETED
@@ -1,12 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- console.log(`
4
- ⚡ xerg v0.0.1
5
-
6
- Unit economics engine for AI agents.
7
- Know what your AI is worth.
8
-
9
- Coming soon: xerg audit, xerg track, and more.
10
-
11
- https://xerg.ai
12
- `);