@compilr-dev/agents 0.0.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 +1277 -0
- package/dist/agent.d.ts +1272 -0
- package/dist/agent.js +1912 -0
- package/dist/anchors/builtin.d.ts +24 -0
- package/dist/anchors/builtin.js +61 -0
- package/dist/anchors/index.d.ts +6 -0
- package/dist/anchors/index.js +5 -0
- package/dist/anchors/manager.d.ts +115 -0
- package/dist/anchors/manager.js +412 -0
- package/dist/anchors/types.d.ts +168 -0
- package/dist/anchors/types.js +10 -0
- package/dist/context/index.d.ts +12 -0
- package/dist/context/index.js +10 -0
- package/dist/context/manager.d.ts +224 -0
- package/dist/context/manager.js +770 -0
- package/dist/context/types.d.ts +377 -0
- package/dist/context/types.js +7 -0
- package/dist/costs/index.d.ts +8 -0
- package/dist/costs/index.js +7 -0
- package/dist/costs/tracker.d.ts +121 -0
- package/dist/costs/tracker.js +295 -0
- package/dist/costs/types.d.ts +157 -0
- package/dist/costs/types.js +8 -0
- package/dist/errors.d.ts +178 -0
- package/dist/errors.js +249 -0
- package/dist/guardrails/builtin.d.ts +27 -0
- package/dist/guardrails/builtin.js +223 -0
- package/dist/guardrails/index.d.ts +6 -0
- package/dist/guardrails/index.js +5 -0
- package/dist/guardrails/manager.d.ts +117 -0
- package/dist/guardrails/manager.js +288 -0
- package/dist/guardrails/types.d.ts +159 -0
- package/dist/guardrails/types.js +7 -0
- package/dist/hooks/index.d.ts +31 -0
- package/dist/hooks/index.js +29 -0
- package/dist/hooks/manager.d.ts +147 -0
- package/dist/hooks/manager.js +600 -0
- package/dist/hooks/types.d.ts +368 -0
- package/dist/hooks/types.js +12 -0
- package/dist/index.d.ts +45 -0
- package/dist/index.js +73 -0
- package/dist/mcp/client.d.ts +93 -0
- package/dist/mcp/client.js +287 -0
- package/dist/mcp/errors.d.ts +60 -0
- package/dist/mcp/errors.js +78 -0
- package/dist/mcp/index.d.ts +43 -0
- package/dist/mcp/index.js +45 -0
- package/dist/mcp/manager.d.ts +120 -0
- package/dist/mcp/manager.js +276 -0
- package/dist/mcp/tools.d.ts +54 -0
- package/dist/mcp/tools.js +99 -0
- package/dist/mcp/types.d.ts +150 -0
- package/dist/mcp/types.js +40 -0
- package/dist/memory/index.d.ts +8 -0
- package/dist/memory/index.js +7 -0
- package/dist/memory/loader.d.ts +114 -0
- package/dist/memory/loader.js +463 -0
- package/dist/memory/types.d.ts +182 -0
- package/dist/memory/types.js +8 -0
- package/dist/messages/index.d.ts +82 -0
- package/dist/messages/index.js +155 -0
- package/dist/permissions/index.d.ts +5 -0
- package/dist/permissions/index.js +4 -0
- package/dist/permissions/manager.d.ts +125 -0
- package/dist/permissions/manager.js +379 -0
- package/dist/permissions/types.d.ts +162 -0
- package/dist/permissions/types.js +7 -0
- package/dist/providers/claude.d.ts +90 -0
- package/dist/providers/claude.js +348 -0
- package/dist/providers/index.d.ts +8 -0
- package/dist/providers/index.js +11 -0
- package/dist/providers/mock.d.ts +133 -0
- package/dist/providers/mock.js +204 -0
- package/dist/providers/types.d.ts +168 -0
- package/dist/providers/types.js +4 -0
- package/dist/rate-limit/index.d.ts +45 -0
- package/dist/rate-limit/index.js +47 -0
- package/dist/rate-limit/limiter.d.ts +104 -0
- package/dist/rate-limit/limiter.js +326 -0
- package/dist/rate-limit/provider-wrapper.d.ts +112 -0
- package/dist/rate-limit/provider-wrapper.js +201 -0
- package/dist/rate-limit/retry.d.ts +108 -0
- package/dist/rate-limit/retry.js +287 -0
- package/dist/rate-limit/types.d.ts +181 -0
- package/dist/rate-limit/types.js +22 -0
- package/dist/rehearsal/file-analyzer.d.ts +22 -0
- package/dist/rehearsal/file-analyzer.js +351 -0
- package/dist/rehearsal/git-analyzer.d.ts +22 -0
- package/dist/rehearsal/git-analyzer.js +472 -0
- package/dist/rehearsal/index.d.ts +35 -0
- package/dist/rehearsal/index.js +36 -0
- package/dist/rehearsal/manager.d.ts +100 -0
- package/dist/rehearsal/manager.js +290 -0
- package/dist/rehearsal/types.d.ts +235 -0
- package/dist/rehearsal/types.js +8 -0
- package/dist/skills/index.d.ts +160 -0
- package/dist/skills/index.js +282 -0
- package/dist/state/agent-state.d.ts +41 -0
- package/dist/state/agent-state.js +88 -0
- package/dist/state/checkpointer.d.ts +110 -0
- package/dist/state/checkpointer.js +362 -0
- package/dist/state/errors.d.ts +66 -0
- package/dist/state/errors.js +88 -0
- package/dist/state/index.d.ts +35 -0
- package/dist/state/index.js +37 -0
- package/dist/state/serializer.d.ts +55 -0
- package/dist/state/serializer.js +172 -0
- package/dist/state/types.d.ts +312 -0
- package/dist/state/types.js +14 -0
- package/dist/tools/builtin/bash-output.d.ts +61 -0
- package/dist/tools/builtin/bash-output.js +90 -0
- package/dist/tools/builtin/bash.d.ts +150 -0
- package/dist/tools/builtin/bash.js +354 -0
- package/dist/tools/builtin/edit.d.ts +50 -0
- package/dist/tools/builtin/edit.js +215 -0
- package/dist/tools/builtin/glob.d.ts +62 -0
- package/dist/tools/builtin/glob.js +244 -0
- package/dist/tools/builtin/grep.d.ts +74 -0
- package/dist/tools/builtin/grep.js +363 -0
- package/dist/tools/builtin/index.d.ts +44 -0
- package/dist/tools/builtin/index.js +69 -0
- package/dist/tools/builtin/kill-shell.d.ts +44 -0
- package/dist/tools/builtin/kill-shell.js +80 -0
- package/dist/tools/builtin/read-file.d.ts +57 -0
- package/dist/tools/builtin/read-file.js +184 -0
- package/dist/tools/builtin/shell-manager.d.ts +176 -0
- package/dist/tools/builtin/shell-manager.js +337 -0
- package/dist/tools/builtin/task.d.ts +202 -0
- package/dist/tools/builtin/task.js +350 -0
- package/dist/tools/builtin/todo.d.ts +207 -0
- package/dist/tools/builtin/todo.js +453 -0
- package/dist/tools/builtin/utils.d.ts +27 -0
- package/dist/tools/builtin/utils.js +70 -0
- package/dist/tools/builtin/web-fetch.d.ts +96 -0
- package/dist/tools/builtin/web-fetch.js +290 -0
- package/dist/tools/builtin/write-file.d.ts +54 -0
- package/dist/tools/builtin/write-file.js +147 -0
- package/dist/tools/define.d.ts +60 -0
- package/dist/tools/define.js +65 -0
- package/dist/tools/index.d.ts +10 -0
- package/dist/tools/index.js +37 -0
- package/dist/tools/registry.d.ts +79 -0
- package/dist/tools/registry.js +151 -0
- package/dist/tools/types.d.ts +59 -0
- package/dist/tools/types.js +4 -0
- package/dist/tracing/hooks.d.ts +58 -0
- package/dist/tracing/hooks.js +377 -0
- package/dist/tracing/index.d.ts +51 -0
- package/dist/tracing/index.js +55 -0
- package/dist/tracing/logging.d.ts +78 -0
- package/dist/tracing/logging.js +310 -0
- package/dist/tracing/manager.d.ts +160 -0
- package/dist/tracing/manager.js +468 -0
- package/dist/tracing/otel.d.ts +102 -0
- package/dist/tracing/otel.js +246 -0
- package/dist/tracing/types.d.ts +346 -0
- package/dist/tracing/types.js +38 -0
- package/dist/utils/index.d.ts +23 -0
- package/dist/utils/index.js +44 -0
- package/package.json +79 -0
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UsageTracker - Tracks token usage across LLM calls
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```typescript
|
|
6
|
+
* const tracker = new UsageTracker({
|
|
7
|
+
* budget: {
|
|
8
|
+
* maxTotalTokens: 100000,
|
|
9
|
+
* warningThreshold: 0.8,
|
|
10
|
+
* },
|
|
11
|
+
* });
|
|
12
|
+
*
|
|
13
|
+
* tracker.onEvent((event) => {
|
|
14
|
+
* if (event.type === 'usage:budget_warning') {
|
|
15
|
+
* console.log('Budget warning!', event.status);
|
|
16
|
+
* }
|
|
17
|
+
* });
|
|
18
|
+
*
|
|
19
|
+
* // Record usage after each LLM call
|
|
20
|
+
* tracker.record({
|
|
21
|
+
* model: 'claude-sonnet-4-20250514',
|
|
22
|
+
* provider: 'anthropic',
|
|
23
|
+
* tokens: { inputTokens: 1000, outputTokens: 500, totalTokens: 1500 },
|
|
24
|
+
* });
|
|
25
|
+
*
|
|
26
|
+
* // Get stats
|
|
27
|
+
* console.log(tracker.getStats());
|
|
28
|
+
* console.log(tracker.formatTokens(tracker.getTotalTokens()));
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
import { generateId } from '../utils/index.js';
|
|
32
|
+
/**
|
|
33
|
+
* UsageTracker tracks token usage across LLM calls
|
|
34
|
+
*/
|
|
35
|
+
export class UsageTracker {
|
|
36
|
+
enabled;
|
|
37
|
+
budget;
|
|
38
|
+
sessionId;
|
|
39
|
+
eventHandlers = new Set();
|
|
40
|
+
/** All usage records */
|
|
41
|
+
records = [];
|
|
42
|
+
/** Cached stats (invalidated on new records) */
|
|
43
|
+
cachedStats;
|
|
44
|
+
constructor(options = {}) {
|
|
45
|
+
this.enabled = options.enabled ?? true;
|
|
46
|
+
this.budget = options.budget;
|
|
47
|
+
this.sessionId = options.sessionId;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Record token usage from an LLM call
|
|
51
|
+
*/
|
|
52
|
+
record(input) {
|
|
53
|
+
if (!this.enabled)
|
|
54
|
+
return undefined;
|
|
55
|
+
const record = {
|
|
56
|
+
id: generateId(),
|
|
57
|
+
timestamp: new Date(),
|
|
58
|
+
model: input.model,
|
|
59
|
+
provider: input.provider,
|
|
60
|
+
tokens: input.tokens,
|
|
61
|
+
sessionId: input.sessionId ?? this.sessionId,
|
|
62
|
+
metadata: input.metadata,
|
|
63
|
+
};
|
|
64
|
+
this.records.push(record);
|
|
65
|
+
this.cachedStats = undefined; // Invalidate cache
|
|
66
|
+
const stats = this.getStats();
|
|
67
|
+
this.emit({ type: 'usage:recorded', record, stats });
|
|
68
|
+
// Check budget
|
|
69
|
+
this.checkBudget();
|
|
70
|
+
return record;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Get aggregated usage statistics
|
|
74
|
+
*/
|
|
75
|
+
getStats() {
|
|
76
|
+
if (this.cachedStats) {
|
|
77
|
+
return this.cachedStats;
|
|
78
|
+
}
|
|
79
|
+
const byModel = {};
|
|
80
|
+
let totalInputTokens = 0;
|
|
81
|
+
let totalOutputTokens = 0;
|
|
82
|
+
let totalCacheReadTokens = 0;
|
|
83
|
+
let totalCacheCreationTokens = 0;
|
|
84
|
+
let firstCall;
|
|
85
|
+
let lastCall;
|
|
86
|
+
for (const record of this.records) {
|
|
87
|
+
totalInputTokens += record.tokens.inputTokens;
|
|
88
|
+
totalOutputTokens += record.tokens.outputTokens;
|
|
89
|
+
totalCacheReadTokens += record.tokens.cacheReadTokens ?? 0;
|
|
90
|
+
totalCacheCreationTokens += record.tokens.cacheCreationTokens ?? 0;
|
|
91
|
+
if (!firstCall || record.timestamp < firstCall) {
|
|
92
|
+
firstCall = record.timestamp;
|
|
93
|
+
}
|
|
94
|
+
if (!lastCall || record.timestamp > lastCall) {
|
|
95
|
+
lastCall = record.timestamp;
|
|
96
|
+
}
|
|
97
|
+
// Aggregate by model
|
|
98
|
+
if (!(record.model in byModel)) {
|
|
99
|
+
byModel[record.model] = {
|
|
100
|
+
calls: 0,
|
|
101
|
+
inputTokens: 0,
|
|
102
|
+
outputTokens: 0,
|
|
103
|
+
totalTokens: 0,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
const modelStats = byModel[record.model];
|
|
107
|
+
modelStats.calls++;
|
|
108
|
+
modelStats.inputTokens += record.tokens.inputTokens;
|
|
109
|
+
modelStats.outputTokens += record.tokens.outputTokens;
|
|
110
|
+
modelStats.totalTokens += record.tokens.totalTokens;
|
|
111
|
+
}
|
|
112
|
+
const totalCalls = this.records.length;
|
|
113
|
+
const totalTokens = totalInputTokens + totalOutputTokens;
|
|
114
|
+
this.cachedStats = {
|
|
115
|
+
totalCalls,
|
|
116
|
+
totalInputTokens,
|
|
117
|
+
totalOutputTokens,
|
|
118
|
+
totalTokens,
|
|
119
|
+
totalCacheReadTokens,
|
|
120
|
+
totalCacheCreationTokens,
|
|
121
|
+
averageTokensPerCall: totalCalls > 0 ? totalTokens / totalCalls : 0,
|
|
122
|
+
firstCall,
|
|
123
|
+
lastCall,
|
|
124
|
+
byModel,
|
|
125
|
+
};
|
|
126
|
+
return this.cachedStats;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Get stats for a specific session
|
|
130
|
+
*/
|
|
131
|
+
getSessionStats(sessionId) {
|
|
132
|
+
const sessionRecords = this.records.filter((r) => r.sessionId === sessionId);
|
|
133
|
+
const tracker = new UsageTracker({ enabled: true });
|
|
134
|
+
for (const record of sessionRecords) {
|
|
135
|
+
tracker.records.push(record);
|
|
136
|
+
}
|
|
137
|
+
return tracker.getStats();
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Get total tokens used
|
|
141
|
+
*/
|
|
142
|
+
getTotalTokens() {
|
|
143
|
+
return this.getStats().totalTokens;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Get total input tokens
|
|
147
|
+
*/
|
|
148
|
+
getTotalInputTokens() {
|
|
149
|
+
return this.getStats().totalInputTokens;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Get total output tokens
|
|
153
|
+
*/
|
|
154
|
+
getTotalOutputTokens() {
|
|
155
|
+
return this.getStats().totalOutputTokens;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Get budget status
|
|
159
|
+
*/
|
|
160
|
+
getBudgetStatus() {
|
|
161
|
+
const stats = this.getStats();
|
|
162
|
+
const tokenLimit = this.budget?.maxTotalTokens;
|
|
163
|
+
const warningThreshold = this.budget?.warningThreshold ?? 0.8;
|
|
164
|
+
const tokenUtilization = tokenLimit ? stats.totalTokens / tokenLimit : undefined;
|
|
165
|
+
const exceeded = (tokenLimit !== undefined && stats.totalTokens >= tokenLimit) ||
|
|
166
|
+
(this.budget?.maxInputTokens !== undefined &&
|
|
167
|
+
stats.totalInputTokens >= this.budget.maxInputTokens) ||
|
|
168
|
+
(this.budget?.maxOutputTokens !== undefined &&
|
|
169
|
+
stats.totalOutputTokens >= this.budget.maxOutputTokens);
|
|
170
|
+
const warning = tokenUtilization !== undefined && tokenUtilization >= warningThreshold;
|
|
171
|
+
return {
|
|
172
|
+
currentTokens: stats.totalTokens,
|
|
173
|
+
currentInputTokens: stats.totalInputTokens,
|
|
174
|
+
currentOutputTokens: stats.totalOutputTokens,
|
|
175
|
+
tokenLimit,
|
|
176
|
+
tokenUtilization,
|
|
177
|
+
exceeded,
|
|
178
|
+
warning,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Check if budget is exceeded
|
|
183
|
+
*/
|
|
184
|
+
isBudgetExceeded() {
|
|
185
|
+
return this.getBudgetStatus().exceeded;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Check budget and emit events
|
|
189
|
+
*/
|
|
190
|
+
checkBudget() {
|
|
191
|
+
if (!this.budget)
|
|
192
|
+
return;
|
|
193
|
+
const status = this.getBudgetStatus();
|
|
194
|
+
// Check for exceeded
|
|
195
|
+
if (status.exceeded) {
|
|
196
|
+
this.emit({ type: 'usage:budget_exceeded', status });
|
|
197
|
+
}
|
|
198
|
+
else if (status.warning) {
|
|
199
|
+
// Check for warning
|
|
200
|
+
this.emit({
|
|
201
|
+
type: 'usage:budget_warning',
|
|
202
|
+
status,
|
|
203
|
+
threshold: this.budget.warningThreshold ?? 0.8,
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Reset all tracking data
|
|
209
|
+
*/
|
|
210
|
+
reset() {
|
|
211
|
+
const previousStats = this.getStats();
|
|
212
|
+
this.records.length = 0;
|
|
213
|
+
this.cachedStats = undefined;
|
|
214
|
+
this.emit({ type: 'usage:reset', previousStats });
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Get all records
|
|
218
|
+
*/
|
|
219
|
+
getRecords() {
|
|
220
|
+
return this.records;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Get records for a specific session
|
|
224
|
+
*/
|
|
225
|
+
getSessionRecords(sessionId) {
|
|
226
|
+
return this.records.filter((r) => r.sessionId === sessionId);
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Format tokens with commas for display
|
|
230
|
+
*/
|
|
231
|
+
formatTokens(tokens) {
|
|
232
|
+
return tokens.toLocaleString();
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Get a human-readable summary
|
|
236
|
+
*/
|
|
237
|
+
getSummary() {
|
|
238
|
+
const stats = this.getStats();
|
|
239
|
+
const lines = [
|
|
240
|
+
`Total Calls: ${String(stats.totalCalls)}`,
|
|
241
|
+
`Total Tokens: ${this.formatTokens(stats.totalTokens)} (${this.formatTokens(stats.totalInputTokens)} in / ${this.formatTokens(stats.totalOutputTokens)} out)`,
|
|
242
|
+
];
|
|
243
|
+
if (stats.totalCacheReadTokens > 0 || stats.totalCacheCreationTokens > 0) {
|
|
244
|
+
lines.push(`Cache: ${this.formatTokens(stats.totalCacheReadTokens)} read / ${this.formatTokens(stats.totalCacheCreationTokens)} created`);
|
|
245
|
+
}
|
|
246
|
+
if (stats.totalCalls > 0) {
|
|
247
|
+
lines.push(`Average per Call: ${this.formatTokens(Math.round(stats.averageTokensPerCall))} tokens`);
|
|
248
|
+
}
|
|
249
|
+
if (this.budget?.maxTotalTokens) {
|
|
250
|
+
const status = this.getBudgetStatus();
|
|
251
|
+
const pct = ((status.tokenUtilization ?? 0) * 100).toFixed(1);
|
|
252
|
+
const limit = status.tokenLimit ?? this.budget.maxTotalTokens;
|
|
253
|
+
lines.push(`Budget: ${this.formatTokens(status.currentTokens)} / ${this.formatTokens(limit)} (${pct}%)`);
|
|
254
|
+
}
|
|
255
|
+
return lines.join('\n');
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Register an event handler
|
|
259
|
+
*/
|
|
260
|
+
onEvent(handler) {
|
|
261
|
+
this.eventHandlers.add(handler);
|
|
262
|
+
return () => this.eventHandlers.delete(handler);
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Emit an event
|
|
266
|
+
*/
|
|
267
|
+
emit(event) {
|
|
268
|
+
for (const handler of this.eventHandlers) {
|
|
269
|
+
try {
|
|
270
|
+
handler(event);
|
|
271
|
+
}
|
|
272
|
+
catch {
|
|
273
|
+
// Ignore handler errors
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Check if tracking is enabled
|
|
279
|
+
*/
|
|
280
|
+
get isEnabled() {
|
|
281
|
+
return this.enabled;
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Get the number of records
|
|
285
|
+
*/
|
|
286
|
+
get size() {
|
|
287
|
+
return this.records.length;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Create a UsageTracker instance
|
|
292
|
+
*/
|
|
293
|
+
export function createUsageTracker(options) {
|
|
294
|
+
return new UsageTracker(options);
|
|
295
|
+
}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Usage Tracking Types
|
|
3
|
+
*
|
|
4
|
+
* Types for tracking token usage across LLM calls.
|
|
5
|
+
* Note: We track tokens only, not dollar costs (pricing changes frequently
|
|
6
|
+
* and providing inaccurate cost info would be misleading).
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Token usage for a single LLM call
|
|
10
|
+
*/
|
|
11
|
+
export interface TokenUsage {
|
|
12
|
+
/** Input/prompt tokens */
|
|
13
|
+
inputTokens: number;
|
|
14
|
+
/** Output/completion tokens */
|
|
15
|
+
outputTokens: number;
|
|
16
|
+
/** Total tokens (input + output) */
|
|
17
|
+
totalTokens: number;
|
|
18
|
+
/** Cache read tokens (if applicable) */
|
|
19
|
+
cacheReadTokens?: number;
|
|
20
|
+
/** Cache creation tokens (if applicable) */
|
|
21
|
+
cacheCreationTokens?: number;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* A single usage record
|
|
25
|
+
*/
|
|
26
|
+
export interface UsageRecord {
|
|
27
|
+
/** Unique ID for this record */
|
|
28
|
+
id: string;
|
|
29
|
+
/** Timestamp of the call */
|
|
30
|
+
timestamp: Date;
|
|
31
|
+
/** Model used */
|
|
32
|
+
model: string;
|
|
33
|
+
/** Provider name */
|
|
34
|
+
provider: string;
|
|
35
|
+
/** Token usage */
|
|
36
|
+
tokens: TokenUsage;
|
|
37
|
+
/** Session ID (if tracking by session) */
|
|
38
|
+
sessionId?: string;
|
|
39
|
+
/** Additional metadata */
|
|
40
|
+
metadata?: Record<string, unknown>;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Aggregated usage statistics
|
|
44
|
+
*/
|
|
45
|
+
export interface UsageStats {
|
|
46
|
+
/** Total number of LLM calls */
|
|
47
|
+
totalCalls: number;
|
|
48
|
+
/** Total input tokens */
|
|
49
|
+
totalInputTokens: number;
|
|
50
|
+
/** Total output tokens */
|
|
51
|
+
totalOutputTokens: number;
|
|
52
|
+
/** Total tokens */
|
|
53
|
+
totalTokens: number;
|
|
54
|
+
/** Total cache read tokens */
|
|
55
|
+
totalCacheReadTokens: number;
|
|
56
|
+
/** Total cache creation tokens */
|
|
57
|
+
totalCacheCreationTokens: number;
|
|
58
|
+
/** Average tokens per call */
|
|
59
|
+
averageTokensPerCall: number;
|
|
60
|
+
/** First call timestamp */
|
|
61
|
+
firstCall?: Date;
|
|
62
|
+
/** Last call timestamp */
|
|
63
|
+
lastCall?: Date;
|
|
64
|
+
/** Usage by model */
|
|
65
|
+
byModel: Record<string, {
|
|
66
|
+
calls: number;
|
|
67
|
+
inputTokens: number;
|
|
68
|
+
outputTokens: number;
|
|
69
|
+
totalTokens: number;
|
|
70
|
+
}>;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Token budget configuration
|
|
74
|
+
*/
|
|
75
|
+
export interface TokenBudgetConfig {
|
|
76
|
+
/** Maximum total tokens allowed */
|
|
77
|
+
maxTotalTokens?: number;
|
|
78
|
+
/** Maximum input tokens allowed */
|
|
79
|
+
maxInputTokens?: number;
|
|
80
|
+
/** Maximum output tokens allowed */
|
|
81
|
+
maxOutputTokens?: number;
|
|
82
|
+
/** Maximum tokens per session */
|
|
83
|
+
maxTokensPerSession?: number;
|
|
84
|
+
/** Warning threshold (0-1, triggers warning event when utilization reaches this) */
|
|
85
|
+
warningThreshold?: number;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Budget status
|
|
89
|
+
*/
|
|
90
|
+
export interface BudgetStatus {
|
|
91
|
+
/** Current total tokens */
|
|
92
|
+
currentTokens: number;
|
|
93
|
+
/** Current input tokens */
|
|
94
|
+
currentInputTokens: number;
|
|
95
|
+
/** Current output tokens */
|
|
96
|
+
currentOutputTokens: number;
|
|
97
|
+
/** Token limit (if set) */
|
|
98
|
+
tokenLimit?: number;
|
|
99
|
+
/** Token utilization (0-1) */
|
|
100
|
+
tokenUtilization?: number;
|
|
101
|
+
/** Whether budget is exceeded */
|
|
102
|
+
exceeded: boolean;
|
|
103
|
+
/** Whether warning threshold is reached */
|
|
104
|
+
warning: boolean;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Usage tracker event types
|
|
108
|
+
*/
|
|
109
|
+
export type UsageEventType = 'usage:recorded' | 'usage:budget_warning' | 'usage:budget_exceeded' | 'usage:reset';
|
|
110
|
+
/**
|
|
111
|
+
* Usage tracker events
|
|
112
|
+
*/
|
|
113
|
+
export type UsageEvent = {
|
|
114
|
+
type: 'usage:recorded';
|
|
115
|
+
record: UsageRecord;
|
|
116
|
+
stats: UsageStats;
|
|
117
|
+
} | {
|
|
118
|
+
type: 'usage:budget_warning';
|
|
119
|
+
status: BudgetStatus;
|
|
120
|
+
threshold: number;
|
|
121
|
+
} | {
|
|
122
|
+
type: 'usage:budget_exceeded';
|
|
123
|
+
status: BudgetStatus;
|
|
124
|
+
} | {
|
|
125
|
+
type: 'usage:reset';
|
|
126
|
+
previousStats: UsageStats;
|
|
127
|
+
};
|
|
128
|
+
/**
|
|
129
|
+
* Event handler for usage events
|
|
130
|
+
*/
|
|
131
|
+
export type UsageEventHandler = (event: UsageEvent) => void;
|
|
132
|
+
/**
|
|
133
|
+
* Options for UsageTracker
|
|
134
|
+
*/
|
|
135
|
+
export interface UsageTrackerOptions {
|
|
136
|
+
/** Whether tracking is enabled (default: true) */
|
|
137
|
+
enabled?: boolean;
|
|
138
|
+
/** Token budget configuration */
|
|
139
|
+
budget?: TokenBudgetConfig;
|
|
140
|
+
/** Session ID for grouping */
|
|
141
|
+
sessionId?: string;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Input for recording usage
|
|
145
|
+
*/
|
|
146
|
+
export interface RecordUsageInput {
|
|
147
|
+
/** Model used */
|
|
148
|
+
model: string;
|
|
149
|
+
/** Provider name */
|
|
150
|
+
provider: string;
|
|
151
|
+
/** Token usage */
|
|
152
|
+
tokens: TokenUsage;
|
|
153
|
+
/** Session ID override */
|
|
154
|
+
sessionId?: string;
|
|
155
|
+
/** Additional metadata */
|
|
156
|
+
metadata?: Record<string, unknown>;
|
|
157
|
+
}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error classes for @compilr-dev/agents
|
|
3
|
+
*
|
|
4
|
+
* Error hierarchy:
|
|
5
|
+
* - AgentError (base)
|
|
6
|
+
* - ProviderError (LLM API errors)
|
|
7
|
+
* - ToolError (tool execution errors)
|
|
8
|
+
* - ValidationError (input validation errors)
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Base error class for all agent-related errors.
|
|
12
|
+
*/
|
|
13
|
+
export declare class AgentError extends Error {
|
|
14
|
+
readonly cause?: Error | undefined;
|
|
15
|
+
constructor(message: string, cause?: Error | undefined);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Error thrown when an LLM provider API call fails.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* throw new ProviderError(
|
|
23
|
+
* 'Rate limit exceeded. Retry after 60s',
|
|
24
|
+
* 'claude',
|
|
25
|
+
* 429
|
|
26
|
+
* );
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export declare class ProviderError extends AgentError {
|
|
30
|
+
readonly provider: string;
|
|
31
|
+
readonly statusCode?: number | undefined;
|
|
32
|
+
constructor(message: string, provider: string, statusCode?: number | undefined, cause?: Error);
|
|
33
|
+
/**
|
|
34
|
+
* Check if this is a rate limit error (HTTP 429)
|
|
35
|
+
*/
|
|
36
|
+
isRateLimitError(): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Check if this is an authentication error (HTTP 401/403)
|
|
39
|
+
*/
|
|
40
|
+
isAuthError(): boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Check if this is a server error (HTTP 5xx)
|
|
43
|
+
*/
|
|
44
|
+
isServerError(): boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Check if this error is retryable
|
|
47
|
+
*/
|
|
48
|
+
isRetryable(): boolean;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Error thrown when a tool execution fails.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```typescript
|
|
55
|
+
* throw new ToolError(
|
|
56
|
+
* 'File not found: /path/to/file.txt',
|
|
57
|
+
* 'read_file',
|
|
58
|
+
* originalError
|
|
59
|
+
* );
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
export declare class ToolError extends AgentError {
|
|
63
|
+
readonly toolName: string;
|
|
64
|
+
constructor(message: string, toolName: string, cause?: Error);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Error thrown when a tool execution times out.
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```typescript
|
|
71
|
+
* throw new ToolTimeoutError('read_file', 30000);
|
|
72
|
+
* ```
|
|
73
|
+
*/
|
|
74
|
+
export declare class ToolTimeoutError extends ToolError {
|
|
75
|
+
readonly toolName: string;
|
|
76
|
+
readonly timeoutMs: number;
|
|
77
|
+
constructor(toolName: string, timeoutMs: number);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Error thrown when input validation fails.
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```typescript
|
|
84
|
+
* throw new ValidationError(
|
|
85
|
+
* 'maxTokens must be a positive number',
|
|
86
|
+
* 'maxTokens'
|
|
87
|
+
* );
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
export declare class ValidationError extends AgentError {
|
|
91
|
+
readonly field: string;
|
|
92
|
+
constructor(message: string, field: string);
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Error thrown when the agentic loop exceeds max iterations.
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* ```typescript
|
|
99
|
+
* throw new MaxIterationsError(10);
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
102
|
+
export declare class MaxIterationsError extends AgentError {
|
|
103
|
+
readonly maxIterations: number;
|
|
104
|
+
constructor(maxIterations: number);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Error thrown when the agent is stuck in a tool call loop.
|
|
108
|
+
*
|
|
109
|
+
* This occurs when the same tool is called with identical input
|
|
110
|
+
* multiple times consecutively, indicating the agent is not
|
|
111
|
+
* processing the tool results properly.
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* ```typescript
|
|
115
|
+
* throw new ToolLoopError('read_file', 3);
|
|
116
|
+
* ```
|
|
117
|
+
*/
|
|
118
|
+
export declare class ToolLoopError extends AgentError {
|
|
119
|
+
readonly toolName: string;
|
|
120
|
+
readonly consecutiveCalls: number;
|
|
121
|
+
readonly input?: Record<string, unknown> | undefined;
|
|
122
|
+
constructor(toolName: string, consecutiveCalls: number, input?: Record<string, unknown> | undefined);
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Error thrown when a request is aborted via AbortSignal.
|
|
126
|
+
*/
|
|
127
|
+
export declare class AbortError extends AgentError {
|
|
128
|
+
constructor(message?: string);
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Error thrown when context window cannot be reduced sufficiently.
|
|
132
|
+
*
|
|
133
|
+
* This occurs when:
|
|
134
|
+
* - Multiple summarization rounds fail to reduce context below target
|
|
135
|
+
* - Content is too large even after aggressive filtering
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* ```typescript
|
|
139
|
+
* throw new ContextOverflowError(
|
|
140
|
+
* 'Unable to reduce context below 90% after 3 summarization rounds',
|
|
141
|
+
* 0.95, // current utilization
|
|
142
|
+
* 3 // rounds attempted
|
|
143
|
+
* );
|
|
144
|
+
* ```
|
|
145
|
+
*/
|
|
146
|
+
export declare class ContextOverflowError extends AgentError {
|
|
147
|
+
readonly utilization: number;
|
|
148
|
+
readonly roundsAttempted?: number | undefined;
|
|
149
|
+
constructor(message: string, utilization: number, roundsAttempted?: number | undefined);
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Type guard to check if an error is a ContextOverflowError
|
|
153
|
+
*/
|
|
154
|
+
export declare function isContextOverflowError(error: unknown): error is ContextOverflowError;
|
|
155
|
+
/**
|
|
156
|
+
* Type guard to check if an error is an AgentError
|
|
157
|
+
*/
|
|
158
|
+
export declare function isAgentError(error: unknown): error is AgentError;
|
|
159
|
+
/**
|
|
160
|
+
* Type guard to check if an error is a ProviderError
|
|
161
|
+
*/
|
|
162
|
+
export declare function isProviderError(error: unknown): error is ProviderError;
|
|
163
|
+
/**
|
|
164
|
+
* Type guard to check if an error is a ToolError
|
|
165
|
+
*/
|
|
166
|
+
export declare function isToolError(error: unknown): error is ToolError;
|
|
167
|
+
/**
|
|
168
|
+
* Type guard to check if an error is a ToolLoopError
|
|
169
|
+
*/
|
|
170
|
+
export declare function isToolLoopError(error: unknown): error is ToolLoopError;
|
|
171
|
+
/**
|
|
172
|
+
* Type guard to check if an error is a ToolTimeoutError
|
|
173
|
+
*/
|
|
174
|
+
export declare function isToolTimeoutError(error: unknown): error is ToolTimeoutError;
|
|
175
|
+
/**
|
|
176
|
+
* Wrap an unknown error into an AgentError
|
|
177
|
+
*/
|
|
178
|
+
export declare function wrapError(error: unknown, message?: string): AgentError;
|