@convex-dev/ai-budget 0.0.2-alpha.4 → 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 +67 -6
- package/dist/client/index.d.ts +318 -43
- package/dist/client/index.js +115 -68
- package/dist/component/_generated/component.d.ts +32 -0
- package/dist/component/lib.d.ts +73 -0
- package/dist/component/lib.js +304 -32
- package/dist/component/schema.d.ts +76 -3
- package/dist/component/schema.js +56 -2
- package/package.json +1 -1
- package/src/client/index.ts +199 -131
- package/src/component/_generated/component.ts +54 -3
- package/src/component/lib.test.ts +118 -0
- package/src/component/lib.ts +375 -48
- package/src/component/schema.ts +59 -2
package/dist/client/index.js
CHANGED
|
@@ -39,14 +39,30 @@ function extractUsage(usage) {
|
|
|
39
39
|
return {
|
|
40
40
|
promptTokens: toTokenCount(usage?.inputTokens ?? usage?.promptTokens),
|
|
41
41
|
completionTokens: toTokenCount(usage?.outputTokens ?? usage?.completionTokens),
|
|
42
|
-
// cached prompt tokens
|
|
43
|
-
// `
|
|
44
|
-
|
|
42
|
+
// cached prompt tokens. The Convex gateway reports these at
|
|
43
|
+
// `usage.inputTokenDetails.cacheReadTokens`; the other paths cover AI SDK v5
|
|
44
|
+
// (`cachedInputTokens`) and raw OpenAI-compatible shapes.
|
|
45
|
+
cachedTokens: toTokenCount(usage?.inputTokenDetails?.cacheReadTokens ??
|
|
46
|
+
usage?.cachedInputTokens ??
|
|
45
47
|
usage?.promptTokensDetails?.cachedTokens ??
|
|
46
48
|
usage?.prompt_tokens_details?.cached_tokens ??
|
|
47
49
|
usage?.cached_tokens),
|
|
48
50
|
};
|
|
49
51
|
}
|
|
52
|
+
// The gateway doesn't report a dollar cost today, but if a future response ever
|
|
53
|
+
// carries an unambiguous nanodollar cost we pass it straight through as
|
|
54
|
+
// authoritative (finishRequest prefers it over the token-based estimate). Only
|
|
55
|
+
// an explicitly nano-denominated field is trusted — a bare `cost` could be in
|
|
56
|
+
// dollars and silently mis-bill by 1e9×.
|
|
57
|
+
function extractGatewayCostNanos(result) {
|
|
58
|
+
const meta = result?.providerMetadata?.convexGateway;
|
|
59
|
+
const candidates = [meta?.costNanos, result?.usage?.costNanos];
|
|
60
|
+
for (const c of candidates) {
|
|
61
|
+
if (typeof c === "number" && Number.isFinite(c) && c >= 0)
|
|
62
|
+
return c;
|
|
63
|
+
}
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
50
66
|
// Flatten an AI SDK prompt (roles + content parts) into simple storable messages.
|
|
51
67
|
function simplifyPrompt(prompt) {
|
|
52
68
|
if (!Array.isArray(prompt))
|
|
@@ -78,24 +94,46 @@ function extractText(result) {
|
|
|
78
94
|
}
|
|
79
95
|
return "";
|
|
80
96
|
}
|
|
81
|
-
// ---------- client ----------
|
|
82
97
|
export class AIBudget {
|
|
83
98
|
component;
|
|
84
99
|
defaultModel;
|
|
85
100
|
onSoftLimit;
|
|
101
|
+
onThreshold;
|
|
102
|
+
onLimitReached;
|
|
86
103
|
constructor(component, options) {
|
|
87
104
|
this.component = component;
|
|
88
105
|
this.defaultModel = options?.defaultModel ?? "openai/gpt-4o-mini";
|
|
89
106
|
this.onSoftLimit = options?.onSoftLimit;
|
|
107
|
+
this.onThreshold = options?.onThreshold;
|
|
108
|
+
this.onLimitReached = options?.onLimitReached;
|
|
90
109
|
}
|
|
91
|
-
|
|
92
|
-
|
|
110
|
+
// Fire the soft-limit + threshold callbacks from a startRequest result.
|
|
111
|
+
async fireBudgetEvents(base, warnings, notices) {
|
|
112
|
+
if (warnings.length > 0 && this.onSoftLimit) {
|
|
113
|
+
try {
|
|
114
|
+
await this.onSoftLimit({ ...base, messages: warnings, warnings });
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
/* never let a callback error break a request */
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (notices.length > 0 && this.onThreshold) {
|
|
121
|
+
try {
|
|
122
|
+
await this.onThreshold({ ...base, messages: notices });
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
/* swallow */
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
async fireLimitReached(info) {
|
|
130
|
+
if (!this.onLimitReached)
|
|
93
131
|
return;
|
|
94
132
|
try {
|
|
95
|
-
await this.
|
|
133
|
+
await this.onLimitReached(info);
|
|
96
134
|
}
|
|
97
135
|
catch {
|
|
98
|
-
|
|
136
|
+
/* swallow */
|
|
99
137
|
}
|
|
100
138
|
}
|
|
101
139
|
/**
|
|
@@ -116,6 +154,14 @@ export class AIBudget {
|
|
|
116
154
|
rerunOf: args.rerunOf,
|
|
117
155
|
});
|
|
118
156
|
if (!started.allowed) {
|
|
157
|
+
await this.fireLimitReached({
|
|
158
|
+
userId,
|
|
159
|
+
action: actionName,
|
|
160
|
+
tags: args.tags,
|
|
161
|
+
messages: [started.reason],
|
|
162
|
+
code: started.code,
|
|
163
|
+
reason: started.reason,
|
|
164
|
+
});
|
|
119
165
|
throw new ConvexError({
|
|
120
166
|
kind: "AIBudgetLimit",
|
|
121
167
|
code: started.code,
|
|
@@ -124,13 +170,8 @@ export class AIBudget {
|
|
|
124
170
|
}
|
|
125
171
|
const requestId = started.requestId;
|
|
126
172
|
const warnings = started.warnings;
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
action: actionName,
|
|
130
|
-
tags: args.tags,
|
|
131
|
-
requestId,
|
|
132
|
-
warnings,
|
|
133
|
-
});
|
|
173
|
+
const notices = started.notices;
|
|
174
|
+
await this.fireBudgetEvents({ userId, action: actionName, tags: args.tags, requestId }, warnings, notices);
|
|
134
175
|
const start = Date.now();
|
|
135
176
|
try {
|
|
136
177
|
// The full chain (incl. system) is stored on the request for audit/replay,
|
|
@@ -150,9 +191,10 @@ export class AIBudget {
|
|
|
150
191
|
requestId,
|
|
151
192
|
responseText: result.text,
|
|
152
193
|
...usage,
|
|
194
|
+
costNanos: extractGatewayCostNanos(result),
|
|
153
195
|
latencyMs: Date.now() - start,
|
|
154
196
|
});
|
|
155
|
-
return { text: result.text, requestId, costNanos, warnings, ...usage };
|
|
197
|
+
return { text: result.text, requestId, costNanos, warnings, notices, ...usage };
|
|
156
198
|
}
|
|
157
199
|
catch (e) {
|
|
158
200
|
await ctx.runMutation(this.component.lib.finishRequest, {
|
|
@@ -172,10 +214,12 @@ export class AIBudget {
|
|
|
172
214
|
languageModel(ctx, opts = {}) {
|
|
173
215
|
const modelId = opts.model ?? this.defaultModel;
|
|
174
216
|
const component = this.component;
|
|
175
|
-
const
|
|
217
|
+
const fireBudgetEvents = this.fireBudgetEvents.bind(this);
|
|
218
|
+
const fireLimitReached = this.fireLimitReached.bind(this);
|
|
176
219
|
const begin = async (params) => {
|
|
177
220
|
const userId = await resolveUserId(ctx, opts.userId);
|
|
178
221
|
const actionName = await resolveActionName(ctx, opts.action);
|
|
222
|
+
const base = { userId, action: actionName, tags: opts.tags };
|
|
179
223
|
const started = await ctx.runMutation(component.lib.startRequest, {
|
|
180
224
|
userId,
|
|
181
225
|
actionName,
|
|
@@ -184,19 +228,19 @@ export class AIBudget {
|
|
|
184
228
|
messages: simplifyPrompt(params.prompt),
|
|
185
229
|
});
|
|
186
230
|
if (!started.allowed) {
|
|
231
|
+
await fireLimitReached({
|
|
232
|
+
...base,
|
|
233
|
+
messages: [started.reason],
|
|
234
|
+
code: started.code,
|
|
235
|
+
reason: started.reason,
|
|
236
|
+
});
|
|
187
237
|
throw new ConvexError({
|
|
188
238
|
kind: "AIBudgetLimit",
|
|
189
239
|
code: started.code,
|
|
190
240
|
reason: started.reason,
|
|
191
241
|
});
|
|
192
242
|
}
|
|
193
|
-
await
|
|
194
|
-
userId,
|
|
195
|
-
action: actionName,
|
|
196
|
-
tags: opts.tags,
|
|
197
|
-
requestId: started.requestId,
|
|
198
|
-
warnings: started.warnings,
|
|
199
|
-
});
|
|
243
|
+
await fireBudgetEvents({ ...base, requestId: started.requestId }, started.warnings, started.notices);
|
|
200
244
|
return started.requestId;
|
|
201
245
|
};
|
|
202
246
|
const finish = async (requestId, fields) => ctx.runMutation(component.lib.finishRequest, { requestId, ...fields });
|
|
@@ -211,6 +255,7 @@ export class AIBudget {
|
|
|
211
255
|
await finish(requestId, {
|
|
212
256
|
responseText: extractText(result),
|
|
213
257
|
...extractUsage(result.usage),
|
|
258
|
+
costNanos: extractGatewayCostNanos(result),
|
|
214
259
|
latencyMs: Date.now() - start,
|
|
215
260
|
});
|
|
216
261
|
return result;
|
|
@@ -295,6 +340,7 @@ export class AIBudget {
|
|
|
295
340
|
get requests() {
|
|
296
341
|
const c = this.component;
|
|
297
342
|
return {
|
|
343
|
+
/** Filter by userId, or by any {dimension, value} (incl. custom tags). */
|
|
298
344
|
list: (ctx, args = {}) => ctx.runQuery(c.lib.listRequests, args),
|
|
299
345
|
/** Ancestors up to the original, plus direct re-runs. */
|
|
300
346
|
lineage: (ctx, args) => ctx.runQuery(c.lib.lineage, { requestId: args.requestId }),
|
|
@@ -307,74 +353,73 @@ export class AIBudget {
|
|
|
307
353
|
* generalization of `users`/`actions`. Give it any dimension name (team,
|
|
308
354
|
* project, tenant, customer, env, feature, …) and set caps per value:
|
|
309
355
|
*
|
|
310
|
-
* ai.tag("customer").setLimits(ctx, { value: "acme",
|
|
311
|
-
* ai.tag("customer").
|
|
356
|
+
* ai.tag("customer").setLimits(ctx, { value: "acme", monthlySpendLimitNanos });
|
|
357
|
+
* ai.tag("customer").history(ctx, { value: "acme", period: "day" });
|
|
312
358
|
*
|
|
313
359
|
* Attribute a call to it by passing `tags` to `chat`/`languageModel`.
|
|
314
360
|
*/
|
|
315
361
|
tag(dimension) {
|
|
362
|
+
return this.dimensionApi(dimension, (a) => a.value);
|
|
363
|
+
}
|
|
364
|
+
// Shared implementation behind tag()/users/actions. `key` maps the namespace's
|
|
365
|
+
// id field (value/userId/name) to the bucket value.
|
|
366
|
+
dimensionApi(dimension, key) {
|
|
316
367
|
const c = this.component;
|
|
317
368
|
return {
|
|
318
369
|
/** All buckets in this dimension. */
|
|
319
370
|
list: (ctx) => ctx.runQuery(c.lib.listBuckets, { dimension }),
|
|
320
371
|
/** One bucket's limits + spend (null if it has none yet). */
|
|
321
|
-
get: (ctx, args) => ctx.runQuery(c.lib.getBucket, { dimension, value: args
|
|
322
|
-
setLimits: (ctx, args) => ctx.runMutation(c.lib.setBucketLimits, { dimension, ...args }),
|
|
323
|
-
/** One-time "approve another $X" bump (daily is today-only). */
|
|
324
|
-
bump: (ctx, args) => ctx.runMutation(c.lib.bumpBucket, { dimension, ...args }),
|
|
325
|
-
/** Delete the bucket (for "user", also its request rows). */
|
|
326
|
-
delete: (ctx, args) => ctx.runMutation(c.lib.deleteBucket, { dimension, value: args.value }),
|
|
327
|
-
};
|
|
328
|
-
}
|
|
329
|
-
/** Per-user budgets and controls — sugar over the "user" dimension. */
|
|
330
|
-
get users() {
|
|
331
|
-
const c = this.component;
|
|
332
|
-
return {
|
|
333
|
-
list: (ctx) => ctx.runQuery(c.lib.listBuckets, { dimension: "user" }),
|
|
372
|
+
get: (ctx, args) => ctx.runQuery(c.lib.getBucket, { dimension, value: key(args) }),
|
|
334
373
|
setLimits: (ctx, args) => {
|
|
335
|
-
const { userId, ...limits } = args;
|
|
374
|
+
const { value, userId, name, ...limits } = args;
|
|
336
375
|
return ctx.runMutation(c.lib.setBucketLimits, {
|
|
337
|
-
dimension
|
|
338
|
-
value:
|
|
376
|
+
dimension,
|
|
377
|
+
value: key(args),
|
|
339
378
|
...limits,
|
|
340
379
|
});
|
|
341
380
|
},
|
|
342
|
-
/** One-time "approve another $X" bump (daily
|
|
381
|
+
/** One-time "approve another $X" bump (daily/monthly reset with the window). */
|
|
343
382
|
bump: (ctx, args) => ctx.runMutation(c.lib.bumpBucket, {
|
|
344
|
-
dimension
|
|
345
|
-
value: args
|
|
383
|
+
dimension,
|
|
384
|
+
value: key(args),
|
|
346
385
|
dailyNanos: args.dailyNanos,
|
|
386
|
+
monthlyNanos: args.monthlyNanos,
|
|
347
387
|
lifetimeNanos: args.lifetimeNanos,
|
|
348
388
|
}),
|
|
349
|
-
/**
|
|
350
|
-
|
|
351
|
-
dimension
|
|
352
|
-
value: args
|
|
389
|
+
/** Manually credit (negative) or debit (positive) this bucket. */
|
|
390
|
+
adjust: (ctx, args) => ctx.runMutation(c.lib.adjustBucket, {
|
|
391
|
+
dimension,
|
|
392
|
+
value: key(args),
|
|
393
|
+
deltaNanos: args.deltaNanos,
|
|
394
|
+
tokens: args.tokens,
|
|
395
|
+
reason: args.reason,
|
|
353
396
|
}),
|
|
397
|
+
/** Durable spend history for this bucket (per day or per month). */
|
|
398
|
+
history: (ctx, args) => ctx.runQuery(c.lib.usageHistory, {
|
|
399
|
+
dimension,
|
|
400
|
+
value: key(args),
|
|
401
|
+
period: args.period ?? "day",
|
|
402
|
+
limit: args.limit,
|
|
403
|
+
}),
|
|
404
|
+
/** Manual-adjustment audit log for this bucket. */
|
|
405
|
+
adjustments: (ctx, args) => ctx.runQuery(c.lib.listAdjustments, {
|
|
406
|
+
dimension,
|
|
407
|
+
value: key(args),
|
|
408
|
+
limit: args.limit,
|
|
409
|
+
}),
|
|
410
|
+
/** Delete the bucket (for "user", also its request rows). */
|
|
411
|
+
delete: (ctx, args) => ctx.runMutation(c.lib.deleteBucket, { dimension, value: key(args) }),
|
|
354
412
|
};
|
|
355
413
|
}
|
|
414
|
+
/** Per-user budgets and controls — sugar over the "user" dimension. */
|
|
415
|
+
get users() {
|
|
416
|
+
return this.dimensionApi("user", (a) => a.userId);
|
|
417
|
+
}
|
|
356
418
|
/** Per-action (per-feature) budgets — sugar over the "action" dimension. */
|
|
357
419
|
get actions() {
|
|
358
|
-
|
|
359
|
-
return {
|
|
360
|
-
list: (ctx) => ctx.runQuery(c.lib.listBuckets, { dimension: "action" }),
|
|
361
|
-
setLimits: (ctx, args) => {
|
|
362
|
-
const { name, ...limits } = args;
|
|
363
|
-
return ctx.runMutation(c.lib.setBucketLimits, {
|
|
364
|
-
dimension: "action",
|
|
365
|
-
value: name,
|
|
366
|
-
...limits,
|
|
367
|
-
});
|
|
368
|
-
},
|
|
369
|
-
bump: (ctx, args) => ctx.runMutation(c.lib.bumpBucket, {
|
|
370
|
-
dimension: "action",
|
|
371
|
-
value: args.name,
|
|
372
|
-
dailyNanos: args.dailyNanos,
|
|
373
|
-
lifetimeNanos: args.lifetimeNanos,
|
|
374
|
-
}),
|
|
375
|
-
};
|
|
420
|
+
return this.dimensionApi("action", (a) => a.name);
|
|
376
421
|
}
|
|
377
|
-
/** The deployment-wide budget and retention config. */
|
|
422
|
+
/** The deployment-wide budget, alerts, and retention config. */
|
|
378
423
|
get global() {
|
|
379
424
|
const c = this.component;
|
|
380
425
|
return {
|
|
@@ -383,6 +428,8 @@ export class AIBudget {
|
|
|
383
428
|
/** A killswitch spend cap across all users/actions (enforced approximately). */
|
|
384
429
|
setLimits: (ctx, args) => ctx.runMutation(c.lib.setGlobalLimits, args),
|
|
385
430
|
bump: (ctx, args) => ctx.runMutation(c.lib.bumpGlobal, args),
|
|
431
|
+
/** Default approaching-limit alert threshold (fraction of a cap, e.g. 0.8). */
|
|
432
|
+
setAlertDefaults: (ctx, args) => ctx.runMutation(c.lib.setAlertDefaults, args),
|
|
386
433
|
/** Request-row retention window in ms (default 1h; 0 disables). */
|
|
387
434
|
setRetention: (ctx, args) => ctx.runMutation(c.lib.setRetention, args),
|
|
388
435
|
};
|
|
@@ -20,15 +20,24 @@ import type { FunctionReference } from "convex/server";
|
|
|
20
20
|
*/
|
|
21
21
|
export type ComponentApi<Name extends string | undefined = string | undefined> = {
|
|
22
22
|
lib: {
|
|
23
|
+
adjustBucket: FunctionReference<"mutation", "internal", {
|
|
24
|
+
deltaNanos: number;
|
|
25
|
+
dimension: string;
|
|
26
|
+
reason?: string;
|
|
27
|
+
tokens?: number;
|
|
28
|
+
value: string;
|
|
29
|
+
}, null, Name>;
|
|
23
30
|
bumpBucket: FunctionReference<"mutation", "internal", {
|
|
24
31
|
dailyNanos?: number;
|
|
25
32
|
dimension: string;
|
|
26
33
|
lifetimeNanos?: number;
|
|
34
|
+
monthlyNanos?: number;
|
|
27
35
|
value: string;
|
|
28
36
|
}, null, Name>;
|
|
29
37
|
bumpGlobal: FunctionReference<"mutation", "internal", {
|
|
30
38
|
dailyNanos?: number;
|
|
31
39
|
lifetimeNanos?: number;
|
|
40
|
+
monthlyNanos?: number;
|
|
32
41
|
}, null, Name>;
|
|
33
42
|
deleteBucket: FunctionReference<"mutation", "internal", {
|
|
34
43
|
dimension: string;
|
|
@@ -40,6 +49,7 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
|
|
|
40
49
|
finishRequest: FunctionReference<"mutation", "internal", {
|
|
41
50
|
cachedTokens?: number;
|
|
42
51
|
completionTokens?: number;
|
|
52
|
+
costNanos?: number;
|
|
43
53
|
error?: string;
|
|
44
54
|
latencyMs?: number;
|
|
45
55
|
promptTokens?: number;
|
|
@@ -69,14 +79,24 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
|
|
|
69
79
|
lineage: FunctionReference<"query", "internal", {
|
|
70
80
|
requestId: string;
|
|
71
81
|
}, any, Name>;
|
|
82
|
+
listAdjustments: FunctionReference<"query", "internal", {
|
|
83
|
+
dimension: string;
|
|
84
|
+
limit?: number;
|
|
85
|
+
value: string;
|
|
86
|
+
}, any, Name>;
|
|
72
87
|
listBuckets: FunctionReference<"query", "internal", {
|
|
73
88
|
dimension?: string;
|
|
74
89
|
}, any, Name>;
|
|
75
90
|
listPrices: FunctionReference<"query", "internal", {}, any, Name>;
|
|
76
91
|
listRequests: FunctionReference<"query", "internal", {
|
|
92
|
+
dimension?: string;
|
|
77
93
|
limit?: number;
|
|
78
94
|
userId?: string;
|
|
95
|
+
value?: string;
|
|
79
96
|
}, any, Name>;
|
|
97
|
+
setAlertDefaults: FunctionReference<"mutation", "internal", {
|
|
98
|
+
warnAtPct?: number;
|
|
99
|
+
}, null, Name>;
|
|
80
100
|
setBucketLimits: FunctionReference<"mutation", "internal", {
|
|
81
101
|
blocked?: boolean;
|
|
82
102
|
dailySpendLimitNanos?: number;
|
|
@@ -85,8 +105,12 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
|
|
|
85
105
|
enforcement?: "hard" | "soft";
|
|
86
106
|
lifetimeSpendLimitNanos?: number;
|
|
87
107
|
lifetimeTokenLimit?: number;
|
|
108
|
+
maxConcurrent?: number;
|
|
109
|
+
monthlySpendLimitNanos?: number;
|
|
110
|
+
monthlyTokenLimit?: number;
|
|
88
111
|
requestsPerMinute?: number;
|
|
89
112
|
value: string;
|
|
113
|
+
warnAtPct?: number;
|
|
90
114
|
}, null, Name>;
|
|
91
115
|
setGlobalLimits: FunctionReference<"mutation", "internal", {
|
|
92
116
|
dailySpendLimitNanos?: number;
|
|
@@ -98,6 +122,7 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
|
|
|
98
122
|
models: Array<string>;
|
|
99
123
|
}, null, Name>;
|
|
100
124
|
setPrice: FunctionReference<"mutation", "internal", {
|
|
125
|
+
cachedNanosPerMTok?: number;
|
|
101
126
|
inputNanosPerMTok: number;
|
|
102
127
|
model: string;
|
|
103
128
|
outputNanosPerMTok: number;
|
|
@@ -120,6 +145,7 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
|
|
|
120
145
|
userId: string;
|
|
121
146
|
}, {
|
|
122
147
|
allowed: true;
|
|
148
|
+
notices: Array<string>;
|
|
123
149
|
requestId: string;
|
|
124
150
|
warnings: Array<string>;
|
|
125
151
|
} | {
|
|
@@ -127,5 +153,11 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
|
|
|
127
153
|
code: string;
|
|
128
154
|
reason: string;
|
|
129
155
|
}, Name>;
|
|
156
|
+
usageHistory: FunctionReference<"query", "internal", {
|
|
157
|
+
dimension: string;
|
|
158
|
+
limit?: number;
|
|
159
|
+
period: "day" | "month";
|
|
160
|
+
value: string;
|
|
161
|
+
}, any, Name>;
|
|
130
162
|
};
|
|
131
163
|
};
|
package/dist/component/lib.d.ts
CHANGED
|
@@ -19,6 +19,7 @@ export declare const startRequest: import("convex/server").RegisteredMutation<"p
|
|
|
19
19
|
allowed: true;
|
|
20
20
|
requestId: import("convex/values").GenericId<"requests">;
|
|
21
21
|
warnings: string[];
|
|
22
|
+
notices: string[];
|
|
22
23
|
}>>;
|
|
23
24
|
export declare const finishRequest: import("convex/server").RegisteredMutation<"public", {
|
|
24
25
|
error?: string | undefined;
|
|
@@ -26,6 +27,7 @@ export declare const finishRequest: import("convex/server").RegisteredMutation<"
|
|
|
26
27
|
promptTokens?: number | undefined;
|
|
27
28
|
completionTokens?: number | undefined;
|
|
28
29
|
cachedTokens?: number | undefined;
|
|
30
|
+
costNanos?: number | undefined;
|
|
29
31
|
latencyMs?: number | undefined;
|
|
30
32
|
requestId: import("convex/values").GenericId<"requests">;
|
|
31
33
|
}, Promise<{
|
|
@@ -136,6 +138,8 @@ export declare const getRequest: import("convex/server").RegisteredQuery<"public
|
|
|
136
138
|
status: "blocked" | "pending" | "success" | "error";
|
|
137
139
|
} | null>>;
|
|
138
140
|
export declare const listRequests: import("convex/server").RegisteredQuery<"public", {
|
|
141
|
+
dimension?: string | undefined;
|
|
142
|
+
value?: string | undefined;
|
|
139
143
|
userId?: string | undefined;
|
|
140
144
|
limit?: number | undefined;
|
|
141
145
|
}, Promise<{
|
|
@@ -171,22 +175,33 @@ export declare const listBuckets: import("convex/server").RegisteredQuery<"publi
|
|
|
171
175
|
dimension?: string | undefined;
|
|
172
176
|
}, Promise<{
|
|
173
177
|
spendTodayNanos: number;
|
|
178
|
+
spendThisMonthNanos: number;
|
|
174
179
|
_id: import("convex/values").GenericId<"buckets">;
|
|
175
180
|
_creationTime: number;
|
|
176
181
|
requestsPerMinute?: number | undefined;
|
|
182
|
+
maxConcurrent?: number | undefined;
|
|
177
183
|
dailySpendLimitNanos?: number | undefined;
|
|
184
|
+
monthlySpendLimitNanos?: number | undefined;
|
|
178
185
|
lifetimeSpendLimitNanos?: number | undefined;
|
|
179
186
|
dailyTokenLimit?: number | undefined;
|
|
187
|
+
monthlyTokenLimit?: number | undefined;
|
|
180
188
|
lifetimeTokenLimit?: number | undefined;
|
|
181
189
|
blocked?: boolean | undefined;
|
|
190
|
+
warnAtPct?: number | undefined;
|
|
182
191
|
enforcement?: "hard" | "soft" | undefined;
|
|
183
192
|
dailyBumpNanos?: number | undefined;
|
|
193
|
+
monthlyBumpNanos?: number | undefined;
|
|
184
194
|
lifetimeBumpNanos?: number | undefined;
|
|
185
195
|
bumpDayStamp?: string | undefined;
|
|
196
|
+
bumpMonthStamp?: string | undefined;
|
|
186
197
|
tokensToday?: number | undefined;
|
|
198
|
+
monthStamp?: string | undefined;
|
|
199
|
+
tokensThisMonth?: number | undefined;
|
|
187
200
|
reservedTodayNanos?: number | undefined;
|
|
201
|
+
reservedMonthNanos?: number | undefined;
|
|
188
202
|
reservedTotalNanos?: number | undefined;
|
|
189
203
|
reservedTodayTokens?: number | undefined;
|
|
204
|
+
reservedMonthTokens?: number | undefined;
|
|
190
205
|
reservedTotalTokens?: number | undefined;
|
|
191
206
|
pendingCount?: number | undefined;
|
|
192
207
|
dimension: string;
|
|
@@ -201,22 +216,33 @@ export declare const getBucket: import("convex/server").RegisteredQuery<"public"
|
|
|
201
216
|
value: string;
|
|
202
217
|
}, Promise<{
|
|
203
218
|
spendTodayNanos: number;
|
|
219
|
+
spendThisMonthNanos: number;
|
|
204
220
|
_id: import("convex/values").GenericId<"buckets">;
|
|
205
221
|
_creationTime: number;
|
|
206
222
|
requestsPerMinute?: number | undefined;
|
|
223
|
+
maxConcurrent?: number | undefined;
|
|
207
224
|
dailySpendLimitNanos?: number | undefined;
|
|
225
|
+
monthlySpendLimitNanos?: number | undefined;
|
|
208
226
|
lifetimeSpendLimitNanos?: number | undefined;
|
|
209
227
|
dailyTokenLimit?: number | undefined;
|
|
228
|
+
monthlyTokenLimit?: number | undefined;
|
|
210
229
|
lifetimeTokenLimit?: number | undefined;
|
|
211
230
|
blocked?: boolean | undefined;
|
|
231
|
+
warnAtPct?: number | undefined;
|
|
212
232
|
enforcement?: "hard" | "soft" | undefined;
|
|
213
233
|
dailyBumpNanos?: number | undefined;
|
|
234
|
+
monthlyBumpNanos?: number | undefined;
|
|
214
235
|
lifetimeBumpNanos?: number | undefined;
|
|
215
236
|
bumpDayStamp?: string | undefined;
|
|
237
|
+
bumpMonthStamp?: string | undefined;
|
|
216
238
|
tokensToday?: number | undefined;
|
|
239
|
+
monthStamp?: string | undefined;
|
|
240
|
+
tokensThisMonth?: number | undefined;
|
|
217
241
|
reservedTodayNanos?: number | undefined;
|
|
242
|
+
reservedMonthNanos?: number | undefined;
|
|
218
243
|
reservedTotalNanos?: number | undefined;
|
|
219
244
|
reservedTodayTokens?: number | undefined;
|
|
245
|
+
reservedMonthTokens?: number | undefined;
|
|
220
246
|
reservedTotalTokens?: number | undefined;
|
|
221
247
|
pendingCount?: number | undefined;
|
|
222
248
|
dimension: string;
|
|
@@ -228,21 +254,65 @@ export declare const getBucket: import("convex/server").RegisteredQuery<"public"
|
|
|
228
254
|
} | null>>;
|
|
229
255
|
export declare const setBucketLimits: import("convex/server").RegisteredMutation<"public", {
|
|
230
256
|
requestsPerMinute?: number | undefined;
|
|
257
|
+
maxConcurrent?: number | undefined;
|
|
231
258
|
dailySpendLimitNanos?: number | undefined;
|
|
259
|
+
monthlySpendLimitNanos?: number | undefined;
|
|
232
260
|
lifetimeSpendLimitNanos?: number | undefined;
|
|
233
261
|
dailyTokenLimit?: number | undefined;
|
|
262
|
+
monthlyTokenLimit?: number | undefined;
|
|
234
263
|
lifetimeTokenLimit?: number | undefined;
|
|
235
264
|
blocked?: boolean | undefined;
|
|
265
|
+
warnAtPct?: number | undefined;
|
|
236
266
|
enforcement?: "hard" | "soft" | undefined;
|
|
237
267
|
dimension: string;
|
|
238
268
|
value: string;
|
|
239
269
|
}, Promise<null>>;
|
|
240
270
|
export declare const bumpBucket: import("convex/server").RegisteredMutation<"public", {
|
|
241
271
|
dailyNanos?: number | undefined;
|
|
272
|
+
monthlyNanos?: number | undefined;
|
|
242
273
|
lifetimeNanos?: number | undefined;
|
|
243
274
|
dimension: string;
|
|
244
275
|
value: string;
|
|
245
276
|
}, Promise<null>>;
|
|
277
|
+
export declare const adjustBucket: import("convex/server").RegisteredMutation<"public", {
|
|
278
|
+
tokens?: number | undefined;
|
|
279
|
+
reason?: string | undefined;
|
|
280
|
+
dimension: string;
|
|
281
|
+
value: string;
|
|
282
|
+
deltaNanos: number;
|
|
283
|
+
}, Promise<null>>;
|
|
284
|
+
export declare const listAdjustments: import("convex/server").RegisteredQuery<"public", {
|
|
285
|
+
limit?: number | undefined;
|
|
286
|
+
dimension: string;
|
|
287
|
+
value: string;
|
|
288
|
+
}, Promise<{
|
|
289
|
+
_id: import("convex/values").GenericId<"adjustments">;
|
|
290
|
+
_creationTime: number;
|
|
291
|
+
tokens?: number | undefined;
|
|
292
|
+
reason?: string | undefined;
|
|
293
|
+
dimension: string;
|
|
294
|
+
value: string;
|
|
295
|
+
deltaNanos: number;
|
|
296
|
+
}[]>>;
|
|
297
|
+
export declare const usageHistory: import("convex/server").RegisteredQuery<"public", {
|
|
298
|
+
limit?: number | undefined;
|
|
299
|
+
dimension: string;
|
|
300
|
+
value: string;
|
|
301
|
+
period: "day" | "month";
|
|
302
|
+
}, Promise<{
|
|
303
|
+
_id: import("convex/values").GenericId<"usage">;
|
|
304
|
+
_creationTime: number;
|
|
305
|
+
dimension: string;
|
|
306
|
+
value: string;
|
|
307
|
+
period: "day" | "month";
|
|
308
|
+
stamp: string;
|
|
309
|
+
spendNanos: number;
|
|
310
|
+
tokens: number;
|
|
311
|
+
requests: number;
|
|
312
|
+
}[]>>;
|
|
313
|
+
export declare const setAlertDefaults: import("convex/server").RegisteredMutation<"public", {
|
|
314
|
+
warnAtPct?: number | undefined;
|
|
315
|
+
}, Promise<null>>;
|
|
246
316
|
export declare const deleteBucket: import("convex/server").RegisteredMutation<"public", {
|
|
247
317
|
dimension: string;
|
|
248
318
|
value: string;
|
|
@@ -268,6 +338,7 @@ export declare const setGlobalLimits: import("convex/server").RegisteredMutation
|
|
|
268
338
|
}, Promise<null>>;
|
|
269
339
|
export declare const bumpGlobal: import("convex/server").RegisteredMutation<"public", {
|
|
270
340
|
dailyNanos?: number | undefined;
|
|
341
|
+
monthlyNanos?: number | undefined;
|
|
271
342
|
lifetimeNanos?: number | undefined;
|
|
272
343
|
}, Promise<null>>;
|
|
273
344
|
export declare const setModelPolicy: import("convex/server").RegisteredMutation<"public", {
|
|
@@ -275,6 +346,7 @@ export declare const setModelPolicy: import("convex/server").RegisteredMutation<
|
|
|
275
346
|
mode: "open" | "allowlist" | "denylist";
|
|
276
347
|
}, Promise<null>>;
|
|
277
348
|
export declare const setPrice: import("convex/server").RegisteredMutation<"public", {
|
|
349
|
+
cachedNanosPerMTok?: number | undefined;
|
|
278
350
|
model: string;
|
|
279
351
|
inputNanosPerMTok: number;
|
|
280
352
|
outputNanosPerMTok: number;
|
|
@@ -282,5 +354,6 @@ export declare const setPrice: import("convex/server").RegisteredMutation<"publi
|
|
|
282
354
|
export declare const listPrices: import("convex/server").RegisteredQuery<"public", {}, Promise<Record<string, {
|
|
283
355
|
input: number;
|
|
284
356
|
output: number;
|
|
357
|
+
cached?: number;
|
|
285
358
|
overridden: boolean;
|
|
286
359
|
}>>>;
|