@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
|
@@ -744,6 +744,14 @@ async function* parseJsonlStream(reader, model, captureContext = {}) {
|
|
|
744
744
|
}
|
|
745
745
|
case "usage": {
|
|
746
746
|
const cacheWrite = (event.cacheCreatedTokens ?? 0) + (event.cacheCreated1hTokens ?? 0);
|
|
747
|
+
if (event.creditsUsed !== undefined &&
|
|
748
|
+
(!Number.isFinite(event.creditsUsed) || event.creditsUsed < 0)) {
|
|
749
|
+
yield gatewayErrorStop({
|
|
750
|
+
error: "Builder gateway returned invalid credit usage",
|
|
751
|
+
errorCode: "builder_gateway_error",
|
|
752
|
+
}, captureContext.creditsLane, captureContext.requestShape);
|
|
753
|
+
return;
|
|
754
|
+
}
|
|
747
755
|
yield {
|
|
748
756
|
type: "usage",
|
|
749
757
|
inputTokens: event.inputTokens ?? 0,
|
|
@@ -752,6 +760,9 @@ async function* parseJsonlStream(reader, model, captureContext = {}) {
|
|
|
752
760
|
? { cacheReadTokens: event.cacheInputTokens }
|
|
753
761
|
: {}),
|
|
754
762
|
...(cacheWrite > 0 ? { cacheWriteTokens: cacheWrite } : {}),
|
|
763
|
+
...(event.creditsUsed !== undefined
|
|
764
|
+
? { builderCreditsUsed: event.creditsUsed }
|
|
765
|
+
: {}),
|
|
755
766
|
};
|
|
756
767
|
break;
|
|
757
768
|
}
|
|
@@ -196,6 +196,7 @@ export type EngineEvent = {
|
|
|
196
196
|
cacheWriteTokens?: number;
|
|
197
197
|
totalTokens?: number;
|
|
198
198
|
reasoningTokens?: number;
|
|
199
|
+
builderCreditsUsed?: number;
|
|
199
200
|
} | {
|
|
200
201
|
/** Final assistant content for the turn. Engines MUST emit this
|
|
201
202
|
* exactly once, immediately before the terminal `stop` event. */
|
|
@@ -571,6 +571,8 @@ export interface AgentLoopUsage {
|
|
|
571
571
|
outputTokens: number;
|
|
572
572
|
cacheReadTokens: number;
|
|
573
573
|
cacheWriteTokens: number;
|
|
574
|
+
builderCreditsUsed?: number;
|
|
575
|
+
engineName?: string;
|
|
574
576
|
model: string;
|
|
575
577
|
/** Number of provider model-stream attempts, including retries. */
|
|
576
578
|
llmCalls?: number;
|
|
@@ -3735,6 +3735,7 @@ export async function runAgentLoop(opts) {
|
|
|
3735
3735
|
outputTokens: 0,
|
|
3736
3736
|
cacheReadTokens: 0,
|
|
3737
3737
|
cacheWriteTokens: 0,
|
|
3738
|
+
engineName: opts.engine.name,
|
|
3738
3739
|
model,
|
|
3739
3740
|
};
|
|
3740
3741
|
const maxIterations = normalizeMaxIterations(opts.maxIterations, getDefaultMaxIterations());
|
|
@@ -4313,12 +4314,21 @@ export async function runAgentLoop(opts) {
|
|
|
4313
4314
|
outputTokens: event.outputTokens,
|
|
4314
4315
|
cacheReadTokens: event.cacheReadTokens ?? 0,
|
|
4315
4316
|
cacheWriteTokens: event.cacheWriteTokens ?? 0,
|
|
4317
|
+
engineName: opts.engine.name,
|
|
4316
4318
|
model,
|
|
4319
|
+
...(event.builderCreditsUsed !== undefined
|
|
4320
|
+
? { builderCreditsUsed: event.builderCreditsUsed }
|
|
4321
|
+
: {}),
|
|
4317
4322
|
};
|
|
4318
4323
|
usage.inputTokens += eventUsage.inputTokens;
|
|
4319
4324
|
usage.outputTokens += eventUsage.outputTokens;
|
|
4320
4325
|
usage.cacheReadTokens += eventUsage.cacheReadTokens;
|
|
4321
4326
|
usage.cacheWriteTokens += eventUsage.cacheWriteTokens;
|
|
4327
|
+
if (eventUsage.builderCreditsUsed !== undefined) {
|
|
4328
|
+
usage.builderCreditsUsed =
|
|
4329
|
+
(usage.builderCreditsUsed ?? 0) +
|
|
4330
|
+
eventUsage.builderCreditsUsed;
|
|
4331
|
+
}
|
|
4322
4332
|
usage.usageReported = true;
|
|
4323
4333
|
opts.onUsage?.(eventUsage);
|
|
4324
4334
|
}
|
|
@@ -6188,6 +6198,7 @@ export async function runAgentLoopWithMainChatInternalContinuations(opts) {
|
|
|
6188
6198
|
outputTokens: 0,
|
|
6189
6199
|
cacheReadTokens: 0,
|
|
6190
6200
|
cacheWriteTokens: 0,
|
|
6201
|
+
engineName: opts.engine.name,
|
|
6191
6202
|
model: opts.model,
|
|
6192
6203
|
};
|
|
6193
6204
|
const addUsage = (next) => {
|
|
@@ -6195,6 +6206,11 @@ export async function runAgentLoopWithMainChatInternalContinuations(opts) {
|
|
|
6195
6206
|
usage.outputTokens += next.outputTokens;
|
|
6196
6207
|
usage.cacheReadTokens += next.cacheReadTokens;
|
|
6197
6208
|
usage.cacheWriteTokens += next.cacheWriteTokens;
|
|
6209
|
+
if (next.builderCreditsUsed !== undefined) {
|
|
6210
|
+
usage.builderCreditsUsed =
|
|
6211
|
+
(usage.builderCreditsUsed ?? 0) + next.builderCreditsUsed;
|
|
6212
|
+
}
|
|
6213
|
+
usage.engineName = next.engineName ?? usage.engineName;
|
|
6198
6214
|
usage.model = next.model;
|
|
6199
6215
|
if (typeof next.llmCalls === "number") {
|
|
6200
6216
|
usage.llmCalls = (usage.llmCalls ?? 0) + next.llmCalls;
|
|
@@ -9074,6 +9090,8 @@ export function createProductionAgentHandler(options) {
|
|
|
9074
9090
|
outputTokens: subUsage.outputTokens,
|
|
9075
9091
|
cacheReadTokens: subUsage.cacheReadTokens,
|
|
9076
9092
|
cacheWriteTokens: subUsage.cacheWriteTokens,
|
|
9093
|
+
builderCreditsUsed: subUsage.builderCreditsUsed,
|
|
9094
|
+
engineName: engine.name,
|
|
9077
9095
|
model: subUsage.model,
|
|
9078
9096
|
label: `custom-agent:${ref.name}`,
|
|
9079
9097
|
runId,
|
|
@@ -9178,6 +9196,7 @@ export function createProductionAgentHandler(options) {
|
|
|
9178
9196
|
outputTokens: 0,
|
|
9179
9197
|
cacheReadTokens: 0,
|
|
9180
9198
|
cacheWriteTokens: 0,
|
|
9199
|
+
engineName: engine.name,
|
|
9181
9200
|
model: effectiveModel,
|
|
9182
9201
|
};
|
|
9183
9202
|
const agentLoopOpts = {
|
|
@@ -9197,6 +9216,11 @@ export function createProductionAgentHandler(options) {
|
|
|
9197
9216
|
turnUsage.outputTokens += usage.outputTokens;
|
|
9198
9217
|
turnUsage.cacheReadTokens += usage.cacheReadTokens;
|
|
9199
9218
|
turnUsage.cacheWriteTokens += usage.cacheWriteTokens;
|
|
9219
|
+
if (usage.builderCreditsUsed !== undefined) {
|
|
9220
|
+
turnUsage.builderCreditsUsed =
|
|
9221
|
+
(turnUsage.builderCreditsUsed ?? 0) + usage.builderCreditsUsed;
|
|
9222
|
+
}
|
|
9223
|
+
turnUsage.engineName = usage.engineName ?? turnUsage.engineName;
|
|
9200
9224
|
turnUsage.model = usage.model;
|
|
9201
9225
|
},
|
|
9202
9226
|
ownerEmail,
|
|
@@ -9367,7 +9391,8 @@ export function createProductionAgentHandler(options) {
|
|
|
9367
9391
|
(turnUsage.inputTokens > 0 ||
|
|
9368
9392
|
turnUsage.outputTokens > 0 ||
|
|
9369
9393
|
turnUsage.cacheReadTokens > 0 ||
|
|
9370
|
-
turnUsage.cacheWriteTokens > 0
|
|
9394
|
+
turnUsage.cacheWriteTokens > 0 ||
|
|
9395
|
+
turnUsage.builderCreditsUsed != null)) {
|
|
9371
9396
|
const { recordUsage } = await import("../usage/store.js");
|
|
9372
9397
|
await recordUsage({
|
|
9373
9398
|
ownerEmail: resolvedOwnerEmail,
|
|
@@ -9375,6 +9400,8 @@ export function createProductionAgentHandler(options) {
|
|
|
9375
9400
|
outputTokens: turnUsage.outputTokens,
|
|
9376
9401
|
cacheReadTokens: turnUsage.cacheReadTokens,
|
|
9377
9402
|
cacheWriteTokens: turnUsage.cacheWriteTokens,
|
|
9403
|
+
builderCreditsUsed: turnUsage.builderCreditsUsed,
|
|
9404
|
+
engineName: engine.name,
|
|
9378
9405
|
model: turnUsage.model,
|
|
9379
9406
|
label: turnUsageLabel || "chat",
|
|
9380
9407
|
// token_usage has had run_id/thread_id/task_id since it was
|
|
@@ -373,6 +373,7 @@ control) {
|
|
|
373
373
|
outputTokens: 0,
|
|
374
374
|
cacheReadTokens: 0,
|
|
375
375
|
cacheWriteTokens: 0,
|
|
376
|
+
engineName: opts.engine.name,
|
|
376
377
|
model: opts.model,
|
|
377
378
|
};
|
|
378
379
|
const addUsage = (next) => {
|
|
@@ -380,6 +381,11 @@ control) {
|
|
|
380
381
|
usage.outputTokens += next.outputTokens;
|
|
381
382
|
usage.cacheReadTokens += next.cacheReadTokens;
|
|
382
383
|
usage.cacheWriteTokens += next.cacheWriteTokens;
|
|
384
|
+
if (next.builderCreditsUsed !== undefined) {
|
|
385
|
+
usage.builderCreditsUsed =
|
|
386
|
+
(usage.builderCreditsUsed ?? 0) + next.builderCreditsUsed;
|
|
387
|
+
}
|
|
388
|
+
usage.engineName = next.engineName ?? usage.engineName;
|
|
383
389
|
usage.model = next.model;
|
|
384
390
|
// Without these, a retry that never got a usage report merges its zeros
|
|
385
391
|
// over an earlier attempt's real numbers, and telemetry reports an
|
|
@@ -186,8 +186,8 @@ export declare function createAutomationCallbackHandler(runtime: AutomationRunti
|
|
|
186
186
|
duplicate?: undefined;
|
|
187
187
|
eventId?: undefined;
|
|
188
188
|
} | {
|
|
189
|
+
error?: undefined;
|
|
189
190
|
accepted: boolean;
|
|
190
191
|
duplicate: boolean;
|
|
191
192
|
eventId: string;
|
|
192
|
-
error?: undefined;
|
|
193
193
|
}>;
|
|
@@ -21,7 +21,7 @@ export const BUILDER_SPACE_SETTINGS_URL = "https://builder.io/account/space?utm_
|
|
|
21
21
|
export const NEW_CHAT_ACTION_HREF = "agent-native:new-chat";
|
|
22
22
|
const OPEN_BUILDER_SPACE_SETTINGS_LABEL = "Open Builder space settings";
|
|
23
23
|
const START_NEW_CHAT_LABEL = "Start new chat";
|
|
24
|
-
const
|
|
24
|
+
const ADD_CREDITS_IN_BUILDER_LABEL = "Add credits in Builder";
|
|
25
25
|
const BUILDER_AUTHENTICATION_ERROR = "Builder rejected the connected credentials. Reconnect Builder.io (free tier available) in Settings, then retry.";
|
|
26
26
|
/**
|
|
27
27
|
* A 401 says the credential this request carried was refused. It does NOT say
|
|
@@ -100,7 +100,7 @@ export function formatChatErrorText(errorMessage, upgradeUrl, errorCode) {
|
|
|
100
100
|
const normalized = normalizeChatError(errorMessage, errorCode);
|
|
101
101
|
if (normalized.message === CREDITS_LIMIT_REACHED_MESSAGE) {
|
|
102
102
|
return upgradeUrl && isSafeUpgradeUrl(upgradeUrl)
|
|
103
|
-
? `${normalized.message}\n\n[${
|
|
103
|
+
? `${normalized.message}\n\n[${ADD_CREDITS_IN_BUILDER_LABEL}](${upgradeUrl})`
|
|
104
104
|
: normalized.message;
|
|
105
105
|
}
|
|
106
106
|
if (!isServerChosenVisitorMessage(normalized.message) &&
|
|
@@ -118,7 +118,7 @@ export function formatChatErrorText(errorMessage, upgradeUrl, errorCode) {
|
|
|
118
118
|
if (!upgradeUrl || !isSafeUpgradeUrl(upgradeUrl)) {
|
|
119
119
|
return `Error: ${normalized.message}`;
|
|
120
120
|
}
|
|
121
|
-
return `Error: ${normalized.message}\n\n[${
|
|
121
|
+
return `Error: ${normalized.message}\n\n[${ADD_CREDITS_IN_BUILDER_LABEL}](${upgradeUrl})`;
|
|
122
122
|
}
|
|
123
123
|
/**
|
|
124
124
|
* True when the server already decided what this reader may be told.
|
|
@@ -229,7 +229,7 @@ const KNOWN_CHAT_ERROR_ACTION_KEYS = new Map([
|
|
|
229
229
|
"agentChat.errorMessages.openBuilderSpaceSettings",
|
|
230
230
|
],
|
|
231
231
|
["Start new chat", "agentChat.errorMessages.startNewChat"],
|
|
232
|
-
["
|
|
232
|
+
["Add credits in Builder", "agentChat.errorMessages.addCreditsInBuilder"],
|
|
233
233
|
]);
|
|
234
234
|
/** Localize only Core's own normalized error copy; preserve provider details. */
|
|
235
235
|
export function localizeKnownChatErrorText(text, t) {
|
|
@@ -8,6 +8,7 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "
|
|
|
8
8
|
import { IconArrowUpRight, IconBell, IconChartLine, IconChevronDown, IconLoader2, IconMail, IconPencil, IconPlus, IconRefresh, IconUsers, IconX, } from "@tabler/icons-react";
|
|
9
9
|
import { useState } from "react";
|
|
10
10
|
import { Link } from "react-router";
|
|
11
|
+
import { useT } from "../i18n.js";
|
|
11
12
|
import { useActionMutation, useActionQuery } from "../use-action.js";
|
|
12
13
|
const LOOKBACKS = [
|
|
13
14
|
{ value: 7, label: "7d" },
|
|
@@ -33,13 +34,53 @@ function compactNumber(value) {
|
|
|
33
34
|
return `${(value / 1_000).toFixed(1)}K`;
|
|
34
35
|
return Math.round(value).toLocaleString();
|
|
35
36
|
}
|
|
36
|
-
function
|
|
37
|
-
if (billing.unit
|
|
38
|
-
|
|
37
|
+
function usageAmount(cents, billing, builderCredits, estimatedBuilderCredits) {
|
|
38
|
+
if (billing.unit !== "usd") {
|
|
39
|
+
if (typeof builderCredits === "number" ||
|
|
40
|
+
typeof estimatedBuilderCredits === "number") {
|
|
41
|
+
return (builderCredits ?? 0) + (estimatedBuilderCredits ?? 0);
|
|
42
|
+
}
|
|
43
|
+
if (billing.unit === "mixed")
|
|
44
|
+
return 0;
|
|
45
|
+
return ((cents / 100) *
|
|
39
46
|
(billing.hardCostMarginMultiplier ?? 1.25) *
|
|
40
|
-
(billing.creditsPerUsd ?? 20);
|
|
41
|
-
return `${credits.toLocaleString(undefined, { maximumFractionDigits: 1 })} credits`;
|
|
47
|
+
(billing.creditsPerUsd ?? 20));
|
|
42
48
|
}
|
|
49
|
+
return cents;
|
|
50
|
+
}
|
|
51
|
+
function formatCost(t, cents, billing, builderCredits, estimatedBuilderCredits, otherCostCents, includeOtherUsd = true) {
|
|
52
|
+
if (billing.unit !== "usd") {
|
|
53
|
+
const parts = [];
|
|
54
|
+
const actual = builderCredits ?? 0;
|
|
55
|
+
const estimated = estimatedBuilderCredits ??
|
|
56
|
+
(typeof builderCredits === "number" || billing.unit === "mixed"
|
|
57
|
+
? 0
|
|
58
|
+
: usageAmount(cents, billing));
|
|
59
|
+
if (actual > 0) {
|
|
60
|
+
parts.push(`${actual.toLocaleString(undefined, { maximumFractionDigits: 3 })} ${t("agentChat.usage.builderCredits", { defaultValue: "Builder credits" })}`);
|
|
61
|
+
}
|
|
62
|
+
if (estimated > 0) {
|
|
63
|
+
parts.push(t("agentChat.usage.estimatedBuilderCredits", {
|
|
64
|
+
defaultValue: "~{{amount}} estimated credits",
|
|
65
|
+
amount: estimated.toLocaleString(undefined, {
|
|
66
|
+
maximumFractionDigits: 3,
|
|
67
|
+
}),
|
|
68
|
+
}));
|
|
69
|
+
}
|
|
70
|
+
if (includeOtherUsd && otherCostCents && otherCostCents > 0) {
|
|
71
|
+
parts.push(t("agentChat.usage.otherUsdSpend", {
|
|
72
|
+
defaultValue: "{{amount}} other USD",
|
|
73
|
+
amount: formatUsdCost(otherCostCents),
|
|
74
|
+
}));
|
|
75
|
+
}
|
|
76
|
+
return (parts.join(" · ") ||
|
|
77
|
+
t("agentChat.usage.noBuilderCredits", {
|
|
78
|
+
defaultValue: "0 Builder credits",
|
|
79
|
+
}));
|
|
80
|
+
}
|
|
81
|
+
return formatUsdCost(cents);
|
|
82
|
+
}
|
|
83
|
+
function formatUsdCost(cents) {
|
|
43
84
|
if (cents < 100)
|
|
44
85
|
return `${cents.toFixed(2)}¢`;
|
|
45
86
|
return `$${(cents / 100).toLocaleString(undefined, {
|
|
@@ -69,11 +110,7 @@ function Trend({ daily, billing, }) {
|
|
|
69
110
|
if (daily.length === 0) {
|
|
70
111
|
return (_jsx("div", { className: "flex h-32 items-center justify-center rounded-lg border border-dashed border-border/70 text-sm text-muted-foreground", children: "No usage recorded in this lookback." }));
|
|
71
112
|
}
|
|
72
|
-
const values = daily.map((day) => billing.
|
|
73
|
-
? (day.costCents / 100) *
|
|
74
|
-
(billing.hardCostMarginMultiplier ?? 1.25) *
|
|
75
|
-
(billing.creditsPerUsd ?? 20)
|
|
76
|
-
: day.costCents);
|
|
113
|
+
const values = daily.map((day) => usageAmount(day.costCents, billing, day.builderCredits, day.estimatedBuilderCredits));
|
|
77
114
|
const max = Math.max(...values, 0.01);
|
|
78
115
|
const points = values.map((value, index) => {
|
|
79
116
|
const x = daily.length === 1 ? 50 : (index / (daily.length - 1)) * 100;
|
|
@@ -90,17 +127,38 @@ function MetricCard({ label, value, detail, accent = false, }) {
|
|
|
90
127
|
return (_jsxs("div", { className: "min-w-0 rounded-lg border border-border/70 bg-card px-4 py-4", children: [_jsx("div", { className: "text-xs font-medium text-muted-foreground", children: label }), _jsx("div", { className: `mt-1 truncate text-xl font-semibold tracking-[-0.02em] tabular-nums ${accent ? "text-primary" : "text-foreground"}`, children: value }), _jsx("div", { className: "mt-1 truncate text-xs text-muted-foreground", children: detail })] }));
|
|
91
128
|
}
|
|
92
129
|
function DriverList({ title, rows, billing, }) {
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
130
|
+
const t = useT();
|
|
131
|
+
const max = Math.max(...rows.map((row) => usageAmount(row.costCents, billing, row.builderCredits, row.estimatedBuilderCredits)), 1);
|
|
132
|
+
const maxOtherUsd = Math.max(...rows.map((row) => row.otherCostCents ?? 0), 1);
|
|
133
|
+
return (_jsxs("div", { children: [_jsxs("div", { className: "mb-3 flex items-center justify-between gap-3", children: [_jsx("h3", { className: "text-sm font-semibold text-foreground", children: title }), _jsx("span", { className: "text-[11px] uppercase tracking-[0.08em] text-muted-foreground", children: billing.unit === "mixed"
|
|
134
|
+
? t("agentChat.usage.driverCreditsAndUsd", {
|
|
135
|
+
defaultValue: "Builder credits / USD",
|
|
136
|
+
})
|
|
137
|
+
: billing.unit === "builder-credits"
|
|
138
|
+
? t("agentChat.usage.builderCredits", {
|
|
139
|
+
defaultValue: "Builder credits",
|
|
140
|
+
})
|
|
141
|
+
: "Spend" })] }), rows.length === 0 ? (_jsx("p", { className: "text-sm text-muted-foreground", children: "No usage recorded yet." })) : (_jsx("div", { className: "space-y-3", children: rows.slice(0, 5).map((row) => {
|
|
142
|
+
const builderAmount = usageAmount(row.costCents, billing, row.builderCredits, row.estimatedBuilderCredits);
|
|
143
|
+
const otherOnly = billing.unit === "mixed" && builderAmount === 0;
|
|
144
|
+
const amount = otherOnly
|
|
145
|
+
? (row.otherCostCents ?? 0)
|
|
146
|
+
: builderAmount;
|
|
147
|
+
const scale = otherOnly ? maxOtherUsd : max;
|
|
148
|
+
return (_jsxs("div", { children: [_jsxs("div", { className: "flex items-center justify-between gap-3 text-sm", children: [_jsx("span", { className: "min-w-0 truncate text-foreground", title: row.label, children: row.label }), _jsx("span", { className: "shrink-0 tabular-nums text-muted-foreground", children: formatCost(t, row.costCents, billing, row.builderCredits, row.estimatedBuilderCredits, row.otherCostCents) })] }), _jsx("div", { className: "mt-1.5 h-1 overflow-hidden rounded-full bg-muted", children: amount > 0 ? (_jsx("div", { className: "h-full rounded-full bg-primary/70", style: {
|
|
149
|
+
width: `${Math.max(4, (amount / scale) * 100)}%`,
|
|
150
|
+
} })) : null })] }, row.key));
|
|
151
|
+
}) }))] }));
|
|
97
152
|
}
|
|
98
153
|
function UsageLoadingState() {
|
|
99
154
|
return (_jsxs("div", { className: "space-y-5", role: "status", "aria-label": "Loading usage", children: [_jsx("div", { className: "grid gap-3 sm:grid-cols-3", children: ["w-24", "w-16", "w-20"].map((width) => (_jsxs("div", { className: "rounded-lg border border-border/70 p-4", children: [_jsx(Skeleton, { className: `h-3 ${width}` }), _jsx(Skeleton, { className: "mt-3 h-6 w-24" }), _jsx(Skeleton, { className: "mt-2 h-3 w-28" })] }, width))) }), _jsxs("div", { className: "rounded-lg border border-border/70 p-4", children: [_jsx(Skeleton, { className: "h-4 w-32" }), _jsx(Skeleton, { className: "mt-3 h-32 w-full" })] })] }));
|
|
100
155
|
}
|
|
101
156
|
function AlertEditor({ draft, onChange, onSave, onCancel, isPending, }) {
|
|
157
|
+
const t = useT();
|
|
102
158
|
const channelCount = Number(draft.inApp) + Number(draft.email);
|
|
103
|
-
return (_jsxs("div", { className: "mt-3 rounded-lg border border-border/70 bg-muted/20 p-3", children: [_jsxs("div", { className: "grid gap-3 sm:grid-cols-[1fr_1fr_1fr]", children: [_jsxs("label", { className: "space-y-1.5 text-xs text-muted-foreground", children: [_jsx("span", { children: "Unit" }), _jsxs(Select, { value: draft.unit, onValueChange: (value) => onChange({ unit: value }), children: [_jsx(SelectTrigger, { className: "h-9 bg-background text-sm", children: _jsx(SelectValue, {}) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "usd", children: "Dollars" }), _jsx(SelectItem, { value: "builder-credits", children:
|
|
159
|
+
return (_jsxs("div", { className: "mt-3 rounded-lg border border-border/70 bg-muted/20 p-3", children: [_jsxs("div", { className: "grid gap-3 sm:grid-cols-[1fr_1fr_1fr]", children: [_jsxs("label", { className: "space-y-1.5 text-xs text-muted-foreground", children: [_jsx("span", { children: "Unit" }), _jsxs(Select, { value: draft.unit, onValueChange: (value) => onChange({ unit: value }), children: [_jsx(SelectTrigger, { className: "h-9 bg-background text-sm", children: _jsx(SelectValue, {}) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "usd", children: "Dollars" }), _jsx(SelectItem, { value: "builder-credits", children: t("agentChat.usage.builderCredits", {
|
|
160
|
+
defaultValue: "Builder credits",
|
|
161
|
+
}) }), _jsx(SelectItem, { value: "tokens", children: "Tokens" })] })] })] }), _jsxs("label", { className: "space-y-1.5 text-xs text-muted-foreground", children: [_jsx("span", { children: "Threshold" }), _jsx(Input, { type: "number", min: "0.01", step: draft.unit === "tokens" ? "1" : "0.01", value: draft.limit, onChange: (event) => onChange({ limit: event.target.value }), className: "h-9 bg-background text-sm" })] }), _jsxs("label", { className: "space-y-1.5 text-xs text-muted-foreground", children: [_jsx("span", { children: "Window" }), _jsxs(Select, { value: draft.period, onValueChange: (value) => onChange({ period: value }), children: [_jsx(SelectTrigger, { className: "h-9 bg-background text-sm", children: _jsx(SelectValue, {}) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "day", children: "Per day" }), _jsx(SelectItem, { value: "month", children: "Per month" })] })] })] })] }), _jsxs("div", { className: "mt-3 flex flex-wrap items-center gap-4 text-xs text-muted-foreground", children: [_jsx("span", { className: "font-medium text-foreground", children: "Deliver via" }), _jsxs("label", { className: "inline-flex items-center gap-2", children: [_jsx(Checkbox, { checked: draft.inApp, onCheckedChange: (checked) => onChange({ inApp: checked === true }) }), _jsx(IconBell, { className: "size-3.5" }), " In app"] }), _jsxs("label", { className: "inline-flex items-center gap-2", children: [_jsx(Checkbox, { checked: draft.email, onCheckedChange: (checked) => onChange({ email: checked === true }) }), _jsx(IconMail, { className: "size-3.5" }), " Email"] }), _jsxs("div", { className: "ms-auto flex items-center gap-2", children: [_jsx(Button, { type: "button", variant: "ghost", size: "sm", onClick: onCancel, children: "Cancel" }), _jsxs(Button, { type: "button", size: "sm", onClick: onSave, disabled: isPending || channelCount === 0, children: [isPending ? _jsx(IconLoader2, { className: "animate-spin" }) : null, "Save alert"] })] })] })] }));
|
|
104
162
|
}
|
|
105
163
|
function UsageAlertsSection({ appId }) {
|
|
106
164
|
const query = useActionQuery("get-usage-alerts", {
|
|
@@ -176,6 +234,7 @@ function UsageAlertsSection({ appId }) {
|
|
|
176
234
|
}), editing && !editing.ruleId ? (_jsxs("div", { className: "px-4 py-4", children: [_jsx("div", { className: "mb-2 text-xs font-medium text-muted-foreground", children: appLabel(editing.appId) }), _jsx(AlertEditor, { draft: editing, onChange: (patch) => setEditing((current) => current ? { ...current, ...patch } : current), onSave: saveDraft, onCancel: () => setEditing(null), isPending: mutation.isPending })] })) : null] })] }));
|
|
177
235
|
}
|
|
178
236
|
export function UsageSection({ appId = null, viewAllHref, }) {
|
|
237
|
+
const t = useT();
|
|
179
238
|
const [sinceDays, setSinceDays] = useState(30);
|
|
180
239
|
const [scope, setScope] = useState("me");
|
|
181
240
|
const [selectedUserEmail, setSelectedUserEmail] = useState(null);
|
|
@@ -199,8 +258,37 @@ export function UsageSection({ appId = null, viewAllHref, }) {
|
|
|
199
258
|
return (_jsxs("div", { className: "mx-auto w-full max-w-5xl space-y-6", children: [_jsxs("header", { className: "flex flex-col gap-4 border-b border-border/70 pb-5 lg:flex-row lg:items-end lg:justify-between", children: [_jsxs("div", { children: [_jsxs("div", { className: "flex items-center gap-2 text-xs font-medium uppercase tracking-[0.1em] text-primary", children: [_jsx(IconChartLine, { className: "size-4" }), " Usage"] }), _jsxs("h1", { className: "mt-2 text-xl font-semibold tracking-[-0.02em] text-foreground", children: [appLabel(appId), " usage"] }), _jsx("p", { className: "mt-1 max-w-xl text-sm leading-6 text-muted-foreground", children: "A focused view of spend, capacity, and the prompts driving this app." })] }), _jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [data?.access.canViewWorkspace ? (_jsxs(Select, { value: scope, onValueChange: (value) => {
|
|
200
259
|
setScope(value);
|
|
201
260
|
setSelectedUserEmail(null);
|
|
202
|
-
}, children: [_jsx(SelectTrigger, { className: "h-9 w-32 text-xs", children: _jsx(SelectValue, {}) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "me", children: "My usage" }), _jsx(SelectItem, { value: "workspace", children: "Workspace" })] })] })) : null, scope === "workspace" && data ? (_jsxs(Select, { value: selectedUserEmail ?? "all", onValueChange: (value) => setSelectedUserEmail(value === "all" ? null : value), children: [_jsx(SelectTrigger, { className: "h-9 w-44 text-xs", children: _jsx(SelectValue, { placeholder: "All users" }) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "all", children: "All users" }), data.availableUsers.map((user) => (_jsx(SelectItem, { value: user.email, children: user.email }, user.email)))] })] })) : null, _jsx("div", { className: "flex items-center rounded-md border border-border/70 p-0.5", children: LOOKBACKS.map((range) => (_jsx(Button, { type: "button", variant: sinceDays === range.value ? "secondary" : "ghost", size: "sm", className: "h-8 px-2.5 text-xs", onClick: () => setSinceDays(range.value), children: range.label }, range.value))) }), _jsx(Button, { type: "button", variant: "outline", size: "icon", onClick: () => void query.refetch(), disabled: query.isFetching, "aria-label": "Refresh usage", title: "Refresh usage", children: query.isFetching ? (_jsx(IconLoader2, { className: "animate-spin" })) : (_jsx(IconRefresh, {})) })] })] }), query.isError && !data ? (_jsxs("div", { className: "rounded-lg border border-destructive/30 bg-destructive/5 px-4 py-4 text-sm", role: "alert", children: [_jsx("div", { className: "font-medium text-destructive", children: "Usage data couldn\u2019t be loaded." }), _jsx(Button, { type: "button", variant: "link", size: "sm", className: "mt-1 h-auto p-0", onClick: () => void query.refetch(), children: "Try again" })] })) : null, !data && query.isLoading ? _jsx(UsageLoadingState, {}) : null, data ? (_jsxs(_Fragment, { children: [_jsxs("div", { className:
|
|
261
|
+
}, children: [_jsx(SelectTrigger, { className: "h-9 w-32 text-xs", children: _jsx(SelectValue, {}) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "me", children: "My usage" }), _jsx(SelectItem, { value: "workspace", children: "Workspace" })] })] })) : null, scope === "workspace" && data ? (_jsxs(Select, { value: selectedUserEmail ?? "all", onValueChange: (value) => setSelectedUserEmail(value === "all" ? null : value), children: [_jsx(SelectTrigger, { className: "h-9 w-44 text-xs", children: _jsx(SelectValue, { placeholder: "All users" }) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "all", children: "All users" }), data.availableUsers.map((user) => (_jsx(SelectItem, { value: user.email, children: user.email }, user.email)))] })] })) : null, _jsx("div", { className: "flex items-center rounded-md border border-border/70 p-0.5", children: LOOKBACKS.map((range) => (_jsx(Button, { type: "button", variant: sinceDays === range.value ? "secondary" : "ghost", size: "sm", className: "h-8 px-2.5 text-xs", onClick: () => setSinceDays(range.value), children: range.label }, range.value))) }), _jsx(Button, { type: "button", variant: "outline", size: "icon", onClick: () => void query.refetch(), disabled: query.isFetching, "aria-label": "Refresh usage", title: "Refresh usage", children: query.isFetching ? (_jsx(IconLoader2, { className: "animate-spin" })) : (_jsx(IconRefresh, {})) })] })] }), query.isError && !data ? (_jsxs("div", { className: "rounded-lg border border-destructive/30 bg-destructive/5 px-4 py-4 text-sm", role: "alert", children: [_jsx("div", { className: "font-medium text-destructive", children: "Usage data couldn\u2019t be loaded." }), _jsx(Button, { type: "button", variant: "link", size: "sm", className: "mt-1 h-auto p-0", onClick: () => void query.refetch(), children: "Try again" })] })) : null, !data && query.isLoading ? _jsx(UsageLoadingState, {}) : null, data ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: `grid gap-3 ${billing.unit === "mixed" ? "sm:grid-cols-2 xl:grid-cols-4" : "sm:grid-cols-3"}`, children: [_jsx(MetricCard, { label: billing.unit === "builder-credits"
|
|
262
|
+
? t("agentChat.usage.builderCredits", {
|
|
263
|
+
defaultValue: "Builder credits",
|
|
264
|
+
})
|
|
265
|
+
: billing.unit === "mixed"
|
|
266
|
+
? t("agentChat.usage.builderCredits", {
|
|
267
|
+
defaultValue: "Builder credits",
|
|
268
|
+
})
|
|
269
|
+
: billing.label, value: formatCost(t, data.totals.costCents, billing, data.totals.builderCredits, data.totals.estimatedBuilderCredits, data.totals.otherCostCents, false), detail: `${sinceDays} day lookback`, accent: true }), billing.unit === "mixed" ? (_jsx(MetricCard, { label: t("agentChat.usage.otherUnclassifiedSpend", {
|
|
270
|
+
defaultValue: "Other or unclassified USD spend",
|
|
271
|
+
}), value: formatUsdCost(data.totals.otherCostCents ?? 0), detail: t("agentChat.usage.providerSpendDetail", {
|
|
272
|
+
defaultValue: "Provider or older calls outside Builder billing",
|
|
273
|
+
}) })) : null, _jsx(MetricCard, { label: "Calls", value: data.totals.calls.toLocaleString(), detail: `${data.currentDay.calls.toLocaleString()} today` }), _jsx(MetricCard, { label: "Tokens", value: compactNumber(totalTokens), detail: `${compactNumber(data.currentDay.tokens)} today` })] }), _jsxs("section", { className: "rounded-lg border border-border/70 bg-card p-4", children: [_jsxs("div", { className: "flex flex-wrap items-start justify-between gap-3", children: [_jsxs("div", { children: [_jsx("h2", { className: "text-sm font-semibold text-foreground", children: "Daily trend" }), _jsxs("p", { className: "mt-1 text-xs text-muted-foreground", children: [formatCost(t, data.currentDay.costCents, billing, data.currentDay.credits, data.currentDay.estimatedBuilderCredits, data.currentDay.otherCostCents, false), " ", "used today \u00B7 ", data.currentDay.calls.toLocaleString(), " calls"] }), billing.unit === "mixed" &&
|
|
274
|
+
(data.currentDay.otherCalls ?? 0) > 0 ? (_jsx("p", { className: "mt-1 text-xs text-muted-foreground", children: t("agentChat.usage.providerSpendToday", {
|
|
275
|
+
defaultValue: "Other or unclassified usage: {{amount}} today",
|
|
276
|
+
amount: formatUsdCost(data.currentDay.otherCostCents ?? 0),
|
|
277
|
+
}) })) : null] }), _jsxs("div", { className: "flex items-center gap-1.5 text-xs text-muted-foreground", children: [scope === "workspace" ? (_jsx(IconUsers, { className: "size-3.5" })) : null, scope === "workspace"
|
|
203
278
|
? (selectedUserEmail ?? "All users")
|
|
204
|
-
: "Your usage"] })] }), _jsx("div", { className: "mt-4", children:
|
|
279
|
+
: "Your usage"] })] }), _jsx("div", { className: "mt-4", children: _jsxs("div", { className: billing.unit === "mixed" &&
|
|
280
|
+
(data.totals.otherCostCents ?? 0) > 0
|
|
281
|
+
? "grid gap-4 md:grid-cols-2"
|
|
282
|
+
: "", children: [_jsxs("div", { children: [billing.unit === "mixed" ? (_jsx("h3", { className: "mb-2 text-xs font-medium text-muted-foreground", children: t("agentChat.usage.builderCredits", {
|
|
283
|
+
defaultValue: "Builder credits",
|
|
284
|
+
}) })) : null, _jsx(Trend, { daily: data.daily, billing: billing })] }), billing.unit === "mixed" &&
|
|
285
|
+
(data.totals.otherCostCents ?? 0) > 0 ? (_jsxs("div", { children: [_jsx("h3", { className: "mb-2 text-xs font-medium text-muted-foreground", children: t("agentChat.usage.otherUnclassifiedSpend", {
|
|
286
|
+
defaultValue: "Other or unclassified USD spend",
|
|
287
|
+
}) }), _jsx(Trend, { daily: data.daily.map((day) => ({
|
|
288
|
+
date: day.date,
|
|
289
|
+
costCents: day.otherCostCents ?? 0,
|
|
290
|
+
calls: day.otherCalls ?? 0,
|
|
291
|
+
tokens: 0,
|
|
292
|
+
})), billing: { unit: "usd", label: "USD" } })] })) : null] }) })] }), _jsxs("details", { className: "group rounded-lg border border-border/70 bg-card", children: [_jsxs("summary", { className: "flex cursor-pointer list-none items-center justify-between gap-3 px-4 py-4 outline-none transition-colors hover:bg-accent/30 focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset [&::-webkit-details-marker]:hidden", children: [_jsxs("span", { children: [_jsx("span", { className: "block text-sm font-semibold text-foreground", children: "Top usage drivers" }), _jsx("span", { className: "mt-1 block text-xs text-muted-foreground", children: "Breakdowns stay collapsed until you need them." })] }), _jsx(IconChevronDown, { className: "size-4 text-muted-foreground transition-transform group-open:rotate-180" })] }), _jsxs("div", { className: "grid gap-6 border-t border-border/70 px-4 py-4 md:grid-cols-2", children: [_jsx(DriverList, { title: "By workflow", rows: data.byLabel, billing: billing }), _jsx(DriverList, { title: "By model", rows: data.byModel, billing: billing })] })] }), _jsxs("details", { className: "group rounded-lg border border-border/70 bg-card", children: [_jsxs("summary", { className: "flex cursor-pointer list-none items-center justify-between gap-3 px-4 py-4 outline-none transition-colors hover:bg-accent/30 focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-inset [&::-webkit-details-marker]:hidden", children: [_jsxs("span", { children: [_jsx("span", { className: "block text-sm font-semibold text-foreground", children: "Recent prompts" }), _jsx("span", { className: "mt-1 block text-xs text-muted-foreground", children: "Latest recorded prompts for the selected app and user scope." })] }), _jsxs("span", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [data.recent.length, _jsx(IconChevronDown, { className: "size-4 transition-transform group-open:rotate-180" })] })] }), _jsx("div", { className: "border-t border-border/70", children: data.recent.length === 0 ? (_jsx("p", { className: "px-4 py-5 text-sm text-muted-foreground", children: "No recent prompts recorded." })) : (_jsx("div", { className: "divide-y divide-border/60", children: data.recent.map((entry) => (_jsxs("div", { className: "px-4 py-3", children: [_jsxs("div", { className: "flex flex-wrap items-center justify-between gap-2 text-[11px] text-muted-foreground", children: [_jsxs("span", { children: [entry.label, " \u00B7 ", entry.model] }), _jsx("span", { children: entry.ownerEmail })] }), _jsx("p", { className: "mt-1 line-clamp-2 text-sm text-foreground", children: entry.prompt ??
|
|
205
293
|
"Prompt text was not captured for this call." })] }, entry.id))) })) })] }), _jsx(UsageAlertsSection, { appId: appId }), viewAllHref ? (_jsx("div", { className: "flex justify-end", children: _jsx(Button, { asChild: true, variant: "link", size: "sm", className: "gap-1.5", children: _jsxs(Link, { to: viewAllHref, children: ["View all usage", _jsx(IconArrowUpRight, {})] }) }) })) : null] })) : null] }));
|
|
206
294
|
}
|
package/dist/collab/routes.d.ts
CHANGED
|
@@ -26,8 +26,8 @@ export declare const getCollabState: import("h3").EventHandlerWithFetch<import("
|
|
|
26
26
|
* Body: { update: string (base64), requestSource?: string }
|
|
27
27
|
*/
|
|
28
28
|
export declare const postCollabUpdate: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
29
|
-
error: string;
|
|
30
29
|
ok?: undefined;
|
|
30
|
+
error: string;
|
|
31
31
|
} | {
|
|
32
32
|
error?: undefined;
|
|
33
33
|
ok: boolean;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { CONNECT_APPS_FLAG, defineFeatureFlag, defineFeatureFlags, getFeatureFlagDefinition, listFeatureFlags, registerFeatureFlags, type FeatureFlagDefinition, } from "./registry.js";
|
|
1
|
+
export { BUILDER_CREDIT_USAGE_REPORTING_FLAG, CONNECT_APPS_FLAG, defineFeatureFlag, defineFeatureFlags, getFeatureFlagDefinition, listFeatureFlags, registerFeatureFlags, type FeatureFlagDefinition, } from "./registry.js";
|
|
2
2
|
export { defaultFeatureFlagRules, evaluateFeatureFlag, evaluateFeatureFlagRules, hasActiveFeatureFlagRollout, isFeatureFlagEnabled, getFeatureFlagRules, normalizeFeatureFlagRules, type FeatureFlagMode, type FeatureFlagRules, type FeatureFlagScope, } from "./store.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { CONNECT_APPS_FLAG, defineFeatureFlag, defineFeatureFlags, getFeatureFlagDefinition, listFeatureFlags, registerFeatureFlags, } from "./registry.js";
|
|
1
|
+
export { BUILDER_CREDIT_USAGE_REPORTING_FLAG, CONNECT_APPS_FLAG, defineFeatureFlag, defineFeatureFlags, getFeatureFlagDefinition, listFeatureFlags, registerFeatureFlags, } from "./registry.js";
|
|
2
2
|
export { defaultFeatureFlagRules, evaluateFeatureFlag, evaluateFeatureFlagRules, hasActiveFeatureFlagRollout, isFeatureFlagEnabled, getFeatureFlagRules, normalizeFeatureFlagRules, } from "./store.js";
|
|
3
3
|
// Plugin and A2A auth stay on `./server` and `@agent-native/core/server`.
|
|
4
4
|
// Re-exporting them here pulls HMAC Node builtins into any Vite client that
|
|
@@ -10,6 +10,7 @@ export interface FeatureFlagDefinition {
|
|
|
10
10
|
export declare function defineFeatureFlag(definition: FeatureFlagDefinition): FeatureFlagDefinition;
|
|
11
11
|
/** Framework-owned labs flag available to every app's feature-flag plugin. */
|
|
12
12
|
export declare const CONNECT_APPS_FLAG: FeatureFlagDefinition;
|
|
13
|
+
export declare const BUILDER_CREDIT_USAGE_REPORTING_FLAG: FeatureFlagDefinition;
|
|
13
14
|
/** Define a small app-owned feature-flag registry. */
|
|
14
15
|
export declare function defineFeatureFlags(definitions: readonly FeatureFlagDefinition[]): readonly FeatureFlagDefinition[];
|
|
15
16
|
/** Register definitions once at Nitro startup. Re-registering identical data is safe for HMR. */
|
|
@@ -25,6 +25,11 @@ export const CONNECT_APPS_FLAG = defineFeatureFlag({
|
|
|
25
25
|
displayName: "Connect apps",
|
|
26
26
|
description: "Show the experimental app connection surface.",
|
|
27
27
|
});
|
|
28
|
+
export const BUILDER_CREDIT_USAGE_REPORTING_FLAG = defineFeatureFlag({
|
|
29
|
+
key: "billing.builder-credit-usage-reporting",
|
|
30
|
+
displayName: "Builder credit usage reporting",
|
|
31
|
+
description: "Use the Builder gateway's reported credit charges in usage reports.",
|
|
32
|
+
});
|
|
28
33
|
/** Define a small app-owned feature-flag registry. */
|
|
29
34
|
export function defineFeatureFlags(definitions) {
|
|
30
35
|
const seen = new Set();
|
|
@@ -44,9 +44,9 @@ declare const _default: import("../../action.js").ActionDefinition<{
|
|
|
44
44
|
url: string;
|
|
45
45
|
id: string;
|
|
46
46
|
provider: string;
|
|
47
|
-
error?: undefined;
|
|
48
47
|
configured?: undefined;
|
|
49
48
|
connectPath?: undefined;
|
|
49
|
+
error?: undefined;
|
|
50
50
|
} | {
|
|
51
51
|
url?: undefined;
|
|
52
52
|
id?: undefined;
|
package/dist/index.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ export { createDevScriptRegistry } from "./scripts/dev/index.js";
|
|
|
11
11
|
export { createAgentChatPlugin, defaultAgentChatPlugin, createAgentNativeEmbeddedPlugin, mountAgentNativeEmbedded, createServer, createSSEHandler, defineNitroPlugin, autoMountAuth, getSession, type AgentChatPluginOptions, type AgentNativeEmbeddedPluginOptions, type AuthSession, type AuthOptions, type CreateServerOptions, type SSEHandlerOptions, } from "./root-server-compat.js";
|
|
12
12
|
export { BUILT_IN_INTEGRATION_CATALOG, INTEGRATION_CATEGORIES, getIntegrationCatalogEntry, listBuiltInChannelIntegrations, listIntegrationCatalog, type AutomationCapabilities, type BuiltInChannelId, type ChannelCapabilities, type IntegrationAvailability, type IntegrationCatalogEntry, type IntegrationCategory, type IntegrationCredentialRequirement, type IntegrationIconKey, type IntegrationSupportMaturity, } from "./integrations/catalog.js";
|
|
13
13
|
export { AutomationConnectorError, createAutomationCallbackHandler, createAutomationRuntime, createInvokeAutomationWorkflowAction, type AutomationCallbackAuthentication, type AutomationCallbackInput, type AutomationCallbackResult, type AutomationInboundDefinition, type AutomationInvocation, type AutomationInvocationResult, type AutomationInvocationStatus, type AutomationOutboundDefinition, type AutomationResponseMode, type AutomationRetryPolicy, type AutomationRuntime, type AutomationRuntimeOptions, type AutomationWorkflowCapabilities, type AutomationWorkflowDefinition, type JsonSchema, } from "./automation/index.js";
|
|
14
|
-
export { CONNECT_APPS_FLAG, defineFeatureFlag, defineFeatureFlags, evaluateFeatureFlag, getFeatureFlagDefinition, getFeatureFlagRules, hasActiveFeatureFlagRollout, isFeatureFlagEnabled, listFeatureFlags, registerFeatureFlags, type FeatureFlagDefinition, type FeatureFlagMode, type FeatureFlagRules, type FeatureFlagScope, } from "./feature-flags/index.js";
|
|
14
|
+
export { BUILDER_CREDIT_USAGE_REPORTING_FLAG, CONNECT_APPS_FLAG, defineFeatureFlag, defineFeatureFlags, evaluateFeatureFlag, getFeatureFlagDefinition, getFeatureFlagRules, hasActiveFeatureFlagRollout, isFeatureFlagEnabled, listFeatureFlags, registerFeatureFlags, type FeatureFlagDefinition, type FeatureFlagMode, type FeatureFlagRules, type FeatureFlagScope, } from "./feature-flags/index.js";
|
|
15
15
|
export { createFeatureFlagA2AActionRouteAuth, createFeatureFlagsPlugin, } from "./feature-flags/server.js";
|
|
16
16
|
export { defineLab, defineLabs, getLabDefinition, listLabs, registerLabs, type LabDefinition, } from "./labs/index.js";
|
|
17
17
|
export { createLabsPlugin } from "./labs/server.js";
|
package/dist/index.js
CHANGED
|
@@ -16,7 +16,7 @@ export { createDevScriptRegistry } from "./scripts/dev/index.js";
|
|
|
16
16
|
export { createAgentChatPlugin, defaultAgentChatPlugin, createAgentNativeEmbeddedPlugin, mountAgentNativeEmbedded, createServer, createSSEHandler, defineNitroPlugin, autoMountAuth, getSession, } from "./root-server-compat.js";
|
|
17
17
|
export { BUILT_IN_INTEGRATION_CATALOG, INTEGRATION_CATEGORIES, getIntegrationCatalogEntry, listBuiltInChannelIntegrations, listIntegrationCatalog, } from "./integrations/catalog.js";
|
|
18
18
|
export { AutomationConnectorError, createAutomationCallbackHandler, createAutomationRuntime, createInvokeAutomationWorkflowAction, } from "./automation/index.js";
|
|
19
|
-
export { CONNECT_APPS_FLAG, defineFeatureFlag, defineFeatureFlags, evaluateFeatureFlag, getFeatureFlagDefinition, getFeatureFlagRules, hasActiveFeatureFlagRollout, isFeatureFlagEnabled, listFeatureFlags, registerFeatureFlags, } from "./feature-flags/index.js";
|
|
19
|
+
export { BUILDER_CREDIT_USAGE_REPORTING_FLAG, CONNECT_APPS_FLAG, defineFeatureFlag, defineFeatureFlags, evaluateFeatureFlag, getFeatureFlagDefinition, getFeatureFlagRules, hasActiveFeatureFlagRollout, isFeatureFlagEnabled, listFeatureFlags, registerFeatureFlags, } from "./feature-flags/index.js";
|
|
20
20
|
export { createFeatureFlagA2AActionRouteAuth, createFeatureFlagsPlugin, } from "./feature-flags/server.js";
|
|
21
21
|
export { defineLab, defineLabs, getLabDefinition, listLabs, registerLabs, } from "./labs/index.js";
|
|
22
22
|
export { createLabsPlugin } from "./labs/server.js";
|
|
@@ -1448,7 +1448,8 @@ async function recordIntegrationUsage(options) {
|
|
|
1448
1448
|
(usage.inputTokens <= 0 &&
|
|
1449
1449
|
usage.outputTokens <= 0 &&
|
|
1450
1450
|
usage.cacheReadTokens <= 0 &&
|
|
1451
|
-
usage.cacheWriteTokens <= 0
|
|
1451
|
+
usage.cacheWriteTokens <= 0 &&
|
|
1452
|
+
usage.builderCreditsUsed == null)) {
|
|
1452
1453
|
return;
|
|
1453
1454
|
}
|
|
1454
1455
|
try {
|
|
@@ -1459,6 +1460,8 @@ async function recordIntegrationUsage(options) {
|
|
|
1459
1460
|
outputTokens: usage.outputTokens,
|
|
1460
1461
|
cacheReadTokens: usage.cacheReadTokens,
|
|
1461
1462
|
cacheWriteTokens: usage.cacheWriteTokens,
|
|
1463
|
+
builderCreditsUsed: usage.builderCreditsUsed,
|
|
1464
|
+
engineName: usage.engineName,
|
|
1462
1465
|
model: usage.model,
|
|
1463
1466
|
label: `integration:${options.incoming.platform}`,
|
|
1464
1467
|
app: options.appId,
|
|
@@ -598,7 +598,8 @@ async function executeBackgroundAutomation(options, deps, historyId, runIdRef) {
|
|
|
598
598
|
(usage.inputTokens > 0 ||
|
|
599
599
|
usage.outputTokens > 0 ||
|
|
600
600
|
usage.cacheReadTokens > 0 ||
|
|
601
|
-
usage.cacheWriteTokens > 0
|
|
601
|
+
usage.cacheWriteTokens > 0 ||
|
|
602
|
+
usage.builderCreditsUsed != null)) {
|
|
602
603
|
try {
|
|
603
604
|
const { recordUsage } = await import("../usage/store.js");
|
|
604
605
|
await recordUsage({
|
|
@@ -607,6 +608,10 @@ async function executeBackgroundAutomation(options, deps, historyId, runIdRef) {
|
|
|
607
608
|
outputTokens: usage.outputTokens,
|
|
608
609
|
cacheReadTokens: usage.cacheReadTokens,
|
|
609
610
|
cacheWriteTokens: usage.cacheWriteTokens,
|
|
611
|
+
...(usage.builderCreditsUsed == null
|
|
612
|
+
? {}
|
|
613
|
+
: { builderCreditsUsed: usage.builderCreditsUsed }),
|
|
614
|
+
engineName: usage.engineName ?? engine.name,
|
|
610
615
|
model: usage.model,
|
|
611
616
|
label: usageLabel,
|
|
612
617
|
app: deps.appId,
|
|
@@ -425,7 +425,7 @@ const messages = {
|
|
|
425
425
|
"errorMessages.providerRateLimit": "يفرض مزوّد النموذج حاليًا حدًا على معدل طلبات هذه المحادثة. انتظر قليلًا، ثم أعد المحاولة.",
|
|
426
426
|
"errorMessages.providerTransientRejection": "رفض مزوّد الذكاء الاصطناعي هذا الطلب مؤقتًا. عادةً ما يُحل هذا خلال دقيقة — أعد المحاولة.",
|
|
427
427
|
"errorMessages.startNewChat": "بدء محادثة جديدة",
|
|
428
|
-
"errorMessages.
|
|
428
|
+
"errorMessages.addCreditsInBuilder": "إضافة أرصدة في Builder",
|
|
429
429
|
"feedback.inaccurate": "غير دقيق",
|
|
430
430
|
"feedback.keyboardHint": "{{shortcut}} Enter للإرسال",
|
|
431
431
|
"feedback.notHelpful": "غير مفيد",
|
|
@@ -753,5 +753,13 @@ const messages = {
|
|
|
753
753
|
"settings.emailChangeError": "تعذر إرسال التأكيد.",
|
|
754
754
|
"settings.emailNewLabel": "البريد الإلكتروني الجديد",
|
|
755
755
|
"settings.emailNewPlaceholder": "أدخل بريدًا إلكترونيًا جديدًا",
|
|
756
|
+
"usage.builderCredits": "أرصدة Builder",
|
|
757
|
+
"usage.estimatedBuilderCredits": "~{{amount}} رصيد مقدّر",
|
|
758
|
+
"usage.otherUsdSpend": "{{amount}} دولار أمريكي أخرى",
|
|
759
|
+
"usage.noBuilderCredits": "0 من أرصدة Builder",
|
|
760
|
+
"usage.otherUnclassifiedSpend": "إنفاق آخر أو غير مصنّف بالدولار الأمريكي",
|
|
761
|
+
"usage.providerSpendDetail": "استخدام المزوّد أو المكالمات الأقدم خارج فوترة Builder",
|
|
762
|
+
"usage.providerSpendToday": "استخدام آخر أو غير مصنّف اليوم: {{amount}}",
|
|
763
|
+
"usage.driverCreditsAndUsd": "أرصدة Builder / دولار أمريكي",
|
|
756
764
|
};
|
|
757
765
|
export default messages;
|
|
@@ -595,7 +595,7 @@ const messages = {
|
|
|
595
595
|
"errorMessages.providerRateLimit": "Der Modellanbieter begrenzt diesen Chat derzeit. Warte einen Moment und versuche es dann erneut.",
|
|
596
596
|
"errorMessages.providerTransientRejection": "Der KI-Anbieter hat diese Anfrage vorübergehend abgelehnt. Das behebt sich meist innerhalb einer Minute – versuche es erneut.",
|
|
597
597
|
"errorMessages.startNewChat": "Neuen Chat starten",
|
|
598
|
-
"errorMessages.
|
|
598
|
+
"errorMessages.addCreditsInBuilder": "Credits bei Builder hinzufügen",
|
|
599
599
|
"feedback.inaccurate": "Ungenau",
|
|
600
600
|
"feedback.keyboardHint": "{{shortcut}} Enter zum Senden",
|
|
601
601
|
"feedback.notHelpful": "Nicht hilfreich",
|
|
@@ -725,5 +725,13 @@ const messages = {
|
|
|
725
725
|
"settings.emailChangeError": "Bestätigung konnte nicht gesendet werden.",
|
|
726
726
|
"settings.emailNewLabel": "Neue E-Mail-Adresse",
|
|
727
727
|
"settings.emailNewPlaceholder": "Neue E-Mail-Adresse eingeben",
|
|
728
|
+
"usage.builderCredits": "Builder-Credits",
|
|
729
|
+
"usage.estimatedBuilderCredits": "~{{amount}} geschätzte Credits",
|
|
730
|
+
"usage.otherUsdSpend": "{{amount}} USD sonstige",
|
|
731
|
+
"usage.noBuilderCredits": "0 Builder-Credits",
|
|
732
|
+
"usage.otherUnclassifiedSpend": "Sonstige oder nicht zugeordnete Ausgaben in USD",
|
|
733
|
+
"usage.providerSpendDetail": "Anbieteraufrufe oder ältere Aufrufe außerhalb der Builder-Abrechnung",
|
|
734
|
+
"usage.providerSpendToday": "Sonstige oder nicht zugeordnete Nutzung heute: {{amount}}",
|
|
735
|
+
"usage.driverCreditsAndUsd": "Builder-Credits / USD",
|
|
728
736
|
};
|
|
729
737
|
export default messages;
|