@agent-native/core 0.187.0 → 0.187.1-nightly-20260924193134
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent/engine/builder-engine.js +11 -0
- package/dist/agent/engine/types.d.ts +1 -0
- package/dist/agent/production-agent.d.ts +2 -0
- package/dist/agent/production-agent.js +28 -1
- package/dist/agent/run-loop-with-resume.js +6 -0
- package/dist/automation/index.d.ts +1 -1
- package/dist/client/error-format.js +4 -4
- package/dist/client/settings/UsageSection.js +105 -17
- package/dist/collab/routes.d.ts +1 -1
- package/dist/feature-flags/index.d.ts +1 -1
- package/dist/feature-flags/index.js +1 -1
- package/dist/feature-flags/registry.d.ts +1 -0
- package/dist/feature-flags/registry.js +5 -0
- package/dist/file-upload/actions/upload-image.d.ts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/integrations/webhook-handler.js +4 -1
- package/dist/jobs/background-automation-runner.js +6 -1
- package/dist/localization/core-messages/ar-SA.js +9 -1
- package/dist/localization/core-messages/de-DE.js +9 -1
- package/dist/localization/core-messages/en-US.d.ts +9 -1
- package/dist/localization/core-messages/en-US.js +9 -1
- package/dist/localization/core-messages/es-ES.js +9 -1
- package/dist/localization/core-messages/fr-FR.js +9 -1
- package/dist/localization/core-messages/hi-IN.js +9 -1
- package/dist/localization/core-messages/ja-JP.js +9 -1
- package/dist/localization/core-messages/ko-KR.js +9 -1
- package/dist/localization/core-messages/pt-BR.js +9 -1
- package/dist/localization/core-messages/zh-CN.js +9 -1
- package/dist/localization/core-messages/zh-TW.js +9 -1
- package/dist/localization/core-messages.d.ts +9 -1
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/routes.d.ts +3 -3
- package/dist/org/handlers.d.ts +1 -1
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/agent-engine-ollama-models-route.d.ts +1 -1
- package/dist/server/agent-teams.js +4 -1
- package/dist/server/core-routes-plugin.d.ts +1 -1
- package/dist/server/core-routes-plugin.js +2 -0
- package/dist/usage/actions/get-usage-metrics.js +4 -1
- package/dist/usage/metrics-store.d.ts +19 -0
- package/dist/usage/metrics-store.js +106 -14
- package/dist/usage/store.d.ts +7 -2
- package/dist/usage/store.js +25 -4
- package/package.json +3 -3
|
@@ -2,7 +2,7 @@ import { getAppConfig } from "../app-config/index.js";
|
|
|
2
2
|
import { getDbExec } from "../db/client.js";
|
|
3
3
|
import { ForbiddenError } from "../sharing/access.js";
|
|
4
4
|
import { isSelfScopedUsageRead, usageOrgScope } from "./org-scope.js";
|
|
5
|
-
import { builderCreditsFromCostCents, usageBillingForEngine, } from "./store.js";
|
|
5
|
+
import { builderCreditsFromCostCents, ensureUsageTable, usageBillingForEngine, MIXED_USAGE_BILLING, } from "./store.js";
|
|
6
6
|
const DAY_MS = 86_400_000;
|
|
7
7
|
function numberField(row, key) {
|
|
8
8
|
return Number(row[key] ?? 0) || 0;
|
|
@@ -133,7 +133,7 @@ async function resolveScope(input, scope, requestedUserEmail) {
|
|
|
133
133
|
function buildUsageCost(row) {
|
|
134
134
|
return numberField(row, "cost_x100") / 100;
|
|
135
135
|
}
|
|
136
|
-
function bucketFromRow(row) {
|
|
136
|
+
function bucketFromRow(row, builderCreditsEnabled) {
|
|
137
137
|
const key = stringField(row, "k");
|
|
138
138
|
return {
|
|
139
139
|
key,
|
|
@@ -144,14 +144,24 @@ function bucketFromRow(row) {
|
|
|
144
144
|
outputTokens: numberField(row, "output_tokens"),
|
|
145
145
|
cacheReadTokens: numberField(row, "cache_read_tokens"),
|
|
146
146
|
cacheWriteTokens: numberField(row, "cache_write_tokens"),
|
|
147
|
+
...(builderCreditsEnabled
|
|
148
|
+
? {
|
|
149
|
+
builderCredits: numberField(row, "builder_credits"),
|
|
150
|
+
estimatedBuilderCredits: builderCreditsFromCostCents(numberField(row, "estimated_builder_cost_x100") / 100),
|
|
151
|
+
otherCostCents: numberField(row, "other_cost_x100") / 100,
|
|
152
|
+
}
|
|
153
|
+
: {}),
|
|
147
154
|
activeUsers: numberField(row, "active_users"),
|
|
148
155
|
lastActiveAt: row.last_active_at == null ? null : numberField(row, "last_active_at"),
|
|
149
156
|
};
|
|
150
157
|
}
|
|
151
|
-
async function usageBuckets(columnExpression, scope, appScope, sinceMs, limit) {
|
|
158
|
+
async function usageBuckets(columnExpression, scope, appScope, sinceMs, limit, builderCreditsEnabled) {
|
|
152
159
|
const result = await getDbExec().execute({
|
|
153
160
|
sql: `SELECT ${columnExpression} AS k,
|
|
154
161
|
COALESCE(SUM(cost_cents_x100), 0) AS cost_x100,
|
|
162
|
+
COALESCE(SUM(builder_credits_used), 0) AS builder_credits,
|
|
163
|
+
COALESCE(SUM(CASE WHEN engine_name = 'builder' AND builder_credits_used IS NULL THEN cost_cents_x100 ELSE 0 END), 0) AS estimated_builder_cost_x100,
|
|
164
|
+
COALESCE(SUM(CASE WHEN engine_name IS DISTINCT FROM 'builder' AND builder_credits_used IS NULL THEN cost_cents_x100 ELSE 0 END), 0) AS other_cost_x100,
|
|
155
165
|
COUNT(*) AS calls,
|
|
156
166
|
COALESCE(SUM(input_tokens), 0) AS input_tokens,
|
|
157
167
|
COALESCE(SUM(output_tokens), 0) AS output_tokens,
|
|
@@ -162,11 +172,11 @@ async function usageBuckets(columnExpression, scope, appScope, sinceMs, limit) {
|
|
|
162
172
|
FROM token_usage
|
|
163
173
|
WHERE ${appScope.where} AND ${scope.where} AND created_at >= ?
|
|
164
174
|
GROUP BY ${columnExpression}
|
|
165
|
-
ORDER BY cost_x100 DESC
|
|
175
|
+
ORDER BY ${builderCreditsEnabled ? "builder_credits DESC, estimated_builder_cost_x100 DESC, other_cost_x100 DESC" : "cost_x100 DESC"}
|
|
166
176
|
LIMIT ?`,
|
|
167
177
|
args: [...appScope.args, ...scope.args, sinceMs, limit],
|
|
168
178
|
});
|
|
169
|
-
return result.rows.map(bucketFromRow);
|
|
179
|
+
return result.rows.map((row) => bucketFromRow(row, builderCreditsEnabled));
|
|
170
180
|
}
|
|
171
181
|
function parseJson(value) {
|
|
172
182
|
if (typeof value !== "string" || !value.trim())
|
|
@@ -221,7 +231,7 @@ function firstUserPrompt(threadData) {
|
|
|
221
231
|
}
|
|
222
232
|
return null;
|
|
223
233
|
}
|
|
224
|
-
async function hydrateRecentPrompts(rows) {
|
|
234
|
+
async function hydrateRecentPrompts(rows, builderCreditsEnabled) {
|
|
225
235
|
const threadIds = [
|
|
226
236
|
...new Set(rows
|
|
227
237
|
.map((row) => nullableStringField(row, "thread_id"))
|
|
@@ -262,6 +272,21 @@ async function hydrateRecentPrompts(rows) {
|
|
|
262
272
|
cacheReadTokens: numberField(row, "cache_read_tokens"),
|
|
263
273
|
cacheWriteTokens: numberField(row, "cache_write_tokens"),
|
|
264
274
|
costCents: numberField(row, "cost_cents_x100") / 100,
|
|
275
|
+
...(builderCreditsEnabled
|
|
276
|
+
? {
|
|
277
|
+
...(row.builder_credits_used != null
|
|
278
|
+
? { builderCredits: numberField(row, "builder_credits_used") }
|
|
279
|
+
: row.engine_name === "builder"
|
|
280
|
+
? {
|
|
281
|
+
estimatedBuilderCredits: builderCreditsFromCostCents(numberField(row, "cost_cents_x100") / 100),
|
|
282
|
+
}
|
|
283
|
+
: {}),
|
|
284
|
+
otherCostCents: row.engine_name === "builder" || row.builder_credits_used != null
|
|
285
|
+
? 0
|
|
286
|
+
: numberField(row, "cost_cents_x100") / 100,
|
|
287
|
+
engineName: nullableStringField(row, "engine_name"),
|
|
288
|
+
}
|
|
289
|
+
: {}),
|
|
265
290
|
prompt: prompt ?? (preview ? preview.slice(0, 359).trimEnd() : null),
|
|
266
291
|
promptSource: prompt
|
|
267
292
|
? "thread"
|
|
@@ -290,7 +315,9 @@ async function detectUsageEngineName() {
|
|
|
290
315
|
return getAppConfig().agent.engine ?? null;
|
|
291
316
|
}
|
|
292
317
|
export async function listAppUsageMetrics(input, accessInput) {
|
|
318
|
+
await ensureUsageTable();
|
|
293
319
|
const scope = input.scope === "workspace" ? "workspace" : "me";
|
|
320
|
+
const builderCreditsEnabled = input.builderCreditsEnabled === true;
|
|
294
321
|
const sinceDays = Math.max(1, Math.min(365, input.sinceDays ?? 30));
|
|
295
322
|
const now = Date.now();
|
|
296
323
|
const sinceMs = now - sinceDays * DAY_MS;
|
|
@@ -304,6 +331,11 @@ export async function listAppUsageMetrics(input, accessInput) {
|
|
|
304
331
|
getDbExec().execute({
|
|
305
332
|
sql: `SELECT
|
|
306
333
|
COALESCE(SUM(cost_cents_x100), 0) AS cost_x100,
|
|
334
|
+
COALESCE(SUM(builder_credits_used), 0) AS builder_credits,
|
|
335
|
+
COALESCE(SUM(CASE WHEN engine_name = 'builder' AND builder_credits_used IS NULL THEN cost_cents_x100 ELSE 0 END), 0) AS estimated_builder_cost_x100,
|
|
336
|
+
COALESCE(SUM(CASE WHEN engine_name IS DISTINCT FROM 'builder' AND builder_credits_used IS NULL THEN cost_cents_x100 ELSE 0 END), 0) AS other_cost_x100,
|
|
337
|
+
COUNT(*) FILTER (WHERE engine_name = 'builder' OR builder_credits_used IS NOT NULL) AS builder_calls,
|
|
338
|
+
COUNT(*) FILTER (WHERE engine_name IS DISTINCT FROM 'builder' AND builder_credits_used IS NULL) AS other_calls,
|
|
307
339
|
COUNT(*) AS calls,
|
|
308
340
|
COALESCE(SUM(input_tokens), 0) AS input_tokens,
|
|
309
341
|
COALESCE(SUM(output_tokens), 0) AS output_tokens,
|
|
@@ -314,11 +346,11 @@ export async function listAppUsageMetrics(input, accessInput) {
|
|
|
314
346
|
WHERE ${appScope.where} AND ${resolved.ownerScope.where} AND created_at >= ?`,
|
|
315
347
|
args: baseArgs,
|
|
316
348
|
}),
|
|
317
|
-
usageBuckets("COALESCE(NULLIF(label, ''), 'chat')", resolved.ownerScope, appScope, sinceMs, 6),
|
|
318
|
-
usageBuckets("COALESCE(NULLIF(model, ''), 'unknown')", resolved.ownerScope, appScope, sinceMs, 4),
|
|
349
|
+
usageBuckets("COALESCE(NULLIF(label, ''), 'chat')", resolved.ownerScope, appScope, sinceMs, 6, builderCreditsEnabled),
|
|
350
|
+
usageBuckets("COALESCE(NULLIF(model, ''), 'unknown')", resolved.ownerScope, appScope, sinceMs, 4, builderCreditsEnabled),
|
|
319
351
|
getDbExec().execute({
|
|
320
352
|
sql: `SELECT created_at, cost_cents_x100, input_tokens, output_tokens,
|
|
321
|
-
cache_read_tokens, cache_write_tokens FROM token_usage
|
|
353
|
+
cache_read_tokens, cache_write_tokens, builder_credits_used, engine_name FROM token_usage
|
|
322
354
|
WHERE ${appScope.where} AND ${resolved.ownerScope.where} AND created_at >= ?
|
|
323
355
|
ORDER BY created_at ASC`,
|
|
324
356
|
args: baseArgs,
|
|
@@ -326,7 +358,7 @@ export async function listAppUsageMetrics(input, accessInput) {
|
|
|
326
358
|
getDbExec().execute({
|
|
327
359
|
sql: `SELECT id, created_at, owner_email, app, label, model,
|
|
328
360
|
input_tokens, output_tokens, cache_read_tokens, cache_write_tokens,
|
|
329
|
-
cost_cents_x100, thread_id
|
|
361
|
+
cost_cents_x100, builder_credits_used, engine_name, thread_id
|
|
330
362
|
FROM token_usage
|
|
331
363
|
WHERE ${appScope.where} AND ${resolved.ownerScope.where} AND created_at >= ?
|
|
332
364
|
ORDER BY created_at DESC
|
|
@@ -340,8 +372,26 @@ export async function listAppUsageMetrics(input, accessInput) {
|
|
|
340
372
|
const date = new Date(numberField(row, "created_at"))
|
|
341
373
|
.toISOString()
|
|
342
374
|
.slice(0, 10);
|
|
343
|
-
const current = dayMap.get(date) ?? {
|
|
375
|
+
const current = dayMap.get(date) ?? {
|
|
376
|
+
costX100: 0,
|
|
377
|
+
calls: 0,
|
|
378
|
+
tokens: 0,
|
|
379
|
+
builderCredits: 0,
|
|
380
|
+
estimatedBuilderCostX100: 0,
|
|
381
|
+
otherCostX100: 0,
|
|
382
|
+
otherCalls: 0,
|
|
383
|
+
};
|
|
344
384
|
current.costX100 += numberField(row, "cost_cents_x100");
|
|
385
|
+
if (row.builder_credits_used != null) {
|
|
386
|
+
current.builderCredits += numberField(row, "builder_credits_used");
|
|
387
|
+
}
|
|
388
|
+
else if (row.engine_name === "builder") {
|
|
389
|
+
current.estimatedBuilderCostX100 += numberField(row, "cost_cents_x100");
|
|
390
|
+
}
|
|
391
|
+
else {
|
|
392
|
+
current.otherCostX100 += numberField(row, "cost_cents_x100");
|
|
393
|
+
current.otherCalls += 1;
|
|
394
|
+
}
|
|
345
395
|
current.calls += 1;
|
|
346
396
|
current.tokens +=
|
|
347
397
|
numberField(row, "input_tokens") +
|
|
@@ -356,6 +406,14 @@ export async function listAppUsageMetrics(input, accessInput) {
|
|
|
356
406
|
costCents: value.costX100 / 100,
|
|
357
407
|
calls: value.calls,
|
|
358
408
|
tokens: value.tokens,
|
|
409
|
+
...(builderCreditsEnabled
|
|
410
|
+
? {
|
|
411
|
+
builderCredits: value.builderCredits,
|
|
412
|
+
estimatedBuilderCredits: builderCreditsFromCostCents(value.estimatedBuilderCostX100 / 100),
|
|
413
|
+
otherCostCents: value.otherCostX100 / 100,
|
|
414
|
+
otherCalls: value.otherCalls,
|
|
415
|
+
}
|
|
416
|
+
: {}),
|
|
359
417
|
}))
|
|
360
418
|
.sort((a, b) => a.date.localeCompare(b.date));
|
|
361
419
|
const today = new Date(now).toISOString().slice(0, 10);
|
|
@@ -364,9 +422,27 @@ export async function listAppUsageMetrics(input, accessInput) {
|
|
|
364
422
|
costCents: 0,
|
|
365
423
|
calls: 0,
|
|
366
424
|
tokens: 0,
|
|
425
|
+
...(builderCreditsEnabled
|
|
426
|
+
? {
|
|
427
|
+
builderCredits: 0,
|
|
428
|
+
estimatedBuilderCredits: 0,
|
|
429
|
+
otherCostCents: 0,
|
|
430
|
+
otherCalls: 0,
|
|
431
|
+
}
|
|
432
|
+
: {}),
|
|
367
433
|
};
|
|
368
|
-
const
|
|
369
|
-
const
|
|
434
|
+
const builderCalls = numberField(totals, "builder_calls");
|
|
435
|
+
const otherCalls = numberField(totals, "other_calls");
|
|
436
|
+
const billing = builderCreditsEnabled
|
|
437
|
+
? builderCalls && otherCalls
|
|
438
|
+
? MIXED_USAGE_BILLING
|
|
439
|
+
: builderCalls
|
|
440
|
+
? usageBillingForEngine("builder")
|
|
441
|
+
: otherCalls
|
|
442
|
+
? usageBillingForEngine(null)
|
|
443
|
+
: usageBillingForEngine(await detectUsageEngineName())
|
|
444
|
+
: usageBillingForEngine(await detectUsageEngineName());
|
|
445
|
+
const recent = await hydrateRecentPrompts(recentResult.rows, builderCreditsEnabled);
|
|
370
446
|
return {
|
|
371
447
|
billing,
|
|
372
448
|
app,
|
|
@@ -388,10 +464,26 @@ export async function listAppUsageMetrics(input, accessInput) {
|
|
|
388
464
|
cacheReadTokens: numberField(totals, "cache_read_tokens"),
|
|
389
465
|
cacheWriteTokens: numberField(totals, "cache_write_tokens"),
|
|
390
466
|
activeUsers: numberField(totals, "active_users"),
|
|
467
|
+
...(builderCreditsEnabled
|
|
468
|
+
? {
|
|
469
|
+
builderCredits: numberField(totals, "builder_credits"),
|
|
470
|
+
estimatedBuilderCredits: builderCreditsFromCostCents(numberField(totals, "estimated_builder_cost_x100") / 100),
|
|
471
|
+
otherCostCents: numberField(totals, "other_cost_x100") / 100,
|
|
472
|
+
otherCalls,
|
|
473
|
+
}
|
|
474
|
+
: {}),
|
|
391
475
|
},
|
|
392
476
|
currentDay: {
|
|
393
477
|
costCents: currentDay.costCents,
|
|
394
|
-
credits:
|
|
478
|
+
credits: currentDay.builderCredits ??
|
|
479
|
+
builderCreditsFromCostCents(currentDay.costCents),
|
|
480
|
+
...(builderCreditsEnabled
|
|
481
|
+
? {
|
|
482
|
+
estimatedBuilderCredits: currentDay.estimatedBuilderCredits ?? 0,
|
|
483
|
+
otherCostCents: currentDay.otherCostCents ?? 0,
|
|
484
|
+
otherCalls: currentDay.otherCalls ?? 0,
|
|
485
|
+
}
|
|
486
|
+
: {}),
|
|
395
487
|
calls: currentDay.calls,
|
|
396
488
|
tokens: currentDay.tokens,
|
|
397
489
|
},
|
package/dist/usage/store.d.ts
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
export { isSelfScopedUsageRead, usageOrgScope, type UsageOrgScope, type UsageOrgScopeOptions, } from "./org-scope.js";
|
|
2
2
|
export declare const BUILDER_AGENT_CREDIT_MARGIN_MULTIPLIER = 1.25;
|
|
3
3
|
export declare const BUILDER_AGENT_CREDITS_PER_USD = 20;
|
|
4
|
-
export type UsageBillingUnit = "usd" | "builder-credits";
|
|
4
|
+
export type UsageBillingUnit = "usd" | "builder-credits" | "mixed";
|
|
5
5
|
export interface UsageBillingMode {
|
|
6
6
|
unit: UsageBillingUnit;
|
|
7
7
|
label: string;
|
|
8
8
|
shortLabel: string;
|
|
9
|
-
source: "estimated-provider-cost" | "builder-agent-credits";
|
|
9
|
+
source: "estimated-provider-cost" | "builder-agent-credits" | "mixed-provider-usage";
|
|
10
10
|
hardCostMarginMultiplier?: number;
|
|
11
11
|
creditsPerUsd?: number;
|
|
12
12
|
}
|
|
13
13
|
export declare const USD_USAGE_BILLING: UsageBillingMode;
|
|
14
14
|
export declare const BUILDER_CREDIT_USAGE_BILLING: UsageBillingMode;
|
|
15
|
+
export declare const MIXED_USAGE_BILLING: UsageBillingMode;
|
|
15
16
|
export declare function usageBillingForEngine(engineName: string | null | undefined): UsageBillingMode;
|
|
16
17
|
export declare function builderCreditsFromCostCents(cents: number): number;
|
|
17
18
|
export interface UsageRecord {
|
|
@@ -37,6 +38,10 @@ export interface UsageRecord {
|
|
|
37
38
|
* provider-reported dollar cost so two surfaces agree exactly.
|
|
38
39
|
*/
|
|
39
40
|
costCentsX100?: number;
|
|
41
|
+
/** Exact credits reported by the Builder gateway for this run, when available. */
|
|
42
|
+
builderCreditsUsed?: number;
|
|
43
|
+
/** Engine selected for this call; nullable on historical and external usage rows. */
|
|
44
|
+
engineName?: string;
|
|
40
45
|
/** Whether cost is provider-reported, estimated, or unavailable. */
|
|
41
46
|
costSource?: UsageCostSource;
|
|
42
47
|
/** Defaults to the active request organization when omitted. */
|
package/dist/usage/store.js
CHANGED
|
@@ -29,6 +29,12 @@ export const BUILDER_CREDIT_USAGE_BILLING = {
|
|
|
29
29
|
hardCostMarginMultiplier: BUILDER_AGENT_CREDIT_MARGIN_MULTIPLIER,
|
|
30
30
|
creditsPerUsd: BUILDER_AGENT_CREDITS_PER_USD,
|
|
31
31
|
};
|
|
32
|
+
export const MIXED_USAGE_BILLING = {
|
|
33
|
+
unit: "mixed",
|
|
34
|
+
label: "Builder credits and provider cost",
|
|
35
|
+
shortLabel: "Mixed",
|
|
36
|
+
source: "mixed-provider-usage",
|
|
37
|
+
};
|
|
32
38
|
export function usageBillingForEngine(engineName) {
|
|
33
39
|
return engineName === "builder"
|
|
34
40
|
? BUILDER_CREDIT_USAGE_BILLING
|
|
@@ -172,6 +178,8 @@ export async function ensureUsageTable() {
|
|
|
172
178
|
cache_read_tokens BIGINT NOT NULL DEFAULT 0,
|
|
173
179
|
cache_write_tokens BIGINT NOT NULL DEFAULT 0,
|
|
174
180
|
cost_cents_x100 BIGINT NOT NULL DEFAULT 0,
|
|
181
|
+
builder_credits_used NUMERIC,
|
|
182
|
+
engine_name TEXT,
|
|
175
183
|
cost_source TEXT NOT NULL DEFAULT 'estimated',
|
|
176
184
|
model TEXT NOT NULL DEFAULT '',
|
|
177
185
|
label TEXT NOT NULL DEFAULT 'chat',
|
|
@@ -192,6 +200,8 @@ export async function ensureUsageTable() {
|
|
|
192
200
|
const additions = [
|
|
193
201
|
["cache_read_tokens", `BIGINT NOT NULL DEFAULT 0`],
|
|
194
202
|
["cache_write_tokens", `BIGINT NOT NULL DEFAULT 0`],
|
|
203
|
+
["builder_credits_used", "NUMERIC"],
|
|
204
|
+
["engine_name", "TEXT"],
|
|
195
205
|
["cost_source", `TEXT NOT NULL DEFAULT 'estimated'`],
|
|
196
206
|
["label", `TEXT NOT NULL DEFAULT 'chat'`],
|
|
197
207
|
["app", `TEXT NOT NULL DEFAULT ''`],
|
|
@@ -288,10 +298,19 @@ export async function recordUsage(recordOrOwner, inputTokens, outputTokens, mode
|
|
|
288
298
|
model: model ?? "",
|
|
289
299
|
}
|
|
290
300
|
: recordOrOwner;
|
|
291
|
-
const { ownerEmail, inputTokens: inTok, outputTokens: outTok, cacheReadTokens = 0, cacheWriteTokens = 0, model: modelName, label, app, refId, costCentsX100, costSource, orgId, runId, threadId, taskId, integrationScopeId, sourcePlatform, sourceId, } = record;
|
|
301
|
+
const { ownerEmail, inputTokens: inTok, outputTokens: outTok, cacheReadTokens = 0, cacheWriteTokens = 0, model: modelName, label, app, refId, costCentsX100, builderCreditsUsed, engineName, costSource, orgId, runId, threadId, taskId, integrationScopeId, sourcePlatform, sourceId, } = record;
|
|
292
302
|
// Skip no-op writes (e.g. a stream aborted before any tokens flowed)
|
|
293
|
-
if (!inTok &&
|
|
303
|
+
if (!inTok &&
|
|
304
|
+
!outTok &&
|
|
305
|
+
!cacheReadTokens &&
|
|
306
|
+
!cacheWriteTokens &&
|
|
307
|
+
builderCreditsUsed == null) {
|
|
294
308
|
return;
|
|
309
|
+
}
|
|
310
|
+
if (builderCreditsUsed != null &&
|
|
311
|
+
(!Number.isFinite(builderCreditsUsed) || builderCreditsUsed < 0)) {
|
|
312
|
+
throw new Error("Builder gateway credits must be a non-negative number.");
|
|
313
|
+
}
|
|
295
314
|
await ensureUsageTable();
|
|
296
315
|
const client = getDbExec();
|
|
297
316
|
const resolvedApp = resolveUsageAppKey(app);
|
|
@@ -319,8 +338,8 @@ export async function recordUsage(recordOrOwner, inputTokens, outputTokens, mode
|
|
|
319
338
|
const id = Date.now() * 1000 + Math.floor(Math.random() * 1000);
|
|
320
339
|
await client.execute({
|
|
321
340
|
sql: `INSERT INTO token_usage
|
|
322
|
-
(id, owner_email, input_tokens, output_tokens, cache_read_tokens, cache_write_tokens, cost_cents_x100, cost_source, model, label, app, ref_id, org_id, run_id, thread_id, task_id, integration_scope_id, source_platform, source_id, created_at)
|
|
323
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
341
|
+
(id, owner_email, input_tokens, output_tokens, cache_read_tokens, cache_write_tokens, cost_cents_x100, builder_credits_used, engine_name, cost_source, model, label, app, ref_id, org_id, run_id, thread_id, task_id, integration_scope_id, source_platform, source_id, created_at)
|
|
342
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
324
343
|
args: [
|
|
325
344
|
id,
|
|
326
345
|
ownerEmail,
|
|
@@ -329,6 +348,8 @@ export async function recordUsage(recordOrOwner, inputTokens, outputTokens, mode
|
|
|
329
348
|
cacheReadTokens,
|
|
330
349
|
cacheWriteTokens,
|
|
331
350
|
costX100,
|
|
351
|
+
builderCreditsUsed ?? null,
|
|
352
|
+
engineName ?? null,
|
|
332
353
|
resolvedCostSource,
|
|
333
354
|
modelName,
|
|
334
355
|
resolvedLabel,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/core",
|
|
3
|
-
"version": "0.187.
|
|
3
|
+
"version": "0.187.1-nightly-20260924193134",
|
|
4
4
|
"description": "The agentic application framework for building autonomous agents with intuitive UIs",
|
|
5
5
|
"homepage": "https://github.com/BuilderIO/agent-native#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -498,9 +498,9 @@
|
|
|
498
498
|
"yaml": "^2.9.0",
|
|
499
499
|
"yjs": "^13.6.32",
|
|
500
500
|
"zod": "^4.3.6",
|
|
501
|
+
"@agent-native/agentkit": "^0.2.9",
|
|
501
502
|
"@agent-native/recap-cli": "0.5.39",
|
|
502
|
-
"@agent-native/toolkit": "^0.20.9"
|
|
503
|
-
"@agent-native/agentkit": "^0.2.9"
|
|
503
|
+
"@agent-native/toolkit": "^0.20.9"
|
|
504
504
|
},
|
|
505
505
|
"devDependencies": {
|
|
506
506
|
"@ai-sdk/anthropic": "^3.0.71",
|