@voltro/ai 0.71.0 → 0.72.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 +435 -0
- package/THIRD-PARTY-NOTICES.md +29 -1
- package/dist/index.d.ts +60 -7
- package/dist/index.js +579 -413
- package/dist/{inferenceQueue-TwTEBG3Q.js → inferenceQueue-BZPicDnu.js} +47 -22
- package/dist/{provider-C_Sms_DA.js → provider-Cts1BRhY.js} +39 -24
- package/dist/test.js +1 -1
- package/dist/workflow.d.ts +43 -1
- package/dist/workflow.js +50 -28
- package/package.json +5 -5
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as e, o as t, r as n } from "./provider-
|
|
1
|
+
import { c as e, o as t, r as n } from "./provider-Cts1BRhY.js";
|
|
2
2
|
import { NoObjectGeneratedError as r, Output as i, experimental_transcribe as a, generateObject as o, generateText as s, jsonSchema as c, stepCountIs as l, tool as u } from "ai";
|
|
3
3
|
import { Context as d, Effect as f, JSONSchema as p, Metric as m, MetricBoundaries as ee, Runtime as te, Schema as h, Stream as ne } from "effect";
|
|
4
4
|
import { and as g, bigint as re, eq as _, generateId as v, gte as ie, id as y, integer as b, isNull as ae, json as x, queryFor as S, registerRetention as C, retentionTtlMsFromEnv as w, table as T, text as E, timestamp as D } from "@voltro/database";
|
|
@@ -189,22 +189,26 @@ var de = (e, t) => e(t), fe = Symbol.for("@voltro/ai/Tool"), pe = (e) => ({
|
|
|
189
189
|
}));
|
|
190
190
|
}), Oe = (e, t) => f.gen(function* () {
|
|
191
191
|
return Ce(t.reservationId), yield* f.promise(() => Te(e, async (e) => {
|
|
192
|
-
let
|
|
193
|
-
if (!
|
|
194
|
-
if (
|
|
195
|
-
let
|
|
196
|
-
if (!r || r.tenantId !== t.tenantId) throw Error("AI budget counter missing or mismatched; refusing unproved credit");
|
|
197
|
-
let i = P(r.reservedMicroUsd), a = P(n.amountMicroUsd);
|
|
198
|
-
if (a > i) throw Error("AI budget receipt exceeds its counter; refusing unproved credit");
|
|
199
|
-
let o = /* @__PURE__ */ new Date();
|
|
192
|
+
let n = S(xe).where(g(_("reservationId", t.reservationId), t.tenantId === null ? ae("tenantId") : _("tenantId", t.tenantId))).descriptor, [r] = await e.query(n);
|
|
193
|
+
if (!r) return "not-found";
|
|
194
|
+
if (r.releasedAt !== null) return "already-released";
|
|
195
|
+
let i = /* @__PURE__ */ new Date();
|
|
200
196
|
if (await e.updateMany("_voltro_ai_budget_reservations", {
|
|
201
|
-
releasedAt:
|
|
202
|
-
updatedAt:
|
|
203
|
-
}, { where: g(_("id",
|
|
197
|
+
releasedAt: i,
|
|
198
|
+
updatedAt: i
|
|
199
|
+
}, { where: g(_("id", r.id), ae("releasedAt")) }) !== 1) {
|
|
200
|
+
let [t] = await e.query(n);
|
|
201
|
+
if (t !== void 0 && t.releasedAt !== null) return "already-released";
|
|
202
|
+
throw new N("AI budget release raced; retry");
|
|
203
|
+
}
|
|
204
|
+
let [a] = await e.query(S(M).where(_("bucket", r.bucket)).descriptor);
|
|
205
|
+
if (!a || a.tenantId !== t.tenantId) throw Error("AI budget counter missing or mismatched; refusing unproved credit");
|
|
206
|
+
let o = P(a.reservedMicroUsd), s = P(r.amountMicroUsd);
|
|
207
|
+
if (s > o) throw Error("AI budget receipt exceeds its counter; refusing unproved credit");
|
|
204
208
|
if (await e.updateMany("_voltro_ai_budget", {
|
|
205
|
-
reservedMicroUsd: String(
|
|
206
|
-
updatedAt:
|
|
207
|
-
}, { where: g(_("id",
|
|
209
|
+
reservedMicroUsd: String(o - s),
|
|
210
|
+
updatedAt: i
|
|
211
|
+
}, { where: g(_("id", a.id), _("reservedMicroUsd", a.reservedMicroUsd)) }) !== 1) throw new N("AI budget counter changed; discard this release and retry");
|
|
208
212
|
return "released";
|
|
209
213
|
}));
|
|
210
214
|
}), ke = {
|
|
@@ -326,8 +330,11 @@ var de = (e, t) => e(t), fe = Symbol.for("@voltro/ai/Tool"), pe = (e) => ({
|
|
|
326
330
|
promptId: E().nullable(),
|
|
327
331
|
promptDigest: E().nullable(),
|
|
328
332
|
promptRevision: b().nullable(),
|
|
333
|
+
requestId: E().maxLength(191).nullable(),
|
|
334
|
+
attempt: b().nullable(),
|
|
335
|
+
receiptKey: E().maxLength(191),
|
|
329
336
|
calledAt: D().default("now")
|
|
330
|
-
}).index(["tenantId"]).index(["promptDigest"]), Ie = (e) => {
|
|
337
|
+
}).index(["tenantId"]).index(["promptDigest"]).unique("byAiUsageReceipt", ["receiptKey"]), Ie = (e) => {
|
|
331
338
|
let t = e?.gateway?.cost, n = typeof t == "string" ? t.trim() : void 0, r = typeof t == "number" ? t : n !== void 0 && /^(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?$/i.test(n) ? Number(n) : NaN;
|
|
332
339
|
return Number.isFinite(r) && r >= 0 ? r : void 0;
|
|
333
340
|
}, Le = (e, t) => (C({
|
|
@@ -340,8 +347,10 @@ var de = (e, t) => e(t), fe = Symbol.for("@voltro/ai/Tool"), pe = (e) => ({
|
|
|
340
347
|
model: t.model,
|
|
341
348
|
...t.price === void 0 ? {} : { price: t.price },
|
|
342
349
|
...t.actualCostUsd === void 0 ? {} : { actualCostUsd: t.actualCostUsd }
|
|
343
|
-
})
|
|
344
|
-
|
|
350
|
+
}), r = t.receiptKey ?? (t.requestId === void 0 ? v({
|
|
351
|
+
kind: "typeid",
|
|
352
|
+
prefix: "aiu"
|
|
353
|
+
}, "_voltro_ai_usage") : `${t.requestId}#${t.attempt ?? 0}`), i = await e.insertIgnoreWithOutcome(L, {
|
|
345
354
|
tenantId: t.tenantId ?? null,
|
|
346
355
|
provider: t.provider,
|
|
347
356
|
model: t.model,
|
|
@@ -355,8 +364,15 @@ var de = (e, t) => e(t), fe = Symbol.for("@voltro/ai/Tool"), pe = (e) => ({
|
|
|
355
364
|
promptId: t.prompt?.promptId ?? null,
|
|
356
365
|
promptDigest: t.prompt?.digest ?? null,
|
|
357
366
|
promptRevision: t.prompt?.revision ?? null,
|
|
367
|
+
requestId: t.requestId ?? null,
|
|
368
|
+
attempt: t.attempt ?? null,
|
|
369
|
+
receiptKey: r,
|
|
358
370
|
calledAt: t.calledAt ?? /* @__PURE__ */ new Date()
|
|
359
|
-
}
|
|
371
|
+
}, { conflictColumns: ["receiptKey"] });
|
|
372
|
+
return {
|
|
373
|
+
...n,
|
|
374
|
+
receipt: i.outcome === "inserted" ? "recorded" : "replayed"
|
|
375
|
+
};
|
|
360
376
|
})), Re = (e, t = {}) => f.promise(async () => {
|
|
361
377
|
let n = [
|
|
362
378
|
...t.tenantId === void 0 ? [] : [_("tenantId", t.tenantId)],
|
|
@@ -480,6 +496,7 @@ var de = (e, t) => e(t), fe = Symbol.for("@voltro/ai/Tool"), pe = (e) => ({
|
|
|
480
496
|
let i = e.tools === void 0 ? void 0 : yield* f.runtime(), a = e.tools === void 0 || i === void 0 ? void 0 : O(e.tools, {
|
|
481
497
|
store: void 0,
|
|
482
498
|
...e.toolContext,
|
|
499
|
+
...e.abortSignal === void 0 ? {} : { abortSignal: e.abortSignal },
|
|
483
500
|
runtime: i
|
|
484
501
|
});
|
|
485
502
|
return yield* q(e.provider ?? n(), e.fallbacks, (n) => H(B(n, "generateText"), (e) => e.usage, f.tryPromise({
|
|
@@ -487,6 +504,7 @@ var de = (e, t) => e(t), fe = Symbol.for("@voltro/ai/Tool"), pe = (e) => ({
|
|
|
487
504
|
let i = t(n), o = await s({
|
|
488
505
|
model: i,
|
|
489
506
|
...r,
|
|
507
|
+
...e.abortSignal === void 0 ? {} : { abortSignal: e.abortSignal },
|
|
490
508
|
...a === void 0 ? {} : {
|
|
491
509
|
tools: a,
|
|
492
510
|
stopWhen: l(e.maxSteps ?? 8)
|
|
@@ -582,6 +600,7 @@ var de = (e, t) => e(t), fe = Symbol.for("@voltro/ai/Tool"), pe = (e) => ({
|
|
|
582
600
|
let a = yield* f.runtime(), o = yield* J(e.schema, "generateObjectWithTools"), u = {
|
|
583
601
|
store: void 0,
|
|
584
602
|
...e.toolContext,
|
|
603
|
+
...e.abortSignal === void 0 ? {} : { abortSignal: e.abortSignal },
|
|
585
604
|
runtime: a
|
|
586
605
|
}, d = O(e.tools, u);
|
|
587
606
|
return yield* q(e.provider ?? n(), e.fallbacks, (n) => H(B(n, "generateObjectWithTools"), (e) => e.usage, f.gen(function* () {
|
|
@@ -590,6 +609,7 @@ var de = (e, t) => e(t), fe = Symbol.for("@voltro/ai/Tool"), pe = (e) => ({
|
|
|
590
609
|
model: a,
|
|
591
610
|
prompt: e.prompt,
|
|
592
611
|
tools: d,
|
|
612
|
+
...e.abortSignal === void 0 ? {} : { abortSignal: e.abortSignal },
|
|
593
613
|
stopWhen: l(e.maxSteps ?? 8),
|
|
594
614
|
output: i.object({ schema: c(o) }),
|
|
595
615
|
...e.system === void 0 ? {} : { system: e.system },
|
|
@@ -803,7 +823,8 @@ var de = (e, t) => e(t), fe = Symbol.for("@voltro/ai/Tool"), pe = (e) => ({
|
|
|
803
823
|
kind: E().oneOf([
|
|
804
824
|
"text",
|
|
805
825
|
"object",
|
|
806
|
-
"transcription"
|
|
826
|
+
"transcription",
|
|
827
|
+
"media"
|
|
807
828
|
]).default("text"),
|
|
808
829
|
provider: E(),
|
|
809
830
|
model: E(),
|
|
@@ -816,9 +837,11 @@ var de = (e, t) => e(t), fe = Symbol.for("@voltro/ai/Tool"), pe = (e) => ({
|
|
|
816
837
|
providerOptions: x().nullable(),
|
|
817
838
|
jsonSchema: x().nullable(),
|
|
818
839
|
transcription: x().nullable(),
|
|
840
|
+
media: x().nullable(),
|
|
819
841
|
result: x().nullable(),
|
|
820
842
|
errorMessage: E().nullable(),
|
|
821
843
|
attempts: b().default(0),
|
|
844
|
+
fence: b().default(0),
|
|
822
845
|
leaseUntil: D().nullable(),
|
|
823
846
|
claimedBy: E().nullable(),
|
|
824
847
|
enqueuedAt: D().default("now"),
|
|
@@ -836,7 +859,7 @@ var de = (e, t) => e(t), fe = Symbol.for("@voltro/ai/Tool"), pe = (e) => ({
|
|
|
836
859
|
runId: $(e.runId),
|
|
837
860
|
signalName: String(e.signalName),
|
|
838
861
|
stepName: String(e.stepName),
|
|
839
|
-
kind: e.kind === "object" ? "object" : e.kind === "transcription" ? "transcription" : "text",
|
|
862
|
+
kind: e.kind === "object" ? "object" : e.kind === "transcription" ? "transcription" : e.kind === "media" ? "media" : "text",
|
|
840
863
|
provider: String(e.provider),
|
|
841
864
|
model: String(e.model),
|
|
842
865
|
prompt: String(e.prompt ?? ""),
|
|
@@ -848,7 +871,9 @@ var de = (e, t) => e(t), fe = Symbol.for("@voltro/ai/Tool"), pe = (e) => ({
|
|
|
848
871
|
providerOptions: e.providerOptions ?? null,
|
|
849
872
|
jsonSchema: e.jsonSchema ?? null,
|
|
850
873
|
transcription: e.transcription ?? null,
|
|
851
|
-
|
|
874
|
+
media: e.media ?? null,
|
|
875
|
+
attempts: Q(e.attempts, 0),
|
|
876
|
+
fence: Q(e.fence, 0)
|
|
852
877
|
}), xt = (e) => {
|
|
853
878
|
let t = e.attempts + 1;
|
|
854
879
|
return t >= e.maxAttempts ? {
|
|
@@ -30,40 +30,55 @@ var u = [], d = (...e) => {
|
|
|
30
30
|
model: n.modelId
|
|
31
31
|
}), e())
|
|
32
32
|
};
|
|
33
|
-
}, g = (e, t) =>
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
a
|
|
42
|
-
|
|
43
|
-
|
|
33
|
+
}, g = (e, t) => {
|
|
34
|
+
let n = Object.fromEntries(Object.entries(t).filter(([, e]) => e !== void 0));
|
|
35
|
+
return {
|
|
36
|
+
...e,
|
|
37
|
+
fetch: async (t, r) => {
|
|
38
|
+
let i = e.fetch ?? globalThis.fetch;
|
|
39
|
+
if (Object.keys(n).length === 0) return i(t, r);
|
|
40
|
+
if (r?.method !== "POST" || typeof r.body != "string") throw Error("Gateway media: expected a JSON POST to preserve the requested parameters");
|
|
41
|
+
let a;
|
|
42
|
+
try {
|
|
43
|
+
a = JSON.parse(r.body);
|
|
44
|
+
} catch {
|
|
45
|
+
throw Error("Gateway media: expected a JSON object to preserve the requested parameters");
|
|
46
|
+
}
|
|
47
|
+
if (typeof a != "object" || !a || Array.isArray(a)) throw Error("Gateway media: expected a JSON object to preserve the requested parameters");
|
|
48
|
+
return i(t, {
|
|
49
|
+
...r,
|
|
50
|
+
body: JSON.stringify({
|
|
51
|
+
...a,
|
|
52
|
+
...n
|
|
53
|
+
})
|
|
54
|
+
});
|
|
44
55
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
...r,
|
|
48
|
-
body: JSON.stringify({
|
|
49
|
-
...a,
|
|
50
|
-
seed: t
|
|
51
|
-
})
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
}), _ = (e, t) => {
|
|
56
|
+
};
|
|
57
|
+
}, _ = (e, t) => {
|
|
55
58
|
let n = Reflect.get(e, t, e);
|
|
56
59
|
return typeof n == "function" && t !== "constructor" ? n.bind(e) : n;
|
|
57
60
|
}, v = (e, t) => {
|
|
58
|
-
let n = i(e).image(t), r = (n) => i(g(e,
|
|
61
|
+
let n = i(e).image(t), r = (n) => i(g(e, {
|
|
62
|
+
seed: n.seed,
|
|
63
|
+
duration: void 0,
|
|
64
|
+
fps: void 0
|
|
65
|
+
})).image(t).doGenerate(n);
|
|
59
66
|
return new Proxy(n, { get: (e, t) => t === "doGenerate" ? r : _(e, t) });
|
|
60
67
|
}, y = (e, t) => {
|
|
61
68
|
let n = i(e).video(t), r = n.doGenerate === void 0 ? void 0 : (n) => {
|
|
62
|
-
let r = i(g(e,
|
|
69
|
+
let r = i(g(e, {
|
|
70
|
+
seed: n.seed,
|
|
71
|
+
duration: n.duration,
|
|
72
|
+
fps: n.fps
|
|
73
|
+
})).video(t);
|
|
63
74
|
if (!r.doGenerate) throw Error("Gateway video does not implement doGenerate");
|
|
64
75
|
return r.doGenerate(n);
|
|
65
76
|
}, a = n.doStart === void 0 ? void 0 : (n) => {
|
|
66
|
-
let r = i(g(e,
|
|
77
|
+
let r = i(g(e, {
|
|
78
|
+
seed: n.seed,
|
|
79
|
+
duration: n.duration,
|
|
80
|
+
fps: n.fps
|
|
81
|
+
})).video(t);
|
|
67
82
|
if (!r.doStart) throw Error("Gateway video does not implement doStart");
|
|
68
83
|
return r.doStart(n);
|
|
69
84
|
};
|
package/dist/test.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as e, u as t } from "./provider-
|
|
1
|
+
import { t as e, u as t } from "./provider-Cts1BRhY.js";
|
|
2
2
|
//#region src/test/index.ts
|
|
3
3
|
var n = (e) => e.turns && e.turns.length > 0 ? e.turns : e.stream && e.stream.length > 0 ? [{ text: e.stream.join("") }] : e.generate ? [{ text: e.generate.text }] : [{ text: "" }], r = (t) => {
|
|
4
4
|
let r = new e(n(t));
|
package/dist/workflow.d.ts
CHANGED
|
@@ -43,7 +43,11 @@ export declare interface AiObjectStepOptions<A, I> extends AiStepBaseOptions {
|
|
|
43
43
|
|
|
44
44
|
export declare class AiOffloadError extends Error {
|
|
45
45
|
readonly attempts: number;
|
|
46
|
-
|
|
46
|
+
/** `failed` — the call was performed and gave up. `unknown` — the worker
|
|
47
|
+
* that submitted it was lost and the provider cannot be asked: the job may
|
|
48
|
+
* have produced (and charged for) its artifact. A media job only. */
|
|
49
|
+
readonly outcome: 'failed' | 'unknown';
|
|
50
|
+
constructor(stepName: string, message: string, attempts: number, outcome?: 'failed' | 'unknown');
|
|
47
51
|
}
|
|
48
52
|
|
|
49
53
|
export declare class AiOffloadMisuseError extends Error {
|
|
@@ -233,6 +237,44 @@ declare type GatewayCreator = 'openai' | 'anthropic' | 'google' | (string & {});
|
|
|
233
237
|
* now a type error, not a boot crash). */
|
|
234
238
|
declare type GatewayModel = `${GatewayCreator}/${string}`;
|
|
235
239
|
|
|
240
|
+
/**
|
|
241
|
+
* A media generation as a durable step — always offloaded, because a media
|
|
242
|
+
* job is an external job: minutes long, paid on submission, and owned by
|
|
243
|
+
* whichever process submitted it.
|
|
244
|
+
*
|
|
245
|
+
* The queue row is the job's identity, allocated before the first paid call.
|
|
246
|
+
* A replay finds the row; a dispatcher that dies mid-job leaves a lease that
|
|
247
|
+
* expires — and the reclaiming dispatcher does NOT submit again: the provider
|
|
248
|
+
* has no lookup, so the outcome is reported to the run as `unknown`
|
|
249
|
+
* (`AiOffloadError.outcome`) rather than paid for twice. Artifacts are
|
|
250
|
+
* persisted through the storage plugin's `mediaPersist` capability under
|
|
251
|
+
* `<row>#<attempt>#<index>`, and the run receives URLs and ref ids.
|
|
252
|
+
*/
|
|
253
|
+
export declare const mediaStep: (options: MediaStepOptions) => Effect.Effect<MediaStepResult, unknown>;
|
|
254
|
+
|
|
255
|
+
export declare interface MediaStepOptions extends Omit<AiStepBaseOptions, 'system' | 'promptTemplate' | 'promptVars' | 'offload' | 'tools' | 'maxSteps' | 'toolContext' | 'fallbacks' | 'maxTokens'> {
|
|
256
|
+
readonly modality: 'image' | 'video' | 'speech';
|
|
257
|
+
/** Provider parameters — `n`, `size`, `aspectRatio`, `seed` for an image;
|
|
258
|
+
* `durationSeconds`, `resolution`, `fps` for a video; `voice`, `format` for
|
|
259
|
+
* speech. Passed through to the generator, journaled with the job. */
|
|
260
|
+
readonly params?: Record<string, unknown>;
|
|
261
|
+
/** URL inputs — reference images, a mask, a starting frame. URLs only: the
|
|
262
|
+
* job row travels through the queue and a resume payload, never bytes. */
|
|
263
|
+
readonly inputs?: Record<string, unknown>;
|
|
264
|
+
/** Required: a media job is always an external job with a durable identity. */
|
|
265
|
+
readonly store: DataStore;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export declare interface MediaStepResult {
|
|
269
|
+
readonly artifacts: ReadonlyArray<{
|
|
270
|
+
readonly url: string;
|
|
271
|
+
readonly refId: string | null;
|
|
272
|
+
readonly mediaType: string;
|
|
273
|
+
}>;
|
|
274
|
+
readonly usage: unknown;
|
|
275
|
+
readonly providerMetadata: unknown;
|
|
276
|
+
}
|
|
277
|
+
|
|
236
278
|
/** A scripted inline file the mock model emits on a turn (usually an image).
|
|
237
279
|
* `data` is base64 (a short ascii string works for assertions). */
|
|
238
280
|
declare interface MockFile {
|
package/dist/workflow.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { r as e } from "./provider-
|
|
2
|
-
import { D as t, E as n, O as r, R as i, U as a, Z as o, b as s, m as c, o as l, p as u, s as d, t as f, w as p, y as m } from "./inferenceQueue-
|
|
1
|
+
import { r as e } from "./provider-Cts1BRhY.js";
|
|
2
|
+
import { D as t, E as n, O as r, R as i, U as a, Z as o, b as s, m as c, o as l, p as u, s as d, t as f, w as p, y as m } from "./inferenceQueue-BZPicDnu.js";
|
|
3
3
|
import { Effect as h, Schema as g } from "effect";
|
|
4
4
|
import { eq as _ } from "@voltro/database";
|
|
5
5
|
import { CurrentWorkflowExecutionId as v, awaitSignalSuspending as y, step as b, suspendForBudget as x } from "@voltro/workflow";
|
|
@@ -69,38 +69,39 @@ var S = {
|
|
|
69
69
|
totalTokens: g.NullOr(g.Number)
|
|
70
70
|
}), j = (e) => typeof e == "object" && !!e && e.__voltro_ai_error === !0, M = class extends Error {
|
|
71
71
|
attempts;
|
|
72
|
-
|
|
73
|
-
|
|
72
|
+
outcome;
|
|
73
|
+
constructor(e, t, n, r = "failed") {
|
|
74
|
+
super(`aiStep('${e}'): the offloaded model call gave up after ${n} attempt(s): ${t}. The queued call is in _voltro_ai_inferences with status 'failed' — the Flow tab shows it with the provider's own message.`), this.name = "AiOffloadError", this.attempts = n, this.outcome = r;
|
|
74
75
|
}
|
|
75
76
|
}, N = class extends Error {
|
|
76
77
|
constructor(e) {
|
|
77
78
|
super(`aiStep('${e}'): offload: true needs \`store\` — the queued call lives in a table and the dispatcher reads it from there. Pass ctx.store.`), this.name = "AiOffloadMisuseError";
|
|
78
79
|
}
|
|
79
|
-
}, P = (e, t, n, r, i, a) => h.gen(function* () {
|
|
80
|
-
let
|
|
81
|
-
if (
|
|
82
|
-
let
|
|
83
|
-
if (
|
|
84
|
-
let { provider:
|
|
80
|
+
}, P = (e, t, n, r, i, a, o) => h.gen(function* () {
|
|
81
|
+
let s = e.store;
|
|
82
|
+
if (s === void 0) return yield* h.die(new N(e.name));
|
|
83
|
+
let c = yield* v;
|
|
84
|
+
if (c === void 0) return yield* h.die(/* @__PURE__ */ Error(`aiStep('${e.name}'): offload: true is only valid inside a workflow body — there is no execution to suspend here.`));
|
|
85
|
+
let { provider: u, model: p } = D(t), m = d(c, e.name), g = yield* h.promise(() => s.query({
|
|
85
86
|
table: "_voltro_workflow_runs",
|
|
86
|
-
predicate: _("executionId",
|
|
87
|
+
predicate: _("executionId", c),
|
|
87
88
|
order: [],
|
|
88
89
|
take: 1,
|
|
89
90
|
skip: void 0,
|
|
90
91
|
projection: void 0
|
|
91
|
-
})),
|
|
92
|
-
return yield* h.promise(() =>
|
|
93
|
-
id:
|
|
92
|
+
})), y = String(g[0]?.tag ?? ""), b = g[0]?.id;
|
|
93
|
+
return yield* h.promise(() => s.insertIgnore(f, {
|
|
94
|
+
id: m,
|
|
94
95
|
tenantId: e.tenantId ?? null,
|
|
95
|
-
executionId:
|
|
96
|
-
workflowName:
|
|
97
|
-
runId: typeof
|
|
98
|
-
signalName: l(
|
|
96
|
+
executionId: c,
|
|
97
|
+
workflowName: y,
|
|
98
|
+
runId: typeof b == "string" ? b : null,
|
|
99
|
+
signalName: l(m),
|
|
99
100
|
stepName: e.name,
|
|
100
101
|
status: "pending",
|
|
101
102
|
kind: n,
|
|
102
|
-
provider:
|
|
103
|
-
model:
|
|
103
|
+
provider: u,
|
|
104
|
+
model: p,
|
|
104
105
|
prompt: i.text,
|
|
105
106
|
system: i.system ?? null,
|
|
106
107
|
promptId: i.rendered?.promptId ?? null,
|
|
@@ -110,23 +111,25 @@ var S = {
|
|
|
110
111
|
providerOptions: e.providerOptions ?? null,
|
|
111
112
|
jsonSchema: r,
|
|
112
113
|
...a === void 0 ? {} : { transcription: a },
|
|
114
|
+
...o === void 0 ? {} : { media: o },
|
|
113
115
|
attempts: 0,
|
|
116
|
+
fence: 0,
|
|
114
117
|
enqueuedAt: /* @__PURE__ */ new Date()
|
|
115
|
-
}, { conflictColumns: ["id"] })),
|
|
116
|
-
}), F = (e, t, n, r, i, a, o) => h.gen(function* () {
|
|
117
|
-
let
|
|
118
|
+
}, { conflictColumns: ["id"] })), m;
|
|
119
|
+
}), F = (e, t, n, r, i, a, o, s) => h.gen(function* () {
|
|
120
|
+
let c = yield* b({
|
|
118
121
|
name: `${e.name}:enqueue`,
|
|
119
122
|
success: g.String,
|
|
120
123
|
input: i,
|
|
121
|
-
execute: P(e, t, n, r, a, o)
|
|
124
|
+
execute: P(e, t, n, r, a, o, s)
|
|
122
125
|
});
|
|
123
126
|
yield* k(e, a.rendered);
|
|
124
|
-
let
|
|
125
|
-
name: l(
|
|
127
|
+
let u = yield* y({ store: e.store }, {
|
|
128
|
+
name: l(c),
|
|
126
129
|
schema: g.Unknown,
|
|
127
130
|
timeoutMs: e.offloadTimeoutMs ?? 36e5
|
|
128
131
|
});
|
|
129
|
-
return j(
|
|
132
|
+
return j(u) ? yield* h.die(new M(e.name, u.message, u.attempts, u.outcome === "unknown" ? "unknown" : "failed")) : u;
|
|
130
133
|
}), I = class extends Error {
|
|
131
134
|
constructor(e) {
|
|
132
135
|
super(`aiStep('${e}'): budget needs \`store\` — the reservation counter and the hold both live in tables. Pass ctx.store.`), this.name = "AiBudgetMisuseError";
|
|
@@ -240,6 +243,25 @@ var S = {
|
|
|
240
243
|
})))
|
|
241
244
|
}));
|
|
242
245
|
}, H = (t) => {
|
|
246
|
+
let n = t.provider ?? e(), r = E({
|
|
247
|
+
...t,
|
|
248
|
+
prompt: t.prompt
|
|
249
|
+
}), i = {
|
|
250
|
+
modality: t.modality,
|
|
251
|
+
params: t.params ?? {},
|
|
252
|
+
inputs: t.inputs ?? {}
|
|
253
|
+
}, a = {
|
|
254
|
+
...D(n),
|
|
255
|
+
operation: `generate${t.modality[0].toUpperCase()}${t.modality.slice(1)}`,
|
|
256
|
+
offloaded: !0,
|
|
257
|
+
modality: t.modality,
|
|
258
|
+
...T(r.text, void 0, t.recordPrompt ?? "digest", r.rendered)
|
|
259
|
+
};
|
|
260
|
+
return ((e) => t.budget === void 0 ? e : h.zipRight(L(t), e))(F({
|
|
261
|
+
...t,
|
|
262
|
+
offload: !0
|
|
263
|
+
}, n, "media", null, a, r, void 0, i));
|
|
264
|
+
}, U = (t) => {
|
|
243
265
|
let i = t.provider ?? e(), a = E(t), o = {
|
|
244
266
|
...D(i),
|
|
245
267
|
operation: "generateObject",
|
|
@@ -277,4 +299,4 @@ var S = {
|
|
|
277
299
|
}));
|
|
278
300
|
};
|
|
279
301
|
//#endregion
|
|
280
|
-
export { S as AI_STEP_RETRY, I as AiBudgetMisuseError, M as AiOffloadError, N as AiOffloadMisuseError, w as DEFAULT_AI_BUDGET_NAME, C as DEFAULT_OFFLOAD_TIMEOUT_MS, B as TranscriptionStepResult,
|
|
302
|
+
export { S as AI_STEP_RETRY, I as AiBudgetMisuseError, M as AiOffloadError, N as AiOffloadMisuseError, w as DEFAULT_AI_BUDGET_NAME, C as DEFAULT_OFFLOAD_TIMEOUT_MS, B as TranscriptionStepResult, U as aiObjectStep, z as aiStep, H as mediaStep, c as promptDigest, T as promptRecordFor, E as resolveStepPrompt, V as transcribeStep };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voltro/ai",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.72.0",
|
|
4
4
|
"description": "Effect-native AI primitives — generateText / generateObject / streamText, tools, agents, media generation, cost tracking + budgets, and provider fallback.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"voltro",
|
|
@@ -55,10 +55,10 @@
|
|
|
55
55
|
"dependencies": {
|
|
56
56
|
"@ai-sdk/anthropic": "^4.0.49",
|
|
57
57
|
"@ai-sdk/openai": "^4.0.58",
|
|
58
|
-
"@voltro/cache": "0.
|
|
59
|
-
"@voltro/database": "0.
|
|
60
|
-
"@voltro/protocol": "0.
|
|
61
|
-
"@voltro/workflow": "0.
|
|
58
|
+
"@voltro/cache": "0.72.0",
|
|
59
|
+
"@voltro/database": "0.72.0",
|
|
60
|
+
"@voltro/protocol": "0.72.0",
|
|
61
|
+
"@voltro/workflow": "0.72.0",
|
|
62
62
|
"ajv": "^8.20.0",
|
|
63
63
|
"ajv-formats": "^3.0.1"
|
|
64
64
|
},
|