@hydra-acp/budgeter 0.1.9 → 0.1.11
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/cost/aggregate.js +1 -1
- package/dist/cost/format.js +5 -5
- package/dist/cost/history-stream.js +1 -1
- package/dist/cost/language.js +1 -1
- package/dist/cost/session-store.js +1 -1
- package/dist/index.js +11 -10
- package/package.json +1 -1
package/dist/cost/aggregate.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{relative as F,resolve as C}from"node:path";import{homedir as L}from"node:os";import{realpathSync as j}from"node:fs";function K(m){const a=m.match(/^(\d+)\s*([dhmwy])$/i);if(a!==null){const v=a[1],l=a[2];if(v===void 0||l===void 0)throw new Error(`invalid since spec: ${m}`);const k=parseInt(v,10),g=l.toLowerCase(),i=new Date;return g==="d"?i.setDate(i.getDate()-k):g==="h"?i.setHours(i.getHours()-k):g==="w"?i.setDate(i.getDate()-k*7):g==="m"?i.setMonth(i.getMonth()-k):g==="y"&&i.setFullYear(i.getFullYear()-k),i}const t=new Date(m);if(Number.isNaN(t.getTime()))throw new Error(`invalid since spec: ${m}`);return t}function z(m){const a=m.locByLanguage;if(a===void 0)return 0;let t=0;for(const v of Object.keys(a)){const l=a[v];l!==void 0&&(t+=l.added-l.removed)}return t}const M=new Map;function B(m){if(M.has(m))return M.get(m);try{const a=j(m);return M.set(m,a),a}catch{return M.set(m,m),m}}function N(m,a){let t=m;if(a.since!==void 0){const k=a.since.getTime(),g=[];for(const i of t)new Date(i.updatedAt).getTime()<k||g.push(i);t=g}if(a.dir!==void 0){const k=B(C(a.dir)),g=[];for(const i of t)i.cwd===void 0||i.cwd===""||(i.cwd.startsWith(k+"/")||i.cwd===k)&&g.push(i);t=g}if(a.host!==void 0&&a.host!=="all"){const k=a.host,g=[];for(const i of t)k==="local"?(!i.importedFromMachine||i.upstreamSessionId)&&g.push(i):i.importedFromMachine===k&&!i.upstreamSessionId&&g.push(i);t=g}if(a.interactive!==void 0){const k=a.interactive,g=[];for(const i of t)i.interactive===k&&g.push(i);t=g}const v=a.min??0,l=[];for(const k of t){let g;a.minMetric==="tokens"?g=k.contextTokens:a.minMetric==="loc"?g=z(k):g=k.costAmount,g>v&&l.push(k)}return l}function H(m){return m.dir!==void 0?C(m.dir):C(L())}function $(m,a,t){if(m===void 0||m==="")return"<unknown>";const v=B(C(m));if(a===void 0){const T=B(C(L()));return v===T?"~":v.startsWith(T+"/")?"~/"+v.slice(T.length+1):v}const l=B(C(t));let k=F(l,v);if(k===""||k===".")return"<root>";if(k.startsWith(".."))return"<unknown>";const g=k.split("/");if(g.length===0)return"<root>";const i=Math.min(a,g.length),S=g.slice(0,i);return S.length===0?"<root>":S.join("/")}function J(m,a,t={},v){let l=t.since;if(l===void 0&&t.bucket!==void 0){const e=new Date;t.bucket==="hour"?(e.setHours(e.getHours()-24),l=e):t.bucket==="day"?(e.setDate(e.getDate()-30),l=e):t.bucket==="week"?(e.setMonth(e.getMonth()-6),l=e):t.bucket==="month"&&(e.setFullYear(e.getFullYear()-2),l=e)}if(!(l!==void 0||t.bucket!==void 0||t.tokens===!0||t.loc===!0||t.by!==void 0||t.dir!==void 0||t.interactive!==void 0)){let e=0;for(const r of m)e+=r.costAmount;let o="";for(const r of m){o=r.costCurrency;break}return{kind:"total",row:{label:"All sessions",costAmount:e,sessionCount:m.length},currency:o}}const g={since:l,dir:t.dir,interactive:t.interactive,min:t.min,minMetric:t.loc===!0?"loc":t.tokens===!0?"tokens":"cost"},i=N(m,g),S=new Map;if(a!==void 0)for(const e of a){const o=S.get(e.sessionId);o===void 0?S.set(e.sessionId,[e]):o.push(e)}let T="";if(a!==void 0&&a.length>0)for(const e of a){T=e.currency;break}else if(i.length>0)for(const e of i){T=e.costCurrency;break}if(t.by==="language"&&t.bucket===void 0){const e=new Map,o=new Set;for(const u of i){const n=u.locByLanguage;if(n===void 0)continue;let f=!1;for(const d of Object.keys(n)){const w=n[d];if(w===void 0)continue;let s=e.get(d);s===void 0&&(s={added:0,removed:0,sessions:new Set},e.set(d,s)),s.added+=w.added,s.removed+=w.removed,(w.added>0||w.removed>0)&&(s.sessions.add(u.sessionId),f=!0)}f&&o.add(u.sessionId)}const r=[];for(const[u,n]of e){const f={label:u,costAmount:0,sessionCount:n.sessions.size,linesAdded:n.added,linesRemoved:n.removed};r.push({label:u,items:[f]})}return{kind:"grouped",groups:r,currency:T,totalSessions:o.size}}const I=e=>t.by==="dir"?$(e.cwd,t.depth,H(t)):t.by==="session"?e.sessionId.startsWith("hydra_session_")?e.sessionId.slice(14):e.sessionId:t.by==="model"?e.model===""?"<unknown>":e.model:t.by==="agent"?e.agentId===""?"<unknown>":e.agentId:"<all>",R=e=>{const o=new Date(e);if(Number.isNaN(o.getTime()))return"<invalid>";if(t.bucket==="hour"){const r=o.toLocaleDateString(void 0,{month:"2-digit",day:"2-digit"}),u=String(o.getHours()).padStart(2,"0");return`${r} ${u}:00`}if(t.bucket==="day")return o.toLocaleDateString(void 0,{year:"numeric",month:"2-digit",day:"2-digit"});if(t.bucket==="week"){const r=new Date(o),u=r.getDay(),n=r.getDate()-u+(u===0?-6:1);return r.setDate(n),r.toLocaleDateString(void 0,{year:"numeric",month:"2-digit",day:"2-digit"})}return t.bucket==="month"?o.toLocaleDateString(void 0,{year:"numeric",month:"2-digit"}):o.toLocaleDateString(void 0,{year:"numeric",month:"2-digit",day:"2-digit"})};if(t.by===void 0&&t.bucket===void 0){let e=0,o=0,r=0,u=0,n=0,f=0;for(const w of i){e+=w.costAmount;const s=S.get(w.sessionId);if(s!==void 0)for(const c of s)o+=c.deltaCost,t.tokens===!0&&(c.inputTokens!==void 0&&(r+=c.inputTokens),c.outputTokens!==void 0&&(u+=c.outputTokens),c.cacheReadTokens!==void 0&&(n+=c.cacheReadTokens),c.cacheWriteTokens!==void 0&&(f+=c.cacheWriteTokens))}const d={label:"All sessions",costAmount:e,deltaCost:o,sessionCount:i.length};if(t.tokens===!0&&(d.inputTokens=r,d.outputTokens=u,d.cacheReadTokens=n,d.cacheWriteTokens=f),t.loc===!0){let w=0,s=0;for(const c of i){const b=c.locByLanguage;if(b!==void 0)for(const p of Object.keys(b)){const h=b[p];h!==void 0&&(w+=h.added,s+=h.removed)}}d.linesAdded=w,d.linesRemoved=s}return{kind:"total",row:d,currency:T}}if(t.by!==void 0&&t.bucket===void 0){const e=new Map;for(const r of i){const u=I(r);let n=e.get(u);if(n===void 0&&(n={label:u,rows:{label:u,costAmount:0,deltaCost:0,sessionCount:0}},e.set(u,n)),n.rows.costAmount+=r.costAmount,n.rows.sessionCount=(n.rows.sessionCount??0)+1,t.tokens===!0&&(n.rows.inputTokens===void 0&&(n.rows.inputTokens=0),n.rows.inputTokens+=r.contextTokens),t.loc===!0){const d=r.locByLanguage;if(d!==void 0){n.rows.linesAdded===void 0&&(n.rows.linesAdded=0),n.rows.linesRemoved===void 0&&(n.rows.linesRemoved=0);for(const w of Object.keys(d)){const s=d[w];s!==void 0&&(n.rows.linesAdded+=s.added,n.rows.linesRemoved+=s.removed)}}}const f=S.get(r.sessionId);if(f!==void 0)for(const d of f)n.rows.deltaCost+=d.deltaCost,t.tokens===!0&&(n.rows.inputTokens===void 0&&(n.rows.inputTokens=0),n.rows.outputTokens===void 0&&(n.rows.outputTokens=0),n.rows.cacheReadTokens===void 0&&(n.rows.cacheReadTokens=0),n.rows.cacheWriteTokens===void 0&&(n.rows.cacheWriteTokens=0),d.inputTokens!==void 0&&(n.rows.inputTokens+=d.inputTokens),d.outputTokens!==void 0&&(n.rows.outputTokens+=d.outputTokens),d.cacheReadTokens!==void 0&&(n.rows.cacheReadTokens+=d.cacheReadTokens),d.cacheWriteTokens!==void 0&&(n.rows.cacheWriteTokens+=d.cacheWriteTokens))}const o=[];for(const r of e.values())o.push({label:r.label,items:[r.rows]});return{kind:"grouped",groups:o,currency:T}}const E=new Map;for(const e of i)E.set(e.sessionId,e);const A=new Map;if(a!==void 0){for(const e of a){if(!E.has(e.sessionId))continue;const o=A.get(e.sessionId);o===void 0?A.set(e.sessionId,[e]):o.push(e)}for(const e of A.values())e.sort((o,r)=>o.ts.localeCompare(r.ts))}const O=(e,o)=>{e._sessions===void 0&&(e._sessions=new Set),e._sessions.add(o),e.sessionCount=e._sessions.size},_=e=>{delete e._sessions},G=(e,o,r)=>{const u=R(o.ts);let n=e.get(u);n===void 0&&(n={bucket:u,costAmount:0,deltaCost:0,sessionCount:0},e.set(u,n)),n.costAmount+=r,n.deltaCost+=r,O(n,o.sessionId),t.tokens===!0&&(n.inputTokens===void 0||(o.inputTokens??0)>n.inputTokens)&&(n.inputTokens=o.inputTokens??n.inputTokens??0)};if(t.loc===!0&&t.bucket!==void 0){const e=new Set;for(const s of i)e.add(s.sessionId);const o=new Map;for(const s of i)o.set(s.sessionId,s);const r=(s,c)=>{let b=s.get(c);return b===void 0&&(b={bucket:c,costAmount:0,deltaCost:0,sessionCount:0,linesAdded:0,linesRemoved:0},s.set(c,b)),(b.linesAdded??void 0)===void 0&&(b.linesAdded=0),(b.linesRemoved??void 0)===void 0&&(b.linesRemoved=0),b},u=(s,c)=>{s.linesAdded=(s.linesAdded??0)+c.linesAdded,s.linesRemoved=(s.linesRemoved??0)+c.linesRemoved,s._sessions===void 0&&(s._sessions=new Set),s._sessions.add(c.sessionId),s.sessionCount=s._sessions.size},n=s=>{delete s._sessions},f=v??[];if(t.by==="language"){const s=new Map,c=new Set;for(const p of f){if(!e.has(p.sessionId)||l!==void 0&&new Date(p.ts)<l)continue;let h=s.get(p.language);h===void 0&&(h={label:p.language,buckets:new Map},s.set(p.language,h));const y=r(h.buckets,R(p.ts));u(y,p),c.add(p.sessionId)}const b=[];for(const p of s.values()){const h=Array.from(p.buckets.values());for(const y of h)n(y);h.sort((y,x)=>y.bucket.localeCompare(x.bucket)),h.length>0&&b.push({label:p.label,items:h})}return{kind:"timeSeriesGrouped",groups:b,currency:T,totalSessions:c.size}}if(t.by!==void 0){const s=new Map;for(const b of f){if(!e.has(b.sessionId)||l!==void 0&&new Date(b.ts)<l)continue;const p=o.get(b.sessionId);if(p===void 0)continue;const h=I(p);let y=s.get(h);y===void 0&&(y={label:h,buckets:new Map},s.set(h,y));const x=r(y.buckets,R(b.ts));u(x,b)}const c=[];for(const b of s.values()){const p=Array.from(b.buckets.values());for(const h of p)n(h);p.sort((h,y)=>h.bucket.localeCompare(y.bucket)),p.length>0&&c.push({label:b.label,items:p})}return{kind:"timeSeriesGrouped",groups:c,currency:T}}const d=new Map;for(const s of f){if(!e.has(s.sessionId)||l!==void 0&&new Date(s.ts)<l)continue;const c=r(d,R(s.ts));u(c,s)}const w=Array.from(d.values());for(const s of w)n(s);return w.sort((s,c)=>s.bucket.localeCompare(c.bucket)),{kind:"timeSeries",timeSeries:w,currency:T}}if(t.by!==void 0&&t.bucket!==void 0){const e=new Map,o=u=>{const n=I(u);let f=e.get(n);return f===void 0&&(f={label:n,buckets:new Map},e.set(n,f)),f.buckets};for(const u of i){const n=A.get(u.sessionId);if(n===void 0||n.length===0)continue;const f=o(u),d=n[0];if(d===void 0)continue;let w=d.cumulativeCost;for(let s=1;s<n.length;s++){const c=n[s];if(c===void 0)continue;const b=Math.max(0,c.cumulativeCost-w);w=c.cumulativeCost,!(l!==void 0&&new Date(c.ts)<l)&&G(f,c,b)}}const r=[];for(const u of e.values()){const n=Array.from(u.buckets.values());for(const f of n)_(f);n.sort((f,d)=>f.bucket.localeCompare(d.bucket)),n.length>0&&r.push({label:u.label,items:n})}return{kind:"timeSeriesGrouped",groups:r,currency:T}}const W=new Map;for(const e of i){const o=A.get(e.sessionId);if(o===void 0||o.length===0)continue;const r=o[0];if(r===void 0)continue;let u=r.cumulativeCost;for(let n=1;n<o.length;n++){const f=o[n];if(f===void 0)continue;const d=Math.max(0,f.cumulativeCost-u);u=f.cumulativeCost,!(l!==void 0&&new Date(f.ts)<l)&&G(W,f,d)}}const D=Array.from(W.values());for(const e of D)_(e);return D.sort((e,o)=>e.bucket.localeCompare(o.bucket)),{kind:"timeSeries",timeSeries:D,currency:T}}export{J as aggregate,N as applyFilters,K as parseSince};
|
|
1
|
+
import{relative as L,resolve as C}from"node:path";import{homedir as W}from"node:os";import{realpathSync as j}from"node:fs";function K(m){const f=m.match(/^(\d+)\s*([dhmwy])$/i);if(f!==null){const v=f[1],l=f[2];if(v===void 0||l===void 0)throw new Error(`invalid since spec: ${m}`);const k=parseInt(v,10),g=l.toLowerCase(),i=new Date;return g==="d"?i.setDate(i.getDate()-k):g==="h"?i.setHours(i.getHours()-k):g==="w"?i.setDate(i.getDate()-k*7):g==="m"?i.setMonth(i.getMonth()-k):g==="y"&&i.setFullYear(i.getFullYear()-k),i}const t=new Date(m);if(Number.isNaN(t.getTime()))throw new Error(`invalid since spec: ${m}`);return t}function z(m){const f=m.locByFiletype;if(f===void 0)return 0;let t=0;for(const v of Object.keys(f)){const l=f[v];l!==void 0&&(t+=l.added-l.removed)}return t}const M=new Map;function B(m){if(M.has(m))return M.get(m);try{const f=j(m);return M.set(m,f),f}catch{return M.set(m,m),m}}function N(m,f){let t=m;if(f.since!==void 0){const k=f.since.getTime(),g=[];for(const i of t)new Date(i.updatedAt).getTime()<k||g.push(i);t=g}if(f.dir!==void 0){const k=B(C(f.dir)),g=[];for(const i of t)i.cwd===void 0||i.cwd===""||(i.cwd.startsWith(k+"/")||i.cwd===k)&&g.push(i);t=g}if(f.host!==void 0&&f.host!=="all"){const k=f.host,g=[];for(const i of t)k==="local"?(!i.importedFromMachine||i.upstreamSessionId)&&g.push(i):i.importedFromMachine===k&&!i.upstreamSessionId&&g.push(i);t=g}if(f.interactive!==void 0){const k=f.interactive,g=[];for(const i of t)i.interactive===k&&g.push(i);t=g}const v=f.min??0,l=[];for(const k of t){let g;f.minMetric==="tokens"?g=k.contextTokens:f.minMetric==="loc"?g=z(k):g=k.costAmount,g>v&&l.push(k)}return l}function H(m){return m.dir!==void 0?C(m.dir):C(W())}function $(m,f,t){if(m===void 0||m==="")return"<unknown>";const v=B(C(m));if(f===void 0){const T=B(C(W()));return v===T?"~":v.startsWith(T+"/")?"~/"+v.slice(T.length+1):v}const l=B(C(t));let k=L(l,v);if(k===""||k===".")return"<root>";if(k.startsWith(".."))return"<unknown>";const g=k.split("/");if(g.length===0)return"<root>";const i=Math.min(f,g.length),S=g.slice(0,i);return S.length===0?"<root>":S.join("/")}function J(m,f,t={},v){let l=t.since;if(l===void 0&&t.bucket!==void 0){const e=new Date;t.bucket==="hour"?(e.setHours(e.getHours()-24),l=e):t.bucket==="day"?(e.setDate(e.getDate()-30),l=e):t.bucket==="week"?(e.setMonth(e.getMonth()-6),l=e):t.bucket==="month"&&(e.setFullYear(e.getFullYear()-2),l=e)}if(!(l!==void 0||t.bucket!==void 0||t.tokens===!0||t.loc===!0||t.by!==void 0||t.dir!==void 0||t.interactive!==void 0)){let e=0;for(const r of m)e+=r.costAmount;let o="";for(const r of m){o=r.costCurrency;break}return{kind:"total",row:{label:"All sessions",costAmount:e,sessionCount:m.length},currency:o}}const g={since:l,dir:t.dir,interactive:t.interactive,min:t.min,minMetric:t.loc===!0?"loc":t.tokens===!0?"tokens":"cost"},i=N(m,g),S=new Map;if(f!==void 0)for(const e of f){const o=S.get(e.sessionId);o===void 0?S.set(e.sessionId,[e]):o.push(e)}let T="";if(f!==void 0&&f.length>0)for(const e of f){T=e.currency;break}else if(i.length>0)for(const e of i){T=e.costCurrency;break}if(t.by==="filetype"&&t.bucket===void 0){const e=new Map,o=new Set;for(const u of i){const n=u.locByFiletype;if(n===void 0)continue;let a=!1;for(const d of Object.keys(n)){const w=n[d];if(w===void 0)continue;let s=e.get(d);s===void 0&&(s={added:0,removed:0,sessions:new Set},e.set(d,s)),s.added+=w.added,s.removed+=w.removed,(w.added>0||w.removed>0)&&(s.sessions.add(u.sessionId),a=!0)}a&&o.add(u.sessionId)}const r=[];for(const[u,n]of e){const a={label:u,costAmount:0,sessionCount:n.sessions.size,linesAdded:n.added,linesRemoved:n.removed};r.push({label:u,items:[a]})}return{kind:"grouped",groups:r,currency:T,totalSessions:o.size}}const I=e=>t.by==="dir"?$(e.cwd,t.depth,H(t)):t.by==="session"?e.sessionId.startsWith("hydra_session_")?e.sessionId.slice(14):e.sessionId:t.by==="model"?e.model===""?"<unknown>":e.model:t.by==="agent"?e.agentId===""?"<unknown>":e.agentId:"<all>",R=e=>{const o=new Date(e);if(Number.isNaN(o.getTime()))return"<invalid>";if(t.bucket==="hour"){const r=o.toLocaleDateString(void 0,{month:"2-digit",day:"2-digit"}),u=String(o.getHours()).padStart(2,"0");return`${r} ${u}:00`}if(t.bucket==="day")return o.toLocaleDateString(void 0,{year:"numeric",month:"2-digit",day:"2-digit"});if(t.bucket==="week"){const r=new Date(o),u=r.getDay(),n=r.getDate()-u+(u===0?-6:1);return r.setDate(n),r.toLocaleDateString(void 0,{year:"numeric",month:"2-digit",day:"2-digit"})}return t.bucket==="month"?o.toLocaleDateString(void 0,{year:"numeric",month:"2-digit"}):o.toLocaleDateString(void 0,{year:"numeric",month:"2-digit",day:"2-digit"})};if(t.by===void 0&&t.bucket===void 0){let e=0,o=0,r=0,u=0,n=0,a=0;for(const w of i){e+=w.costAmount;const s=S.get(w.sessionId);if(s!==void 0)for(const c of s)o+=c.deltaCost,t.tokens===!0&&(c.inputTokens!==void 0&&(r+=c.inputTokens),c.outputTokens!==void 0&&(u+=c.outputTokens),c.cacheReadTokens!==void 0&&(n+=c.cacheReadTokens),c.cacheWriteTokens!==void 0&&(a+=c.cacheWriteTokens))}const d={label:"All sessions",costAmount:e,deltaCost:o,sessionCount:i.length};if(t.tokens===!0&&(d.inputTokens=r,d.outputTokens=u,d.cacheReadTokens=n,d.cacheWriteTokens=a),t.loc===!0){let w=0,s=0;for(const c of i){const p=c.locByFiletype;if(p!==void 0)for(const b of Object.keys(p)){const h=p[b];h!==void 0&&(w+=h.added,s+=h.removed)}}d.linesAdded=w,d.linesRemoved=s}return{kind:"total",row:d,currency:T}}if(t.by!==void 0&&t.bucket===void 0){const e=new Map;for(const r of i){const u=I(r);let n=e.get(u);if(n===void 0&&(n={label:u,rows:{label:u,costAmount:0,deltaCost:0,sessionCount:0}},e.set(u,n)),n.rows.costAmount+=r.costAmount,n.rows.sessionCount=(n.rows.sessionCount??0)+1,t.tokens===!0&&(n.rows.inputTokens===void 0&&(n.rows.inputTokens=0),n.rows.inputTokens+=r.contextTokens),t.loc===!0){const d=r.locByFiletype;if(d!==void 0){n.rows.linesAdded===void 0&&(n.rows.linesAdded=0),n.rows.linesRemoved===void 0&&(n.rows.linesRemoved=0);for(const w of Object.keys(d)){const s=d[w];s!==void 0&&(n.rows.linesAdded+=s.added,n.rows.linesRemoved+=s.removed)}}}const a=S.get(r.sessionId);if(a!==void 0)for(const d of a)n.rows.deltaCost+=d.deltaCost,t.tokens===!0&&(n.rows.inputTokens===void 0&&(n.rows.inputTokens=0),n.rows.outputTokens===void 0&&(n.rows.outputTokens=0),n.rows.cacheReadTokens===void 0&&(n.rows.cacheReadTokens=0),n.rows.cacheWriteTokens===void 0&&(n.rows.cacheWriteTokens=0),d.inputTokens!==void 0&&(n.rows.inputTokens+=d.inputTokens),d.outputTokens!==void 0&&(n.rows.outputTokens+=d.outputTokens),d.cacheReadTokens!==void 0&&(n.rows.cacheReadTokens+=d.cacheReadTokens),d.cacheWriteTokens!==void 0&&(n.rows.cacheWriteTokens+=d.cacheWriteTokens))}const o=[];for(const r of e.values())o.push({label:r.label,items:[r.rows]});return{kind:"grouped",groups:o,currency:T}}const E=new Map;for(const e of i)E.set(e.sessionId,e);const A=new Map;if(f!==void 0){for(const e of f){if(!E.has(e.sessionId))continue;const o=A.get(e.sessionId);o===void 0?A.set(e.sessionId,[e]):o.push(e)}for(const e of A.values())e.sort((o,r)=>o.ts.localeCompare(r.ts))}const O=(e,o)=>{e._sessions===void 0&&(e._sessions=new Set),e._sessions.add(o),e.sessionCount=e._sessions.size},_=e=>{delete e._sessions},F=(e,o,r)=>{const u=R(o.ts);let n=e.get(u);n===void 0&&(n={bucket:u,costAmount:0,deltaCost:0,sessionCount:0},e.set(u,n)),n.costAmount+=r,n.deltaCost+=r,O(n,o.sessionId),t.tokens===!0&&(n.inputTokens===void 0||(o.inputTokens??0)>n.inputTokens)&&(n.inputTokens=o.inputTokens??n.inputTokens??0)};if(t.loc===!0&&t.bucket!==void 0){const e=new Set;for(const s of i)e.add(s.sessionId);const o=new Map;for(const s of i)o.set(s.sessionId,s);const r=(s,c)=>{let p=s.get(c);return p===void 0&&(p={bucket:c,costAmount:0,deltaCost:0,sessionCount:0,linesAdded:0,linesRemoved:0},s.set(c,p)),(p.linesAdded??void 0)===void 0&&(p.linesAdded=0),(p.linesRemoved??void 0)===void 0&&(p.linesRemoved=0),p},u=(s,c)=>{s.linesAdded=(s.linesAdded??0)+c.linesAdded,s.linesRemoved=(s.linesRemoved??0)+c.linesRemoved,s._sessions===void 0&&(s._sessions=new Set),s._sessions.add(c.sessionId),s.sessionCount=s._sessions.size},n=s=>{delete s._sessions},a=v??[];if(t.by==="filetype"){const s=new Map,c=new Set;for(const b of a){if(!e.has(b.sessionId)||l!==void 0&&new Date(b.ts)<l)continue;let h=s.get(b.filetype);h===void 0&&(h={label:b.filetype,buckets:new Map},s.set(b.filetype,h));const y=r(h.buckets,R(b.ts));u(y,b),c.add(b.sessionId)}const p=[];for(const b of s.values()){const h=Array.from(b.buckets.values());for(const y of h)n(y);h.sort((y,x)=>y.bucket.localeCompare(x.bucket)),h.length>0&&p.push({label:b.label,items:h})}return{kind:"timeSeriesGrouped",groups:p,currency:T,totalSessions:c.size}}if(t.by!==void 0){const s=new Map;for(const p of a){if(!e.has(p.sessionId)||l!==void 0&&new Date(p.ts)<l)continue;const b=o.get(p.sessionId);if(b===void 0)continue;const h=I(b);let y=s.get(h);y===void 0&&(y={label:h,buckets:new Map},s.set(h,y));const x=r(y.buckets,R(p.ts));u(x,p)}const c=[];for(const p of s.values()){const b=Array.from(p.buckets.values());for(const h of b)n(h);b.sort((h,y)=>h.bucket.localeCompare(y.bucket)),b.length>0&&c.push({label:p.label,items:b})}return{kind:"timeSeriesGrouped",groups:c,currency:T}}const d=new Map;for(const s of a){if(!e.has(s.sessionId)||l!==void 0&&new Date(s.ts)<l)continue;const c=r(d,R(s.ts));u(c,s)}const w=Array.from(d.values());for(const s of w)n(s);return w.sort((s,c)=>s.bucket.localeCompare(c.bucket)),{kind:"timeSeries",timeSeries:w,currency:T}}if(t.by!==void 0&&t.bucket!==void 0){const e=new Map,o=u=>{const n=I(u);let a=e.get(n);return a===void 0&&(a={label:n,buckets:new Map},e.set(n,a)),a.buckets};for(const u of i){const n=A.get(u.sessionId);if(n===void 0||n.length===0)continue;const a=o(u),d=n[0];if(d===void 0)continue;let w=d.cumulativeCost;for(let s=1;s<n.length;s++){const c=n[s];if(c===void 0)continue;const p=Math.max(0,c.cumulativeCost-w);w=c.cumulativeCost,!(l!==void 0&&new Date(c.ts)<l)&&F(a,c,p)}}const r=[];for(const u of e.values()){const n=Array.from(u.buckets.values());for(const a of n)_(a);n.sort((a,d)=>a.bucket.localeCompare(d.bucket)),n.length>0&&r.push({label:u.label,items:n})}return{kind:"timeSeriesGrouped",groups:r,currency:T}}const G=new Map;for(const e of i){const o=A.get(e.sessionId);if(o===void 0||o.length===0)continue;const r=o[0];if(r===void 0)continue;let u=r.cumulativeCost;for(let n=1;n<o.length;n++){const a=o[n];if(a===void 0)continue;const d=Math.max(0,a.cumulativeCost-u);u=a.cumulativeCost,!(l!==void 0&&new Date(a.ts)<l)&&F(G,a,d)}}const D=Array.from(G.values());for(const e of D)_(e);return D.sort((e,o)=>e.bucket.localeCompare(o.bucket)),{kind:"timeSeries",timeSeries:D,currency:T}}export{J as aggregate,N as applyFilters,K as parseSince};
|
package/dist/cost/format.js
CHANGED
|
@@ -6,11 +6,11 @@ function h(e){return"label"in e?e.label:e.bucket}function x(e){let n=0,i=!1;for(
|
|
|
6
6
|
${s.label}:
|
|
7
7
|
`;const d=s.items,c=d.some(p=>p.inputTokens!==void 0||p.outputTokens!==void 0);r?o+=k(d,i,l,u):o+=R(d,c,l,u)}else if(e.kind==="timeSeries"){const t=e.timeSeries.some(s=>s.inputTokens!==void 0||s.outputTokens!==void 0);r?o+=k(e.timeSeries,i,l,u):o+=R(e.timeSeries,t,l,u)}else if(e.kind==="timeSeriesGrouped")for(const t of e.groups){o+=`
|
|
8
8
|
${t.label}:
|
|
9
|
-
`;const s=t.items.some(d=>d.inputTokens!==void 0||d.outputTokens!==void 0);r?o+=k(t.items,i,l,u):o+=R(t.items,s,l,u)}return o}function S(e,n,i){return i?v(e):n?T(e):e.costAmount}function
|
|
10
|
-
`;let r=0;for(const t of e)t.label.length>r&&(r=t.label.length);const l=e.map(t=>
|
|
9
|
+
`;const s=t.items.some(d=>d.inputTokens!==void 0||d.outputTokens!==void 0);r?o+=k(t.items,i,l,u):o+=R(t.items,s,l,u)}return o}function S(e,n,i){return i?v(e):n?T(e):e.costAmount}function B(e,n,i){return i?$(v(e)):n?b(T(e)):A(e.costAmount)}function j(e,n,i){if(e.length===0)return` (no data)
|
|
10
|
+
`;let r=0;for(const t of e)t.label.length>r&&(r=t.label.length);const l=e.map(t=>B(t,n,i));let u=0;for(const t of l)t.length>u&&(u=t.length);const{strs:o,width:f}=x(e.map(t=>t.sessionCount)),a=[];for(let t=0;t<e.length;t++){const s=e[t];if(s===void 0)continue;const d=l[t]??"";let c=` ${s.label.padEnd(r)} ${d.padStart(u)}`;f>0&&(c+=` ${o[t]}`),a.push(c+`
|
|
11
11
|
`)}return a.join("")}function k(e,n,i,r){if(e.length===0)return` (no data)
|
|
12
|
-
`;let l=0;for(const m of e){const g=h(m);g.length>l&&(l=g.length)}const u=e.map(m=>{const g=S(m,i,r);return r?Math.abs(g):g}),o=e.map(m=>
|
|
12
|
+
`;let l=0;for(const m of e){const g=h(m);g.length>l&&(l=g.length)}const u=e.map(m=>{const g=S(m,i,r);return r?Math.abs(g):g}),o=e.map(m=>B(m,i,r));let f=0;for(const m of o)m.length>f&&(f=m.length);const{strs:a,width:t}=x(e.map(m=>m.sessionCount)),s=t>0?t+2:0;let d=n-l-f-s-8;d<1&&(d=e.length>1?1:0);const c=w(u,d),p=[];for(let m=0;m<e.length;m++){const g=e[m];if(g===void 0)continue;const G=h(g).padEnd(l),y=(o[m]??"").padStart(f);let C=` ${G} ${y} ${c[m]??""}`;t>0&&(C+=` ${a[m]}`),p.push(C+`
|
|
13
13
|
`)}return p.join("")}function R(e,n,i,r){if(e.length===0)return` (no data)
|
|
14
|
-
`;let l=28;for(const o of e){const f=h(o);f.length>l&&(l=f.length)}let u=" ";u+=N("
|
|
14
|
+
`;let l=28;for(const o of e){const f=h(o);f.length>l&&(l=f.length)}let u=" ";u+=N("",l),u+=" ",r?u+=" +Added -Removed Net":i?u+=" Tokens":(u+=" Cost",n&&(u+=" Tokens")),u+=`
|
|
15
15
|
`;for(const o of e){const f=h(o).padEnd(l);let a=" ";if(a+=f,a+=" ",r){const t=o.linesAdded??0,s=o.linesRemoved??0;a+=t.toLocaleString().padStart(10),a+=" ",a+=s.toLocaleString().padStart(8),a+=" ",a+=$(t-s).padStart(8)}else if(i){const t=T(o);a+=b(t).padStart(12)}else{const t=o.costAmount??0;if(a+=A(t).padStart(10),n){const s=T(o);a+=" ".padStart(2),a+=b(s).padStart(12)}}u+=a+`
|
|
16
|
-
`}return u}function F(e){const n={kind:e.kind,currency:e.currency};if(e.kind==="total")n.row=
|
|
16
|
+
`}return u}function F(e){const n={kind:e.kind,currency:e.currency};if(e.kind==="total")n.row=L(e.row);else if(e.kind==="grouped"){const i=e.groups.slice().sort((r,l)=>r.label.localeCompare(l.label));n.groups=i.map(r=>({label:r.label,items:r.items.map(L)}))}else if(e.kind==="timeSeries")n.timeSeries=e.timeSeries.map(W);else if(e.kind==="timeSeriesGrouped"){const i=e.groups.slice().sort((r,l)=>r.label.localeCompare(l.label));n.groups=i.map(r=>({label:r.label,items:r.items.map(W)}))}return JSON.stringify(n,null,2)}function L(e){const n={label:e.label,costAmount:e.costAmount};return e.deltaCost!==void 0&&(n.deltaCost=e.deltaCost),e.inputTokens!==void 0&&(n.inputTokens=e.inputTokens),e.outputTokens!==void 0&&(n.outputTokens=e.outputTokens),e.cacheReadTokens!==void 0&&(n.cacheReadTokens=e.cacheReadTokens),e.cacheWriteTokens!==void 0&&(n.cacheWriteTokens=e.cacheWriteTokens),e.linesAdded!==void 0&&(n.linesAdded=e.linesAdded),e.linesRemoved!==void 0&&(n.linesRemoved=e.linesRemoved),(e.linesAdded!==void 0||e.linesRemoved!==void 0)&&(n.linesNet=(e.linesAdded??0)-(e.linesRemoved??0)),n}function W(e){const n={bucket:e.bucket,costAmount:e.costAmount,deltaCost:e.deltaCost};return e.inputTokens!==void 0&&(n.inputTokens=e.inputTokens),e.outputTokens!==void 0&&(n.outputTokens=e.outputTokens),e.cacheReadTokens!==void 0&&(n.cacheReadTokens=e.cacheReadTokens),e.cacheWriteTokens!==void 0&&(n.cacheWriteTokens=e.cacheWriteTokens),e.linesAdded!==void 0&&(n.linesAdded=e.linesAdded),e.linesRemoved!==void 0&&(n.linesRemoved=e.linesRemoved),(e.linesAdded!==void 0||e.linesRemoved!==void 0)&&(n.linesNet=(e.linesAdded??0)-(e.linesRemoved??0)),n}function A(e){return`$${e.toFixed(2)}`}function v(e){const n=e.linesAdded??0,i=e.linesRemoved??0;return n-i}function $(e){return`${e>0?"+":""}${e.toLocaleString()}`}function T(e){let n=0;return e.inputTokens!==void 0&&(n+=e.inputTokens),e.outputTokens!==void 0&&(n+=e.outputTokens),n}function N(e,n){return e.length>=n?e:e+" ".repeat(n-e.length)}function _(e){let n=0;for(const i of e)for(const r of i.items)n+=r.costAmount;return n}export{F as renderJson,E as renderText};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createInterface as
|
|
1
|
+
import{createInterface as j}from"node:readline";import{createReadStream as S,statSync as x}from"node:fs";import{resolve as N}from"node:path";import{logger as _}from"../util/log.js";import{sessionsDir as $}from"./session-store.js";import{filetypeForPath as D}from"./language.js";const R=_("cost/history-stream");function M(n){if(!n||typeof n!="object"||Array.isArray(n))return;const t=n["hydra-acp"];if(!t||typeof t!="object"||Array.isArray(t))return;const e=t.cumulativeCost;return typeof e=="number"?e:void 0}function L(n){const t=M(n._meta),e=n.cost??void 0,c=t!==void 0?t:typeof e?.amount=="number"?e.amount:void 0;if(c===void 0)return;const f=typeof e?.currency=="string"?e.currency:void 0;return{amount:c,currency:f}}function O(n){const t=n.recordedAt;return typeof t=="number"?new Date(t).toISOString():typeof t=="string"?t:""}async function*q(n){const t=Array.isArray(n)?n:[n];for(const e of t){const c=N($(),e.sessionId,"history.jsonl");try{x(c)}catch(y){const o=y;if(o.code==="ENOENT"){R.debug(`no history for ${e.sessionId}`);continue}R.debug(`stat failed for ${c}: ${o.message}`);continue}const f=S(c,{encoding:"utf8"}),h=j({input:f,crlfDelay:1/0}),m=new Map;try{for await(const y of h){if(y.length===0)continue;let o;try{o=JSON.parse(y)}catch{R.debug(`malformed JSON in history.jsonl for ${e.sessionId}`);continue}if(!o||typeof o!="object"||Array.isArray(o))continue;const r=o;if(r.method!=="session/update")continue;const a=r.params??void 0;if(!a||typeof a!="object"||Array.isArray(a))continue;const i=a.update??void 0;if(!i||typeof i!="object"||Array.isArray(i)||i.sessionUpdate!=="usage_update")continue;const u=O(r),p=L(i);if(p===void 0)continue;const w=p.currency??"",b=p.amount,g=m.get(e.sessionId)??0,d=Math.max(0,b-g);m.set(e.sessionId,b);const s=i.usage??void 0;let A,k,l,v;if(s&&typeof s=="object"&&!Array.isArray(s)){const I=s.inputTokens;typeof I=="number"&&(A=I);const T=s.outputTokens;typeof T=="number"&&(k=T);const E=s.cacheReadInputTokens;typeof E=="number"&&(l=E);const C=s.cacheCreationInputTokens;typeof C=="number"&&(v=C)}yield{sessionId:e.sessionId,ts:u,deltaCost:d,cumulativeCost:b,currency:w,...A!==void 0&&{inputTokens:A},...k!==void 0&&{outputTokens:k},...l!==void 0&&{cacheReadTokens:l},...v!==void 0&&{cacheWriteTokens:v}}}}finally{h.close(),f.destroy()}}}function J(n){if(n.length===0)return 0;let t=1;for(let e=0;e<n.length;e++)n.charCodeAt(e)===10&&t++;return n.charCodeAt(n.length-1)===10&&t--,t}async function*z(n){const t=Array.isArray(n)?n:[n];for(const e of t){const c=N($(),e.sessionId,"history.jsonl");try{x(c)}catch(o){const r=o;if(r.code==="ENOENT")continue;R.debug(`stat failed for ${c}: ${r.message}`);continue}const f=S(c,{encoding:"utf8"}),h=j({input:f,crlfDelay:1/0}),m=new Map,y=[];try{for await(const o of h){if(o.length===0)continue;let r;try{r=JSON.parse(o)}catch{continue}if(!r||typeof r!="object"||Array.isArray(r))continue;const a=r;if(a.method!=="session/update")continue;const i=a.params??void 0;if(!i||typeof i!="object"||Array.isArray(i))continue;const u=i.update??void 0;if(!u||typeof u!="object"||Array.isArray(u)||u.sessionUpdate!=="tool_call"&&u.sessionUpdate!=="tool_call_update")continue;const p=u.content;if(!Array.isArray(p)||p.length===0)continue;const w=typeof u.toolCallId=="string"?u.toolCallId:"";if(w==="")continue;const b=O(a);for(const g of p){if(!g||typeof g!="object"||Array.isArray(g))continue;const d=g;if(d.type!=="diff")continue;const s=typeof d.path=="string"?d.path:"";if(s==="")continue;const A=typeof d.oldText=="string"?d.oldText:"",k=typeof d.newText=="string"?d.newText:"",l=`${w}|${s}`;m.has(l)||y.push(l),m.set(l,{sessionId:e.sessionId,ts:b,path:s,filetype:D(s),linesAdded:J(k),linesRemoved:J(A)})}}}finally{h.close(),f.destroy()}for(const o of y){const r=m.get(o);r!==void 0&&(yield r)}}}export{z as streamHistoryEditEvents,q as streamHistoryEvents};
|
package/dist/cost/language.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const
|
|
1
|
+
const f={Dockerfile:"Dockerfile",Makefile:"Makefile",GNUmakefile:"Makefile",Rakefile:"Rakefile",Gemfile:"Gemfile","CMakeLists.txt":"CMakeLists.txt"};function l(e){const i=e.lastIndexOf("/"),t=i>=0?e.slice(i+1):e,s=f[t];if(s!==void 0)return s;const n=t.lastIndexOf(".");return n<=0?"<no ext>":t.slice(n).toLowerCase()}export{l as filetypeForPath};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{readdirSync as k,readFileSync as M,realpathSync as C,statSync as E}from"node:fs";import{isAbsolute as x,resolve as a}from"node:path";import{homedir as
|
|
1
|
+
import{readdirSync as k,readFileSync as M,realpathSync as C,statSync as E}from"node:fs";import{isAbsolute as x,resolve as a}from"node:path";import{homedir as F}from"node:os";import{logger as j}from"../util/log.js";const c=j("cost/session-store"),f=new Map;function $(n){if(f.has(n))return f.get(n);try{const s=C(n);return f.set(n,s),s}catch{f.set(n,void 0);return}}function N(){const n=process.env.HYDRA_ACP_HOME??a(F(),".hydra-acp");return a(n,"sessions")}function J(n){const s=a(n,"meta.json");let o;try{o=M(s,"utf8")}catch(p){const g=p;if(g.code==="ENOENT")return;c.debug(`skipping ${n}: read meta.json failed: ${g.message}`);return}let t;try{t=JSON.parse(o)}catch{c.debug(`skipping ${n}: meta.json is not valid JSON`);return}if(!t||typeof t!="object"||Array.isArray(t)){c.debug(`skipping ${n}: meta.json is not an object`);return}const e=t,r=typeof e.sessionId=="string"?e.sessionId:void 0;if(r===void 0){c.debug(`skipping ${n}: missing sessionId`);return}let i;const u=typeof e.cwd=="string"?e.cwd:void 0;u!==void 0&&(x(u)?i=$(u):i=u);const m=typeof e.agentId=="string"?e.agentId:"",y=typeof e.currentModel=="string"?e.currentModel:"",l=e.interactive===!0,d=e.currentUsage??void 0,S=typeof d?.costAmount=="number"?d.costAmount:0,A=typeof d?.costCurrency=="string"?d.costCurrency:"",b=typeof d?.used=="number"?d.used:0,w=typeof e.title=="string"?e.title:"",h=typeof e.createdAt=="string"?e.createdAt:"",v=typeof e.updatedAt=="string"?e.updatedAt:"",I=typeof e.importedFromMachine=="string"&&e.importedFromMachine.length>0?e.importedFromMachine:void 0,R=typeof e.upstreamSessionId=="string"&&e.upstreamSessionId.length>0?e.upstreamSessionId:void 0;return{sessionId:r,cwd:i,agentId:m,model:y,interactive:l,costAmount:S,costCurrency:A,contextTokens:b,title:w,createdAt:h,updatedAt:v,importedFromMachine:I,upstreamSessionId:R}}async function U(n){const{streamHistoryEditEvents:s}=await import("./history-stream.js");for(const o of n){const t={};for await(const e of s(o)){const r=t[e.filetype]??{added:0,removed:0};r.added+=e.linesAdded,r.removed+=e.linesRemoved,t[e.filetype]=r}o.locByFiletype=t}return n}function _(){const n=N();let s;try{s=k(n)}catch(t){const e=t;return c.debug(`session store not found at ${n}: ${e.message}`),[]}const o=[];for(const t of s){const e=a(n,t);let r;try{r=E(e)}catch{continue}if(!r.isDirectory())continue;const i=J(e);i!==void 0&&o.push(i)}return o}export{U as enrichSessionsWithLoc,_ as scanSessions,N as sessionsDir};
|
package/dist/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{readFileSync as
|
|
2
|
+
import{readFileSync as $}from"node:fs";import{dirname as C,resolve as U}from"node:path";import{fileURLToPath as P}from"node:url";import{loadConfig as N}from"./config.js";import{BudgeterBridge as x}from"./bridge.js";import{stateFilePath as I}from"./paths.js";import{DEFAULT_RULE as M}from"./rule.js";import{deleteStateFile as G}from"./tracker.js";import{logger as H,setDebug as W}from"./util/log.js";import{scanSessions as j,enrichSessionsWithLoc as A}from"./cost/session-store.js";import{listSessionsFromDaemon as B,fetchUsageEventsFromDaemon as _}from"./cost/daemon-client.js";import{streamHistoryEditEvents as J}from"./cost/history-stream.js";import{aggregate as Y,applyFilters as q,parseSince as V}from"./cost/aggregate.js";import{renderText as K,renderJson as Z}from"./cost/format.js";const D=H("main");function O(){try{const t=C(P(import.meta.url));return JSON.parse($(U(t,"../package.json"),"utf8")).version??"unknown"}catch{return"unknown"}}function z(){G(I()),process.stdout.write(`hydra-acp-budgeter accumulated cost reset
|
|
3
3
|
`)}const Q=`Usage: hydra budgeter usage [OPTIONS]
|
|
4
4
|
|
|
5
5
|
Options:
|
|
6
6
|
--since <date|duration> Only include sessions updated after this date (e.g. 7d, 2024-01-01)
|
|
7
7
|
--bucket <hour|day|week|month> Group results into time buckets (implies --since 24h/30d/6m/2y)
|
|
8
|
-
--by <dir|session|model|agent|
|
|
8
|
+
--by <dir|session|model|agent|filetype> Group by dimension (filetype requires --metric loc)
|
|
9
9
|
--depth <N> Depth for --by dir grouping (default: 1)
|
|
10
10
|
--dir <path> Only include sessions under this directory prefix
|
|
11
11
|
--interactive Only include interactive sessions (default: include both)
|
|
@@ -14,17 +14,18 @@ Options:
|
|
|
14
14
|
every session; <name> shows passive mirrors imported from
|
|
15
15
|
that host.
|
|
16
16
|
--min <N> Drop sessions whose active-metric value is <= N (default: 0)
|
|
17
|
-
--histogram Show an ASCII histogram bar next to each row (implies --bucket
|
|
17
|
+
--histogram Show an ASCII histogram bar next to each row (implies --bucket hour if no bucket given)
|
|
18
18
|
--metric <cost|tokens|loc> Display metric (default: cost). "loc" counts net lines of code
|
|
19
19
|
from Edit/Write tool diffs in session history.
|
|
20
20
|
--json Output as JSON
|
|
21
|
-
--help Show this help message`;async function
|
|
22
|
-
`);return}let
|
|
21
|
+
--help Show this help message`;async function R(t){if(t.includes("--help")){process.stdout.write(Q+`
|
|
22
|
+
`);return}let r,n,i,u,l,p=!1,f,c=!1,o,g=!1,h;for(let e=0;e<t.length;e++){const s=t[e];if(s!==void 0){if(s==="--since")e+=1,r=t[e];else if(s==="--bucket")e+=1,n=t[e];else if(s==="--by")e+=1,i=t[e];else if(s==="--depth")e+=1,u=t[e];else if(s==="--dir")e+=1,l=t[e];else if(s==="--interactive")p=!0;else if(s==="--min")e+=1,f=t[e];else if(s==="--histogram")c=!0;else if(s==="--metric")e+=1,o=t[e];else if(s==="--json")g=!0;else if(s==="--host")e+=1,h=t[e];else if(s.startsWith("--host="))h=s.slice(7);else if(s.startsWith("--"))throw new Error(`Unknown option: ${s}
|
|
23
23
|
Run "hydra budgeter usage --help" for usage.`)}}if(o!==void 0&&o!=="cost"&&o!=="tokens"&&o!=="loc")throw new Error(`Invalid --metric value. Must be 'cost', 'tokens', or 'loc'.
|
|
24
|
-
Run "hydra budgeter usage --help" for usage.`);const
|
|
25
|
-
Run "hydra budgeter usage --help" for usage.`);
|
|
26
|
-
Run "hydra budgeter usage --help" for usage.`)
|
|
27
|
-
|
|
24
|
+
Run "hydra budgeter usage --help" for usage.`);const a=o==="loc";if(i!==void 0&&!new Set(["dir","session","model","agent","filetype"]).has(i))throw new Error(`Invalid --by value: ${i}. Must be one of: dir, session, model, agent, filetype.
|
|
25
|
+
Run "hydra budgeter usage --help" for usage.`);if(i==="filetype"&&!a)throw new Error(`--by filetype requires --metric loc.
|
|
26
|
+
Run "hydra budgeter usage --help" for usage.`);let y;if(r!==void 0)try{y=V(r)}catch(e){const s=e;throw new Error(`Invalid --since value: ${s.message}
|
|
27
|
+
Run "hydra budgeter usage --help" for usage.`)}t.length===0&&(c=!0),c&&n===void 0&&(n="hour");let d=y;if(d===void 0&&n!==void 0){const e=new Date;n==="hour"?(e.setHours(e.getHours()-24),d=e):n==="day"?(e.setDate(e.getDate()-30),d=e):n==="week"?(e.setMonth(e.getMonth()-6),d=e):n==="month"&&(e.setFullYear(e.getFullYear()-2),d=e)}const w=p?!0:void 0,m=o==="tokens",v=f!==void 0?parseFloat(f):void 0,b=await B()??j();(a||i==="filetype")&&await A(b);const E=q(b,{since:d,dir:l,interactive:w,min:v,minMetric:a?"loc":m?"tokens":"cost",host:h??"local"});let k;if(n!==void 0){const e=await _();e!==void 0&&(k=e.map(s=>({sessionId:s.sessionId,ts:s.ts,deltaCost:0,cumulativeCost:s.costCumulative,currency:s.costCurrency,inputTokens:s.contextTokens})))}let S;if(a&&n!==void 0){const e=[];for await(const s of J(E))e.push(s);S=e}const F=u!==void 0?parseInt(u,10):void 0,T=Y(E,k,{by:i,depth:F,bucket:n,since:d,interactive:w,dir:l,tokens:m,loc:a,min:v},S);if(g)process.stdout.write(Z(T)+`
|
|
28
|
+
`);else{const e=K(T,{histogram:c,tokens:m,loc:a});process.stdout.write(e)}}async function X(){const t=N();W(t.debug);const r=I(),n=new x({daemonWsUrl:t.hydraWsUrl,token:t.hydraToken,softLimit:t.softLimit,hardLimit:t.hardLimit,currency:t.currency,rule:M,statePath:r});n.start();const i=u=>{D.info(`${u} received \u2014 shutting down`),n.stop(),setTimeout(()=>process.exit(0),200).unref()};process.on("SIGINT",()=>i("SIGINT")),process.on("SIGTERM",()=>i("SIGTERM")),D.info(`hydra-acp-budgeter up; daemon=${t.hydraDaemonUrl} soft=${t.softLimit} hard=${t.hardLimit} ${t.currency} state=${r}`)}function ee(){process.stdout.write(`hydra-acp-budgeter ${O()}
|
|
28
29
|
|
|
29
30
|
Usage:
|
|
30
31
|
hydra budgeter [usage] <flags> Report historical cost/usage across sessions
|
|
@@ -34,5 +35,5 @@ Flags:
|
|
|
34
35
|
-v, --version Print version and exit
|
|
35
36
|
-h, --help Show this help
|
|
36
37
|
`)}async function te(){const t=process.argv.slice(2);if(t.includes("--version")||t.includes("-v")){process.stdout.write(`hydra-acp-budgeter ${O()}
|
|
37
|
-
`);return}if((t[0]==="help"||t.includes("--help")||t.includes("-h"))&&t[0]!=="usage"&&t[0]!=="cost"){ee();return}if(t[0]==="reset"){z();return}if(t[0]==="usage"||t[0]==="cost"){await
|
|
38
|
+
`);return}if((t[0]==="help"||t.includes("--help")||t.includes("-h"))&&t[0]!=="usage"&&t[0]!=="cost"){ee();return}if(t[0]==="reset"){z();return}if(t[0]==="usage"||t[0]==="cost"){await R(t.slice(1));return}if(t[0]==="run"||process.env.HYDRA_ACP_TOKEN){await X();return}await R(t)}te().catch(t=>{process.stderr.write(`hydra-acp-budgeter: ${t.message}
|
|
38
39
|
`),process.exit(1)});
|
package/package.json
CHANGED