@convex-dev/ai-budget 0.0.2-alpha.3 → 0.0.2-alpha.5
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 +116 -17
- package/dist/client/index.d.ts +433 -34
- package/dist/client/index.js +141 -33
- package/dist/component/_generated/component.d.ts +54 -24
- package/dist/component/lib.d.ts +130 -40
- package/dist/component/lib.js +550 -290
- package/dist/component/schema.d.ts +103 -53
- package/dist/component/schema.js +81 -38
- package/package.json +1 -1
- package/src/client/index.ts +241 -71
- package/src/component/_generated/component.ts +77 -29
- package/src/component/lib.test.ts +167 -15
- package/src/component/lib.ts +640 -313
- package/src/component/schema.ts +84 -38
package/dist/client/index.d.ts
CHANGED
|
@@ -11,21 +11,44 @@ type UseApi<API> = Expand<{
|
|
|
11
11
|
export type AIBudgetApi = UseApi<typeof api>;
|
|
12
12
|
/** @deprecated use AIBudgetApi */
|
|
13
13
|
export type AIGatewayApi = AIBudgetApi;
|
|
14
|
-
/**
|
|
15
|
-
|
|
14
|
+
/**
|
|
15
|
+
* One attribution tag: a (dimension, value) pair, e.g. {dimension:"customer",
|
|
16
|
+
* value:"acme"}. `user` and `action` are built-in dimensions (set via
|
|
17
|
+
* userId/action); use tags for anything else — team, project, tenant, env, ….
|
|
18
|
+
* Any tagged bucket can carry its own budget (see `ai.tag(dimension)`).
|
|
19
|
+
*/
|
|
20
|
+
export type Tag = {
|
|
21
|
+
dimension: string;
|
|
22
|
+
value: string;
|
|
23
|
+
};
|
|
24
|
+
/** Common shape for budget-event callbacks. */
|
|
25
|
+
export type BudgetEventInfo = {
|
|
16
26
|
userId: string;
|
|
17
27
|
action?: string;
|
|
18
|
-
|
|
28
|
+
tags?: Tag[];
|
|
29
|
+
requestId?: string;
|
|
30
|
+
/** soft-cap warnings (onSoftLimit) or approaching-cap notices (onThreshold). */
|
|
31
|
+
messages: string[];
|
|
32
|
+
/** rejection code/reason (onLimitReached only). */
|
|
33
|
+
code?: string;
|
|
34
|
+
reason?: string;
|
|
35
|
+
};
|
|
36
|
+
/** @deprecated use BudgetEventInfo */
|
|
37
|
+
export type SoftLimitInfo = BudgetEventInfo & {
|
|
19
38
|
warnings: string[];
|
|
20
39
|
};
|
|
21
40
|
export type AIBudgetOptions = {
|
|
22
41
|
defaultModel?: string;
|
|
23
42
|
/**
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
43
|
+
* A *soft* limit was exceeded (request still allowed). Lets you surface budget
|
|
44
|
+
* warnings even on the languageModel/Agent path where they can't be returned.
|
|
45
|
+
* Errors thrown in any of these callbacks are swallowed.
|
|
27
46
|
*/
|
|
28
47
|
onSoftLimit?: (info: SoftLimitInfo) => void | Promise<void>;
|
|
48
|
+
/** Usage crossed a bucket's warnAtPct threshold (approaching a cap). */
|
|
49
|
+
onThreshold?: (info: BudgetEventInfo) => void | Promise<void>;
|
|
50
|
+
/** A *hard* limit blocked the request (fires just before chat/model throws). */
|
|
51
|
+
onLimitReached?: (info: BudgetEventInfo) => void | Promise<void>;
|
|
29
52
|
};
|
|
30
53
|
type RunQueryCtx = {
|
|
31
54
|
runQuery: <Query extends FunctionReference<"query", "internal">>(query: Query, args: Query["_args"]) => Promise<Query["_returnType"]>;
|
|
@@ -56,13 +79,39 @@ export type ChatResult = {
|
|
|
56
79
|
cachedTokens: number;
|
|
57
80
|
/** Soft-limit warnings raised at admission (empty unless a soft cap was hit). */
|
|
58
81
|
warnings: string[];
|
|
82
|
+
/** Approaching-cap notices (empty unless a warnAtPct threshold was crossed). */
|
|
83
|
+
notices: string[];
|
|
84
|
+
};
|
|
85
|
+
/** Limits/controls settable on any budget bucket (user, action, or tag). */
|
|
86
|
+
export type BucketLimits = {
|
|
87
|
+
requestsPerMinute?: number;
|
|
88
|
+
maxConcurrent?: number;
|
|
89
|
+
dailySpendLimitNanos?: number;
|
|
90
|
+
monthlySpendLimitNanos?: number;
|
|
91
|
+
lifetimeSpendLimitNanos?: number;
|
|
92
|
+
dailyTokenLimit?: number;
|
|
93
|
+
monthlyTokenLimit?: number;
|
|
94
|
+
lifetimeTokenLimit?: number;
|
|
95
|
+
/** Fire an approaching-limit alert at this fraction of a cap (e.g. 0.8). */
|
|
96
|
+
warnAtPct?: number;
|
|
97
|
+
enforcement?: "hard" | "soft";
|
|
98
|
+
blocked?: boolean;
|
|
99
|
+
};
|
|
100
|
+
/** One-time bump amounts, added on top of a standing cap. */
|
|
101
|
+
export type BumpArgs = {
|
|
102
|
+
dailyNanos?: number;
|
|
103
|
+
monthlyNanos?: number;
|
|
104
|
+
lifetimeNanos?: number;
|
|
59
105
|
};
|
|
60
106
|
export declare class AIBudget {
|
|
61
107
|
component: AIBudgetApi;
|
|
62
108
|
defaultModel: string;
|
|
63
109
|
private onSoftLimit?;
|
|
110
|
+
private onThreshold?;
|
|
111
|
+
private onLimitReached?;
|
|
64
112
|
constructor(component: AIBudgetApi, options?: AIBudgetOptions);
|
|
65
|
-
private
|
|
113
|
+
private fireBudgetEvents;
|
|
114
|
+
private fireLimitReached;
|
|
66
115
|
/**
|
|
67
116
|
* One-shot chat through the AI Gateway with tracking + limits.
|
|
68
117
|
* Call from an action. `userId` defaults to the authenticated caller.
|
|
@@ -76,6 +125,8 @@ export declare class AIBudget {
|
|
|
76
125
|
rerunOf?: string;
|
|
77
126
|
/** Attribute spend to this action name. Defaults to the calling Convex action. */
|
|
78
127
|
action?: string;
|
|
128
|
+
/** Extra attribution dimensions to bill/limit (team, customer, env, …). */
|
|
129
|
+
tags?: Tag[];
|
|
79
130
|
}): Promise<ChatResult>;
|
|
80
131
|
/**
|
|
81
132
|
* An AI SDK LanguageModel that enforces limits and records usage/cost for
|
|
@@ -87,17 +138,26 @@ export declare class AIBudget {
|
|
|
87
138
|
userId?: string;
|
|
88
139
|
model?: string;
|
|
89
140
|
action?: string;
|
|
141
|
+
/** Extra attribution dimensions to bill/limit (team, customer, env, …). */
|
|
142
|
+
tags?: Tag[];
|
|
90
143
|
}): LanguageModel;
|
|
91
144
|
private rerunImpl;
|
|
92
145
|
/** The request audit log, replay, and re-run lineage. */
|
|
93
146
|
get requests(): {
|
|
147
|
+
/** Filter by userId, or by any {dimension, value} (incl. custom tags). */
|
|
94
148
|
list: (ctx: RunQueryCtx, args?: {
|
|
95
149
|
userId?: string;
|
|
150
|
+
dimension?: string;
|
|
151
|
+
value?: string;
|
|
96
152
|
limit?: number;
|
|
97
153
|
}) => Promise<{
|
|
98
154
|
_id: string;
|
|
99
155
|
_creationTime: number;
|
|
100
156
|
actionName?: string | undefined;
|
|
157
|
+
tags?: {
|
|
158
|
+
dimension: string;
|
|
159
|
+
value: string;
|
|
160
|
+
}[] | undefined;
|
|
101
161
|
estimatedNanos?: number | undefined;
|
|
102
162
|
estimatedTokens?: number | undefined;
|
|
103
163
|
unpricedModel?: boolean | undefined;
|
|
@@ -127,6 +187,10 @@ export declare class AIBudget {
|
|
|
127
187
|
_id: string;
|
|
128
188
|
_creationTime: number;
|
|
129
189
|
actionName?: string | undefined;
|
|
190
|
+
tags?: {
|
|
191
|
+
dimension: string;
|
|
192
|
+
value: string;
|
|
193
|
+
}[] | undefined;
|
|
130
194
|
estimatedNanos?: number | undefined;
|
|
131
195
|
estimatedTokens?: number | undefined;
|
|
132
196
|
unpricedModel?: boolean | undefined;
|
|
@@ -152,6 +216,10 @@ export declare class AIBudget {
|
|
|
152
216
|
_id: string;
|
|
153
217
|
_creationTime: number;
|
|
154
218
|
actionName?: string | undefined;
|
|
219
|
+
tags?: {
|
|
220
|
+
dimension: string;
|
|
221
|
+
value: string;
|
|
222
|
+
}[] | undefined;
|
|
155
223
|
estimatedNanos?: number | undefined;
|
|
156
224
|
estimatedTokens?: number | undefined;
|
|
157
225
|
unpricedModel?: boolean | undefined;
|
|
@@ -181,51 +249,281 @@ export declare class AIBudget {
|
|
|
181
249
|
model?: string;
|
|
182
250
|
}) => Promise<ChatResult>;
|
|
183
251
|
};
|
|
184
|
-
/**
|
|
252
|
+
/**
|
|
253
|
+
* Budgets and controls for an arbitrary attribution dimension — the
|
|
254
|
+
* generalization of `users`/`actions`. Give it any dimension name (team,
|
|
255
|
+
* project, tenant, customer, env, feature, …) and set caps per value:
|
|
256
|
+
*
|
|
257
|
+
* ai.tag("customer").setLimits(ctx, { value: "acme", monthlySpendLimitNanos });
|
|
258
|
+
* ai.tag("customer").history(ctx, { value: "acme", period: "day" });
|
|
259
|
+
*
|
|
260
|
+
* Attribute a call to it by passing `tags` to `chat`/`languageModel`.
|
|
261
|
+
*/
|
|
262
|
+
tag(dimension: string): {
|
|
263
|
+
/** All buckets in this dimension. */
|
|
264
|
+
list: (ctx: RunQueryCtx) => Promise<{
|
|
265
|
+
spendTodayNanos: number;
|
|
266
|
+
spendThisMonthNanos: number;
|
|
267
|
+
_id: string;
|
|
268
|
+
_creationTime: number;
|
|
269
|
+
requestsPerMinute?: number | undefined;
|
|
270
|
+
maxConcurrent?: number | undefined;
|
|
271
|
+
dailySpendLimitNanos?: number | undefined;
|
|
272
|
+
monthlySpendLimitNanos?: number | undefined;
|
|
273
|
+
lifetimeSpendLimitNanos?: number | undefined;
|
|
274
|
+
dailyTokenLimit?: number | undefined;
|
|
275
|
+
monthlyTokenLimit?: number | undefined;
|
|
276
|
+
lifetimeTokenLimit?: number | undefined;
|
|
277
|
+
blocked?: boolean | undefined;
|
|
278
|
+
warnAtPct?: number | undefined;
|
|
279
|
+
enforcement?: "hard" | "soft" | undefined;
|
|
280
|
+
dailyBumpNanos?: number | undefined;
|
|
281
|
+
monthlyBumpNanos?: number | undefined;
|
|
282
|
+
lifetimeBumpNanos?: number | undefined;
|
|
283
|
+
bumpDayStamp?: string | undefined;
|
|
284
|
+
bumpMonthStamp?: string | undefined;
|
|
285
|
+
tokensToday?: number | undefined;
|
|
286
|
+
monthStamp?: string | undefined;
|
|
287
|
+
tokensThisMonth?: number | undefined;
|
|
288
|
+
reservedTodayNanos?: number | undefined;
|
|
289
|
+
reservedMonthNanos?: number | undefined;
|
|
290
|
+
reservedTotalNanos?: number | undefined;
|
|
291
|
+
reservedTodayTokens?: number | undefined;
|
|
292
|
+
reservedMonthTokens?: number | undefined;
|
|
293
|
+
reservedTotalTokens?: number | undefined;
|
|
294
|
+
pendingCount?: number | undefined;
|
|
295
|
+
dimension: string;
|
|
296
|
+
value: string;
|
|
297
|
+
totalSpendNanos: number;
|
|
298
|
+
totalRequests: number;
|
|
299
|
+
totalTokens: number;
|
|
300
|
+
dayStamp: string;
|
|
301
|
+
}[]>;
|
|
302
|
+
/** One bucket's limits + spend (null if it has none yet). */
|
|
303
|
+
get: (ctx: RunQueryCtx, args: {
|
|
304
|
+
value: string;
|
|
305
|
+
}) => Promise<{
|
|
306
|
+
spendTodayNanos: number;
|
|
307
|
+
spendThisMonthNanos: number;
|
|
308
|
+
_id: string;
|
|
309
|
+
_creationTime: number;
|
|
310
|
+
requestsPerMinute?: number | undefined;
|
|
311
|
+
maxConcurrent?: number | undefined;
|
|
312
|
+
dailySpendLimitNanos?: number | undefined;
|
|
313
|
+
monthlySpendLimitNanos?: number | undefined;
|
|
314
|
+
lifetimeSpendLimitNanos?: number | undefined;
|
|
315
|
+
dailyTokenLimit?: number | undefined;
|
|
316
|
+
monthlyTokenLimit?: number | undefined;
|
|
317
|
+
lifetimeTokenLimit?: number | undefined;
|
|
318
|
+
blocked?: boolean | undefined;
|
|
319
|
+
warnAtPct?: number | undefined;
|
|
320
|
+
enforcement?: "hard" | "soft" | undefined;
|
|
321
|
+
dailyBumpNanos?: number | undefined;
|
|
322
|
+
monthlyBumpNanos?: number | undefined;
|
|
323
|
+
lifetimeBumpNanos?: number | undefined;
|
|
324
|
+
bumpDayStamp?: string | undefined;
|
|
325
|
+
bumpMonthStamp?: string | undefined;
|
|
326
|
+
tokensToday?: number | undefined;
|
|
327
|
+
monthStamp?: string | undefined;
|
|
328
|
+
tokensThisMonth?: number | undefined;
|
|
329
|
+
reservedTodayNanos?: number | undefined;
|
|
330
|
+
reservedMonthNanos?: number | undefined;
|
|
331
|
+
reservedTotalNanos?: number | undefined;
|
|
332
|
+
reservedTodayTokens?: number | undefined;
|
|
333
|
+
reservedMonthTokens?: number | undefined;
|
|
334
|
+
reservedTotalTokens?: number | undefined;
|
|
335
|
+
pendingCount?: number | undefined;
|
|
336
|
+
dimension: string;
|
|
337
|
+
value: string;
|
|
338
|
+
totalSpendNanos: number;
|
|
339
|
+
totalRequests: number;
|
|
340
|
+
totalTokens: number;
|
|
341
|
+
dayStamp: string;
|
|
342
|
+
} | null>;
|
|
343
|
+
setLimits: (ctx: RunMutationCtx, args: {
|
|
344
|
+
value: string;
|
|
345
|
+
} & BucketLimits) => Promise<null>;
|
|
346
|
+
/** One-time "approve another $X" bump (daily/monthly reset with the window). */
|
|
347
|
+
bump: (ctx: RunMutationCtx, args: {
|
|
348
|
+
value: string;
|
|
349
|
+
} & BumpArgs) => Promise<null>;
|
|
350
|
+
/** Manually credit (negative) or debit (positive) this bucket. */
|
|
351
|
+
adjust: (ctx: RunMutationCtx, args: {
|
|
352
|
+
value: string;
|
|
353
|
+
} & {
|
|
354
|
+
deltaNanos: number;
|
|
355
|
+
tokens?: number;
|
|
356
|
+
reason?: string;
|
|
357
|
+
}) => Promise<null>;
|
|
358
|
+
/** Durable spend history for this bucket (per day or per month). */
|
|
359
|
+
history: (ctx: RunQueryCtx, args: {
|
|
360
|
+
value: string;
|
|
361
|
+
} & {
|
|
362
|
+
period?: "day" | "month";
|
|
363
|
+
limit?: number;
|
|
364
|
+
}) => Promise<{
|
|
365
|
+
_id: string;
|
|
366
|
+
_creationTime: number;
|
|
367
|
+
dimension: string;
|
|
368
|
+
value: string;
|
|
369
|
+
period: "day" | "month";
|
|
370
|
+
stamp: string;
|
|
371
|
+
spendNanos: number;
|
|
372
|
+
tokens: number;
|
|
373
|
+
requests: number;
|
|
374
|
+
}[]>;
|
|
375
|
+
/** Manual-adjustment audit log for this bucket. */
|
|
376
|
+
adjustments: (ctx: RunQueryCtx, args: {
|
|
377
|
+
value: string;
|
|
378
|
+
} & {
|
|
379
|
+
limit?: number;
|
|
380
|
+
}) => Promise<{
|
|
381
|
+
_id: string;
|
|
382
|
+
_creationTime: number;
|
|
383
|
+
tokens?: number | undefined;
|
|
384
|
+
reason?: string | undefined;
|
|
385
|
+
dimension: string;
|
|
386
|
+
value: string;
|
|
387
|
+
deltaNanos: number;
|
|
388
|
+
}[]>;
|
|
389
|
+
/** Delete the bucket (for "user", also its request rows). */
|
|
390
|
+
delete: (ctx: RunMutationCtx, args: {
|
|
391
|
+
value: string;
|
|
392
|
+
}) => Promise<{
|
|
393
|
+
deletedThisBatch: number;
|
|
394
|
+
done: boolean;
|
|
395
|
+
}>;
|
|
396
|
+
};
|
|
397
|
+
private dimensionApi;
|
|
398
|
+
/** Per-user budgets and controls — sugar over the "user" dimension. */
|
|
185
399
|
get users(): {
|
|
400
|
+
/** All buckets in this dimension. */
|
|
186
401
|
list: (ctx: RunQueryCtx) => Promise<{
|
|
187
402
|
spendTodayNanos: number;
|
|
403
|
+
spendThisMonthNanos: number;
|
|
188
404
|
_id: string;
|
|
189
405
|
_creationTime: number;
|
|
190
406
|
requestsPerMinute?: number | undefined;
|
|
407
|
+
maxConcurrent?: number | undefined;
|
|
191
408
|
dailySpendLimitNanos?: number | undefined;
|
|
409
|
+
monthlySpendLimitNanos?: number | undefined;
|
|
192
410
|
lifetimeSpendLimitNanos?: number | undefined;
|
|
193
411
|
dailyTokenLimit?: number | undefined;
|
|
412
|
+
monthlyTokenLimit?: number | undefined;
|
|
194
413
|
lifetimeTokenLimit?: number | undefined;
|
|
195
414
|
blocked?: boolean | undefined;
|
|
415
|
+
warnAtPct?: number | undefined;
|
|
196
416
|
enforcement?: "hard" | "soft" | undefined;
|
|
197
417
|
dailyBumpNanos?: number | undefined;
|
|
418
|
+
monthlyBumpNanos?: number | undefined;
|
|
198
419
|
lifetimeBumpNanos?: number | undefined;
|
|
199
420
|
bumpDayStamp?: string | undefined;
|
|
421
|
+
bumpMonthStamp?: string | undefined;
|
|
200
422
|
tokensToday?: number | undefined;
|
|
423
|
+
monthStamp?: string | undefined;
|
|
424
|
+
tokensThisMonth?: number | undefined;
|
|
201
425
|
reservedTodayNanos?: number | undefined;
|
|
426
|
+
reservedMonthNanos?: number | undefined;
|
|
202
427
|
reservedTotalNanos?: number | undefined;
|
|
203
428
|
reservedTodayTokens?: number | undefined;
|
|
429
|
+
reservedMonthTokens?: number | undefined;
|
|
204
430
|
reservedTotalTokens?: number | undefined;
|
|
205
431
|
pendingCount?: number | undefined;
|
|
206
|
-
|
|
432
|
+
dimension: string;
|
|
433
|
+
value: string;
|
|
207
434
|
totalSpendNanos: number;
|
|
208
435
|
totalRequests: number;
|
|
209
436
|
totalTokens: number;
|
|
210
437
|
dayStamp: string;
|
|
211
438
|
}[]>;
|
|
439
|
+
/** One bucket's limits + spend (null if it has none yet). */
|
|
440
|
+
get: (ctx: RunQueryCtx, args: {
|
|
441
|
+
userId: string;
|
|
442
|
+
}) => Promise<{
|
|
443
|
+
spendTodayNanos: number;
|
|
444
|
+
spendThisMonthNanos: number;
|
|
445
|
+
_id: string;
|
|
446
|
+
_creationTime: number;
|
|
447
|
+
requestsPerMinute?: number | undefined;
|
|
448
|
+
maxConcurrent?: number | undefined;
|
|
449
|
+
dailySpendLimitNanos?: number | undefined;
|
|
450
|
+
monthlySpendLimitNanos?: number | undefined;
|
|
451
|
+
lifetimeSpendLimitNanos?: number | undefined;
|
|
452
|
+
dailyTokenLimit?: number | undefined;
|
|
453
|
+
monthlyTokenLimit?: number | undefined;
|
|
454
|
+
lifetimeTokenLimit?: number | undefined;
|
|
455
|
+
blocked?: boolean | undefined;
|
|
456
|
+
warnAtPct?: number | undefined;
|
|
457
|
+
enforcement?: "hard" | "soft" | undefined;
|
|
458
|
+
dailyBumpNanos?: number | undefined;
|
|
459
|
+
monthlyBumpNanos?: number | undefined;
|
|
460
|
+
lifetimeBumpNanos?: number | undefined;
|
|
461
|
+
bumpDayStamp?: string | undefined;
|
|
462
|
+
bumpMonthStamp?: string | undefined;
|
|
463
|
+
tokensToday?: number | undefined;
|
|
464
|
+
monthStamp?: string | undefined;
|
|
465
|
+
tokensThisMonth?: number | undefined;
|
|
466
|
+
reservedTodayNanos?: number | undefined;
|
|
467
|
+
reservedMonthNanos?: number | undefined;
|
|
468
|
+
reservedTotalNanos?: number | undefined;
|
|
469
|
+
reservedTodayTokens?: number | undefined;
|
|
470
|
+
reservedMonthTokens?: number | undefined;
|
|
471
|
+
reservedTotalTokens?: number | undefined;
|
|
472
|
+
pendingCount?: number | undefined;
|
|
473
|
+
dimension: string;
|
|
474
|
+
value: string;
|
|
475
|
+
totalSpendNanos: number;
|
|
476
|
+
totalRequests: number;
|
|
477
|
+
totalTokens: number;
|
|
478
|
+
dayStamp: string;
|
|
479
|
+
} | null>;
|
|
212
480
|
setLimits: (ctx: RunMutationCtx, args: {
|
|
213
481
|
userId: string;
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
lifetimeSpendLimitNanos?: number;
|
|
217
|
-
dailyTokenLimit?: number;
|
|
218
|
-
lifetimeTokenLimit?: number;
|
|
219
|
-
enforcement?: "hard" | "soft";
|
|
220
|
-
blocked?: boolean;
|
|
221
|
-
}) => Promise<null>;
|
|
222
|
-
/** One-time "approve another $X" bump (daily is today-only). */
|
|
482
|
+
} & BucketLimits) => Promise<null>;
|
|
483
|
+
/** One-time "approve another $X" bump (daily/monthly reset with the window). */
|
|
223
484
|
bump: (ctx: RunMutationCtx, args: {
|
|
224
485
|
userId: string;
|
|
225
|
-
|
|
226
|
-
|
|
486
|
+
} & BumpArgs) => Promise<null>;
|
|
487
|
+
/** Manually credit (negative) or debit (positive) this bucket. */
|
|
488
|
+
adjust: (ctx: RunMutationCtx, args: {
|
|
489
|
+
userId: string;
|
|
490
|
+
} & {
|
|
491
|
+
deltaNanos: number;
|
|
492
|
+
tokens?: number;
|
|
493
|
+
reason?: string;
|
|
227
494
|
}) => Promise<null>;
|
|
228
|
-
/**
|
|
495
|
+
/** Durable spend history for this bucket (per day or per month). */
|
|
496
|
+
history: (ctx: RunQueryCtx, args: {
|
|
497
|
+
userId: string;
|
|
498
|
+
} & {
|
|
499
|
+
period?: "day" | "month";
|
|
500
|
+
limit?: number;
|
|
501
|
+
}) => Promise<{
|
|
502
|
+
_id: string;
|
|
503
|
+
_creationTime: number;
|
|
504
|
+
dimension: string;
|
|
505
|
+
value: string;
|
|
506
|
+
period: "day" | "month";
|
|
507
|
+
stamp: string;
|
|
508
|
+
spendNanos: number;
|
|
509
|
+
tokens: number;
|
|
510
|
+
requests: number;
|
|
511
|
+
}[]>;
|
|
512
|
+
/** Manual-adjustment audit log for this bucket. */
|
|
513
|
+
adjustments: (ctx: RunQueryCtx, args: {
|
|
514
|
+
userId: string;
|
|
515
|
+
} & {
|
|
516
|
+
limit?: number;
|
|
517
|
+
}) => Promise<{
|
|
518
|
+
_id: string;
|
|
519
|
+
_creationTime: number;
|
|
520
|
+
tokens?: number | undefined;
|
|
521
|
+
reason?: string | undefined;
|
|
522
|
+
dimension: string;
|
|
523
|
+
value: string;
|
|
524
|
+
deltaNanos: number;
|
|
525
|
+
}[]>;
|
|
526
|
+
/** Delete the bucket (for "user", also its request rows). */
|
|
229
527
|
delete: (ctx: RunMutationCtx, args: {
|
|
230
528
|
userId: string;
|
|
231
529
|
}) => Promise<{
|
|
@@ -233,49 +531,143 @@ export declare class AIBudget {
|
|
|
233
531
|
done: boolean;
|
|
234
532
|
}>;
|
|
235
533
|
};
|
|
236
|
-
/** Per-action (per-feature) budgets. */
|
|
534
|
+
/** Per-action (per-feature) budgets — sugar over the "action" dimension. */
|
|
237
535
|
get actions(): {
|
|
536
|
+
/** All buckets in this dimension. */
|
|
238
537
|
list: (ctx: RunQueryCtx) => Promise<{
|
|
239
538
|
spendTodayNanos: number;
|
|
539
|
+
spendThisMonthNanos: number;
|
|
240
540
|
_id: string;
|
|
241
541
|
_creationTime: number;
|
|
542
|
+
requestsPerMinute?: number | undefined;
|
|
543
|
+
maxConcurrent?: number | undefined;
|
|
242
544
|
dailySpendLimitNanos?: number | undefined;
|
|
545
|
+
monthlySpendLimitNanos?: number | undefined;
|
|
243
546
|
lifetimeSpendLimitNanos?: number | undefined;
|
|
244
547
|
dailyTokenLimit?: number | undefined;
|
|
548
|
+
monthlyTokenLimit?: number | undefined;
|
|
245
549
|
lifetimeTokenLimit?: number | undefined;
|
|
550
|
+
blocked?: boolean | undefined;
|
|
551
|
+
warnAtPct?: number | undefined;
|
|
246
552
|
enforcement?: "hard" | "soft" | undefined;
|
|
247
553
|
dailyBumpNanos?: number | undefined;
|
|
554
|
+
monthlyBumpNanos?: number | undefined;
|
|
248
555
|
lifetimeBumpNanos?: number | undefined;
|
|
249
556
|
bumpDayStamp?: string | undefined;
|
|
557
|
+
bumpMonthStamp?: string | undefined;
|
|
250
558
|
tokensToday?: number | undefined;
|
|
559
|
+
monthStamp?: string | undefined;
|
|
560
|
+
tokensThisMonth?: number | undefined;
|
|
251
561
|
reservedTodayNanos?: number | undefined;
|
|
562
|
+
reservedMonthNanos?: number | undefined;
|
|
252
563
|
reservedTotalNanos?: number | undefined;
|
|
253
564
|
reservedTodayTokens?: number | undefined;
|
|
565
|
+
reservedMonthTokens?: number | undefined;
|
|
254
566
|
reservedTotalTokens?: number | undefined;
|
|
255
567
|
pendingCount?: number | undefined;
|
|
256
|
-
|
|
568
|
+
dimension: string;
|
|
569
|
+
value: string;
|
|
257
570
|
totalSpendNanos: number;
|
|
258
571
|
totalRequests: number;
|
|
259
572
|
totalTokens: number;
|
|
260
573
|
dayStamp: string;
|
|
261
|
-
name: string;
|
|
262
574
|
}[]>;
|
|
575
|
+
/** One bucket's limits + spend (null if it has none yet). */
|
|
576
|
+
get: (ctx: RunQueryCtx, args: {
|
|
577
|
+
name: string;
|
|
578
|
+
}) => Promise<{
|
|
579
|
+
spendTodayNanos: number;
|
|
580
|
+
spendThisMonthNanos: number;
|
|
581
|
+
_id: string;
|
|
582
|
+
_creationTime: number;
|
|
583
|
+
requestsPerMinute?: number | undefined;
|
|
584
|
+
maxConcurrent?: number | undefined;
|
|
585
|
+
dailySpendLimitNanos?: number | undefined;
|
|
586
|
+
monthlySpendLimitNanos?: number | undefined;
|
|
587
|
+
lifetimeSpendLimitNanos?: number | undefined;
|
|
588
|
+
dailyTokenLimit?: number | undefined;
|
|
589
|
+
monthlyTokenLimit?: number | undefined;
|
|
590
|
+
lifetimeTokenLimit?: number | undefined;
|
|
591
|
+
blocked?: boolean | undefined;
|
|
592
|
+
warnAtPct?: number | undefined;
|
|
593
|
+
enforcement?: "hard" | "soft" | undefined;
|
|
594
|
+
dailyBumpNanos?: number | undefined;
|
|
595
|
+
monthlyBumpNanos?: number | undefined;
|
|
596
|
+
lifetimeBumpNanos?: number | undefined;
|
|
597
|
+
bumpDayStamp?: string | undefined;
|
|
598
|
+
bumpMonthStamp?: string | undefined;
|
|
599
|
+
tokensToday?: number | undefined;
|
|
600
|
+
monthStamp?: string | undefined;
|
|
601
|
+
tokensThisMonth?: number | undefined;
|
|
602
|
+
reservedTodayNanos?: number | undefined;
|
|
603
|
+
reservedMonthNanos?: number | undefined;
|
|
604
|
+
reservedTotalNanos?: number | undefined;
|
|
605
|
+
reservedTodayTokens?: number | undefined;
|
|
606
|
+
reservedMonthTokens?: number | undefined;
|
|
607
|
+
reservedTotalTokens?: number | undefined;
|
|
608
|
+
pendingCount?: number | undefined;
|
|
609
|
+
dimension: string;
|
|
610
|
+
value: string;
|
|
611
|
+
totalSpendNanos: number;
|
|
612
|
+
totalRequests: number;
|
|
613
|
+
totalTokens: number;
|
|
614
|
+
dayStamp: string;
|
|
615
|
+
} | null>;
|
|
263
616
|
setLimits: (ctx: RunMutationCtx, args: {
|
|
264
617
|
name: string;
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
dailyTokenLimit?: number;
|
|
268
|
-
lifetimeTokenLimit?: number;
|
|
269
|
-
enforcement?: "hard" | "soft";
|
|
270
|
-
disabled?: boolean;
|
|
271
|
-
}) => Promise<null>;
|
|
618
|
+
} & BucketLimits) => Promise<null>;
|
|
619
|
+
/** One-time "approve another $X" bump (daily/monthly reset with the window). */
|
|
272
620
|
bump: (ctx: RunMutationCtx, args: {
|
|
273
621
|
name: string;
|
|
274
|
-
|
|
275
|
-
|
|
622
|
+
} & BumpArgs) => Promise<null>;
|
|
623
|
+
/** Manually credit (negative) or debit (positive) this bucket. */
|
|
624
|
+
adjust: (ctx: RunMutationCtx, args: {
|
|
625
|
+
name: string;
|
|
626
|
+
} & {
|
|
627
|
+
deltaNanos: number;
|
|
628
|
+
tokens?: number;
|
|
629
|
+
reason?: string;
|
|
276
630
|
}) => Promise<null>;
|
|
631
|
+
/** Durable spend history for this bucket (per day or per month). */
|
|
632
|
+
history: (ctx: RunQueryCtx, args: {
|
|
633
|
+
name: string;
|
|
634
|
+
} & {
|
|
635
|
+
period?: "day" | "month";
|
|
636
|
+
limit?: number;
|
|
637
|
+
}) => Promise<{
|
|
638
|
+
_id: string;
|
|
639
|
+
_creationTime: number;
|
|
640
|
+
dimension: string;
|
|
641
|
+
value: string;
|
|
642
|
+
period: "day" | "month";
|
|
643
|
+
stamp: string;
|
|
644
|
+
spendNanos: number;
|
|
645
|
+
tokens: number;
|
|
646
|
+
requests: number;
|
|
647
|
+
}[]>;
|
|
648
|
+
/** Manual-adjustment audit log for this bucket. */
|
|
649
|
+
adjustments: (ctx: RunQueryCtx, args: {
|
|
650
|
+
name: string;
|
|
651
|
+
} & {
|
|
652
|
+
limit?: number;
|
|
653
|
+
}) => Promise<{
|
|
654
|
+
_id: string;
|
|
655
|
+
_creationTime: number;
|
|
656
|
+
tokens?: number | undefined;
|
|
657
|
+
reason?: string | undefined;
|
|
658
|
+
dimension: string;
|
|
659
|
+
value: string;
|
|
660
|
+
deltaNanos: number;
|
|
661
|
+
}[]>;
|
|
662
|
+
/** Delete the bucket (for "user", also its request rows). */
|
|
663
|
+
delete: (ctx: RunMutationCtx, args: {
|
|
664
|
+
name: string;
|
|
665
|
+
}) => Promise<{
|
|
666
|
+
deletedThisBatch: number;
|
|
667
|
+
done: boolean;
|
|
668
|
+
}>;
|
|
277
669
|
};
|
|
278
|
-
/** The deployment-wide budget and retention config. */
|
|
670
|
+
/** The deployment-wide budget, alerts, and retention config. */
|
|
279
671
|
get global(): {
|
|
280
672
|
/** Limits + spend today/total. */
|
|
281
673
|
status: (ctx: RunQueryCtx) => Promise<{
|
|
@@ -295,6 +687,10 @@ export declare class AIBudget {
|
|
|
295
687
|
dailyNanos?: number;
|
|
296
688
|
lifetimeNanos?: number;
|
|
297
689
|
}) => Promise<null>;
|
|
690
|
+
/** Default approaching-limit alert threshold (fraction of a cap, e.g. 0.8). */
|
|
691
|
+
setAlertDefaults: (ctx: RunMutationCtx, args: {
|
|
692
|
+
warnAtPct?: number;
|
|
693
|
+
}) => Promise<null>;
|
|
298
694
|
/** Request-row retention window in ms (default 1h; 0 disables). */
|
|
299
695
|
setRetention: (ctx: RunMutationCtx, args: {
|
|
300
696
|
retentionMs: number;
|
|
@@ -318,6 +714,7 @@ export declare class AIBudget {
|
|
|
318
714
|
[x: string]: {
|
|
319
715
|
input: number;
|
|
320
716
|
output: number;
|
|
717
|
+
cached?: number | undefined;
|
|
321
718
|
overridden: boolean;
|
|
322
719
|
};
|
|
323
720
|
}>;
|
|
@@ -325,6 +722,8 @@ export declare class AIBudget {
|
|
|
325
722
|
model: string;
|
|
326
723
|
inputNanosPerMTok: number;
|
|
327
724
|
outputNanosPerMTok: number;
|
|
725
|
+
/** Cache-read rate; defaults to a discount off input if omitted. */
|
|
726
|
+
cachedNanosPerMTok?: number;
|
|
328
727
|
}) => Promise<null>;
|
|
329
728
|
};
|
|
330
729
|
}
|