@adhd/agent-plugin-budget 0.2.1 → 0.2.3

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.
Files changed (4) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/index.cjs +7 -9
  3. package/index.js +529 -703
  4. package/package.json +2 -2
package/CHANGELOG.md CHANGED
@@ -1,3 +1,18 @@
1
+ ## 0.2.2 (2026-09-26)
2
+
3
+ ### 🚀 Features
4
+
5
+ - **vite-plugins:** absorb perf/test-resolve-fix — test-time @adhd/* source resolution ([3e344506](https://github.com/PseudoSky/adhd/commit/3e344506))
6
+
7
+ ### 🩹 Fixes
8
+
9
+ - **vite:** restore import.meta.url in CJS output under vite 8 ([7916e639](https://github.com/PseudoSky/adhd/commit/7916e639))
10
+ - **nx:** finish the ESLint v9 flat-config migration and unblock the gate ([53f4ff3e](https://github.com/PseudoSky/adhd/commit/53f4ff3e))
11
+
12
+ ### ❤️ Thank You
13
+
14
+ - pseudosky
15
+
1
16
  ## 0.2.1 (2026-09-24)
2
17
 
3
18
  This was a version bump only for agent-plugin-budget to align it with other projects, there were no code changes.
package/index.cjs CHANGED
@@ -1,29 +1,27 @@
1
- "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const u=require("zod"),M=require("@adhd/agent-base-types");function b(c){const t=/^P(?:(\d+)Y)?(?:(\d+)M)?(?:(\d+)D)?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+(?:\.\d+)?)S)?)?$/,e=c.match(t);if(!e)throw new Error(`invalid ISO 8601 duration: ${c}`);const[,o,s,n,i,r,a]=e;let l=0;return o&&(l+=parseInt(o)*365.25*864e5),s&&(l+=parseInt(s)*30.44*864e5),n&&(l+=parseInt(n)*864e5),i&&(l+=parseInt(i)*36e5),r&&(l+=parseInt(r)*6e4),a&&(l+=parseFloat(a)*1e3),Math.round(l)}const y=["context","inputTokens","outputTokens","calls","wallClock","modelMs","cost","toolCalls","errors","consecutiveErrors","responseSize"],_=new Set(["toolCalls","errors","consecutiveErrors"]),A=u.z.object({field:u.z.enum(y),maximum:u.z.number().min(0).optional(),contextWindowFraction:u.z.number().min(0).max(1).optional(),window:u.z.string().optional(),scope:u.z.enum(["task","session","agent","global"]).optional(),mode:u.z.enum(["warning","block"]).optional(),message:u.z.string().optional()}).superRefine((c,t)=>{if(c.field==="context"){const e=c.maximum!==void 0,o=c.contextWindowFraction!==void 0;e===o&&t.addIssue({code:u.z.ZodIssueCode.custom,path:["contextWindowFraction"],message:"cap field 'context' requires exactly one of 'maximum' or 'contextWindowFraction'"}),c.window!==void 0&&t.addIssue({code:u.z.ZodIssueCode.custom,path:["window"],message:"cap field 'context' rejects 'window' — a windowed peak is meaningless; windowed cumulative volume is expressible via 'inputTokens'/'outputTokens' + 'window'"})}else(c.field==="errors"||c.field==="consecutiveErrors")&&(c.window!==void 0&&t.addIssue({code:u.z.ZodIssueCode.custom,path:["window"],message:`cap field '${c.field}' rejects 'window' — windowed error budgets are not expressible this wave`}),c.scope!==void 0&&c.scope!=="task"&&t.addIssue({code:u.z.ZodIssueCode.custom,path:["scope"],message:`cap field '${c.field}' is counted per-task in memory (no task_usage column) — only 'task' scope is expressible this wave`})),c.window!==void 0&&(c.scope===void 0||c.scope==="task")&&t.addIssue({code:u.z.ZodIssueCode.custom,path:["scope"],message:`cap field '${c.field}' carries 'window' but resolves to 'task' scope, where windowed caps are a silent no-op (no task-level window query); set an explicit 'scope': 'session' | 'agent' | 'global'`}),c.contextWindowFraction!==void 0&&t.addIssue({code:u.z.ZodIssueCode.custom,path:["contextWindowFraction"],message:`'contextWindowFraction' is only valid on cap field 'context' (got '${c.field}')`}),c.maximum===void 0&&t.addIssue({code:u.z.ZodIssueCode.custom,path:["maximum"],message:`cap field '${c.field}' requires a 'maximum'`})}),g=u.z.object({caps:u.z.array(A).optional(),mode:u.z.enum(["warning","block"]).optional(),costPerInputToken:u.z.number().min(0).optional(),costPerOutputToken:u.z.number().min(0).optional(),costPerCacheReadToken:u.z.number().min(0).optional(),costPerCacheWriteToken:u.z.number().min(0).optional(),scope:u.z.enum(["task","session","agent","global"]).optional()}),x=g.partial().superRefine((c,t)=>{const e=c.caps??[];for(const[o,s]of e.entries())s.field==="context"&&t.addIssue({code:u.z.ZodIssueCode.custom,path:["caps",o,"field"],message:"cap field 'context' is only valid at model scope — a tool-scoped 'context' cap is a silent no-op (enforced on the model path, invisible to tool overrides); place it in 'defaults'/'agent'/'provider' instead"})}),S=u.z.object({defaults:g.optional(),agent:u.z.object({default:g.optional(),overrides:u.z.record(u.z.string(),g.partial()).optional().default({})}).optional(),provider:u.z.object({default:g.optional(),overrides:u.z.record(u.z.string(),g.partial()).optional().default({})}).optional(),tool:u.z.object({default:x.optional(),overrides:u.z.record(u.z.string(),x).optional().default({})}).optional()}),O=u.z.object({}).passthrough(),P={maxInputTokens:{field:"inputTokens"},maxOutputTokens:{field:"outputTokens"},maxModelCalls:{field:"calls"},maxWallClockMs:{field:"wallClock"},maxModelMs:{field:"modelMs"},maxCostUSD:{field:"cost"},maxTokensPer24h:{field:"inputTokens",window:"PT24H"},maxCalls:{field:"toolCalls"}};function I(c){const t=[],e={};for(const[n,i]of Object.entries(c)){const r=P[n];if(r&&typeof i=="number"){const a={field:r.field,maximum:i};r.window&&(a.window=r.window),t.push(a)}else(n==="scope"||n==="mode"||n==="costPerInputToken"||n==="costPerOutputToken"||n==="costPerCacheReadToken"||n==="costPerCacheWriteToken"||n==="message")&&(e[n]=i)}t.length>0&&(e.caps=t);const o=e.scope,s=o==="task"||o==="session"||o==="agent"||o==="global"?o:void 0;for(const n of t)n.window!==void 0&&n.scope===void 0&&(n.scope=s??"global");return g.parse(e)}const w=c=>`legacy 'tokens' budget cap detected (${c}): cap field 'tokens' is removed; use 'context' (peak request input) or 'inputTokens'/'outputTokens' (windowed volume)`;function z(c){const t=c??{};if(typeof t.maxTotalTokens=="number")throw new Error(w("flat 'maxTotalTokens'"));const e=s=>{if(typeof s!="object"||s===null)return;const n=s;if(typeof n.maxTotalTokens=="number")throw new Error(w("structured 'maxTotalTokens'"));const i=n.caps;if(Array.isArray(i)){for(const r of i)if(typeof r=="object"&&r!==null&&r.field==="tokens")throw new Error(w("caps[].field === 'tokens'"))}},o=s=>{if(typeof s!="object"||s===null)return;const n=s;e(n),"default"in n&&e(n.default);const i=n.overrides;if(typeof i=="object"&&i!==null)for(const r of Object.values(i))e(r)};e(t.defaults),o(t.agent),o(t.provider),o(t.tool)}function $(c){z(c);const t=c;if(t.defaults!==void 0||t.agent!==void 0||t.provider!==void 0||t.tool!==void 0){const e=S.parse(c);return{defaults:e.defaults??g.parse({}),agent:e.agent??{overrides:{}},provider:e.provider??{overrides:{}},tool:e.tool??{overrides:{}}}}return{defaults:I(t),agent:{overrides:{}},provider:{overrides:{}},tool:{overrides:{}}}}function v(c,t,e,o){return{isEnforcementError:!0,code:"BUDGET_EXCEEDED",message:o??`${c} limit is ${t}, current value is ${Math.round(e)}`}}function R(c,t,e){return{isToolWarning:!0,toolName:c,callId:t,message:e}}function L(c,t){var o;let e=0;for(const s of c){e+=((o=s.content)==null?void 0:o.length)??0;for(const n of s.toolCalls??[])e+=JSON.stringify(n.arguments??{}).length;for(const n of s.toolResults??[])e+=JSON.stringify(n.result??null).length}for(const s of t)e+=JSON.stringify({name:s.name,description:s.description,inputSchema:s.inputSchema}).length;return Math.ceil(e/4)}class W{constructor(t,e,o=0,s=0,n=0,i=0){this.db=t,this.cfg=e,this.costPerInput=o,this.costPerOutput=s,this.costPerCacheRead=n,this.costPerCacheWrite=i,this.name="agent-mcp-budget",this.accumulators=new Map}install(t){this.hooks=t,t.register("task:start",e=>{try{this.onTaskStart(e)}catch{}}),t.register("pre:model_request",e=>{try{this.onPreModelRequest(e)}catch{}}),t.register("post:model_response",e=>{try{this.onPostModelResponse(e)}catch{}}),t.register("post:tool_call",e=>{try{this.onPostToolCall(e)}catch{}}),t.register("task:completed",e=>{try{this.onTerminal(e.executionContext.taskId)}catch{}}),t.register("task:failed",e=>{try{this.onTerminal(e.executionContext.taskId)}catch{}}),t.register("task:cancelled",e=>{try{this.onTerminal(e.executionContext.taskId)}catch{}}),t.registerEnforcement("pre:model_request",e=>this.enforcePreModel(e)),t.registerEnforcement("pre:tool_call",e=>this.enforcePreTool(e)),t.register("transform:tool_result",e=>{try{this.enforceResponseSize(e)}catch{}})}onTaskStart(t){var i,r;const{taskId:e,sessionId:o,agentName:s}=t.executionContext,n=((r=(i=t.executionContext.agentDefinition)==null?void 0:i.provider)==null?void 0:r.type)??"unknown";this.accumulators.set(e,{taskId:e,sessionId:o??void 0,agentName:s,providerType:n,startedAtMs:Date.now(),uncachedInputTokens:0,cacheReadTokens:0,cacheCreationTokens:0,inputTokens:0,outputTokens:0,peakContextTokens:0,modelCalls:0,totalModelMs:0,toolCalls:new Map,errors:0,consecutiveErrors:0})}onPreModelRequest(t){const e=this.accumulators.get(t.executionContext.taskId);e&&(e.modelCallStartMs=Date.now())}onPostModelResponse(t){const e=this.accumulators.get(t.executionContext.taskId);if(!e)return;const o=t.tokenUsage;if(o){const s=o.inputTokens??0,n=o.cacheReadTokens??0,i=o.cacheCreationTokens??0,a=o.uncachedInputTokens!==void 0||o.cacheReadTokens!==void 0||o.cacheCreationTokens!==void 0?o.uncachedInputTokens??Math.max(0,s-n-i):s;e.uncachedInputTokens+=a,e.cacheReadTokens+=n,e.cacheCreationTokens+=i,e.inputTokens+=a+n+i,e.outputTokens+=o.outputTokens??0,e.peakContextTokens=Math.max(e.peakContextTokens,s)}e.modelCalls+=1,e.modelCallStartMs!==void 0&&(e.totalModelMs+=Date.now()-e.modelCallStartMs,e.modelCallStartMs=void 0)}onTerminal(t){this.accumulators.delete(t)}onPostToolCall(t){const e=this.accumulators.get(t.executionContext.taskId);e&&(t.isError?(e.errors+=1,e.consecutiveErrors+=1):e.consecutiveErrors=0)}mergeDim(t){let e={caps:[]};for(const o of t)o&&(e={caps:[...e.caps??[],...o.caps??[]],mode:o.mode??e.mode,costPerInputToken:o.costPerInputToken??e.costPerInputToken,costPerOutputToken:o.costPerOutputToken??e.costPerOutputToken,costPerCacheReadToken:o.costPerCacheReadToken??e.costPerCacheReadToken,costPerCacheWriteToken:o.costPerCacheWriteToken??e.costPerCacheWriteToken,scope:o.scope??e.scope});return e}resolveCaps(t,e,o){var f,d,k;const s=this.cfg.defaults,n=this.cfg.agent,i=this.cfg.provider,r=this.cfg.tool;if(o){const m=(f=r==null?void 0:r.overrides)==null?void 0:f[o],h=this.mergeDim([s,r==null?void 0:r.default,m]);return{caps:h.caps??[],mode:h.mode,scope:h.scope}}const a=(d=n==null?void 0:n.overrides)==null?void 0:d[t],l=(k=i==null?void 0:i.overrides)==null?void 0:k[e],p=this.mergeDim([s,n==null?void 0:n.default,a,i==null?void 0:i.default,l]);return{caps:p.caps??[],mode:p.mode,scope:p.scope}}queryScopeTotals(t,e,o,s){const n=this.accumulators.get(t),i=n?{inputTokens:n.inputTokens,outputTokens:n.outputTokens,modelCalls:n.modelCalls,peakContextTokens:n.peakContextTokens}:{inputTokens:0,outputTokens:0,modelCalls:0,peakContextTokens:0};if(s==="task"||!this.db)return i;try{const r=this.db;let a;if(s==="session"&&e?a=r.prepare(`SELECT
1
+ Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});let e=require("zod"),t=require("@adhd/agent-base-types");function n(e){let t=e.match(/^P(?:(\d+)Y)?(?:(\d+)M)?(?:(\d+)D)?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+(?:\.\d+)?)S)?)?$/);if(!t)throw Error(`invalid ISO 8601 duration: ${e}`);let[,n,r,i,a,o,s]=t,c=0;return n&&(c+=parseInt(n)*365.25*864e5),r&&(c+=parseInt(r)*30.44*864e5),i&&(c+=parseInt(i)*864e5),a&&(c+=parseInt(a)*36e5),o&&(c+=parseInt(o)*6e4),s&&(c+=parseFloat(s)*1e3),Math.round(c)}var r=[`context`,`inputTokens`,`outputTokens`,`calls`,`wallClock`,`modelMs`,`cost`,`toolCalls`,`errors`,`consecutiveErrors`,`responseSize`],i=new Set([`toolCalls`,`errors`,`consecutiveErrors`]),a=e.z.object({field:e.z.enum(r),maximum:e.z.number().min(0).optional(),contextWindowFraction:e.z.number().min(0).max(1).optional(),window:e.z.string().optional(),scope:e.z.enum([`task`,`session`,`agent`,`global`]).optional(),mode:e.z.enum([`warning`,`block`]).optional(),message:e.z.string().optional()}).superRefine((t,n)=>{t.field===`context`?(t.maximum!==void 0==(t.contextWindowFraction!==void 0)&&n.addIssue({code:e.z.ZodIssueCode.custom,path:[`contextWindowFraction`],message:`cap field 'context' requires exactly one of 'maximum' or 'contextWindowFraction'`}),t.window!==void 0&&n.addIssue({code:e.z.ZodIssueCode.custom,path:[`window`],message:`cap field 'context' rejects 'window' — a windowed peak is meaningless; windowed cumulative volume is expressible via 'inputTokens'/'outputTokens' + 'window'`})):((t.field===`errors`||t.field===`consecutiveErrors`)&&(t.window!==void 0&&n.addIssue({code:e.z.ZodIssueCode.custom,path:[`window`],message:`cap field '${t.field}' rejects 'window' — windowed error budgets are not expressible this wave`}),t.scope!==void 0&&t.scope!==`task`&&n.addIssue({code:e.z.ZodIssueCode.custom,path:[`scope`],message:`cap field '${t.field}' is counted per-task in memory (no task_usage column) — only 'task' scope is expressible this wave`})),t.window!==void 0&&(t.scope===void 0||t.scope===`task`)&&n.addIssue({code:e.z.ZodIssueCode.custom,path:[`scope`],message:`cap field '${t.field}' carries 'window' but resolves to 'task' scope, where windowed caps are a silent no-op (no task-level window query); set an explicit 'scope': 'session' | 'agent' | 'global'`}),t.contextWindowFraction!==void 0&&n.addIssue({code:e.z.ZodIssueCode.custom,path:[`contextWindowFraction`],message:`'contextWindowFraction' is only valid on cap field 'context' (got '${t.field}')`}),t.maximum===void 0&&n.addIssue({code:e.z.ZodIssueCode.custom,path:[`maximum`],message:`cap field '${t.field}' requires a 'maximum'`}))}),o=e.z.object({caps:e.z.array(a).optional(),mode:e.z.enum([`warning`,`block`]).optional(),costPerInputToken:e.z.number().min(0).optional(),costPerOutputToken:e.z.number().min(0).optional(),costPerCacheReadToken:e.z.number().min(0).optional(),costPerCacheWriteToken:e.z.number().min(0).optional(),scope:e.z.enum([`task`,`session`,`agent`,`global`]).optional()}),s=o.partial().superRefine((t,n)=>{let r=t.caps??[];for(let[t,i]of r.entries())i.field===`context`&&n.addIssue({code:e.z.ZodIssueCode.custom,path:[`caps`,t,`field`],message:`cap field 'context' is only valid at model scope — a tool-scoped 'context' cap is a silent no-op (enforced on the model path, invisible to tool overrides); place it in 'defaults'/'agent'/'provider' instead`})}),c=e.z.object({defaults:o.optional(),agent:e.z.object({default:o.optional(),overrides:e.z.record(e.z.string(),o.partial()).optional().default({})}).optional(),provider:e.z.object({default:o.optional(),overrides:e.z.record(e.z.string(),o.partial()).optional().default({})}).optional(),tool:e.z.object({default:s.optional(),overrides:e.z.record(e.z.string(),s).optional().default({})}).optional()}),l=e.z.object({}).passthrough(),u={maxInputTokens:{field:`inputTokens`},maxOutputTokens:{field:`outputTokens`},maxModelCalls:{field:`calls`},maxWallClockMs:{field:`wallClock`},maxModelMs:{field:`modelMs`},maxCostUSD:{field:`cost`},maxTokensPer24h:{field:`inputTokens`,window:`PT24H`},maxCalls:{field:`toolCalls`}};function d(e){let t=[],n={};for(let[r,i]of Object.entries(e)){let e=u[r];if(e&&typeof i==`number`){let n={field:e.field,maximum:i};e.window&&(n.window=e.window),t.push(n)}else(r===`scope`||r===`mode`||r===`costPerInputToken`||r===`costPerOutputToken`||r===`costPerCacheReadToken`||r===`costPerCacheWriteToken`||r===`message`)&&(n[r]=i)}t.length>0&&(n.caps=t);let r=n.scope,i=r===`task`||r===`session`||r===`agent`||r===`global`?r:void 0;for(let e of t)e.window!==void 0&&e.scope===void 0&&(e.scope=i??`global`);return o.parse(n)}var f=e=>`legacy 'tokens' budget cap detected (${e}): cap field 'tokens' is removed; use 'context' (peak request input) or 'inputTokens'/'outputTokens' (windowed volume)`;function p(e){let t=e??{};if(typeof t.maxTotalTokens==`number`)throw Error(f(`flat 'maxTotalTokens'`));let n=e=>{if(typeof e!=`object`||!e)return;let t=e;if(typeof t.maxTotalTokens==`number`)throw Error(f(`structured 'maxTotalTokens'`));let n=t.caps;if(Array.isArray(n)){for(let e of n)if(typeof e==`object`&&e&&e.field===`tokens`)throw Error(f(`caps[].field === 'tokens'`))}},r=e=>{if(typeof e!=`object`||!e)return;let t=e;n(t),`default`in t&&n(t.default);let r=t.overrides;if(typeof r==`object`&&r)for(let e of Object.values(r))n(e)};n(t.defaults),r(t.agent),r(t.provider),r(t.tool)}function m(e){p(e);let t=e;if(t.defaults!==void 0||t.agent!==void 0||t.provider!==void 0||t.tool!==void 0){let t=c.parse(e);return{defaults:t.defaults??o.parse({}),agent:t.agent??{overrides:{}},provider:t.provider??{overrides:{}},tool:t.tool??{overrides:{}}}}return{defaults:d(t),agent:{overrides:{}},provider:{overrides:{}},tool:{overrides:{}}}}function h(e,t,n,r){return{isEnforcementError:!0,code:`BUDGET_EXCEEDED`,message:r??`${e} limit is ${t}, current value is ${Math.round(n)}`}}function g(e,t,n){return{isToolWarning:!0,toolName:e,callId:t,message:n}}function _(e,t){let n=0;for(let t of e){n+=t.content?.length??0;for(let e of t.toolCalls??[])n+=JSON.stringify(e.arguments??{}).length;for(let e of t.toolResults??[])n+=JSON.stringify(e.result??null).length}for(let e of t)n+=JSON.stringify({name:e.name,description:e.description,inputSchema:e.inputSchema}).length;return Math.ceil(n/4)}var v=class{constructor(e,t,n=0,r=0,i=0,a=0){this.db=e,this.cfg=t,this.costPerInput=n,this.costPerOutput=r,this.costPerCacheRead=i,this.costPerCacheWrite=a,this.name=`agent-mcp-budget`,this.accumulators=new Map}install(e){this.hooks=e,e.register(`task:start`,e=>{try{this.onTaskStart(e)}catch{}}),e.register(`pre:model_request`,e=>{try{this.onPreModelRequest(e)}catch{}}),e.register(`post:model_response`,e=>{try{this.onPostModelResponse(e)}catch{}}),e.register(`post:tool_call`,e=>{try{this.onPostToolCall(e)}catch{}}),e.register(`task:completed`,e=>{try{this.onTerminal(e.executionContext.taskId)}catch{}}),e.register(`task:failed`,e=>{try{this.onTerminal(e.executionContext.taskId)}catch{}}),e.register(`task:cancelled`,e=>{try{this.onTerminal(e.executionContext.taskId)}catch{}}),e.registerEnforcement(`pre:model_request`,e=>this.enforcePreModel(e)),e.registerEnforcement(`pre:tool_call`,e=>this.enforcePreTool(e)),e.register(`transform:tool_result`,e=>{try{this.enforceResponseSize(e)}catch{}})}onTaskStart(e){let{taskId:t,sessionId:n,agentName:r}=e.executionContext,i=e.executionContext.agentDefinition?.provider?.type??`unknown`;this.accumulators.set(t,{taskId:t,sessionId:n??void 0,agentName:r,providerType:i,startedAtMs:Date.now(),uncachedInputTokens:0,cacheReadTokens:0,cacheCreationTokens:0,inputTokens:0,outputTokens:0,peakContextTokens:0,modelCalls:0,totalModelMs:0,toolCalls:new Map,errors:0,consecutiveErrors:0})}onPreModelRequest(e){let t=this.accumulators.get(e.executionContext.taskId);t&&(t.modelCallStartMs=Date.now())}onPostModelResponse(e){let t=this.accumulators.get(e.executionContext.taskId);if(!t)return;let n=e.tokenUsage;if(n){let e=n.inputTokens??0,r=n.cacheReadTokens??0,i=n.cacheCreationTokens??0,a=n.uncachedInputTokens!==void 0||n.cacheReadTokens!==void 0||n.cacheCreationTokens!==void 0?n.uncachedInputTokens??Math.max(0,e-r-i):e;t.uncachedInputTokens+=a,t.cacheReadTokens+=r,t.cacheCreationTokens+=i,t.inputTokens+=a+r+i,t.outputTokens+=n.outputTokens??0,t.peakContextTokens=Math.max(t.peakContextTokens,e)}t.modelCalls+=1,t.modelCallStartMs!==void 0&&(t.totalModelMs+=Date.now()-t.modelCallStartMs,t.modelCallStartMs=void 0)}onTerminal(e){this.accumulators.delete(e)}onPostToolCall(e){let t=this.accumulators.get(e.executionContext.taskId);t&&(e.isError?(t.errors+=1,t.consecutiveErrors+=1):t.consecutiveErrors=0)}mergeDim(e){let t={caps:[]};for(let n of e)n&&(t={caps:[...t.caps??[],...n.caps??[]],mode:n.mode??t.mode,costPerInputToken:n.costPerInputToken??t.costPerInputToken,costPerOutputToken:n.costPerOutputToken??t.costPerOutputToken,costPerCacheReadToken:n.costPerCacheReadToken??t.costPerCacheReadToken,costPerCacheWriteToken:n.costPerCacheWriteToken??t.costPerCacheWriteToken,scope:n.scope??t.scope});return t}resolveCaps(e,t,n){let r=this.cfg.defaults,i=this.cfg.agent,a=this.cfg.provider,o=this.cfg.tool;if(n){let e=o?.overrides?.[n],t=this.mergeDim([r,o?.default,e]);return{caps:t.caps??[],mode:t.mode,scope:t.scope}}let s=i?.overrides?.[e],c=a?.overrides?.[t],l=this.mergeDim([r,i?.default,s,a?.default,c]);return{caps:l.caps??[],mode:l.mode,scope:l.scope}}queryScopeTotals(e,t,n,r){let i=this.accumulators.get(e),a=i?{inputTokens:i.inputTokens,outputTokens:i.outputTokens,modelCalls:i.modelCalls,peakContextTokens:i.peakContextTokens}:{inputTokens:0,outputTokens:0,modelCalls:0,peakContextTokens:0};if(r===`task`||!this.db)return a;try{let i=this.db,o;if(r===`session`&&t?o=i.prepare(`SELECT
2
2
  COALESCE(SUM(tu.input_tokens), 0) AS input,
3
3
  COALESCE(SUM(tu.output_tokens), 0) AS output,
4
4
  COALESCE(SUM(tu.model_calls), 0) AS calls,
5
5
  COALESCE(MAX(tu.peak_context_tokens), 0) AS peak
6
6
  FROM task_usage tu
7
7
  JOIN tasks t ON tu.task_id = t.id
8
- WHERE t.session_id = ? AND tu.task_id != ?`).get(e,t):s==="agent"?a=r.prepare(`SELECT
8
+ WHERE t.session_id = ? AND tu.task_id != ?`).get(t,e):r===`agent`?o=i.prepare(`SELECT
9
9
  COALESCE(SUM(input_tokens), 0) AS input,
10
10
  COALESCE(SUM(output_tokens), 0) AS output,
11
11
  COALESCE(SUM(model_calls), 0) AS calls,
12
12
  COALESCE(MAX(peak_context_tokens), 0) AS peak
13
13
  FROM task_usage
14
- WHERE agent_name = ? AND task_id != ?`).get(o,t):s==="global"&&(a=r.prepare(`SELECT
14
+ WHERE agent_name = ? AND task_id != ?`).get(n,e):r===`global`&&(o=i.prepare(`SELECT
15
15
  COALESCE(SUM(input_tokens), 0) AS input,
16
16
  COALESCE(SUM(output_tokens), 0) AS output,
17
17
  COALESCE(SUM(model_calls), 0) AS calls,
18
18
  COALESCE(MAX(peak_context_tokens), 0) AS peak
19
19
  FROM task_usage
20
- WHERE task_id != ?`).get(t)),a)return{inputTokens:(a.input??0)+i.inputTokens,outputTokens:(a.output??0)+i.outputTokens,modelCalls:(a.calls??0)+i.modelCalls,peakContextTokens:Math.max(a.peak??0,i.peakContextTokens)}}catch{}return i}queryWindowTokens(t,e,o,s){if(!this.db)return 0;try{const n=this.db,i=new Date(Date.now()-o).toISOString();let r;if(t==="session"){const a=s?" AND tu.task_id != ?":"",l=[e,i];s&&l.push(s),r=n.prepare(`SELECT COALESCE(SUM(tu.input_tokens + tu.output_tokens), 0) AS total
20
+ WHERE task_id != ?`).get(e)),o)return{inputTokens:(o.input??0)+a.inputTokens,outputTokens:(o.output??0)+a.outputTokens,modelCalls:(o.calls??0)+a.modelCalls,peakContextTokens:Math.max(o.peak??0,a.peakContextTokens)}}catch{}return a}queryWindowTokens(e,t,n,r){if(!this.db)return 0;try{let i=this.db,a=new Date(Date.now()-n).toISOString(),o;if(e===`session`){let e=r?` AND tu.task_id != ?`:``,n=[t,a];r&&n.push(r),o=i.prepare(`SELECT COALESCE(SUM(tu.input_tokens + tu.output_tokens), 0) AS total
21
21
  FROM task_usage tu
22
22
  JOIN tasks t ON tu.task_id = t.id
23
- WHERE t.session_id = ? AND tu.created_at >= ?${a}`).get(...l)}else if(t==="agent"){const a=s?" AND task_id != ?":"",l=[e,i];s&&l.push(s),r=n.prepare(`SELECT COALESCE(SUM(input_tokens + output_tokens), 0) AS total
23
+ WHERE t.session_id = ? AND tu.created_at >= ?${e}`).get(...n)}else if(e===`agent`){let e=r?` AND task_id != ?`:``,n=[t,a];r&&n.push(r),o=i.prepare(`SELECT COALESCE(SUM(input_tokens + output_tokens), 0) AS total
24
24
  FROM task_usage
25
- WHERE agent_name = ? AND created_at >= ?${a}`).get(...l)}else if(t==="global"){const a=s?" AND task_id != ?":"",l=[i];s&&l.push(s),r=n.prepare(`SELECT COALESCE(SUM(input_tokens + output_tokens), 0) AS total
25
+ WHERE agent_name = ? AND created_at >= ?${e}`).get(...n)}else if(e===`global`){let e=r?` AND task_id != ?`:``,t=[a];r&&t.push(r),o=i.prepare(`SELECT COALESCE(SUM(input_tokens + output_tokens), 0) AS total
26
26
  FROM task_usage
27
- WHERE created_at >= ?${a}`).get(...l)}return(r==null?void 0:r.total)??0}catch{return 0}}buildSnapshot(t,e,o,s,n,i,r=0){const a={};a.inputTokens=e.inputTokens,a.outputTokens=e.outputTokens,a.calls=e.modelCalls,a.wallClock=Date.now()-e.startedAtMs,a.modelMs=e.totalModelMs,a.context=Math.max(e.peakContextTokens,r),a.errors=e.errors,a.consecutiveErrors=e.consecutiveErrors,a.cost=e.uncachedInputTokens*this.costPerInput+e.cacheReadTokens*this.costPerCacheRead+e.cacheCreationTokens*this.costPerCacheWrite+e.outputTokens*this.costPerOutput;const l=new Set,p=new Map;for(const f of t){const d=f.scope??i??"task";if(d!=="task"&&l.add(d),f.window){const k=`${d}:${f.window}`;p.has(k)||p.set(k,{scope:d,windowMs:b(f.window)})}}for(const f of l){const d=this.queryScopeTotals(o,s,n,f);a[`${f}:inputTokens`]=d.inputTokens,a[`${f}:outputTokens`]=d.outputTokens,a[`${f}:calls`]=d.modelCalls,a[`${f}:context`]=Math.max(d.peakContextTokens,r)}for(const[f,{scope:d,windowMs:k}]of p){let m="";d==="session"?m=s??"":d==="agent"&&(m=n??""),a[f]=this.queryWindowTokens(d,m,k,o)}return a}getSnapshotValue(t,e,o){const s=e.scope??o??"task";let n;e.window?n="":n=s!=="task"?`${s}:`:"";let i;switch(e.field){case"inputTokens":i=t[`${n}inputTokens`]??t.inputTokens;break;case"outputTokens":i=t[`${n}outputTokens`]??t.outputTokens;break;case"context":i=t[`${n}context`]??t.context;break;case"calls":i=t[`${n}calls`]??t.calls;break;case"wallClock":i=t.wallClock;break;case"modelMs":i=t.modelMs;break;case"cost":i=t.cost;break;case"toolCalls":i=0;break;case"errors":i=t.errors;break;case"consecutiveErrors":i=t.consecutiveErrors;break;default:i=0}return e.window&&(i+=t[`${s}:${e.window}`]??0),i}async emitBudgetEvent(t,e,o,s,n,i){this.hooks&&await this.hooks.emit(t,{executionContext:e,field:o.field,maximum:n,current:s,message:i??o.message??`${o.field} limit is ${n}, current value is ${Math.round(s)}`})}resolveCapLimit(t,e){if(t.maximum!==void 0)return t.maximum;const o=e.agentDefinition.provider;return Math.floor(M.contextWindowFor(o.model)*(t.contextWindowFraction??0))}async evaluateCap(t,e,o,s,n){const i=this.resolveCapLimit(t,o),r=this.getSnapshotValue(e,t,n);if(r<i)return;if((t.mode??s??"warning")==="warning"){await this.emitBudgetEvent("budget:warning",o,t,r,i);return}throw await this.emitBudgetEvent("budget:block",o,t,r,i),v(t.field,i,r,t.message)}async enforcePreModel(t){var d,k;const{taskId:e,sessionId:o,agentName:s}=t.executionContext,n=((k=(d=t.executionContext.agentDefinition)==null?void 0:d.provider)==null?void 0:k.type)??"unknown",i=this.accumulators.get(e);if(!i)return;const{caps:r,mode:a,scope:l}=this.resolveCaps(s,n),p=r.filter(m=>!_.has(m.field));if(p.length===0)return;const f=this.buildSnapshot(p,i,e,o,s,l,L(t.messages,t.tools));for(const m of p)await this.evaluateCap(m,f,t.executionContext,a,l)}async enforcePreTool(t){const{toolName:e,callId:o,executionContext:s}=t,{caps:n,mode:i,scope:r}=this.resolveCaps(s.agentName,"",e),a=this.accumulators.get(s.taskId);if(!a)return;const l=n.filter(d=>d.field!=="context");if(l.length===0)return;const p=a.toolCalls.get(e)??0,f=this.buildSnapshot(l,a,s.taskId,s.sessionId,s.agentName,r);for(const d of l){const k=this.resolveCapLimit(d,s),m=d.field==="toolCalls"?p:this.getSnapshotValue(f,d,r);if(m>=k){const h=d.message??`tool "${e}": ${d.field} limit is ${k}, current value is ${Math.round(m)}`;throw(d.mode??i??"warning")==="warning"?(await this.emitBudgetEvent("budget:warning",s,d,m,k,h),R(e,o,h)):(await this.emitBudgetEvent("budget:block",s,d,m,k,h),v(`tool:${e}:${d.field}`,k,m,d.message))}}a.toolCalls.set(e,p+1)}enforceResponseSize(t){const{toolName:e,result:o}=t;if(typeof o!="object"||o===null)return;const{caps:s,mode:n}=this.resolveCaps("","",e),i=s.filter(p=>p.field==="responseSize");if(i.length===0)return;const r=o,a=r.content;if(!Array.isArray(a))return;let l=0;for(const p of a)if(typeof p=="object"&&p!==null){const f=p;f.type==="text"&&(l+=(f.text??"").length)}for(const p of i){const f=this.resolveCapLimit(p,t.executionContext);if(l<=f)continue;if((p.mode??n??"warning")==="block")r.content=[{type:"text",text:p.message??`Response size (${l} chars) exceeds limit of ${f}. Use offset/limit or shell paging tools instead.`}],t.isError=!0;else{let k=f;const m=[];for(const h of a){if(typeof h!="object"||h===null){m.push(h);continue}const C=h;if(C.type!=="text"){m.push(h);continue}const T=C.text??"";if(T.length<=k)m.push(h),k-=T.length;else{m.push({type:"text",text:T.slice(0,k)});break}}m.push({type:"text",text:`
28
-
29
- [truncated: response was ${l} chars, limited to ${p.maximum}. ${p.message??"Use offset/limit or shell paging tools for full content."}]`}),r.content=m}break}}}const E=({db:c,config:t})=>{var r,a,l,p;const e=$(t),o=((r=e.defaults)==null?void 0:r.costPerInputToken)??0,s=((a=e.defaults)==null?void 0:a.costPerOutputToken)??0,n=((l=e.defaults)==null?void 0:l.costPerCacheReadToken)??o,i=((p=e.defaults)==null?void 0:p.costPerCacheWriteToken)??o;return new W(c,e,o,s,n,i)};exports.configSchema=O;exports.createPlugin=E;exports.default=E;exports.pluginConfigSchema=S;
27
+ WHERE created_at >= ?${e}`).get(...t)}return o?.total??0}catch{return 0}}buildSnapshot(e,t,r,i,a,o,s=0){let c={};c.inputTokens=t.inputTokens,c.outputTokens=t.outputTokens,c.calls=t.modelCalls,c.wallClock=Date.now()-t.startedAtMs,c.modelMs=t.totalModelMs,c.context=Math.max(t.peakContextTokens,s),c.errors=t.errors,c.consecutiveErrors=t.consecutiveErrors,c.cost=t.uncachedInputTokens*this.costPerInput+t.cacheReadTokens*this.costPerCacheRead+t.cacheCreationTokens*this.costPerCacheWrite+t.outputTokens*this.costPerOutput;let l=new Set,u=new Map;for(let t of e){let e=t.scope??o??`task`;if(e!==`task`&&l.add(e),t.window){let r=`${e}:${t.window}`;u.has(r)||u.set(r,{scope:e,windowMs:n(t.window)})}}for(let e of l){let t=this.queryScopeTotals(r,i,a,e);c[`${e}:inputTokens`]=t.inputTokens,c[`${e}:outputTokens`]=t.outputTokens,c[`${e}:calls`]=t.modelCalls,c[`${e}:context`]=Math.max(t.peakContextTokens,s)}for(let[e,{scope:t,windowMs:n}]of u){let o=``;t===`session`?o=i??``:t===`agent`&&(o=a??``),c[e]=this.queryWindowTokens(t,o,n,r)}return c}getSnapshotValue(e,t,n){let r=t.scope??n??`task`,i;i=t.window||r===`task`?``:`${r}:`;let a;switch(t.field){case`inputTokens`:a=e[`${i}inputTokens`]??e.inputTokens;break;case`outputTokens`:a=e[`${i}outputTokens`]??e.outputTokens;break;case`context`:a=e[`${i}context`]??e.context;break;case`calls`:a=e[`${i}calls`]??e.calls;break;case`wallClock`:a=e.wallClock;break;case`modelMs`:a=e.modelMs;break;case`cost`:a=e.cost;break;case`toolCalls`:a=0;break;case`errors`:a=e.errors;break;case`consecutiveErrors`:a=e.consecutiveErrors;break;default:a=0}return t.window&&(a+=e[`${r}:${t.window}`]??0),a}async emitBudgetEvent(e,t,n,r,i,a){this.hooks&&await this.hooks.emit(e,{executionContext:t,field:n.field,maximum:i,current:r,message:a??n.message??`${n.field} limit is ${i}, current value is ${Math.round(r)}`})}resolveCapLimit(e,n){if(e.maximum!==void 0)return e.maximum;let r=n.agentDefinition.provider;return Math.floor((0,t.contextWindowFor)(r.model)*(e.contextWindowFraction??0))}async evaluateCap(e,t,n,r,i){let a=this.resolveCapLimit(e,n),o=this.getSnapshotValue(t,e,i);if(!(o<a)){if((e.mode??r??`warning`)===`warning`){await this.emitBudgetEvent(`budget:warning`,n,e,o,a);return}throw await this.emitBudgetEvent(`budget:block`,n,e,o,a),h(e.field,a,o,e.message)}}async enforcePreModel(e){let{taskId:t,sessionId:n,agentName:r}=e.executionContext,a=e.executionContext.agentDefinition?.provider?.type??`unknown`,o=this.accumulators.get(t);if(!o)return;let{caps:s,mode:c,scope:l}=this.resolveCaps(r,a),u=s.filter(e=>!i.has(e.field));if(u.length===0)return;let d=this.buildSnapshot(u,o,t,n,r,l,_(e.messages,e.tools));for(let t of u)await this.evaluateCap(t,d,e.executionContext,c,l)}async enforcePreTool(e){let{toolName:t,callId:n,executionContext:r}=e,{caps:i,mode:a,scope:o}=this.resolveCaps(r.agentName,``,t),s=this.accumulators.get(r.taskId);if(!s)return;let c=i.filter(e=>e.field!==`context`);if(c.length===0)return;let l=s.toolCalls.get(t)??0,u=this.buildSnapshot(c,s,r.taskId,r.sessionId,r.agentName,o);for(let e of c){let i=this.resolveCapLimit(e,r),s=e.field===`toolCalls`?l:this.getSnapshotValue(u,e,o);if(s>=i){let o=e.message??`tool "${t}": ${e.field} limit is ${i}, current value is ${Math.round(s)}`;throw(e.mode??a??`warning`)===`warning`?(await this.emitBudgetEvent(`budget:warning`,r,e,s,i,o),g(t,n,o)):(await this.emitBudgetEvent(`budget:block`,r,e,s,i,o),h(`tool:${t}:${e.field}`,i,s,e.message))}}s.toolCalls.set(t,l+1)}enforceResponseSize(e){let{toolName:t,result:n}=e;if(typeof n!=`object`||!n)return;let{caps:r,mode:i}=this.resolveCaps(``,``,t),a=r.filter(e=>e.field===`responseSize`);if(a.length===0)return;let o=n,s=o.content;if(!Array.isArray(s))return;let c=0;for(let e of s)if(typeof e==`object`&&e){let t=e;t.type===`text`&&(c+=(t.text??``).length)}for(let t of a){let n=this.resolveCapLimit(t,e.executionContext);if(!(c<=n)){if((t.mode??i??`warning`)===`block`)o.content=[{type:`text`,text:t.message??`Response size (${c} chars) exceeds limit of ${n}. Use offset/limit or shell paging tools instead.`}],e.isError=!0;else{let e=n,r=[];for(let t of s){if(typeof t!=`object`||!t){r.push(t);continue}let n=t;if(n.type!==`text`){r.push(t);continue}let i=n.text??``;if(i.length<=e)r.push(t),e-=i.length;else{r.push({type:`text`,text:i.slice(0,e)});break}}r.push({type:`text`,text:`\n\n[truncated: response was ${c} chars, limited to ${t.maximum}. ${t.message??`Use offset/limit or shell paging tools for full content.`}]`}),o.content=r}break}}}},y=({db:e,config:t})=>{let n=m(t),r=n.defaults?.costPerInputToken??0;return new v(e,n,r,n.defaults?.costPerOutputToken??0,n.defaults?.costPerCacheReadToken??r,n.defaults?.costPerCacheWriteToken??r)};exports.configSchema=l,exports.createPlugin=y,exports.default=y,exports.pluginConfigSchema=c;