@shop-os/modelkit 0.3.8 → 0.4.1
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/CHANGELOG.md +25 -0
- package/README.md +2 -2
- package/dist/catalog.cjs +50 -36
- package/dist/catalog.cjs.map +1 -1
- package/dist/catalog.d.cts +12 -1
- package/dist/catalog.d.ts +12 -1
- package/dist/catalog.js +50 -36
- package/dist/catalog.js.map +1 -1
- package/dist/index.cjs +165 -70
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -2
- package/dist/index.d.ts +13 -2
- package/dist/index.js +165 -70
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -341,35 +341,43 @@ var IMAGE_MODELS = [
|
|
|
341
341
|
GEMINI_PROMPT_MAX_CHARS,
|
|
342
342
|
NANO_BANANA_2_1_RATIOS
|
|
343
343
|
),
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
344
|
+
// Google retired the -preview endpoints for the GA ids; the catalog ids stay because they
|
|
345
|
+
// are pricing keys and stored model ids.
|
|
346
|
+
{
|
|
347
|
+
...geminiImage(
|
|
348
|
+
"gemini-3-pro-image-preview",
|
|
349
|
+
"Nano Banana Pro",
|
|
350
|
+
["nb-pro"],
|
|
351
|
+
["1K", "2K", "4K"],
|
|
352
|
+
{
|
|
353
|
+
provider: "google",
|
|
354
|
+
description: "Create stunning, production-quality visuals with exceptional realism, detail, and typography. Best for campaigns, e-commerce, product photography, and hero creatives.",
|
|
355
|
+
logo: "https://d31vvfpk2ppdyq.cloudfront.net/assets/image/192485d2-a76a-4657-9c06-930b2c70badd_compressed.png"
|
|
356
|
+
},
|
|
357
|
+
["cowork", "space_builder"],
|
|
358
|
+
{ images: 14 },
|
|
359
|
+
GEMINI_PROMPT_MAX_CHARS
|
|
360
|
+
),
|
|
361
|
+
providerModelId: "gemini-3-pro-image"
|
|
362
|
+
},
|
|
363
|
+
{
|
|
364
|
+
...geminiImage(
|
|
365
|
+
"gemini-3.1-flash-image-preview",
|
|
366
|
+
"Nano Banana 2",
|
|
367
|
+
["nb-2"],
|
|
368
|
+
// Flash 3.1 is the only Gemini image model with the 512 tier.
|
|
369
|
+
["512", "1K", "2K", "4K"],
|
|
370
|
+
{
|
|
371
|
+
provider: "google",
|
|
372
|
+
description: "Generate high-quality images at speed. Perfect for brainstorming, concept boards, concept testing, creative exploration, and large batch workflows.",
|
|
373
|
+
logo: "https://d31vvfpk2ppdyq.cloudfront.net/assets/image/192485d2-a76a-4657-9c06-930b2c70badd_compressed.png"
|
|
374
|
+
},
|
|
375
|
+
["cowork", "space_builder"],
|
|
376
|
+
{ images: 14 },
|
|
377
|
+
GEMINI_PROMPT_MAX_CHARS
|
|
378
|
+
),
|
|
379
|
+
providerModelId: "gemini-3.1-flash-image"
|
|
380
|
+
},
|
|
373
381
|
geminiImage(
|
|
374
382
|
"gemini-3.1-flash-lite-image",
|
|
375
383
|
"Nano Banana Lite",
|
|
@@ -1503,6 +1511,7 @@ var OMNI_PROMPT = { referenceSyntax: "caption", maxChars: 5e4 };
|
|
|
1503
1511
|
var BYTEDANCE_LOGO = "https://d31vvfpk2ppdyq.cloudfront.net/assets/image/3bba5d81-4e57-4e71-911b-cdfa05acca2c_compressed.png";
|
|
1504
1512
|
var GOOGLE_LOGO2 = "https://d31vvfpk2ppdyq.cloudfront.net/assets/image/192485d2-a76a-4657-9c06-930b2c70badd_compressed.png";
|
|
1505
1513
|
var VIDEO_MODELS = [
|
|
1514
|
+
// Google shuts down the Veo 3.1 previews and Omni Flash 1.0 on 2026-10-22.
|
|
1506
1515
|
{
|
|
1507
1516
|
id: "veo-3.1",
|
|
1508
1517
|
aliases: [
|
|
@@ -1515,8 +1524,9 @@ var VIDEO_MODELS = [
|
|
|
1515
1524
|
type: "video",
|
|
1516
1525
|
adapter: "google-genai",
|
|
1517
1526
|
providerModelId: "veo-3.1-generate-preview",
|
|
1518
|
-
lifecycle: "
|
|
1519
|
-
|
|
1527
|
+
lifecycle: "deprecated",
|
|
1528
|
+
replacedBy: "gemini-omni-1.1-flash",
|
|
1529
|
+
exposure: [],
|
|
1520
1530
|
constraints: {
|
|
1521
1531
|
aspectRatios: [...OMNI_RATIOS],
|
|
1522
1532
|
resolutions: ["720p", "1080p", "4k"],
|
|
@@ -1551,7 +1561,8 @@ var VIDEO_MODELS = [
|
|
|
1551
1561
|
type: "video",
|
|
1552
1562
|
adapter: "google-genai",
|
|
1553
1563
|
providerModelId: "veo-3.1-fast-generate-preview",
|
|
1554
|
-
lifecycle: "
|
|
1564
|
+
lifecycle: "deprecated",
|
|
1565
|
+
replacedBy: "gemini-omni-1.1-flash",
|
|
1555
1566
|
exposure: [],
|
|
1556
1567
|
constraints: {
|
|
1557
1568
|
aspectRatios: [...OMNI_RATIOS],
|
|
@@ -1581,7 +1592,8 @@ var VIDEO_MODELS = [
|
|
|
1581
1592
|
type: "video",
|
|
1582
1593
|
adapter: "google-genai",
|
|
1583
1594
|
providerModelId: "veo-3.1-lite-generate-preview",
|
|
1584
|
-
lifecycle: "
|
|
1595
|
+
lifecycle: "deprecated",
|
|
1596
|
+
replacedBy: "gemini-omni-1.1-flash",
|
|
1585
1597
|
exposure: [],
|
|
1586
1598
|
constraints: {
|
|
1587
1599
|
aspectRatios: [...OMNI_RATIOS],
|
|
@@ -1612,8 +1624,9 @@ var VIDEO_MODELS = [
|
|
|
1612
1624
|
type: "video",
|
|
1613
1625
|
adapter: "google-genai",
|
|
1614
1626
|
providerModelId: "gemini-omni-flash-preview",
|
|
1615
|
-
lifecycle: "
|
|
1616
|
-
|
|
1627
|
+
lifecycle: "deprecated",
|
|
1628
|
+
replacedBy: "gemini-omni-1.1-flash",
|
|
1629
|
+
exposure: [],
|
|
1617
1630
|
constraints: {
|
|
1618
1631
|
// 1.0 rejects `resolution`; it renders 720p. No defaults: the adapter
|
|
1619
1632
|
// sends ratio and duration only when the caller set them, so a
|
|
@@ -2168,7 +2181,8 @@ var VIDEO_MODELS = [
|
|
|
2168
2181
|
},
|
|
2169
2182
|
defaults: {},
|
|
2170
2183
|
usage: { ...VIDEO_USAGE },
|
|
2171
|
-
|
|
2184
|
+
// Higgsfield bills DoP per generation: a fixed-length clip with no duration knob.
|
|
2185
|
+
pricingKind: "flat",
|
|
2172
2186
|
display: {
|
|
2173
2187
|
provider: "higgsfield",
|
|
2174
2188
|
description: "Higgsfield DOP image-to-video model; animates a required first-frame image from a text prompt with an optional last-frame image and motion controls."
|
|
@@ -3404,6 +3418,36 @@ function describeThrown(cause) {
|
|
|
3404
3418
|
|
|
3405
3419
|
// src/retry.ts
|
|
3406
3420
|
var textBody = import_zod6.z.string();
|
|
3421
|
+
var BILLING_CODES = /* @__PURE__ */ new Set([
|
|
3422
|
+
"insufficient_quota",
|
|
3423
|
+
"billing_hard_limit_reached",
|
|
3424
|
+
"billing_not_active",
|
|
3425
|
+
"payment_required",
|
|
3426
|
+
"insufficient_balance",
|
|
3427
|
+
"insufficient_credits",
|
|
3428
|
+
"insufficient_credit"
|
|
3429
|
+
]);
|
|
3430
|
+
var errorCodes = import_zod6.z.object({
|
|
3431
|
+
code: import_zod6.z.string().optional(),
|
|
3432
|
+
type: import_zod6.z.string().optional(),
|
|
3433
|
+
error: import_zod6.z.object({ code: import_zod6.z.string().optional(), type: import_zod6.z.string().optional() }).optional()
|
|
3434
|
+
});
|
|
3435
|
+
var BILLING_TEXT = /insufficient_quota|payment[ _]required|exhausted balance|insufficient (?:credits?|balance|funds)|billing_hard_limit/i;
|
|
3436
|
+
var BILLING_TEXT_STATUSES = /* @__PURE__ */ new Set([403, 429]);
|
|
3437
|
+
function billingCode(body) {
|
|
3438
|
+
const parsed = errorCodes.safeParse(body);
|
|
3439
|
+
if (!parsed.success) return false;
|
|
3440
|
+
const { code, type, error } = parsed.data;
|
|
3441
|
+
return [code, type, error?.code, error?.type].some(
|
|
3442
|
+
(value) => value !== void 0 && BILLING_CODES.has(value.toLowerCase())
|
|
3443
|
+
);
|
|
3444
|
+
}
|
|
3445
|
+
function isBillingFailure(status, body, text2) {
|
|
3446
|
+
if (status === 402) return true;
|
|
3447
|
+
if (status === void 0 || status < 400 || status >= 500) return false;
|
|
3448
|
+
if (billingCode(body)) return true;
|
|
3449
|
+
return BILLING_TEXT_STATUSES.has(status) && BILLING_TEXT.test(text2);
|
|
3450
|
+
}
|
|
3407
3451
|
function classifyHttpError(status, body, provider, model) {
|
|
3408
3452
|
const asText = textBody.safeParse(body);
|
|
3409
3453
|
const text2 = asText.success ? asText.data : JSON.stringify(body);
|
|
@@ -3412,6 +3456,7 @@ function classifyHttpError(status, body, provider, model) {
|
|
|
3412
3456
|
);
|
|
3413
3457
|
let code = "provider_rejected";
|
|
3414
3458
|
if (blocked) code = "content_blocked";
|
|
3459
|
+
else if (isBillingFailure(status, body, text2)) code = "provider_billing";
|
|
3415
3460
|
else if (status === 401 || status === 403) code = "auth";
|
|
3416
3461
|
else if (status === 429) code = "rate_limited";
|
|
3417
3462
|
else if (status === 408 || status === 504) code = "timeout";
|
|
@@ -3474,12 +3519,11 @@ function sleep(ms, signal) {
|
|
|
3474
3519
|
rejectAborted();
|
|
3475
3520
|
return;
|
|
3476
3521
|
}
|
|
3477
|
-
let timer;
|
|
3478
3522
|
const onAbort = () => {
|
|
3479
|
-
|
|
3523
|
+
clearTimeout(timer);
|
|
3480
3524
|
rejectAborted();
|
|
3481
3525
|
};
|
|
3482
|
-
timer = setTimeout(() => {
|
|
3526
|
+
const timer = setTimeout(() => {
|
|
3483
3527
|
signal?.removeEventListener("abort", onAbort);
|
|
3484
3528
|
resolve();
|
|
3485
3529
|
}, ms);
|
|
@@ -9260,6 +9304,13 @@ function createModelKit(config, adapters) {
|
|
|
9260
9304
|
model: model.id
|
|
9261
9305
|
});
|
|
9262
9306
|
}
|
|
9307
|
+
function timed(event, startedAt) {
|
|
9308
|
+
if (event.latencyMs !== void 0) return event;
|
|
9309
|
+
return { ...event, latencyMs: Math.max(0, Date.now() - startedAt) };
|
|
9310
|
+
}
|
|
9311
|
+
function textTimed(event, stepCount, startedAt) {
|
|
9312
|
+
return stepCount === 1 ? timed(event, startedAt) : event;
|
|
9313
|
+
}
|
|
9263
9314
|
async function emit(event) {
|
|
9264
9315
|
try {
|
|
9265
9316
|
await config.onUsage?.(event);
|
|
@@ -9343,17 +9394,21 @@ function createModelKit(config, adapters) {
|
|
|
9343
9394
|
const abortSignal = combineSignals(req.abortSignal, call.signal);
|
|
9344
9395
|
if (abortSignal) options.abortSignal = abortSignal;
|
|
9345
9396
|
if (call.maxRetries !== void 0) options.maxRetries = call.maxRetries;
|
|
9397
|
+
const startedAt = Date.now();
|
|
9346
9398
|
const result = await (0, import_ai5.generateImage)(options);
|
|
9347
9399
|
const images = result.images.map(
|
|
9348
9400
|
(file) => toGeneratedImage({ bytes: file.uint8Array, mime: file.mediaType })
|
|
9349
9401
|
);
|
|
9350
|
-
const usage2 =
|
|
9351
|
-
|
|
9352
|
-
|
|
9353
|
-
|
|
9354
|
-
|
|
9355
|
-
|
|
9356
|
-
|
|
9402
|
+
const usage2 = timed(
|
|
9403
|
+
{
|
|
9404
|
+
model: model.modelId,
|
|
9405
|
+
provider: model.provider,
|
|
9406
|
+
modality: "IMAGE",
|
|
9407
|
+
unit: "images",
|
|
9408
|
+
quantity: images.length
|
|
9409
|
+
},
|
|
9410
|
+
startedAt
|
|
9411
|
+
);
|
|
9357
9412
|
await emit(usage2);
|
|
9358
9413
|
return { image: images[0], images, usage: usage2, raw: result, warnings };
|
|
9359
9414
|
}
|
|
@@ -9426,18 +9481,22 @@ function createModelKit(config, adapters) {
|
|
|
9426
9481
|
if (providerOptions) options.providerOptions = providerOptions;
|
|
9427
9482
|
if (abortSignal) options.abortSignal = abortSignal;
|
|
9428
9483
|
logCoercions(logger, model.modelId, warnings);
|
|
9484
|
+
const startedAt = Date.now();
|
|
9429
9485
|
const pending = (0, import_ai5.experimental_generateVideo)(options);
|
|
9430
9486
|
let settled;
|
|
9431
9487
|
let failed = false;
|
|
9432
9488
|
const done = pending.then(async (result) => {
|
|
9433
|
-
const usage2 =
|
|
9434
|
-
|
|
9435
|
-
|
|
9436
|
-
|
|
9437
|
-
|
|
9438
|
-
|
|
9439
|
-
|
|
9440
|
-
|
|
9489
|
+
const usage2 = timed(
|
|
9490
|
+
{
|
|
9491
|
+
model: model.modelId,
|
|
9492
|
+
provider: model.provider,
|
|
9493
|
+
modality: "VIDEO",
|
|
9494
|
+
unit: "seconds",
|
|
9495
|
+
quantity: seconds2 ?? 0,
|
|
9496
|
+
...seconds2 !== void 0 && { durationSeconds: seconds2 }
|
|
9497
|
+
},
|
|
9498
|
+
startedAt
|
|
9499
|
+
);
|
|
9441
9500
|
settled = {
|
|
9442
9501
|
video: { bytes: result.video.uint8Array, mime: result.video.mediaType },
|
|
9443
9502
|
usage: usage2,
|
|
@@ -9494,8 +9553,12 @@ function createModelKit(config, adapters) {
|
|
|
9494
9553
|
message: `${adapter.id} cannot generate images`,
|
|
9495
9554
|
model: model.id
|
|
9496
9555
|
});
|
|
9556
|
+
const startedAt = Date.now();
|
|
9497
9557
|
const result = await adapter.generateImage(request, ctx);
|
|
9498
|
-
const usage2 =
|
|
9558
|
+
const usage2 = timed(
|
|
9559
|
+
{ ...result.usage, model: model.id, unit: model.usage.unit },
|
|
9560
|
+
startedAt
|
|
9561
|
+
);
|
|
9499
9562
|
await emit(usage2);
|
|
9500
9563
|
const images = result.images.map(toGeneratedImage);
|
|
9501
9564
|
const first = images[0];
|
|
@@ -9538,6 +9601,7 @@ function createModelKit(config, adapters) {
|
|
|
9538
9601
|
message: `${adapter.id} cannot generate video`,
|
|
9539
9602
|
model: model.id
|
|
9540
9603
|
});
|
|
9604
|
+
const startedAt = Date.now();
|
|
9541
9605
|
const job = await adapter.generateVideo(request, ctx);
|
|
9542
9606
|
const result = job.result.bind(job);
|
|
9543
9607
|
let settled;
|
|
@@ -9547,11 +9611,14 @@ function createModelKit(config, adapters) {
|
|
|
9547
9611
|
result(opts) {
|
|
9548
9612
|
if (settled) return settled;
|
|
9549
9613
|
const pending = result(opts).then(
|
|
9550
|
-
(out) =>
|
|
9551
|
-
|
|
9552
|
-
|
|
9553
|
-
|
|
9554
|
-
|
|
9614
|
+
async (out) => {
|
|
9615
|
+
const usage2 = timed(
|
|
9616
|
+
{ ...out.usage, model: model.id, unit: model.usage.unit },
|
|
9617
|
+
startedAt
|
|
9618
|
+
);
|
|
9619
|
+
await emit(usage2);
|
|
9620
|
+
return { ...out, usage: usage2 };
|
|
9621
|
+
},
|
|
9555
9622
|
(cause) => {
|
|
9556
9623
|
settled = void 0;
|
|
9557
9624
|
throw cause;
|
|
@@ -9588,9 +9655,14 @@ function createModelKit(config, adapters) {
|
|
|
9588
9655
|
model: model.id
|
|
9589
9656
|
});
|
|
9590
9657
|
}
|
|
9658
|
+
const startedAt = Date.now();
|
|
9591
9659
|
const result = await adapter.generateAudio(resolved, ctx);
|
|
9592
|
-
|
|
9593
|
-
|
|
9660
|
+
const usage2 = timed(
|
|
9661
|
+
{ ...result.usage, model: model.id, unit: model.usage.unit },
|
|
9662
|
+
startedAt
|
|
9663
|
+
);
|
|
9664
|
+
await emit(usage2);
|
|
9665
|
+
return { ...result, usage: usage2 };
|
|
9594
9666
|
},
|
|
9595
9667
|
async prepareMediaPart(modelId, ref, mediaType, call = {}) {
|
|
9596
9668
|
mediaRetryOptions(call);
|
|
@@ -9619,11 +9691,13 @@ function createModelKit(config, adapters) {
|
|
|
9619
9691
|
const { webhookUrl, ...rest } = call;
|
|
9620
9692
|
const { adapter, ctx } = videoToolTarget(req.model, rest);
|
|
9621
9693
|
if (!adapter.submitVideoTool) throw noVideoTools(adapter, ctx.model);
|
|
9622
|
-
|
|
9694
|
+
const submittedAt = Date.now();
|
|
9695
|
+
const submission = await adapter.submitVideoTool(
|
|
9623
9696
|
req,
|
|
9624
9697
|
ctx,
|
|
9625
9698
|
webhookUrl !== void 0 ? { webhookUrl } : {}
|
|
9626
9699
|
);
|
|
9700
|
+
return { ...submission, submittedAt };
|
|
9627
9701
|
},
|
|
9628
9702
|
async videoToolStatus(sub, call = {}) {
|
|
9629
9703
|
const { adapter, ctx } = videoToolTarget(sub.model, call);
|
|
@@ -9635,8 +9709,10 @@ function createModelKit(config, adapters) {
|
|
|
9635
9709
|
const { adapter, ctx } = videoToolTarget(sub.model, rest);
|
|
9636
9710
|
if (!adapter.videoToolResult) throw noVideoTools(adapter, ctx.model);
|
|
9637
9711
|
const result = await adapter.videoToolResult(sub, ctx, webhook);
|
|
9638
|
-
|
|
9639
|
-
|
|
9712
|
+
const base = { ...result.usage, model: ctx.model.id, unit: ctx.model.usage.unit };
|
|
9713
|
+
const usage2 = sub.submittedAt === void 0 ? base : timed(base, sub.submittedAt);
|
|
9714
|
+
await emit(usage2);
|
|
9715
|
+
return { ...result, usage: usage2 };
|
|
9640
9716
|
},
|
|
9641
9717
|
async cancelVideoTool(sub, call = {}) {
|
|
9642
9718
|
const { adapter, ctx } = videoToolTarget(sub.model, call);
|
|
@@ -9658,6 +9734,7 @@ function createModelKit(config, adapters) {
|
|
|
9658
9734
|
(model) => textTarget(model, call),
|
|
9659
9735
|
options.providerOptions
|
|
9660
9736
|
);
|
|
9737
|
+
const startedAt = Date.now();
|
|
9661
9738
|
const result = await (0, import_ai5.generateText)({
|
|
9662
9739
|
...options,
|
|
9663
9740
|
...textAbortOptions(options.abortSignal, call.signal),
|
|
@@ -9667,7 +9744,8 @@ function createModelKit(config, adapters) {
|
|
|
9667
9744
|
options.prepareStep ?? options.experimental_prepareStep
|
|
9668
9745
|
)
|
|
9669
9746
|
});
|
|
9670
|
-
for (const event of steps.usage(result.steps))
|
|
9747
|
+
for (const event of steps.usage(result.steps))
|
|
9748
|
+
await emit(textTimed(withRowUnit(event), result.steps.length, startedAt));
|
|
9671
9749
|
return result;
|
|
9672
9750
|
},
|
|
9673
9751
|
streamText(options, call = {}) {
|
|
@@ -9678,6 +9756,7 @@ function createModelKit(config, adapters) {
|
|
|
9678
9756
|
options.providerOptions
|
|
9679
9757
|
);
|
|
9680
9758
|
const callerOnFinish = options.onFinish;
|
|
9759
|
+
const startedAt = Date.now();
|
|
9681
9760
|
return (0, import_ai5.streamText)({
|
|
9682
9761
|
...options,
|
|
9683
9762
|
...textAbortOptions(options.abortSignal, call.signal),
|
|
@@ -9687,7 +9766,8 @@ function createModelKit(config, adapters) {
|
|
|
9687
9766
|
options.prepareStep ?? options.experimental_prepareStep
|
|
9688
9767
|
),
|
|
9689
9768
|
onFinish: async (event) => {
|
|
9690
|
-
for (const usage2 of steps.usage(event.steps))
|
|
9769
|
+
for (const usage2 of steps.usage(event.steps))
|
|
9770
|
+
await emit(textTimed(withRowUnit(usage2), event.steps.length, startedAt));
|
|
9691
9771
|
await callerOnFinish?.(event);
|
|
9692
9772
|
}
|
|
9693
9773
|
});
|
|
@@ -9700,15 +9780,22 @@ function createModelKit(config, adapters) {
|
|
|
9700
9780
|
model: languageModel2,
|
|
9701
9781
|
providerOptions: mergeTextProviderOptions(entry, options.providerOptions)
|
|
9702
9782
|
};
|
|
9783
|
+
const startedAt = Date.now();
|
|
9703
9784
|
const result = await (0, import_ai5.generateObject)(sdkOptions);
|
|
9704
9785
|
await emit(
|
|
9705
|
-
|
|
9786
|
+
timed(
|
|
9787
|
+
withRowUnit(
|
|
9788
|
+
textUsageEvent(entry, provider, result.usage, result.providerMetadata)
|
|
9789
|
+
),
|
|
9790
|
+
startedAt
|
|
9791
|
+
)
|
|
9706
9792
|
);
|
|
9707
9793
|
return result;
|
|
9708
9794
|
},
|
|
9709
9795
|
streamObject(options, call = {}) {
|
|
9710
9796
|
const { entry, languageModel: languageModel2, provider } = textTarget(options.model, call);
|
|
9711
9797
|
const callerOnFinish = options.onFinish;
|
|
9798
|
+
const startedAt = Date.now();
|
|
9712
9799
|
const sdkOptions = {
|
|
9713
9800
|
...options,
|
|
9714
9801
|
...textAbortOptions(options.abortSignal, call.signal),
|
|
@@ -9716,8 +9803,16 @@ function createModelKit(config, adapters) {
|
|
|
9716
9803
|
providerOptions: mergeTextProviderOptions(entry, options.providerOptions),
|
|
9717
9804
|
onFinish: async (event) => {
|
|
9718
9805
|
await emit(
|
|
9719
|
-
|
|
9720
|
-
|
|
9806
|
+
timed(
|
|
9807
|
+
withRowUnit(
|
|
9808
|
+
textUsageEvent(
|
|
9809
|
+
entry,
|
|
9810
|
+
provider,
|
|
9811
|
+
event.usage,
|
|
9812
|
+
event.providerMetadata
|
|
9813
|
+
)
|
|
9814
|
+
),
|
|
9815
|
+
startedAt
|
|
9721
9816
|
)
|
|
9722
9817
|
);
|
|
9723
9818
|
await callerOnFinish?.(event);
|