@broberg/ai-sdk 0.52.0 → 0.53.0
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/chunk-ZSLRCOYM.js +478 -0
- package/dist/chunk-ZSLRCOYM.js.map +1 -0
- package/dist/index.d.ts +85 -60
- package/dist/index.js +124 -4
- package/dist/index.js.map +1 -1
- package/dist/pricing.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-O4LR6X4U.js +0 -478
- package/dist/chunk-O4LR6X4U.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
listMediaPrices,
|
|
19
19
|
pricingFreshness,
|
|
20
20
|
pricingGeneratedAt
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-ZSLRCOYM.js";
|
|
22
22
|
|
|
23
23
|
// src/cost/default-hosts.ts
|
|
24
24
|
var DEFAULT_BASE_URLS = {
|
|
@@ -517,6 +517,7 @@ function anthropicAdapter(config = {}) {
|
|
|
517
517
|
cacheReadTokens: data.usage?.cache_read_input_tokens ?? 0,
|
|
518
518
|
cacheCreationTokens: data.usage?.cache_creation_input_tokens ?? 0
|
|
519
519
|
});
|
|
520
|
+
if (typeof data.model === "string" && data.model) usage.servedModel = data.model;
|
|
520
521
|
const result = { text, usage };
|
|
521
522
|
if (toolCalls.length > 0) result.toolCalls = toolCalls;
|
|
522
523
|
return result;
|
|
@@ -809,6 +810,7 @@ function makeOpenAICompatibleAdapter(config) {
|
|
|
809
810
|
if (config.costFromResponseField && typeof data.usage?.cost === "number") {
|
|
810
811
|
usage.costUsd = data.usage.cost;
|
|
811
812
|
}
|
|
813
|
+
if (typeof data.model === "string" && data.model) usage.servedModel = data.model;
|
|
812
814
|
const result = { text, usage };
|
|
813
815
|
if (toolCalls && toolCalls.length > 0) result.toolCalls = toolCalls;
|
|
814
816
|
return result;
|
|
@@ -876,6 +878,7 @@ function makeOpenAICompatibleAdapter(config) {
|
|
|
876
878
|
if (config.costFromResponseField && typeof chunk.usage.cost === "number") {
|
|
877
879
|
usage.costUsd = chunk.usage.cost;
|
|
878
880
|
}
|
|
881
|
+
if (typeof chunk.model === "string" && chunk.model) usage.servedModel = chunk.model;
|
|
879
882
|
yield { type: "usage", costUsd: usage.costUsd, model: usage.model, usage };
|
|
880
883
|
}
|
|
881
884
|
}
|
|
@@ -3520,8 +3523,8 @@ var aiConfigSchema = z.object({
|
|
|
3520
3523
|
import { randomUUID } from "crypto";
|
|
3521
3524
|
|
|
3522
3525
|
// src/version.ts
|
|
3523
|
-
var VERSION = "0.
|
|
3524
|
-
var SDK_TAG = "@broberg/ai-sdk@0.
|
|
3526
|
+
var VERSION = "0.53.0";
|
|
3527
|
+
var SDK_TAG = "@broberg/ai-sdk@0.53.0";
|
|
3525
3528
|
|
|
3526
3529
|
// src/cost/sinks/upmetrics.ts
|
|
3527
3530
|
function isRetryableStatus(status) {
|
|
@@ -3571,6 +3574,9 @@ function upmetricsSink(config) {
|
|
|
3571
3574
|
// capability/transport — no ingest-schema change, and without it the one
|
|
3572
3575
|
// field built for auditability existed only in memory.
|
|
3573
3576
|
region: usage.region,
|
|
3577
|
+
// F071.2 — the model that answered (contract with upmetrics F048). Omitted when
|
|
3578
|
+
// the provider did not say, rather than echoing the requested model as a guess.
|
|
3579
|
+
...usage.servedModel ? { served_model: usage.servedModel } : {},
|
|
3574
3580
|
// F050: HOW cost_usd was arrived at. upmetrics already distinguishes
|
|
3575
3581
|
// reported / computed / unpriced — we were sending an assumed number in
|
|
3576
3582
|
// the same field as a measured one, so their labels could not be right
|
|
@@ -3597,6 +3603,36 @@ function upmetricsSink(config) {
|
|
|
3597
3603
|
void config.complianceMode;
|
|
3598
3604
|
return JSON.stringify(body);
|
|
3599
3605
|
}
|
|
3606
|
+
function buildFailureBody(f) {
|
|
3607
|
+
const endedAt = new Date(new Date(f.ts).getTime()).toISOString();
|
|
3608
|
+
const startedAt = new Date(new Date(f.ts).getTime() - (f.latencyMs || 0)).toISOString();
|
|
3609
|
+
const body = {
|
|
3610
|
+
mode: "record",
|
|
3611
|
+
agent_kind: config.agentKind ?? (f.capability === "embedding" ? "embedding" : "chatbot"),
|
|
3612
|
+
agent_name: config.agentName,
|
|
3613
|
+
provider: f.provider,
|
|
3614
|
+
model: f.model,
|
|
3615
|
+
status: "error",
|
|
3616
|
+
input_tokens: 0,
|
|
3617
|
+
output_tokens: 0,
|
|
3618
|
+
cost_usd: 0,
|
|
3619
|
+
duration_ms: f.latencyMs,
|
|
3620
|
+
started_at: startedAt,
|
|
3621
|
+
ended_at: endedAt,
|
|
3622
|
+
tags: {
|
|
3623
|
+
...f.labels,
|
|
3624
|
+
capability: f.capability,
|
|
3625
|
+
transport: f.transport,
|
|
3626
|
+
error_code: f.errorCode,
|
|
3627
|
+
error_kind: f.errorKind,
|
|
3628
|
+
sdk: SDK_TAG,
|
|
3629
|
+
idempotencyKey: randomUUID()
|
|
3630
|
+
}
|
|
3631
|
+
};
|
|
3632
|
+
if (f.tier !== void 0) body.tier = f.tier;
|
|
3633
|
+
if (f.purpose !== void 0) body.purpose = f.purpose;
|
|
3634
|
+
return JSON.stringify(body);
|
|
3635
|
+
}
|
|
3600
3636
|
async function send(body) {
|
|
3601
3637
|
try {
|
|
3602
3638
|
const res = await doFetch(url, {
|
|
@@ -3690,6 +3726,30 @@ function upmetricsSink(config) {
|
|
|
3690
3726
|
config.onError?.(err);
|
|
3691
3727
|
}
|
|
3692
3728
|
},
|
|
3729
|
+
async recordFailure(failure) {
|
|
3730
|
+
try {
|
|
3731
|
+
const body = buildFailureBody(failure);
|
|
3732
|
+
const r = await send(body);
|
|
3733
|
+
if (r.kind === "ok") {
|
|
3734
|
+
counts.sent += 1;
|
|
3735
|
+
return;
|
|
3736
|
+
}
|
|
3737
|
+
if (r.kind === "reject") {
|
|
3738
|
+
counts.rejected += 1;
|
|
3739
|
+
config.onError?.(r.err);
|
|
3740
|
+
return;
|
|
3741
|
+
}
|
|
3742
|
+
if (!retry) {
|
|
3743
|
+
lose(r.err);
|
|
3744
|
+
return;
|
|
3745
|
+
}
|
|
3746
|
+
queue.push({ body, attempts: 1 });
|
|
3747
|
+
enforceCap();
|
|
3748
|
+
schedule();
|
|
3749
|
+
} catch (err) {
|
|
3750
|
+
config.onError?.(err);
|
|
3751
|
+
}
|
|
3752
|
+
},
|
|
3693
3753
|
async flush() {
|
|
3694
3754
|
if (timer) {
|
|
3695
3755
|
clearTimeout(timer);
|
|
@@ -3745,6 +3805,29 @@ function assertByokProviders(providers) {
|
|
|
3745
3805
|
}
|
|
3746
3806
|
}
|
|
3747
3807
|
|
|
3808
|
+
// src/cost/failure.ts
|
|
3809
|
+
function classifyFailure(err) {
|
|
3810
|
+
const e = err;
|
|
3811
|
+
const name = e?.name ?? "";
|
|
3812
|
+
const message = String(e?.message ?? "");
|
|
3813
|
+
if (name === "AbortError" || name === "TimeoutError" || /timed? ?out/i.test(message.split("\n")[0] ?? "")) {
|
|
3814
|
+
return { errorCode: "timeout", errorKind: "timeout" };
|
|
3815
|
+
}
|
|
3816
|
+
let status = typeof e?.status === "number" ? e.status : void 0;
|
|
3817
|
+
if (status === void 0) {
|
|
3818
|
+
const m = /(?:^|\s)([45]\d{2})(?=[:\s]|$)/.exec(message.split("\n")[0] ?? "");
|
|
3819
|
+
if (m) status = Number(m[1]);
|
|
3820
|
+
}
|
|
3821
|
+
if (status !== void 0) {
|
|
3822
|
+
const kind = status === 401 || status === 403 ? "auth" : status === 404 ? "not_found" : status === 429 ? "rate_limit" : status >= 500 ? "server" : "other";
|
|
3823
|
+
return { errorCode: String(status), errorKind: kind };
|
|
3824
|
+
}
|
|
3825
|
+
if (name === "TypeError" && /fetch failed|network|ECONN|ENOTFOUND/i.test(message + (e?.cause?.code ?? ""))) {
|
|
3826
|
+
return { errorCode: "network", errorKind: "network" };
|
|
3827
|
+
}
|
|
3828
|
+
return { errorCode: "unknown", errorKind: "other" };
|
|
3829
|
+
}
|
|
3830
|
+
|
|
3748
3831
|
// src/client.ts
|
|
3749
3832
|
var DEFAULT_IMAGE_SPEC = {
|
|
3750
3833
|
provider: "fal",
|
|
@@ -3840,6 +3923,13 @@ function createAI(config = {}) {
|
|
|
3840
3923
|
if (!usage.ts) usage.ts = (/* @__PURE__ */ new Date()).toISOString();
|
|
3841
3924
|
return usage;
|
|
3842
3925
|
}
|
|
3926
|
+
async function reportFailure(f, err) {
|
|
3927
|
+
if (!costSink?.recordFailure) return;
|
|
3928
|
+
try {
|
|
3929
|
+
await costSink.recordFailure({ ...f, ...classifyFailure(err), ts: (/* @__PURE__ */ new Date()).toISOString() });
|
|
3930
|
+
} catch {
|
|
3931
|
+
}
|
|
3932
|
+
}
|
|
3843
3933
|
async function report(usage) {
|
|
3844
3934
|
if (!costSink) return;
|
|
3845
3935
|
try {
|
|
@@ -3875,8 +3965,8 @@ function createAI(config = {}) {
|
|
|
3875
3965
|
for (let i = 0; i < routes.length; i++) {
|
|
3876
3966
|
const spec = routes[i];
|
|
3877
3967
|
await preflight(spec, opts.estIn, opts.estOut);
|
|
3968
|
+
const t0 = performance.now();
|
|
3878
3969
|
try {
|
|
3879
|
-
const t0 = performance.now();
|
|
3880
3970
|
const res = await opts.invoke(spec);
|
|
3881
3971
|
enrich(res.usage, opts.capability, i === 0 ? opts.tier : void 0, opts.purpose, performance.now() - t0, opts.labels);
|
|
3882
3972
|
await settle(res.usage);
|
|
@@ -3884,6 +3974,20 @@ function createAI(config = {}) {
|
|
|
3884
3974
|
return res;
|
|
3885
3975
|
} catch (e) {
|
|
3886
3976
|
lastErr = e;
|
|
3977
|
+
const labels = { ...cfg.labels, ...opts.labels };
|
|
3978
|
+
await reportFailure(
|
|
3979
|
+
{
|
|
3980
|
+
provider: spec.provider,
|
|
3981
|
+
model: spec.model,
|
|
3982
|
+
transport: spec.transport,
|
|
3983
|
+
capability: opts.capability,
|
|
3984
|
+
...i === 0 && opts.tier ? { tier: opts.tier } : {},
|
|
3985
|
+
...opts.purpose ? { purpose: opts.purpose } : {},
|
|
3986
|
+
...Object.keys(labels).length ? { labels } : {},
|
|
3987
|
+
latencyMs: Math.round(performance.now() - t0)
|
|
3988
|
+
},
|
|
3989
|
+
e
|
|
3990
|
+
);
|
|
3887
3991
|
}
|
|
3888
3992
|
}
|
|
3889
3993
|
throw lastErr;
|
|
@@ -3953,6 +4057,19 @@ function createAI(config = {}) {
|
|
|
3953
4057
|
return;
|
|
3954
4058
|
} catch (e) {
|
|
3955
4059
|
lastErr = e;
|
|
4060
|
+
await reportFailure(
|
|
4061
|
+
{
|
|
4062
|
+
provider: spec.provider,
|
|
4063
|
+
model: spec.model,
|
|
4064
|
+
transport: spec.transport,
|
|
4065
|
+
capability: "chat",
|
|
4066
|
+
...i === 0 ? { tier } : {},
|
|
4067
|
+
...input.purpose ? { purpose: input.purpose } : {},
|
|
4068
|
+
...Object.keys({ ...cfg.labels, ...input.labels }).length ? { labels: { ...cfg.labels, ...input.labels } } : {},
|
|
4069
|
+
latencyMs: Math.round(performance.now() - t0)
|
|
4070
|
+
},
|
|
4071
|
+
e
|
|
4072
|
+
);
|
|
3956
4073
|
if (emitted || !eligibleForFallback(e)) {
|
|
3957
4074
|
yield errorEvent(e);
|
|
3958
4075
|
return;
|
|
@@ -4499,6 +4616,9 @@ function multiSink(sinks) {
|
|
|
4499
4616
|
return {
|
|
4500
4617
|
async record(usage) {
|
|
4501
4618
|
await Promise.allSettled(sinks.map(async (s) => s.record(usage)));
|
|
4619
|
+
},
|
|
4620
|
+
async recordFailure(failure) {
|
|
4621
|
+
await Promise.allSettled(sinks.map(async (s) => s.recordFailure?.(failure)));
|
|
4502
4622
|
}
|
|
4503
4623
|
};
|
|
4504
4624
|
}
|