@shop-os/modelkit 0.3.8 → 0.4.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/CHANGELOG.md +15 -0
- package/README.md +2 -2
- 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.map +1 -1
- package/dist/index.cjs +115 -34
- 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 +115 -34
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -3404,6 +3404,36 @@ function describeThrown(cause) {
|
|
|
3404
3404
|
|
|
3405
3405
|
// src/retry.ts
|
|
3406
3406
|
var textBody = import_zod6.z.string();
|
|
3407
|
+
var BILLING_CODES = /* @__PURE__ */ new Set([
|
|
3408
|
+
"insufficient_quota",
|
|
3409
|
+
"billing_hard_limit_reached",
|
|
3410
|
+
"billing_not_active",
|
|
3411
|
+
"payment_required",
|
|
3412
|
+
"insufficient_balance",
|
|
3413
|
+
"insufficient_credits",
|
|
3414
|
+
"insufficient_credit"
|
|
3415
|
+
]);
|
|
3416
|
+
var errorCodes = import_zod6.z.object({
|
|
3417
|
+
code: import_zod6.z.string().optional(),
|
|
3418
|
+
type: import_zod6.z.string().optional(),
|
|
3419
|
+
error: import_zod6.z.object({ code: import_zod6.z.string().optional(), type: import_zod6.z.string().optional() }).optional()
|
|
3420
|
+
});
|
|
3421
|
+
var BILLING_TEXT = /insufficient_quota|payment[ _]required|exhausted balance|insufficient (?:credits?|balance|funds)|billing_hard_limit/i;
|
|
3422
|
+
var BILLING_TEXT_STATUSES = /* @__PURE__ */ new Set([403, 429]);
|
|
3423
|
+
function billingCode(body) {
|
|
3424
|
+
const parsed = errorCodes.safeParse(body);
|
|
3425
|
+
if (!parsed.success) return false;
|
|
3426
|
+
const { code, type, error } = parsed.data;
|
|
3427
|
+
return [code, type, error?.code, error?.type].some(
|
|
3428
|
+
(value) => value !== void 0 && BILLING_CODES.has(value.toLowerCase())
|
|
3429
|
+
);
|
|
3430
|
+
}
|
|
3431
|
+
function isBillingFailure(status, body, text2) {
|
|
3432
|
+
if (status === 402) return true;
|
|
3433
|
+
if (status === void 0 || status < 400 || status >= 500) return false;
|
|
3434
|
+
if (billingCode(body)) return true;
|
|
3435
|
+
return BILLING_TEXT_STATUSES.has(status) && BILLING_TEXT.test(text2);
|
|
3436
|
+
}
|
|
3407
3437
|
function classifyHttpError(status, body, provider, model) {
|
|
3408
3438
|
const asText = textBody.safeParse(body);
|
|
3409
3439
|
const text2 = asText.success ? asText.data : JSON.stringify(body);
|
|
@@ -3412,6 +3442,7 @@ function classifyHttpError(status, body, provider, model) {
|
|
|
3412
3442
|
);
|
|
3413
3443
|
let code = "provider_rejected";
|
|
3414
3444
|
if (blocked) code = "content_blocked";
|
|
3445
|
+
else if (isBillingFailure(status, body, text2)) code = "provider_billing";
|
|
3415
3446
|
else if (status === 401 || status === 403) code = "auth";
|
|
3416
3447
|
else if (status === 429) code = "rate_limited";
|
|
3417
3448
|
else if (status === 408 || status === 504) code = "timeout";
|
|
@@ -3474,12 +3505,11 @@ function sleep(ms, signal) {
|
|
|
3474
3505
|
rejectAborted();
|
|
3475
3506
|
return;
|
|
3476
3507
|
}
|
|
3477
|
-
let timer;
|
|
3478
3508
|
const onAbort = () => {
|
|
3479
|
-
|
|
3509
|
+
clearTimeout(timer);
|
|
3480
3510
|
rejectAborted();
|
|
3481
3511
|
};
|
|
3482
|
-
timer = setTimeout(() => {
|
|
3512
|
+
const timer = setTimeout(() => {
|
|
3483
3513
|
signal?.removeEventListener("abort", onAbort);
|
|
3484
3514
|
resolve();
|
|
3485
3515
|
}, ms);
|
|
@@ -9260,6 +9290,13 @@ function createModelKit(config, adapters) {
|
|
|
9260
9290
|
model: model.id
|
|
9261
9291
|
});
|
|
9262
9292
|
}
|
|
9293
|
+
function timed(event, startedAt) {
|
|
9294
|
+
if (event.latencyMs !== void 0) return event;
|
|
9295
|
+
return { ...event, latencyMs: Math.max(0, Date.now() - startedAt) };
|
|
9296
|
+
}
|
|
9297
|
+
function textTimed(event, stepCount, startedAt) {
|
|
9298
|
+
return stepCount === 1 ? timed(event, startedAt) : event;
|
|
9299
|
+
}
|
|
9263
9300
|
async function emit(event) {
|
|
9264
9301
|
try {
|
|
9265
9302
|
await config.onUsage?.(event);
|
|
@@ -9343,17 +9380,21 @@ function createModelKit(config, adapters) {
|
|
|
9343
9380
|
const abortSignal = combineSignals(req.abortSignal, call.signal);
|
|
9344
9381
|
if (abortSignal) options.abortSignal = abortSignal;
|
|
9345
9382
|
if (call.maxRetries !== void 0) options.maxRetries = call.maxRetries;
|
|
9383
|
+
const startedAt = Date.now();
|
|
9346
9384
|
const result = await (0, import_ai5.generateImage)(options);
|
|
9347
9385
|
const images = result.images.map(
|
|
9348
9386
|
(file) => toGeneratedImage({ bytes: file.uint8Array, mime: file.mediaType })
|
|
9349
9387
|
);
|
|
9350
|
-
const usage2 =
|
|
9351
|
-
|
|
9352
|
-
|
|
9353
|
-
|
|
9354
|
-
|
|
9355
|
-
|
|
9356
|
-
|
|
9388
|
+
const usage2 = timed(
|
|
9389
|
+
{
|
|
9390
|
+
model: model.modelId,
|
|
9391
|
+
provider: model.provider,
|
|
9392
|
+
modality: "IMAGE",
|
|
9393
|
+
unit: "images",
|
|
9394
|
+
quantity: images.length
|
|
9395
|
+
},
|
|
9396
|
+
startedAt
|
|
9397
|
+
);
|
|
9357
9398
|
await emit(usage2);
|
|
9358
9399
|
return { image: images[0], images, usage: usage2, raw: result, warnings };
|
|
9359
9400
|
}
|
|
@@ -9426,18 +9467,22 @@ function createModelKit(config, adapters) {
|
|
|
9426
9467
|
if (providerOptions) options.providerOptions = providerOptions;
|
|
9427
9468
|
if (abortSignal) options.abortSignal = abortSignal;
|
|
9428
9469
|
logCoercions(logger, model.modelId, warnings);
|
|
9470
|
+
const startedAt = Date.now();
|
|
9429
9471
|
const pending = (0, import_ai5.experimental_generateVideo)(options);
|
|
9430
9472
|
let settled;
|
|
9431
9473
|
let failed = false;
|
|
9432
9474
|
const done = pending.then(async (result) => {
|
|
9433
|
-
const usage2 =
|
|
9434
|
-
|
|
9435
|
-
|
|
9436
|
-
|
|
9437
|
-
|
|
9438
|
-
|
|
9439
|
-
|
|
9440
|
-
|
|
9475
|
+
const usage2 = timed(
|
|
9476
|
+
{
|
|
9477
|
+
model: model.modelId,
|
|
9478
|
+
provider: model.provider,
|
|
9479
|
+
modality: "VIDEO",
|
|
9480
|
+
unit: "seconds",
|
|
9481
|
+
quantity: seconds2 ?? 0,
|
|
9482
|
+
...seconds2 !== void 0 && { durationSeconds: seconds2 }
|
|
9483
|
+
},
|
|
9484
|
+
startedAt
|
|
9485
|
+
);
|
|
9441
9486
|
settled = {
|
|
9442
9487
|
video: { bytes: result.video.uint8Array, mime: result.video.mediaType },
|
|
9443
9488
|
usage: usage2,
|
|
@@ -9494,8 +9539,12 @@ function createModelKit(config, adapters) {
|
|
|
9494
9539
|
message: `${adapter.id} cannot generate images`,
|
|
9495
9540
|
model: model.id
|
|
9496
9541
|
});
|
|
9542
|
+
const startedAt = Date.now();
|
|
9497
9543
|
const result = await adapter.generateImage(request, ctx);
|
|
9498
|
-
const usage2 =
|
|
9544
|
+
const usage2 = timed(
|
|
9545
|
+
{ ...result.usage, model: model.id, unit: model.usage.unit },
|
|
9546
|
+
startedAt
|
|
9547
|
+
);
|
|
9499
9548
|
await emit(usage2);
|
|
9500
9549
|
const images = result.images.map(toGeneratedImage);
|
|
9501
9550
|
const first = images[0];
|
|
@@ -9538,6 +9587,7 @@ function createModelKit(config, adapters) {
|
|
|
9538
9587
|
message: `${adapter.id} cannot generate video`,
|
|
9539
9588
|
model: model.id
|
|
9540
9589
|
});
|
|
9590
|
+
const startedAt = Date.now();
|
|
9541
9591
|
const job = await adapter.generateVideo(request, ctx);
|
|
9542
9592
|
const result = job.result.bind(job);
|
|
9543
9593
|
let settled;
|
|
@@ -9547,11 +9597,14 @@ function createModelKit(config, adapters) {
|
|
|
9547
9597
|
result(opts) {
|
|
9548
9598
|
if (settled) return settled;
|
|
9549
9599
|
const pending = result(opts).then(
|
|
9550
|
-
(out) =>
|
|
9551
|
-
|
|
9552
|
-
|
|
9553
|
-
|
|
9554
|
-
|
|
9600
|
+
async (out) => {
|
|
9601
|
+
const usage2 = timed(
|
|
9602
|
+
{ ...out.usage, model: model.id, unit: model.usage.unit },
|
|
9603
|
+
startedAt
|
|
9604
|
+
);
|
|
9605
|
+
await emit(usage2);
|
|
9606
|
+
return { ...out, usage: usage2 };
|
|
9607
|
+
},
|
|
9555
9608
|
(cause) => {
|
|
9556
9609
|
settled = void 0;
|
|
9557
9610
|
throw cause;
|
|
@@ -9588,9 +9641,14 @@ function createModelKit(config, adapters) {
|
|
|
9588
9641
|
model: model.id
|
|
9589
9642
|
});
|
|
9590
9643
|
}
|
|
9644
|
+
const startedAt = Date.now();
|
|
9591
9645
|
const result = await adapter.generateAudio(resolved, ctx);
|
|
9592
|
-
|
|
9593
|
-
|
|
9646
|
+
const usage2 = timed(
|
|
9647
|
+
{ ...result.usage, model: model.id, unit: model.usage.unit },
|
|
9648
|
+
startedAt
|
|
9649
|
+
);
|
|
9650
|
+
await emit(usage2);
|
|
9651
|
+
return { ...result, usage: usage2 };
|
|
9594
9652
|
},
|
|
9595
9653
|
async prepareMediaPart(modelId, ref, mediaType, call = {}) {
|
|
9596
9654
|
mediaRetryOptions(call);
|
|
@@ -9619,11 +9677,13 @@ function createModelKit(config, adapters) {
|
|
|
9619
9677
|
const { webhookUrl, ...rest } = call;
|
|
9620
9678
|
const { adapter, ctx } = videoToolTarget(req.model, rest);
|
|
9621
9679
|
if (!adapter.submitVideoTool) throw noVideoTools(adapter, ctx.model);
|
|
9622
|
-
|
|
9680
|
+
const submittedAt = Date.now();
|
|
9681
|
+
const submission = await adapter.submitVideoTool(
|
|
9623
9682
|
req,
|
|
9624
9683
|
ctx,
|
|
9625
9684
|
webhookUrl !== void 0 ? { webhookUrl } : {}
|
|
9626
9685
|
);
|
|
9686
|
+
return { ...submission, submittedAt };
|
|
9627
9687
|
},
|
|
9628
9688
|
async videoToolStatus(sub, call = {}) {
|
|
9629
9689
|
const { adapter, ctx } = videoToolTarget(sub.model, call);
|
|
@@ -9635,8 +9695,10 @@ function createModelKit(config, adapters) {
|
|
|
9635
9695
|
const { adapter, ctx } = videoToolTarget(sub.model, rest);
|
|
9636
9696
|
if (!adapter.videoToolResult) throw noVideoTools(adapter, ctx.model);
|
|
9637
9697
|
const result = await adapter.videoToolResult(sub, ctx, webhook);
|
|
9638
|
-
|
|
9639
|
-
|
|
9698
|
+
const base = { ...result.usage, model: ctx.model.id, unit: ctx.model.usage.unit };
|
|
9699
|
+
const usage2 = sub.submittedAt === void 0 ? base : timed(base, sub.submittedAt);
|
|
9700
|
+
await emit(usage2);
|
|
9701
|
+
return { ...result, usage: usage2 };
|
|
9640
9702
|
},
|
|
9641
9703
|
async cancelVideoTool(sub, call = {}) {
|
|
9642
9704
|
const { adapter, ctx } = videoToolTarget(sub.model, call);
|
|
@@ -9658,6 +9720,7 @@ function createModelKit(config, adapters) {
|
|
|
9658
9720
|
(model) => textTarget(model, call),
|
|
9659
9721
|
options.providerOptions
|
|
9660
9722
|
);
|
|
9723
|
+
const startedAt = Date.now();
|
|
9661
9724
|
const result = await (0, import_ai5.generateText)({
|
|
9662
9725
|
...options,
|
|
9663
9726
|
...textAbortOptions(options.abortSignal, call.signal),
|
|
@@ -9667,7 +9730,8 @@ function createModelKit(config, adapters) {
|
|
|
9667
9730
|
options.prepareStep ?? options.experimental_prepareStep
|
|
9668
9731
|
)
|
|
9669
9732
|
});
|
|
9670
|
-
for (const event of steps.usage(result.steps))
|
|
9733
|
+
for (const event of steps.usage(result.steps))
|
|
9734
|
+
await emit(textTimed(withRowUnit(event), result.steps.length, startedAt));
|
|
9671
9735
|
return result;
|
|
9672
9736
|
},
|
|
9673
9737
|
streamText(options, call = {}) {
|
|
@@ -9678,6 +9742,7 @@ function createModelKit(config, adapters) {
|
|
|
9678
9742
|
options.providerOptions
|
|
9679
9743
|
);
|
|
9680
9744
|
const callerOnFinish = options.onFinish;
|
|
9745
|
+
const startedAt = Date.now();
|
|
9681
9746
|
return (0, import_ai5.streamText)({
|
|
9682
9747
|
...options,
|
|
9683
9748
|
...textAbortOptions(options.abortSignal, call.signal),
|
|
@@ -9687,7 +9752,8 @@ function createModelKit(config, adapters) {
|
|
|
9687
9752
|
options.prepareStep ?? options.experimental_prepareStep
|
|
9688
9753
|
),
|
|
9689
9754
|
onFinish: async (event) => {
|
|
9690
|
-
for (const usage2 of steps.usage(event.steps))
|
|
9755
|
+
for (const usage2 of steps.usage(event.steps))
|
|
9756
|
+
await emit(textTimed(withRowUnit(usage2), event.steps.length, startedAt));
|
|
9691
9757
|
await callerOnFinish?.(event);
|
|
9692
9758
|
}
|
|
9693
9759
|
});
|
|
@@ -9700,15 +9766,22 @@ function createModelKit(config, adapters) {
|
|
|
9700
9766
|
model: languageModel2,
|
|
9701
9767
|
providerOptions: mergeTextProviderOptions(entry, options.providerOptions)
|
|
9702
9768
|
};
|
|
9769
|
+
const startedAt = Date.now();
|
|
9703
9770
|
const result = await (0, import_ai5.generateObject)(sdkOptions);
|
|
9704
9771
|
await emit(
|
|
9705
|
-
|
|
9772
|
+
timed(
|
|
9773
|
+
withRowUnit(
|
|
9774
|
+
textUsageEvent(entry, provider, result.usage, result.providerMetadata)
|
|
9775
|
+
),
|
|
9776
|
+
startedAt
|
|
9777
|
+
)
|
|
9706
9778
|
);
|
|
9707
9779
|
return result;
|
|
9708
9780
|
},
|
|
9709
9781
|
streamObject(options, call = {}) {
|
|
9710
9782
|
const { entry, languageModel: languageModel2, provider } = textTarget(options.model, call);
|
|
9711
9783
|
const callerOnFinish = options.onFinish;
|
|
9784
|
+
const startedAt = Date.now();
|
|
9712
9785
|
const sdkOptions = {
|
|
9713
9786
|
...options,
|
|
9714
9787
|
...textAbortOptions(options.abortSignal, call.signal),
|
|
@@ -9716,8 +9789,16 @@ function createModelKit(config, adapters) {
|
|
|
9716
9789
|
providerOptions: mergeTextProviderOptions(entry, options.providerOptions),
|
|
9717
9790
|
onFinish: async (event) => {
|
|
9718
9791
|
await emit(
|
|
9719
|
-
|
|
9720
|
-
|
|
9792
|
+
timed(
|
|
9793
|
+
withRowUnit(
|
|
9794
|
+
textUsageEvent(
|
|
9795
|
+
entry,
|
|
9796
|
+
provider,
|
|
9797
|
+
event.usage,
|
|
9798
|
+
event.providerMetadata
|
|
9799
|
+
)
|
|
9800
|
+
),
|
|
9801
|
+
startedAt
|
|
9721
9802
|
)
|
|
9722
9803
|
);
|
|
9723
9804
|
await callerOnFinish?.(event);
|